github.com/nycdavid/zeus@v0.0.0-20201208104106-9ba439429e03/go/cmd/zeus/zeus.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "path" 8 "strings" 9 "syscall" 10 11 "time" 12 13 "github.com/burke/zeus/go/config" 14 "github.com/burke/zeus/go/filemonitor" 15 slog "github.com/burke/zeus/go/shinylog" 16 "github.com/burke/zeus/go/zeusclient" 17 "github.com/burke/zeus/go/zeusmaster" 18 "github.com/burke/zeus/go/zeusversion" 19 ) 20 21 var color bool = true 22 23 func main() { 24 args := os.Args[1:] 25 configFile := "zeus.json" 26 simpleStatus := false 27 fileChangeDelay := filemonitor.DefaultFileChangeDelay 28 29 for ; args != nil && len(args) > 0 && args[0][0] == '-'; args = args[1:] { 30 switch args[0] { 31 case "--no-color": 32 color = false 33 slog.DisableColor() 34 case "--simple-status": 35 slog.DisableColor() 36 simpleStatus = true 37 case "--log": 38 tracefile, err := os.OpenFile(args[1], os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666) 39 if err == nil { 40 slog.SetTraceLogger(slog.NewTraceLogger(tracefile)) 41 args = args[1:] 42 } else { 43 fmt.Printf("Could not open trace file %s\n", args[1]) 44 return 45 } 46 case "--file-change-delay": 47 if len(args) > 1 { 48 delay, err := time.ParseDuration(args[1]) 49 if err != nil { 50 execManPage("zeus") 51 } 52 args = args[1:] 53 fileChangeDelay = delay 54 } else { 55 execManPage("zeus") 56 } 57 case "--config": 58 _, err := os.Stat(args[1]) 59 if err != nil { 60 fmt.Printf("Config file doesn't exist: %s (%e)\n", args[1], err) 61 return 62 } 63 configFile = args[1] 64 args = args[1:] 65 case "--version": 66 printVersion() 67 return 68 } 69 } 70 if len(args) == 0 { 71 execManPage("zeus") 72 return 73 } 74 75 if generalHelpRequested(args) { 76 execManPage("zeus") 77 } else if args[0] == "help" { 78 commandSpecificHelp(args) 79 } else if args[0] == "version" { 80 printVersion() 81 } else if args[0] == "start" { 82 os.Exit(zeusmaster.Run(configFile, fileChangeDelay, simpleStatus)) 83 } else if args[0] == "init" { 84 zeusInit() 85 } else if args[0] == "commands" { 86 zeusCommands(configFile) 87 } else { 88 tree := config.BuildProcessTree(configFile, nil) 89 for _, name := range tree.AllCommandsAndAliases() { 90 if args[0] == name { 91 // Don't confuse the master by sending *full* args to 92 // it; just those that are not zeus-specific. 93 os.Exit(zeusclient.Run(args, os.Stdin, os.Stdout, os.Stderr)) 94 } 95 } 96 97 commandNotFound(args[0]) 98 } 99 } 100 101 func execManPage(page string) { 102 binaryPath := os.Args[0] 103 gemDir := path.Dir(path.Dir(binaryPath)) 104 manDir := path.Join(gemDir, "man/build") 105 zeus := path.Join(manDir, page) 106 syscall.Exec("/usr/bin/env", []string{"/usr/bin/env", "man", zeus}, os.Environ()) 107 } 108 109 func red() string { 110 if color { 111 return "\x1b[31m" 112 } 113 return "" 114 } 115 116 func reset() string { 117 if color { 118 return "\x1b[0m" 119 } 120 return "" 121 } 122 123 func copyFile(from, to string) (err error) { 124 var src, dst *os.File 125 wd, _ := os.Getwd() 126 target := path.Join(wd, to) 127 128 if src, err = os.Open(from); err != nil { 129 slog.Colorized(" {red}fail{reset} " + to) 130 return err 131 } 132 defer src.Close() 133 134 if dst, err = os.OpenFile(target, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666); err != nil { 135 slog.Colorized(" {red}exists{reset} " + to) 136 return err 137 } 138 defer dst.Close() 139 140 if _, err = io.Copy(dst, src); err != nil { 141 slog.Colorized(" {red}fail{reset} " + to) 142 return err 143 } 144 145 slog.Colorized(" {brightgreen}create{reset} " + to) 146 return nil 147 } 148 149 func zeusInit() { 150 binaryPath := os.Args[0] 151 gemDir := path.Dir(path.Dir(binaryPath)) 152 jsonPath := path.Join(gemDir, "examples/custom_plan/zeus.json") 153 planPath := path.Join(gemDir, "examples/custom_plan/custom_plan.rb") 154 copyFile(jsonPath, "zeus.json") 155 copyFile(planPath, "custom_plan.rb") 156 } 157 158 func zeusCommands(configFile string) { 159 tree := config.BuildProcessTree(configFile, nil) 160 for _, command := range tree.Commands { 161 alia := strings.Join(command.Aliases, ", ") 162 var aliasPart string 163 if len(alia) > 0 { 164 aliasPart = " (alias: " + alia + ")" 165 } 166 println("zeus " + command.Name + aliasPart) 167 } 168 } 169 170 func commandNotFound(command string) { 171 println(red() + "Could not find command \"" + command + "\"." + reset()) 172 } 173 174 func commandSpecificHelp(args []string) { 175 if args[1] == "start" { 176 execManPage("zeus-start") 177 } else if args[1] == "init" { 178 execManPage("zeus-init") 179 } else { 180 println(red() + "Command-level help is not yet fully implemented." + reset()) 181 } 182 } 183 184 func generalHelpRequested(args []string) bool { 185 helps := []string{"help", "--help", "-h", "--help", "-?", "?"} 186 if len(args) == 1 { 187 for _, str := range helps { 188 if args[0] == str { 189 return true 190 } 191 } 192 } 193 return false 194 } 195 196 func printVersion() { 197 println("Zeus version " + zeusversion.VERSION) 198 }