diff options
| author | Quentin Carbonneaux | 2021-11-18 14:18:38 +0100 |
|---|---|---|
| committer | Quentin Carbonneaux | 2021-11-18 14:18:38 +0100 |
| commit | 6f0be3654cab0d3e7b498a3adf36b06b68d22dc3 (patch) | |
| tree | 95ea0f527ce0bc7d947f1d5741074eeb494bc990 | |
| parent | 0fdba5997702034203407b228e82fc5dd3169427 (diff) | |
[mx] better doc, reset, sync
| -rw-r--r-- | memex/main.go | 248 | ||||
| -rw-r--r-- | memex/sdar.go | 8 |
2 files changed, 182 insertions, 74 deletions
diff --git a/memex/main.go b/memex/main.go index 01da47d..4a9c385 100644 --- a/memex/main.go +++ b/memex/main.go @@ -547,25 +547,8 @@ func diffCmd(args diffArgs) int { ad.add.from = ad.del.path } } - next := 0 - move := "\x00" - for _, chg := range chgs { - if chg.kind == Cskip { - continue - } - if chg.kind == Cmove { - if strings.HasPrefix(chg.path, move) { - continue - } - move = chg.path - } - chgs[next] = chg - next += 1 - } - chgs = chgs[:next] suff := map[EntryKind]string{Edir: "/", Elnk: "@", Ereg: ""} - for _, chg := range chgs { e1, e2 := chg.e1, chg.e2 if chg.kind == Cmod && @@ -1023,15 +1006,19 @@ func resetCmd(args resetArgs) { addr := parseRevspec(args.rev, rd) - if args.ref == "" && !args.sync { - fmt.Println(addr) + if args.sync { + sync := addr.String() + if RevAbsolute(args.rev) { + sync = args.rev + } + if SetSync(sync, &config) != nil { + fail("could not update config to sync=%s", sync) + } return } - if args.sync { - if SetSync(addr.String(), &config) != nil { - fail("could not update config to sync=%s", addr) - } + if args.ref == "" { + fmt.Println(addr) return } @@ -1046,8 +1033,132 @@ func resetCmd(args resetArgs) { } } +type UsageAlt struct{ args, desc string } + +var docs = map[string][]UsageAlt{ + "commit": {{ + "[-f] [-m MESSAGE] [PATH ...]", + `Commits the filesystem objects listed; if the list + is empty, all files from the current working + directory are committed + + -f allow an empty commit message`, + }}, + "log": {{ + "[-r REV] [PATH ...]", + `Lists commits starting from the revision specified + using '-r'; if paths are specified, only commits + where those paths changed are listed + + -r starting revision, default is .`, + }}, + "walk": {{ + "[-Rv] [-r REV] [PATH ...]", + `Dumps the archive contents at the given revision + and paths; if the path list is empty, it is taken + to be / + + -r revision to walk, default is . + -R recursively walk directories + -v verbose output`, + }}, + "diff": {{ + "[-Rs] [-a REVA] [-b REVB]", + `Diffs revision '-a' against revision '-b'; + if '-b' is missing, the file system is + compared; if '-a' is missing REVB^ is used; + if both are missing '-a' is taken to be . + + -R recursive diff + -s silent mode, exit with code 1 + if revisions differ, 0 if they + do not, and 2 if errors`, + }}, + "get": {{ + "[-t] [-r REV] [PATH ...]", + `Extracts the specified paths from a revision; + if a single path to a regular file is given + the file is extracted and output on the standard + output as is; in other cases, or if '-t' is set, + a tar archive is output on the standard output + + -r revision, default is . + -t output a tar archive`, + }}, + "sync": {{ + "[-f] REV [PATH ...]", + `Updates the paths to match a given revision; + if the path list is empty it defaults to / + + -f force modifications to paths that + differ from the sync revision`, + }, { + "", + `Displays the current sync revision`, + }}, + "reset": {{ + "REV", + `Displays the address of REV`, + }, { + "-s REV", + `Resets the sync revision to REV`, + }, { + "[-c] REF REV", + `Resets the ref REF to the address of REV; + if '-c' is set and the ref does not exist, + it is created`, + }}, + "check": {{ + "", + `Verifies the integrity of the archive, + starting from all the refs available; + returns non-zero in case of problem`, + }}, +} + +func usage(arg0, subcmd string) { + o := flag.CommandLine.Output() + multi := len(docs[subcmd]) > 1 + for i, u := range docs[subcmd] { + if multi { + if i == 0 { + fmt.Fprintf(o, "usage %d: ", i+1) + } else { + fmt.Fprintf(o, " or %d: ", i+1) + } + } else { + fmt.Fprintf(o, "usage: ") + } + fmt.Fprintf(o, "%s %s %s\n", arg0, subcmd, u.args) + } + for i, u := range docs[subcmd] { + var desc string + if multi { + fmt.Fprintf(o, "\n%d: ", i+1) + } else { + fmt.Fprintf(o, "\n ") + } + desc = strings.ReplaceAll(u.desc, "\t\t", " ") + fmt.Fprintf(o, "%s\n", desc) + } + fmt.Fprintf(o, "\n") +} + +func parseArgs(subcmd string, fs *flag.FlagSet) { + fs.Usage = func() { } + if err := fs.Parse(os.Args[2:]); err != nil { + if err != flag.ErrHelp { + os.Exit(2) + } + usage(os.Args[0], subcmd) + os.Exit(1) + } +} + func main() { - FindSdarBin() + if !FindSdarBin() { + fail("could not find sdar") + } if len(os.Args) < 2 { fail("subcommand expected") @@ -1062,7 +1173,7 @@ func main() { cur, err := ParseConfig(dir, &config) if err != nil { if err == notFoundError { - fail("%s is not a memex checkout", dir) + fail("not in a memex checkout") } else { fail("could parse config: %v", err) } @@ -1072,10 +1183,10 @@ func main() { case "commit": var args commitArgs - cmd := flag.NewFlagSet("commit", flag.ExitOnError) - cmd.StringVar(&args.msg, "m", "", "commit message") - cmd.BoolVar(&args.force, "f", false, "allow empty message") - cmd.Parse(os.Args[2:]) + cmd := flag.NewFlagSet("commit", flag.ContinueOnError) + cmd.StringVar(&args.msg, "m", "", "") + cmd.BoolVar(&args.force, "f", false, "") + parseArgs("commit", cmd) args.cur = cur args.now = time.Now() @@ -1083,14 +1194,10 @@ func main() { commitCmd(args) case "log": - /* - no paths : log from the -r revision - with paths : log only revisions where paths changed - */ var args logArgs - cmd := flag.NewFlagSet("log", flag.ExitOnError) - cmd.StringVar(&args.rev, "r", ".", "revision") - cmd.Parse(os.Args[2:]) + cmd := flag.NewFlagSet("log", flag.ContinueOnError) + cmd.StringVar(&args.rev, "r", ".", "") + parseArgs("log", cmd) args.cur = cur args.paths = cmd.Args() @@ -1098,32 +1205,24 @@ func main() { case "walk": var args walkArgs - cmd := flag.NewFlagSet("walk", flag.ExitOnError) - cmd.StringVar(&args.rev, "r", ".", "revision") - cmd.BoolVar(&args.deep, "R", false, "recursive walk") - cmd.BoolVar(&args.verb, "v", false, "verbose output") - cmd.Parse(os.Args[2:]) + cmd := flag.NewFlagSet("walk", flag.ContinueOnError) + cmd.StringVar(&args.rev, "r", ".", "") + cmd.BoolVar(&args.deep, "R", false, "") + cmd.BoolVar(&args.verb, "v", false, "") + parseArgs("walk", cmd) args.cur = cur args.paths = cmd.Args() walkCmd(args) case "diff": - /* - -a -b - ------------------------------------ - _ _ : sync to fs tree - A _ : rev A to tree - _ B : rev B^ to B - A B : rev A to B - */ var args diffArgs - cmd := flag.NewFlagSet("diff", flag.ExitOnError) - cmd.StringVar(&args.arev, "a", "", "base revision") - cmd.StringVar(&args.brev, "b", "", "other revision") - cmd.BoolVar(&args.deep, "R", false, "recursive") - cmd.BoolVar(&args.shush, "s", false, "silent") - cmd.Parse(os.Args[2:]) + cmd := flag.NewFlagSet("diff", flag.ContinueOnError) + cmd.StringVar(&args.arev, "a", "", "") + cmd.StringVar(&args.brev, "b", "", "") + cmd.BoolVar(&args.deep, "R", false, "") + cmd.BoolVar(&args.shush, "s", false, "") + parseArgs("diff", cmd) args.cur = cur args.paths = cmd.Args() @@ -1131,10 +1230,10 @@ func main() { case "get": var args getArgs - cmd := flag.NewFlagSet("get", flag.ExitOnError) - cmd.StringVar(&args.rev, "r", ".", "revision") - cmd.BoolVar(&args.tar, "t", false, "force tar output") - cmd.Parse(os.Args[2:]) + cmd := flag.NewFlagSet("get", flag.ContinueOnError) + cmd.StringVar(&args.rev, "r", ".", "") + cmd.BoolVar(&args.tar, "t", false, "") + parseArgs("get", cmd) args.cur = cur args.paths = cmd.Args() @@ -1142,21 +1241,23 @@ func main() { case "sync": var args syncArgs - cmd := flag.NewFlagSet("sync", flag.ExitOnError) - cmd.StringVar(&args.rev, "r", "", "revision") - cmd.BoolVar(&args.force, "f", false, "force sync") - cmd.Parse(os.Args[2:]) + cmd := flag.NewFlagSet("sync", flag.ContinueOnError) + cmd.BoolVar(&args.force, "f", false, "") + parseArgs("sync", cmd) + if rest := cmd.Args(); len(rest) > 0 { + args.rev = rest[0] + args.paths = rest[1:] + } args.cur = cur - args.paths = cmd.Args() syncCmd(args) case "reset": var args resetArgs - cmd := flag.NewFlagSet("reset", flag.ExitOnError) - cmd.BoolVar(&args.sync, "s", false, "resets the sync rev") - cmd.BoolVar(&args.creat, "c", false, "create a new ref") - cmd.Parse(os.Args[2:]) + cmd := flag.NewFlagSet("reset", flag.ContinueOnError) + cmd.BoolVar(&args.sync, "s", false, "") + cmd.BoolVar(&args.creat, "c", false, "") + parseArgs("reset", cmd) rest := cmd.Args() if args.sync { @@ -1178,10 +1279,17 @@ func main() { resetCmd(args) case "check": - os.Exit(checkCmd(os.Args[2:])) + cmd := flag.NewFlagSet("check", flag.ContinueOnError) + parseArgs("check", cmd) + os.Exit(checkCmd(cmd.Args())) default: - fail("unkown command '%s'", os.Args[1]) + errf("unknown subcommand '%s'", os.Args[1]) + fmt.Fprintf(os.Stderr, "subcommands:") + for c := range docs { + fmt.Fprintf(os.Stderr, " %s", c) + } + fail("") } os.Exit(0) diff --git a/memex/sdar.go b/memex/sdar.go index dc3a6a9..e7d61f9 100644 --- a/memex/sdar.go +++ b/memex/sdar.go @@ -74,9 +74,9 @@ func AddrEqual(a1, a2 Addr) bool { return bytes.Equal(a1, a2) } -func FindSdarBin() { +func FindSdarBin() bool { if SdarPath != "" { - return + return true } /* finds sdar in dev builds */ @@ -95,10 +95,10 @@ func FindSdarBin() { _, err = os.Stat(SdarPath) } if err == nil { - return + return true } } - panic("cannot find sdar") + return false } func startSdar(command, archive_path string) (*SdarProcess, error) { |
