From 74a6dd0233bd0c983e191b9708e0ed257e78b0ff Mon Sep 17 00:00:00 2001 From: Přemysl Eric Janouch
Date: Tue, 26 Dec 2023 05:58:19 +0100 Subject: WIP: Command arguments --- main.go | 81 ++++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 28 deletions(-) (limited to 'main.go') diff --git a/main.go b/main.go index 0d89b06..67c0850 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,7 @@ import ( "encoding/hex" "encoding/json" "errors" + "flag" "fmt" "html/template" "image" @@ -260,9 +261,9 @@ func parallelize(strings []string, callback parallelFunc) error { // cmdInit initializes a "gallery directory" that contains gallery.sqlite, // images, thumbs. -func cmdInit(args []string) error { +func cmdInit(fs *flag.FlagSet, args []string) error { if len(args) != 1 { - return errors.New("usage: GD") + return errWrongUsage } if err := openDB(args[0]); err != nil { @@ -1074,9 +1075,9 @@ func handleAPISearch(w http.ResponseWriter, r *http.Request) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // cmdWeb runs a web UI against GD on ADDRESS. -func cmdWeb(args []string) error { +func cmdWeb(fs *flag.FlagSet, args []string) error { if len(args) != 2 { - return errors.New("usage: GD ADDRESS") + return errWrongUsage } if err := openDB(args[0]); err != nil { return err @@ -1681,11 +1682,17 @@ func syncRun(ctx context.Context, tx *sql.Tx, roots []string) error { // cmdSync ensures the given (sub)roots are accurately reflected // in the database. -func cmdSync(args []string) error { - if len(args) < 2 { - return errors.New("usage: GD ROOT...") +func cmdSync(fs *flag.FlagSet, args []string) error { + // TODO: Convert the other commands as well. + fullpaths := fs.Bool("fullpaths", false, "don't basename the arguments") + if err := fs.Parse(args); err != nil { + return err } - if err := openDB(args[0]); err != nil { + if fs.NArg() < 2 { + return errWrongUsage + } + + if err := openDB(fs.Arg(0)); err != nil { return err } @@ -1709,9 +1716,12 @@ func cmdSync(args []string) error { return err } + // TODO: Handle sensibly. + _ = fullpaths + // Normalize arguments. // At least for now, turn all roots into absolute paths. - roots := args[1:] + roots := fs.Args()[1:] for i := range roots { roots[i], err = filepath.Abs(filepath.Clean(roots[i])) if err != nil { @@ -1739,9 +1749,9 @@ func cmdSync(args []string) error { // cmdRemove is for manual removal of subtrees from the database. // Beware that inputs are database, not filesystem paths. -func cmdRemove(args []string) error { +func cmdRemove(fs *flag.FlagSet, args []string) error { if len(args) < 2 { - return errors.New("usage: GD PATH...") + return errWrongUsage } if err := openDB(args[0]); err != nil { return err @@ -1784,7 +1794,7 @@ func cmdRemove(args []string) error { // cmdTag mass imports tags from data passed on stdin as a TSV // of SHA1 TAG WEIGHT entries. -func cmdTag(args []string) error { +func cmdTag(fs *flag.FlagSet, args []string) error { if len(args) < 2 || len(args) > 3 { return errors.New("usage: GD SPACE [DESCRIPTION]") } @@ -1935,7 +1945,7 @@ func checkFiles(root, suffix string, hashes []string) (bool, []string, error) { } // cmdCheck carries out various database consistency checks. -func cmdCheck(args []string) error { +func cmdCheck(fs *flag.FlagSet, args []string) error { if len(args) != 1 { return errors.New("usage: GD") } @@ -2052,9 +2062,9 @@ func makeThumbnailFor(sha1 string) (message string, err error) { } // cmdThumbnail generates missing thumbnails, in parallel. -func cmdThumbnail(args []string) error { +func cmdThumbnail(fs *flag.FlagSet, args []string) error { if len(args) < 1 { - return errors.New("usage: GD [SHA1...]") + return errWrongUsage } if err := openDB(args[0]); err != nil { return err @@ -2207,9 +2217,9 @@ func makeDhashFor(sha1 string) (message string, err error) { } // cmdDhash generates perceptual hash from thumbnails. -func cmdDhash(args []string) error { +func cmdDhash(fs *flag.FlagSet, args []string) error { if len(args) < 1 { - return errors.New("usage: GD [SHA1...]") + return errWrongUsage } if err := openDB(args[0]); err != nil { return err @@ -2229,20 +2239,25 @@ func cmdDhash(args []string) error { // --- Main -------------------------------------------------------------------- +var errWrongUsage = errors.New("wrong usage") + var commands = map[string]struct { - handler func(args []string) error + handler func(*flag.FlagSet, []string) error + usage string }{ - "init": {cmdInit}, - "web": {cmdWeb}, - "tag": {cmdTag}, - "sync": {cmdSync}, - "remove": {cmdRemove}, - "check": {cmdCheck}, - "thumbnail": {cmdThumbnail}, - "dhash": {cmdDhash}, + "init": {cmdInit, "GD"}, + "web": {cmdWeb, "GD ADDRESS"}, + "tag": {cmdTag, "GD SPACE [DESCRIPTION]"}, + "sync": {cmdSync, "GD ROOT..."}, + "remove": {cmdRemove, "GD PATH..."}, + "check": {cmdCheck, "GD"}, + "thumbnail": {cmdThumbnail, "GD [SHA1...]"}, + "dhash": {cmdDhash, "GD [SHA1...]"}, } func main() { + // TODO: Implement a global -h command. + // The flag package doesn't reorder, unlike GNU, so it's fine. if len(os.Args) <= 2 { log.Fatalln("Missing arguments") } @@ -2252,8 +2267,15 @@ func main() { log.Fatalln("Unknown command: " + os.Args[1]) } + fs := flag.NewFlagSet(os.Args[1], flag.ExitOnError) + fs.Usage = func() { + fmt.Fprintf(fs.Output(), + "Usage: %s [OPTION...] %s...\n", fs.Name(), cmd.usage) + fs.PrintDefaults() + } + taskSemaphore = newSemaphore(runtime.NumCPU()) - err := cmd.handler(os.Args[2:]) + err := cmd.handler(fs, os.Args[2:]) // Note that the database object has a closing finalizer, // we just additionally print any errors coming from there. @@ -2263,7 +2285,10 @@ func main() { } } - if err != nil { + if errors.Is(err, errWrongUsage) { + fs.Usage() + os.Exit(2) + } else if err != nil { log.Fatalln(err) } } -- cgit v1.2.3-70-g09d2