go/cmd/zeus/zeus.go
package main
import (
"fmt"
"io"
"os"
"path"
"strings"
"syscall"
"time"
"github.com/burke/zeus/go/config"
"github.com/burke/zeus/go/filemonitor"
slog "github.com/burke/zeus/go/shinylog"
"github.com/burke/zeus/go/zeusclient"
"github.com/burke/zeus/go/zeusmaster"
"github.com/burke/zeus/go/zeusversion"
)
var color = true
func main() {
args := os.Args[1:]
configFile := "zeus.json"
simpleStatus := false
fileChangeDelay := filemonitor.DefaultFileChangeDelay
for ; args != nil && len(args) > 0 && args[0][0] == '-'; args = args[1:] {
switch args[0] {
case "--no-color":
color = false
slog.DisableColor()
case "--simple-status":
slog.DisableColor()
simpleStatus = true
case "--log":
tracefile, err := os.OpenFile(args[1], os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err == nil {
slog.SetTraceLogger(slog.NewTraceLogger(tracefile))
args = args[1:]
} else {
fmt.Printf("Could not open trace file %s\n", args[1])
return
}
case "--file-change-delay":
if len(args) > 1 {
delay, err := time.ParseDuration(args[1])
if err != nil {
execManPage("zeus")
}
args = args[1:]
fileChangeDelay = delay
} else {
execManPage("zeus")
}
case "--config":
_, err := os.Stat(args[1])
if err != nil {
fmt.Printf("Config file doesn't exist: %s (%e)\n", args[1], err)
return
}
configFile = args[1]
args = args[1:]
case "--version":
printVersion()
return
}
}
if len(args) == 0 {
execManPage("zeus")
return
}
if generalHelpRequested(args) {
execManPage("zeus")
} else if args[0] == "help" {
commandSpecificHelp(args)
} else if args[0] == "version" {
printVersion()
} else if args[0] == "start" {
os.Exit(zeusmaster.Run(configFile, fileChangeDelay, simpleStatus))
} else if args[0] == "init" {
zeusInit()
} else if args[0] == "commands" {
zeusCommands(configFile)
} else {
tree := config.BuildProcessTree(configFile, nil)
for _, name := range tree.AllCommandsAndAliases() {
if args[0] == name {
// Don't confuse the master by sending *full* args to
// it; just those that are not zeus-specific.
os.Exit(zeusclient.Run(args, os.Stdin, os.Stdout, os.Stderr))
}
}
commandNotFound(args[0])
}
}
func execManPage(page string) {
binaryPath := os.Args[0]
gemDir := path.Dir(path.Dir(binaryPath))
manDir := path.Join(gemDir, "man/build")
zeus := path.Join(manDir, page)
syscall.Exec("/usr/bin/env", []string{"/usr/bin/env", "man", zeus}, os.Environ())
}
func red() string {
if color {
return "\x1b[31m"
}
return ""
}
func reset() string {
if color {
return "\x1b[0m"
}
return ""
}
func copyFile(from, to string) (err error) {
var src, dst *os.File
wd, _ := os.Getwd()
target := path.Join(wd, to)
if src, err = os.Open(from); err != nil {
slog.Colorized(" {red}fail{reset} " + to)
return err
}
defer src.Close()
if dst, err = os.OpenFile(target, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666); err != nil {
slog.Colorized(" {red}exists{reset} " + to)
return err
}
defer dst.Close()
if _, err = io.Copy(dst, src); err != nil {
slog.Colorized(" {red}fail{reset} " + to)
return err
}
slog.Colorized(" {brightgreen}create{reset} " + to)
return nil
}
func zeusInit() {
binaryPath := os.Args[0]
gemDir := path.Dir(path.Dir(binaryPath))
jsonPath := path.Join(gemDir, "examples/custom_plan/zeus.json")
planPath := path.Join(gemDir, "examples/custom_plan/custom_plan.rb")
copyFile(jsonPath, "zeus.json")
copyFile(planPath, "custom_plan.rb")
}
func zeusCommands(configFile string) {
tree := config.BuildProcessTree(configFile, nil)
for _, command := range tree.Commands {
alia := strings.Join(command.Aliases, ", ")
var aliasPart string
if len(alia) > 0 {
aliasPart = " (alias: " + alia + ")"
}
println("zeus " + command.Name + aliasPart)
}
}
func commandNotFound(command string) {
println(red() + "Could not find command \"" + command + "\"." + reset())
}
func commandSpecificHelp(args []string) {
if args[1] == "start" {
execManPage("zeus-start")
} else if args[1] == "init" {
execManPage("zeus-init")
} else {
println(red() + "Command-level help is not yet fully implemented." + reset())
}
}
func generalHelpRequested(args []string) bool {
helps := []string{"help", "--help", "-h", "--help", "-?", "?"}
if len(args) == 1 {
for _, str := range helps {
if args[0] == str {
return true
}
}
}
return false
}
func printVersion() {
println("Zeus version " + zeusversion.VERSION)
}