// loomctl fetches documents this repository depends on, and finds out when they // change. // // It reports and never repairs. Everything it writes, it writes to the working // tree — committing and pushing are yours, because the consequences of a push // land on people a tool cannot experience. package main import ( "flag" "fmt" "os" "git.hypertheory-labs.dev/loom/loom-cli/internal/external" ) const usage = `loomctl — fetch what you depend on, and find out when it changed. loomctl external list what a repository publishes loomctl external add [--path p] adopt one document and lock it loomctl external check ask every publisher whether theirs moved check reports and does not fix. A changed document is a candidate, not a replacement, and somebody decides. It exits 0 whether or not anything moved: the report is the answer. Adopted documents live in .loom/externals////.md, and their origins in .loom/externals/.locks. The path is for a person to read; the lock is what a machine uses, because the path does not round-trip to a URL. Credentials are read-only and per host, in ~/.config/loomctl/config.json or in LOOMCTL_TOKEN_. loomctl never writes over the network, so a token it is given should never carry write scope. Requires git on PATH, for list only. ` func main() { if err := run(os.Args[1:]); err != nil { fmt.Fprintln(os.Stderr, "loomctl: "+err.Error()) os.Exit(1) } } func run(args []string) error { if len(args) == 0 || args[0] == "-h" || args[0] == "--help" || args[0] == "help" { fmt.Print(usage) return nil } switch args[0] { case "external": return runExternal(args[1:]) default: return fmt.Errorf("unknown command %q\n\n%s", args[0], usage) } } func runExternal(args []string) error { if len(args) == 0 { return fmt.Errorf("external needs a subcommand: list, add, check") } switch args[0] { case "list": if len(args) != 2 { return fmt.Errorf("usage: loomctl external list ") } return external.List(args[1], os.Stdout) case "add": fs := flag.NewFlagSet("add", flag.ContinueOnError) path := fs.String("path", "", "where to keep it, relative to .loom/externals (default: derived from the URL)") if err := fs.Parse(args[1:]); err != nil { return err } if fs.NArg() != 1 { return fmt.Errorf("usage: loomctl external add [--path p]") } root, err := root() if err != nil { return err } return external.Add(root, fs.Arg(0), *path, os.Stdout) case "check": root, err := root() if err != nil { return err } return external.Check(root, os.Stdout) default: return fmt.Errorf("unknown external subcommand %q", args[0]) } } func root() (string, error) { wd, err := os.Getwd() if err != nil { return "", err } return external.FindRoot(wd) }