936ca8d48f
The new code runs the equivalent functionality within the daemon go code. It was required to make Env be immutable in order to prevent race conditions (this really should have been done from the beginning anyway).
122 lines
2.4 KiB
Go
122 lines
2.4 KiB
Go
package entrypoint
|
|
|
|
import (
|
|
crypticnet "cryptic-net"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/spf13/pflag"
|
|
)
|
|
|
|
// subCmdCtx contains all information available to a subCmd's do method.
|
|
type subCmdCtx struct {
|
|
subCmd subCmd // the subCmd itself
|
|
args []string // command-line arguments, excluding the subCmd itself.
|
|
subCmdNames []string // names of subCmds so far, including this one
|
|
env crypticnet.Env
|
|
}
|
|
|
|
type subCmd struct {
|
|
name string
|
|
descr string
|
|
checkLock bool
|
|
do func(subCmdCtx) error
|
|
}
|
|
|
|
func (ctx subCmdCtx) usagePrefix() string {
|
|
|
|
subCmdNamesStr := strings.Join(ctx.subCmdNames, " ")
|
|
if subCmdNamesStr != "" {
|
|
subCmdNamesStr += " "
|
|
}
|
|
|
|
return fmt.Sprintf("\nUSAGE: %s %s", os.Args[0], subCmdNamesStr)
|
|
}
|
|
|
|
func (ctx subCmdCtx) flagSet(withPassthrough bool) *pflag.FlagSet {
|
|
flags := pflag.NewFlagSet(ctx.subCmd.name, pflag.ExitOnError)
|
|
flags.Usage = func() {
|
|
|
|
var passthroughStr string
|
|
if withPassthrough {
|
|
passthroughStr = " [--] [args...]"
|
|
}
|
|
|
|
fmt.Fprintf(
|
|
os.Stderr, "%s[-h|--help] [%s flags...]%s\n\n",
|
|
ctx.usagePrefix(), ctx.subCmd.name, passthroughStr,
|
|
)
|
|
fmt.Fprintf(os.Stderr, "%s FLAGS:\n\n", strings.ToUpper(ctx.subCmd.name))
|
|
fmt.Fprintln(os.Stderr, flags.FlagUsages())
|
|
|
|
os.Stderr.Sync()
|
|
os.Exit(2)
|
|
}
|
|
return flags
|
|
}
|
|
|
|
func (ctx subCmdCtx) doSubCmd(subCmds ...subCmd) error {
|
|
|
|
printUsageExit := func(subCmdName string) {
|
|
|
|
fmt.Fprintf(os.Stderr, "unknown sub-command %q\n", subCmdName)
|
|
|
|
fmt.Fprintf(
|
|
os.Stderr,
|
|
"%s<subCmd> [-h|--help] [sub-command flags...]\n",
|
|
ctx.usagePrefix(),
|
|
)
|
|
|
|
fmt.Fprintf(os.Stderr, "\nSUB-COMMANDS:\n\n")
|
|
|
|
for _, subCmd := range subCmds {
|
|
fmt.Fprintf(os.Stderr, " %s\t%s\n", subCmd.name, subCmd.descr)
|
|
}
|
|
|
|
fmt.Fprintf(os.Stderr, "\n")
|
|
os.Stderr.Sync()
|
|
os.Exit(2)
|
|
}
|
|
|
|
args := ctx.args
|
|
|
|
if len(args) == 0 {
|
|
printUsageExit("")
|
|
}
|
|
|
|
subCmdsMap := map[string]subCmd{}
|
|
for _, subCmd := range subCmds {
|
|
subCmdsMap[subCmd.name] = subCmd
|
|
}
|
|
|
|
subCmdName, args := args[0], args[1:]
|
|
subCmd, ok := subCmdsMap[subCmdName]
|
|
|
|
if !ok {
|
|
printUsageExit(subCmdName)
|
|
}
|
|
|
|
if subCmd.checkLock {
|
|
|
|
err := crypticnet.NewProcLock(ctx.env.RuntimeDirPath).AssertLock()
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("checking lock file: %w", err)
|
|
}
|
|
}
|
|
|
|
err := subCmd.do(subCmdCtx{
|
|
subCmd: subCmd,
|
|
args: args,
|
|
subCmdNames: append(ctx.subCmdNames, subCmdName),
|
|
env: ctx.env,
|
|
})
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|