Merge pull request #2592 from andersonvom/remove_globals

Remove some global variables from main.go
This commit is contained in:
Jakob Borg 2015-12-19 09:05:05 +01:00
commit 2b89f33765
2 changed files with 107 additions and 103 deletions

View File

@ -110,19 +110,13 @@ func init() {
date := BuildDate.UTC().Format("2006-01-02 15:04:05 MST") date := BuildDate.UTC().Format("2006-01-02 15:04:05 MST")
LongVersion = fmt.Sprintf(`syncthing %s "%s" (%s %s-%s) %s@%s %s`, Version, Codename, runtime.Version(), runtime.GOOS, runtime.GOARCH, BuildUser, BuildHost, date) LongVersion = fmt.Sprintf(`syncthing %s "%s" (%s %s-%s) %s@%s %s`, Version, Codename, runtime.Version(), runtime.GOOS, runtime.GOARCH, BuildUser, BuildHost, date)
if os.Getenv("STTRACE") != "" {
logFlags = log.Ltime | log.Ldate | log.Lmicroseconds | log.Lshortfile
}
} }
var ( var (
myID protocol.DeviceID myID protocol.DeviceID
confDir string stop = make(chan int)
logFlags = log.Ltime cert tls.Certificate
stop = make(chan int) lans []*net.IPNet
cert tls.Certificate
lans []*net.IPNet
) )
const ( const (
@ -190,8 +184,14 @@ The following are valid values for the STTRACE variable:
%s` %s`
) )
// Command line and environment options // Environment options
var ( var (
noUpgrade = os.Getenv("STNOUPGRADE") != ""
innerProcess = os.Getenv("STNORESTART") != "" || os.Getenv("STMONITORED") != ""
)
type RuntimeOptions struct {
confDir string
reset bool reset bool
showVersion bool showVersion bool
doUpgrade bool doUpgrade bool
@ -199,7 +199,7 @@ var (
upgradeTo string upgradeTo string
noBrowser bool noBrowser bool
browserOnly bool browserOnly bool
noConsole bool hideConsole bool
logFile string logFile string
auditEnabled bool auditEnabled bool
verbose bool verbose bool
@ -207,132 +207,145 @@ var (
guiAddress string guiAddress string
guiAPIKey string guiAPIKey string
generateDir string generateDir string
noRestart = os.Getenv("STNORESTART") != "" noRestart bool
noUpgrade = os.Getenv("STNOUPGRADE") != "" profiler string
profiler = os.Getenv("STPROFILER") assetDir string
guiAssets = os.Getenv("STGUIASSETS") cpuProfile bool
cpuProfile = os.Getenv("STCPUPROFILE") != "" stRestarting bool
stRestarting = os.Getenv("STRESTART") != "" logFlags int
innerProcess = os.Getenv("STNORESTART") != "" || os.Getenv("STMONITORED") != "" }
)
func parseCommandLineOptions() { func defaultRuntimeOptions() RuntimeOptions {
if runtime.GOOS == "windows" { options := RuntimeOptions{
// On Windows, we use a log file by default. Setting the -logfile flag noRestart: os.Getenv("STNORESTART") != "",
// to "-" disables this behavior. profiler: os.Getenv("STPROFILER"),
flag.StringVar(&logFile, "logfile", "", "Log file name (use \"-\" for stdout)") assetDir: os.Getenv("STGUIASSETS"),
cpuProfile: os.Getenv("STCPUPROFILE") != "",
// We also add an option to hide the console window stRestarting: os.Getenv("STRESTART") != "",
flag.BoolVar(&noConsole, "no-console", false, "Hide console window") logFile: "-", // Output to stdout
} else { logFlags: log.Ltime,
flag.StringVar(&logFile, "logfile", "-", "Log file name (use \"-\" for stdout)")
} }
flag.StringVar(&generateDir, "generate", "", "Generate key and config in specified dir, then exit") if options.assetDir != "" {
flag.StringVar(&guiAddress, "gui-address", guiAddress, "Override GUI address (e.g. \"http://192.0.2.42:8443\")") options.assetDir = locations[locGUIAssets]
flag.StringVar(&guiAPIKey, "gui-apikey", guiAPIKey, "Override GUI API key") }
flag.StringVar(&confDir, "home", "", "Set configuration directory")
flag.IntVar(&logFlags, "logflags", logFlags, "Select information in log line prefix (see below)") if os.Getenv("STTRACE") != "" {
flag.BoolVar(&noBrowser, "no-browser", false, "Do not start browser") options.logFlags = log.Ltime | log.Ldate | log.Lmicroseconds | log.Lshortfile
flag.BoolVar(&browserOnly, "browser-only", false, "Open GUI in browser") }
flag.BoolVar(&noRestart, "no-restart", noRestart, "Do not restart; just exit")
flag.BoolVar(&reset, "reset", false, "Reset the database") if runtime.GOOS == "windows" {
flag.BoolVar(&doUpgrade, "upgrade", false, "Perform upgrade") options.logFile = locations[locLogFile]
flag.BoolVar(&doUpgradeCheck, "upgrade-check", false, "Check for available upgrade") }
flag.BoolVar(&showVersion, "version", false, "Show version")
flag.StringVar(&upgradeTo, "upgrade-to", upgradeTo, "Force upgrade directly from specified URL") return options
flag.BoolVar(&auditEnabled, "audit", false, "Write events to audit file") }
flag.BoolVar(&verbose, "verbose", false, "Print verbose log output")
flag.BoolVar(&paused, "paused", false, "Start with all devices paused") func parseCommandLineOptions() RuntimeOptions {
options := defaultRuntimeOptions()
flag.StringVar(&options.generateDir, "generate", "", "Generate key and config in specified dir, then exit")
flag.StringVar(&options.guiAddress, "gui-address", options.guiAddress, "Override GUI address (e.g. \"http://192.0.2.42:8443\")")
flag.StringVar(&options.guiAPIKey, "gui-apikey", options.guiAPIKey, "Override GUI API key")
flag.StringVar(&options.confDir, "home", "", "Set configuration directory")
flag.IntVar(&options.logFlags, "logflags", options.logFlags, "Select information in log line prefix (see below)")
flag.BoolVar(&options.noBrowser, "no-browser", false, "Do not start browser")
flag.BoolVar(&options.browserOnly, "browser-only", false, "Open GUI in browser")
flag.BoolVar(&options.noRestart, "no-restart", options.noRestart, "Do not restart; just exit")
flag.BoolVar(&options.reset, "reset", false, "Reset the database")
flag.BoolVar(&options.doUpgrade, "upgrade", false, "Perform upgrade")
flag.BoolVar(&options.doUpgradeCheck, "upgrade-check", false, "Check for available upgrade")
flag.BoolVar(&options.showVersion, "version", false, "Show version")
flag.StringVar(&options.upgradeTo, "upgrade-to", options.upgradeTo, "Force upgrade directly from specified URL")
flag.BoolVar(&options.auditEnabled, "audit", false, "Write events to audit file")
flag.BoolVar(&options.verbose, "verbose", false, "Print verbose log output")
flag.BoolVar(&options.paused, "paused", false, "Start with all devices paused")
flag.StringVar(&options.logFile, "logfile", options.logFile, "Log file name (use \"-\" for stdout)")
if runtime.GOOS == "windows" {
// Allow user to hide the console window
flag.BoolVar(&options.hideConsole, "no-console", false, "Hide console window")
}
longUsage := fmt.Sprintf(extraUsage, baseDirs["config"], debugFacilities()) longUsage := fmt.Sprintf(extraUsage, baseDirs["config"], debugFacilities())
flag.Usage = usageFor(flag.CommandLine, usage, longUsage) flag.Usage = usageFor(flag.CommandLine, usage, longUsage)
flag.Parse() flag.Parse()
return options
} }
func main() { func main() {
parseCommandLineOptions() options := parseCommandLineOptions()
l.SetFlags(options.logFlags)
if guiAddress != "" { if options.guiAddress != "" {
// The config picks this up from the environment. // The config picks this up from the environment.
os.Setenv("STGUIADDRESS", guiAddress) os.Setenv("STGUIADDRESS", options.guiAddress)
} }
if guiAPIKey != "" { if options.guiAPIKey != "" {
// The config picks this up from the environment. // The config picks this up from the environment.
os.Setenv("STGUIAPIKEY", guiAPIKey) os.Setenv("STGUIAPIKEY", options.guiAPIKey)
} }
if noConsole { if options.hideConsole {
osutil.HideConsole() osutil.HideConsole()
} }
if confDir != "" { if options.confDir != "" {
// Not set as default above because the string can be really long. // Not set as default above because the string can be really long.
baseDirs["config"] = confDir baseDirs["config"] = options.confDir
} }
if err := expandLocations(); err != nil { if err := expandLocations(); err != nil {
l.Fatalln(err) l.Fatalln(err)
} }
if guiAssets == "" { if options.showVersion {
guiAssets = locations[locGUIAssets]
}
if logFile == "" {
// Use the default log file location
logFile = locations[locLogFile]
}
if showVersion {
fmt.Println(LongVersion) fmt.Println(LongVersion)
return return
} }
if browserOnly { if options.browserOnly {
openGUI() openGUI()
return return
} }
l.SetFlags(logFlags) if options.generateDir != "" {
generate(options.generateDir)
if generateDir != "" {
generate(generateDir)
return return
} }
// Ensure that our home directory exists. // Ensure that our home directory exists.
ensureDir(baseDirs["config"], 0700) ensureDir(baseDirs["config"], 0700)
if upgradeTo != "" { if options.upgradeTo != "" {
err := upgrade.ToURL(upgradeTo) err := upgrade.ToURL(options.upgradeTo)
if err != nil { if err != nil {
l.Fatalln("Upgrade:", err) // exits 1 l.Fatalln("Upgrade:", err) // exits 1
} }
l.Okln("Upgraded from", upgradeTo) l.Okln("Upgraded from", options.upgradeTo)
return return
} }
if doUpgradeCheck { if options.doUpgradeCheck {
checkUpgrade() checkUpgrade()
return return
} }
if doUpgrade { if options.doUpgrade {
release := checkUpgrade() release := checkUpgrade()
performUpgrade(release) performUpgrade(release)
return return
} }
if reset { if options.reset {
resetDB() resetDB()
return return
} }
if noRestart { if options.noRestart {
syncthingMain() syncthingMain(options)
} else { } else {
monitorMain() monitorMain(options)
} }
} }
@ -353,17 +366,7 @@ func generate(generateDir string) {
if err != nil { if err != nil {
l.Fatalln("generate:", err) l.Fatalln("generate:", err)
} }
ensureDir(dir, 0700)
info, err := os.Stat(dir)
if err == nil && !info.IsDir() {
l.Fatalln(dir, "is not a directory")
}
if err != nil && os.IsNotExist(err) {
err = osutil.MkdirAll(dir, 0700)
if err != nil {
l.Fatalln("generate:", err)
}
}
certFile, keyFile := filepath.Join(dir, "cert.pem"), filepath.Join(dir, "key.pem") certFile, keyFile := filepath.Join(dir, "cert.pem"), filepath.Join(dir, "key.pem")
cert, err := tls.LoadX509KeyPair(certFile, keyFile) cert, err := tls.LoadX509KeyPair(certFile, keyFile)
@ -494,7 +497,7 @@ func upgradeViaRest() error {
return err return err
} }
func syncthingMain() { func syncthingMain(runtimeOptions RuntimeOptions) {
setupSignalHandling() setupSignalHandling()
// Create a main service manager. We'll add things to this as we go along. // Create a main service manager. We'll add things to this as we go along.
@ -510,11 +513,11 @@ func syncthingMain() {
// lines look ugly. // lines look ugly.
l.SetPrefix("[start] ") l.SetPrefix("[start] ")
if auditEnabled { if runtimeOptions.auditEnabled {
startAuditing(mainSvc) startAuditing(mainSvc)
} }
if verbose { if runtimeOptions.verbose {
mainSvc.Add(newVerboseSvc()) mainSvc.Add(newVerboseSvc())
} }
@ -594,11 +597,11 @@ func syncthingMain() {
l.Fatalln("Short device IDs are in conflict. Unlucky!\n Regenerate the device ID of one if the following:\n ", err) l.Fatalln("Short device IDs are in conflict. Unlucky!\n Regenerate the device ID of one if the following:\n ", err)
} }
if len(profiler) > 0 { if len(runtimeOptions.profiler) > 0 {
go func() { go func() {
l.Debugln("Starting profiler on", profiler) l.Debugln("Starting profiler on", runtimeOptions.profiler)
runtime.SetBlockProfileRate(1) runtime.SetBlockProfileRate(1)
err := http.ListenAndServe(profiler, nil) err := http.ListenAndServe(runtimeOptions.profiler, nil)
if err != nil { if err != nil {
l.Fatalln(err) l.Fatalln(err)
} }
@ -693,7 +696,7 @@ func syncthingMain() {
m.StartDeadlockDetector(20 * time.Minute) m.StartDeadlockDetector(20 * time.Minute)
} }
if paused { if runtimeOptions.paused {
for device := range cfg.Devices() { for device := range cfg.Devices() {
m.PauseDevice(device) m.PauseDevice(device)
} }
@ -798,14 +801,14 @@ func syncthingMain() {
// GUI // GUI
setupGUI(mainSvc, cfg, m, apiSub, cachedDiscovery, relaySvc, errors, systemLog) setupGUI(mainSvc, cfg, m, apiSub, cachedDiscovery, relaySvc, errors, systemLog, runtimeOptions)
// Start connection management // Start connection management
connectionSvc := connections.NewConnectionSvc(cfg, myID, m, tlsCfg, cachedDiscovery, relaySvc, bepProtocolName, tlsDefaultCommonName, lans) connectionSvc := connections.NewConnectionSvc(cfg, myID, m, tlsCfg, cachedDiscovery, relaySvc, bepProtocolName, tlsDefaultCommonName, lans)
mainSvc.Add(connectionSvc) mainSvc.Add(connectionSvc)
if cpuProfile { if runtimeOptions.cpuProfile {
f, err := os.Create(fmt.Sprintf("cpu-%d.pprof", os.Getpid())) f, err := os.Create(fmt.Sprintf("cpu-%d.pprof", os.Getpid()))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@ -867,7 +870,7 @@ func syncthingMain() {
l.Okln("Exiting") l.Okln("Exiting")
if cpuProfile { if runtimeOptions.cpuProfile {
pprof.StopCPUProfile() pprof.StopCPUProfile()
} }
@ -952,7 +955,7 @@ func startAuditing(mainSvc *suture.Supervisor) {
l.Infoln("Audit log in", auditFile) l.Infoln("Audit log in", auditFile)
} }
func setupGUI(mainSvc *suture.Supervisor, cfg *config.Wrapper, m *model.Model, apiSub *events.BufferedSubscription, discoverer *discover.CachingMux, relaySvc *relay.Svc, errors, systemLog *logger.Recorder) { func setupGUI(mainSvc *suture.Supervisor, cfg *config.Wrapper, m *model.Model, apiSub *events.BufferedSubscription, discoverer *discover.CachingMux, relaySvc *relay.Svc, errors, systemLog *logger.Recorder, runtimeOptions RuntimeOptions) {
guiCfg := cfg.GUI() guiCfg := cfg.GUI()
if !guiCfg.Enabled { if !guiCfg.Enabled {
@ -963,14 +966,14 @@ func setupGUI(mainSvc *suture.Supervisor, cfg *config.Wrapper, m *model.Model, a
l.Warnln("Insecure admin access is enabled.") l.Warnln("Insecure admin access is enabled.")
} }
api, err := newAPISvc(myID, cfg, guiAssets, m, apiSub, discoverer, relaySvc, errors, systemLog) api, err := newAPISvc(myID, cfg, runtimeOptions.assetDir, m, apiSub, discoverer, relaySvc, errors, systemLog)
if err != nil { if err != nil {
l.Fatalln("Cannot start GUI:", err) l.Fatalln("Cannot start GUI:", err)
} }
cfg.Subscribe(api) cfg.Subscribe(api)
mainSvc.Add(api) mainSvc.Add(api)
if cfg.Options().StartBrowser && !noBrowser && !stRestarting { if cfg.Options().StartBrowser && !runtimeOptions.noBrowser && !runtimeOptions.stRestarting {
// Can potentially block if the utility we are invoking doesn't // Can potentially block if the utility we are invoking doesn't
// fork, and just execs, hence keep it in it's own routine. // fork, and just execs, hence keep it in it's own routine.
go openURL(guiCfg.URL()) go openURL(guiCfg.URL())

View File

@ -34,13 +34,14 @@ const (
logFileMaxOpenTime = time.Minute logFileMaxOpenTime = time.Minute
) )
func monitorMain() { func monitorMain(runtimeOptions RuntimeOptions) {
os.Setenv("STNORESTART", "yes") os.Setenv("STNORESTART", "yes")
os.Setenv("STMONITORED", "yes") os.Setenv("STMONITORED", "yes")
l.SetPrefix("[monitor] ") l.SetPrefix("[monitor] ")
var dst io.Writer = os.Stdout var dst io.Writer = os.Stdout
logFile := runtimeOptions.logFile
if logFile != "-" { if logFile != "-" {
var fileDst io.Writer = newAutoclosedFile(logFile, logFileAutoCloseDelay, logFileMaxOpenTime) var fileDst io.Writer = newAutoclosedFile(logFile, logFileAutoCloseDelay, logFileMaxOpenTime)