-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
129 lines (111 loc) · 3.96 KB
/
main.go
File metadata and controls
129 lines (111 loc) · 3.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package main
import (
"flag"
"fmt"
"log"
"os"
"os/signal"
"syscall"
"retrosync/internal/config"
"retrosync/internal/node"
)
// version is set at build time via -ldflags "-X main.version=<value>".
// Use: go build -ldflags "-X main.version=$(git rev-list --count HEAD)"
var version = "dev"
func main() {
serviceCmd := flag.String("service", "", "Windows service control: install, uninstall, start, stop")
logFile := flag.String("logfile", "", "Path to log file (default: <binary-dir>/retrosync.log when running as a service)")
configFile := flag.String("config", "", "Path to retrosync.toml")
createConfig := flag.String("createconfig", "", "Write a default config template to the given path and exit")
syncDir := flag.String("dir", "sync", "Sync directory (legacy, used when -config is absent)")
port := flag.Int("port", 9877, "HTTP server port for file transfer")
discoveryPort := flag.Int("discovery", 9876, "UDP port for peer discovery")
paused := flag.Bool("paused", false, "start with all sync groups paused")
flag.Parse()
// Handle -createconfig before anything else — write template and exit.
if *createConfig != "" {
if err := config.WriteDefaultConfig(*createConfig); err != nil {
fmt.Fprintf(os.Stderr, "[retrosync] createconfig: %v\n", err)
os.Exit(1)
}
fmt.Printf("[retrosync] default config written to %s\n", *createConfig)
return
}
log.SetFlags(log.Ldate | log.Ltime | log.Lmsgprefix)
log.SetPrefix("[retrosync] ")
log.Printf("version %s", version)
// Handle -service install/uninstall/start/stop before anything else.
if *serviceCmd != "" {
exe, err := os.Executable()
if err != nil {
log.Fatalf("cannot determine executable path: %v", err)
}
// Reconstruct flags to persist as the service's stored arguments.
var svcArgs []string
if *configFile != "" { svcArgs = append(svcArgs, "-config", *configFile) }
if *port != 9877 { svcArgs = append(svcArgs, "-port", fmt.Sprintf("%d", *port)) }
if *discoveryPort != 9876 { svcArgs = append(svcArgs, "-discovery", fmt.Sprintf("%d", *discoveryPort)) }
if *paused { svcArgs = append(svcArgs, "-paused") }
if *logFile != "" { svcArgs = append(svcArgs, "-logfile", *logFile) }
if err := handleServiceCommand(*serviceCmd, exe, svcArgs); err != nil {
log.Fatalf("service %s: %v", *serviceCmd, err)
}
return
}
acquireSingleInstance()
// Redirect log output to a file when running as a service or when -logfile is set.
runningAsService := isWindowsService()
if runningAsService || *logFile != "" {
f, err := setupLogFile(*logFile, !runningAsService)
if err != nil {
log.Fatalf("log file setup: %v", err)
}
if f != nil {
defer f.Close()
}
}
var cfg *config.Config
if *configFile != "" {
if _, err := os.Stat(*configFile); os.IsNotExist(err) {
log.Fatalf("config file not found: %s — use -createconfig %s to generate a default template", *configFile, *configFile)
}
var err error
cfg, err = config.Load(*configFile)
if err != nil {
log.Fatalf("config error: %v", err)
}
} else {
cfg = config.DefaultConfig(*syncDir, *port, *discoveryPort)
}
// CLI flags override config file network settings when no config file is used.
if *configFile == "" {
cfg.Node.Port = *port
cfg.Node.DiscoveryPort = *discoveryPort
}
if *paused {
for i := range cfg.Syncs {
cfg.Syncs[i].Paused = true
}
}
n, err := node.New(cfg, *configFile, version)
if err != nil {
log.Fatalf("init error: %v", err)
}
// When launched by the SCM, hand control to the service runner.
if runningAsService {
if err := runAsService(n.Start, n.Stop); err != nil {
log.Fatalf("service execution error: %v", err)
}
return
}
// Interactive path.
if err := n.Start(); err != nil {
log.Fatalf("start error: %v", err)
}
log.Printf("press Ctrl+C to stop")
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("shutting down...")
n.Stop()
}