Artifact df5d27c921ebe62057cc242bf0189d6b465be48eaabe60d9832cb90821bc3c51:
- File
cli/repo_structural_test.go
— part of check-in
[c11b3055fb]
at
2026-10-22 17:36:26
on branch feat/horizon-cones
— feat(horizon): deepen as a verb, discarding the seed for the old C
Section 5.8 makes deepen the universal remedy of the draft: name a C' that is an ancestor of C and synchronize at it. sync.Deepen finds C' as zit's deepenPoint does, the target itself when it is C's ancestor, else a common ancestor over the P cards the store holds or asked of the origin with the merge-base query; it refuses rather than move C off its own ancestry when none can be established. Repo.DeepenHorizon and 'repo cone deepen' expose it, and the crossing diagnostic now names that command.
Moving a structural horizon through FetchCone now discards the held seed before the transfer, so the request offers none and the seed for C, applied at a later date, cannot shadow propagation from the seed for C'. A transfer that fails puts the old cone and seed back, as zit's deepen does: a store left structural without a seed derives no branch state for K. (user: [email protected], size: 3489) [annotate] [blame] [check-ins using]
package cli import ( "path/filepath" "strings" "testing" ) // A structural clone (draft-fossil-horizon-00 §5): --structural takes the // structural cut and the clone says so; the store cone shows it; info names // the horizon and the check-ins below it rather than leaving bare phantoms; // verify counts the manifests below the horizon as elided, never as damage // (§5.4); and checking out, diffing or annotating a check-in below C fails // naming the horizon (§5.5). func TestRepoCloneStructural(t *testing.T) { url, c1, c2, _ := horizonSource(t) path := filepath.Join(t.TempDir(), "s.fossil") if err := (&RepoCloneCmd{URL: url, Path: path, Structural: true}).Run(&Globals{}); err == nil { t.Fatal("--structural without --horizon was accepted") } out := requiredHTTPStdout(t, func() error { return (&RepoCloneCmd{URL: url, Path: path, Horizon: c2, Structural: true}).Run(&Globals{}) }) if !strings.Contains(out, "Horizon: structural\n") { t.Fatalf("clone output = %q", out) } if got, want := storeConeOutput(t, path), "horizon "+c2+" descendants structural\n"; got != want { t.Fatalf("store cone = %q, want %q", got, want) } info := requiredHTTPStdout(t, func() error { return (&RepoInfoCmd{}).Run(&Globals{Repo: path}) }) for _, line := range []string{"horizon: " + c2 + " descendants structural\n", "below horizon: 1 check-in(s)\n"} { if !strings.Contains(info, line) { t.Fatalf("info lacks %q:\n%s", line, info) } } var verifyErr error verified := requiredHTTPStdout(t, func() error { verifyErr = (&RepoVerifyCmd{}).Run(&Globals{Repo: path}) return nil }) if verifyErr != nil || !strings.Contains(verified, "0 transit phantoms") || !strings.Contains(verified, "1 check-in(s) below the horizon") { t.Fatalf("verify: %v\n%s", verifyErr, verified) } for name, run := range map[string]func() error{ "co": func() error { return (&RepoCoCmd{Version: c1, Dir: t.TempDir()}).Run(&Globals{Repo: path}) }, "diff": func() error { return (&RepoDiffCmd{Version: c1, To: c2}).Run(&Globals{Repo: path}) }, "annotate": func() error { return (&RepoAnnotateCmd{File: "a", Version: c1}).Run(&Globals{Repo: path}) }, } { err := run() if err == nil || !strings.Contains(err.Error(), "below the structural horizon at "+c2) { t.Errorf("%s below C: %v, want a diagnostic naming the horizon", name, err) } } } // `repo cone deepen` moves a structural store's horizon to a check-in below // it, from the saved remote, and keeps the structural depth // (draft-fossil-horizon-00 §5.8); the check-in below the old horizon can // then be checked out. func TestRepoConeDeepen(t *testing.T) { url, c1, c2, _ := horizonSource(t) path := filepath.Join(t.TempDir(), "s.fossil") requiredHTTPStdout(t, func() error { return (&RepoCloneCmd{URL: url, Path: path, Horizon: c2, Structural: true}).Run(&Globals{}) }) out := requiredHTTPStdout(t, func() error { return (&RepoConeDeepenCmd{Checkin: c1}).Run(&Globals{Repo: path}) }) if !strings.Contains(out, "horizon "+c1+" descendants structural\n") { t.Fatalf("deepen output = %q", out) } if got, want := storeConeOutput(t, path), "horizon "+c1+" descendants structural\n"; got != want { t.Fatalf("store cone = %q, want %q", got, want) } if !holdsBlob(t, path, "old a\n") { t.Fatal("the deepen fetched no blob the deeper horizon keeps") } requiredHTTPStdout(t, func() error { return (&RepoCoCmd{Version: c1, Dir: t.TempDir()}).Run(&Globals{Repo: path}) }) }