@@ -975,11 +975,11 @@ func Version() (simple, full string) {
975975 if CustomVersion != "" {
976976 full = CustomVersion
977977 simple = CustomVersion
978- return
978+ return simple , full
979979 }
980980 full = "unknown"
981981 simple = "unknown"
982- return
982+ return simple , full
983983 }
984984 // find the Caddy module in the dependency list
985985 for _ , dep := range bi .Deps {
@@ -1059,7 +1059,7 @@ func Version() (simple, full string) {
10591059 }
10601060 }
10611061
1062- return
1062+ return simple , full
10631063}
10641064
10651065// Event represents something that has happened or is happening.
@@ -1197,6 +1197,91 @@ var (
11971197 rawCfgMu sync.RWMutex
11981198)
11991199
1200+ // lastConfigFile and lastConfigAdapter remember the source config
1201+ // file and adapter used when Caddy was started via the CLI "run" command.
1202+ // These are consulted by the SIGUSR1 handler to attempt reloading from
1203+ // the same source. They are intentionally not set for other entrypoints
1204+ // such as "caddy start" or subcommands like file-server.
1205+ var (
1206+ lastConfigMu sync.RWMutex
1207+ lastConfigFile string
1208+ lastConfigAdapter string
1209+ )
1210+
1211+ // reloadFromSourceFunc is the type of stored callback
1212+ // which is called when we receive a SIGUSR1 signal.
1213+ type reloadFromSourceFunc func (file , adapter string ) error
1214+
1215+ // reloadFromSourceCallback is the stored callback
1216+ // which is called when we receive a SIGUSR1 signal.
1217+ var reloadFromSourceCallback reloadFromSourceFunc
1218+
1219+ // errReloadFromSourceUnavailable is returned when no reload-from-source callback is set.
1220+ var errReloadFromSourceUnavailable = errors .New ("reload from source unavailable in this process" ) //nolint:unused
1221+
1222+ // SetLastConfig records the given source file and adapter as the
1223+ // last-known external configuration source. Intended to be called
1224+ // only when starting via "caddy run --config <file> --adapter <adapter>".
1225+ func SetLastConfig (file , adapter string , fn reloadFromSourceFunc ) {
1226+ lastConfigMu .Lock ()
1227+ lastConfigFile = file
1228+ lastConfigAdapter = adapter
1229+ reloadFromSourceCallback = fn
1230+ lastConfigMu .Unlock ()
1231+ }
1232+
1233+ // ClearLastConfigIfDifferent clears the recorded last-config if the provided
1234+ // source file/adapter do not match the recorded last-config. If both srcFile
1235+ // and srcAdapter are empty, the last-config is cleared.
1236+ func ClearLastConfigIfDifferent (srcFile , srcAdapter string ) {
1237+ if (srcFile != "" || srcAdapter != "" ) && lastConfigMatches (srcFile , srcAdapter ) {
1238+ return
1239+ }
1240+ SetLastConfig ("" , "" , nil )
1241+ }
1242+
1243+ // getLastConfig returns the last-known config file and adapter.
1244+ func getLastConfig () (file , adapter string , fn reloadFromSourceFunc ) {
1245+ lastConfigMu .RLock ()
1246+ f , a , cb := lastConfigFile , lastConfigAdapter , reloadFromSourceCallback
1247+ lastConfigMu .RUnlock ()
1248+ return f , a , cb
1249+ }
1250+
1251+ // lastConfigMatches returns true if the provided source file and/or adapter
1252+ // matches the recorded last-config. Matching rules (in priority order):
1253+ // 1. If srcAdapter is provided and differs from the recorded adapter, no match.
1254+ // 2. If srcFile exactly equals the recorded file, match.
1255+ // 3. If both sides can be made absolute and equal, match.
1256+ // 4. If basenames are equal, match.
1257+ func lastConfigMatches (srcFile , srcAdapter string ) bool {
1258+ lf , la , _ := getLastConfig ()
1259+
1260+ // If adapter is provided, it must match.
1261+ if srcAdapter != "" && srcAdapter != la {
1262+ return false
1263+ }
1264+
1265+ // Quick equality check.
1266+ if srcFile == lf {
1267+ return true
1268+ }
1269+
1270+ // Try absolute path comparison.
1271+ sAbs , sErr := filepath .Abs (srcFile )
1272+ lAbs , lErr := filepath .Abs (lf )
1273+ if sErr == nil && lErr == nil && sAbs == lAbs {
1274+ return true
1275+ }
1276+
1277+ // Final fallback: basename equality.
1278+ if filepath .Base (srcFile ) == filepath .Base (lf ) {
1279+ return true
1280+ }
1281+
1282+ return false
1283+ }
1284+
12001285// errSameConfig is returned if the new config is the same
12011286// as the old one. This isn't usually an actual, actionable
12021287// error; it's mostly a sentinel value.
0 commit comments