Artifact 8e80721f1e9f101c2fc44e69d2a8829af3ce48a7b8b27adfc852ca61e57f2e68:
- File
internal/zitcli/create.go
— part of check-in
[4aaf089616]
at
2026-08-24 12:27:52
on branch timing-wall
— timing: the footer reports wall time, not a sum of concurrent calls
A diff is two zit subprocesses on purpose, run at once. Adding their durations printed more time than the whole request took — "rendered in 410.1ms (zit 706.8ms×2)", and "79.94s (zit 159.05s×2)" on a cold tcl page. A number larger than the total reads as a broken page rather than as two calls overlapping.
Record now takes the start instant instead of a duration, because a duration cannot say whether two calls overlapped, and the union of the spans is what a reader actually waited. (user: dmestas, size: 4095) [annotate] [blame] [check-ins using] [more...]
package zitcli import ( "bytes" "context" "fmt" "os" "os/exec" "path/filepath" "sort" "strings" "time" "craftdesign.group/quarry/internal/timing" ) // Init creates an empty repository at dir, creating dir if needed. // // A package function rather than a Client method because a Client is // bound to a repository that already exists; this is what makes one. func Init(ctx context.Context, dir string) error { return create(ctx, "init", []string{"init", dir}, dir) } // Clone copies the repository served at url into dir. // // zit saves url as dir's default remote, and never with a password: a // `user:secret@host` URL is stored as `user@host`. That is worth knowing // here because quarry keeps its own mirror configuration — the saved // remote is a convenience for anyone running zit by hand in that // directory, not the thing quarry's scheduler reads. func Clone(ctx context.Context, url, dir string) error { return create(ctx, "clone", []string{"clone", url, dir}, dir) } // create runs a repository-making verb. These are the two zit calls // with no repository to name, so they take neither -R nor a working // directory — the target is an argument. func create(ctx context.Context, verb string, args []string, dir string) error { if ctx == nil { ctx = context.Background() } start := time.Now() cmd := exec.CommandContext(ctx, "zit", args...) var stderr bytes.Buffer cmd.Stderr = &stderr _, err := cmd.Output() timing.Record(ctx, timing.Zit, start) if err != nil { return fmt.Errorf("zitcli: %s %s: %w: %s", verb, dir, err, strings.TrimSpace(stderr.String())) } return nil } // SeedFiles writes files into a freshly created repository and records // them as its first check-in, so the repository has a born trunk. // // This matters more than the convenience suggests: until a repository // has a check-in, its default branch is unborn, so the timeline, the // file tree and every "clone this" instruction have nothing to point at. // GitHub offers a README at creation for the same reason. // // Like Init and Clone this is directory-scoped rather than -R: `zit add` // and `zit commit` operate on a checkout, and a store made by Init has // one. Content is written by quarry rather than by zit, so paths are // checked against the repository root before anything is created — a // name reaching the filesystem is the one place traversal matters. func SeedFiles(ctx context.Context, dir, user, message string, files map[string]string) error { if len(files) == 0 { return nil } root, err := filepath.Abs(dir) if err != nil { return err } names := make([]string, 0, len(files)) for name := range files { full := filepath.Join(root, name) if !strings.HasPrefix(full, root+string(os.PathSeparator)) { return fmt.Errorf("zitcli: seed path %q escapes the repository", name) } if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil { return err } if err := os.WriteFile(full, []byte(files[name]), 0o644); err != nil { return err } names = append(names, name) } sort.Strings(names) add, doneAdd := commandIn(ctx, dir, append([]string{"add"}, names...)...) defer doneAdd() var stderr bytes.Buffer add.Stderr = &stderr if _, err := add.Output(); err != nil { return fmt.Errorf("zitcli: seed add: %w: %s", err, strings.TrimSpace(stderr.String())) } if user == "" { user = "quarry" } commit, doneCommit := commandIn(ctx, dir, "commit", "-m", message, "--user", user) defer doneCommit() stderr.Reset() commit.Stderr = &stderr if _, err := commit.Output(); err != nil { return fmt.Errorf("zitcli: seed commit: %w: %s", err, strings.TrimSpace(stderr.String())) } return nil } // commandIn runs a zit verb with the working directory set, for the // verbs that operate on a checkout rather than taking -R. func commandIn(ctx context.Context, dir string, args ...string) (*exec.Cmd, func()) { if ctx == nil { ctx = context.Background() } start := time.Now() cmd := exec.CommandContext(ctx, "zit", args...) cmd.Dir = dir return cmd, func() { timing.Record(ctx, timing.Zit, start) } }