Artifact cc313a91ba71a6acdf930e56c08ce2ac44dea5fd973a4dcfe766f09c4833fe25:
- File
cli/repo_cone_test.go
— part of check-in
[94304a520c]
at
2026-10-18 18:29:54
on branch feat/submanifest-reader
— feat: sparse checkouts in the public API and the CLI
Cone, NewCone, CheckoutCreateOpts.Cone, Checkout.Cone and SetCone, UpdateResult.OutOfCone and ErrOutsideCone; repo open --cone/--cone-not and repo cone (show, add, remove, set, dense, test). (user: [email protected], size: 3423) [annotate] [blame] [check-ins using]
package cli_test import ( "errors" "fmt" "os" "path/filepath" "strings" "testing" "time" "github.com/alecthomas/kong" libfossil "github.com/danmestas/go-libfossil" "github.com/danmestas/go-libfossil/cli" ) // repo open --cone makes a sparse checkout; repo cone shows it, widens it, // narrows it, tests paths against it and returns it to dense. func TestRepoConeCmd(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "r.fossil") r, err := libfossil.Create(path, libfossil.CreateOpts{User: "u"}) if err != nil { t.Fatal(err) } var files []libfossil.FileToCommit for _, name := range []string{"README", "src/a.c", "src/vendor/v.c", "tools/t.c"} { files = append(files, libfossil.FileToCommit{Name: name, Content: []byte(name + "\n")}) } if _, _, err := r.Commit(libfossil.CommitOpts{Comment: "c", User: "u", Time: time.Now(), Files: files}); err != nil { t.Fatal(err) } r.Close() work := filepath.Join(dir, "work") run := func(args ...string) (string, error) { var c submanifestsTestCLI parser, err := kong.New(&c) if err != nil { t.Fatal(err) } var runErr error out := captureStdout(t, func() error { ctx, err := parser.Parse(append([]string{"-R", path, "repo"}, args...)) if err != nil { runErr = err return nil } runErr = ctx.Run(&c.Globals) return nil }) return out, runErr } present := func(name string) bool { _, err := os.Stat(filepath.Join(work, name)) return err == nil } if _, err := run("open", work, "--cone", "src", "--cone-not", "src/vendor"); err != nil { t.Fatal(err) } if !present("src/a.c") || present("src/vendor/v.c") || present("README") { t.Fatal("open --cone did not materialize exactly the cone") } if out, err := run("cone", "-d", work); err != nil || out != "src\n!src/vendor\n" { t.Fatalf("cone = %q, %v", out, err) } out, err := run("cone", "test", "-d", work, "src/a.c", "src/vendor/v.c", "README") if !errors.Is(err, cli.ErrConeTestElided) { t.Fatalf("cone test with elided paths: %v", err) } // zit's layout: the verdict, the path and the deciding member, aligned. want := fmt.Sprintf("%-8s%-16s%s\n%-8s%-16s%s\n%-8s%-16s%s\n", "covered", "src/a.c", "src", "elided", "src/vendor/v.c", "src/vendor", "elided", "README", "(no member covers)") if out != want { t.Fatalf("cone test =\n%s\nwant\n%s", out, want) } if _, err := run("cone", "add", "-d", work, "tools"); err != nil || !present("tools/t.c") { t.Fatalf("cone add tools: %v", err) } if _, err := run("cone", "remove", "-d", work, "src/vendor"); err != nil || !present("src/vendor/v.c") { t.Fatalf("cone remove src/vendor (an exclusion): %v", err) } if _, err := run("cone", "add", "-d", work, "--not", "src/vendor"); err != nil || present("src/vendor/v.c") { t.Fatalf("cone add --not src/vendor: %v", err) } if _, err := run("cone", "set", "-d", work, "README"); err != nil || present("src/a.c") || !present("README") { t.Fatalf("cone set README: %v", err) } if out, err := run("add", "-d", work, filepath.Join(work, "src/a.c")); err == nil || !strings.Contains(err.Error(), "sparse cone") { t.Fatalf("add outside the cone: %q, %v", out, err) } if _, err := run("cone", "dense", "-d", work); err != nil || !present("src/a.c") { t.Fatalf("cone dense: %v", err) } if out, err := run("cone", "-d", work); err != nil || out != "dense\n" { t.Fatalf("cone after dense = %q, %v", out, err) } }