summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Carbonneaux2021-11-18 14:18:38 +0100
committerQuentin Carbonneaux2021-11-18 14:18:38 +0100
commit6f0be3654cab0d3e7b498a3adf36b06b68d22dc3 (patch)
tree95ea0f527ce0bc7d947f1d5741074eeb494bc990
parent0fdba5997702034203407b228e82fc5dd3169427 (diff)
[mx] better doc, reset, sync
-rw-r--r--memex/main.go248
-rw-r--r--memex/sdar.go8
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) {