mirror of
https://github.com/therootcompany/golib.git
synced 2026-04-24 12:48:00 +00:00
test(gitshallow): regression test for upstream force-push recovery
Sets up a local bare upstream, clones via gitshallow, then rewrites upstream history as an unrelated commit and force-pushes. A fresh Repo instance's Fetch must succeed and install the new HEAD — the old pull-based flow would fail with "refusing to merge unrelated histories". Runs under the default test build (no integration tag) because it uses only a local bare repo; no network access required.
This commit is contained in:
parent
da2b230bc3
commit
0d9df94a24
102
net/gitshallow/forcepush_test.go
Normal file
102
net/gitshallow/forcepush_test.go
Normal file
@ -0,0 +1,102 @@
|
||||
package gitshallow_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/therootcompany/golib/net/gitshallow"
|
||||
)
|
||||
|
||||
// TestRepo_ForcePushRecovery verifies that Fetch transparently picks up an
|
||||
// upstream history rewrite. The previous pull-based flow could fail with
|
||||
// "refusing to merge unrelated histories"; the current fetch+reset must
|
||||
// succeed and install the new HEAD.
|
||||
func TestRepo_ForcePushRecovery(t *testing.T) {
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
t.Skip("git not available")
|
||||
}
|
||||
|
||||
root := t.TempDir()
|
||||
upstream := filepath.Join(root, "upstream.git") // bare
|
||||
scratch := filepath.Join(root, "scratch") // working copy that rewrites history
|
||||
clone := filepath.Join(root, "clone") // gitshallow clone under test
|
||||
|
||||
mustGit := func(t *testing.T, dir string, args ...string) {
|
||||
t.Helper()
|
||||
cmd := exec.Command("git", args...)
|
||||
cmd.Dir = dir
|
||||
cmd.Env = append(os.Environ(),
|
||||
"GIT_AUTHOR_NAME=test", "GIT_AUTHOR_EMAIL=test@example.com",
|
||||
"GIT_COMMITTER_NAME=test", "GIT_COMMITTER_EMAIL=test@example.com",
|
||||
)
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Fatalf("git %v (in %s): %v\n%s", args, dir, err, out)
|
||||
}
|
||||
}
|
||||
|
||||
// Bare upstream.
|
||||
if err := os.MkdirAll(upstream, 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mustGit(t, upstream, "init", "--bare", "--initial-branch=main")
|
||||
|
||||
// Scratch working copy with one commit, push to upstream.
|
||||
if err := os.MkdirAll(scratch, 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mustGit(t, scratch, "init", "--initial-branch=main")
|
||||
mustGit(t, scratch, "remote", "add", "origin", upstream)
|
||||
if err := os.WriteFile(filepath.Join(scratch, "data.txt"), []byte("v1\n"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mustGit(t, scratch, "add", "data.txt")
|
||||
mustGit(t, scratch, "commit", "-m", "v1")
|
||||
mustGit(t, scratch, "push", "-u", "origin", "main")
|
||||
|
||||
// gitshallow clones, reads v1.
|
||||
repo := gitshallow.New(upstream, clone, 1, "main")
|
||||
if updated, err := repo.Fetch(); err != nil {
|
||||
t.Fatalf("first Fetch: %v", err)
|
||||
} else if !updated {
|
||||
t.Fatal("first Fetch: expected updated=true")
|
||||
}
|
||||
got, err := os.ReadFile(filepath.Join(clone, "data.txt"))
|
||||
if err != nil {
|
||||
t.Fatalf("read v1: %v", err)
|
||||
}
|
||||
if string(got) != "v1\n" {
|
||||
t.Fatalf("v1: got %q want %q", got, "v1\n")
|
||||
}
|
||||
|
||||
// Rewrite upstream history with an unrelated commit and force-push.
|
||||
mustGit(t, scratch, "checkout", "--orphan", "fresh")
|
||||
mustGit(t, scratch, "rm", "-rf", ".")
|
||||
if err := os.WriteFile(filepath.Join(scratch, "data.txt"), []byte("v2\n"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mustGit(t, scratch, "add", "data.txt")
|
||||
mustGit(t, scratch, "commit", "-m", "v2")
|
||||
mustGit(t, scratch, "branch", "-M", "main")
|
||||
mustGit(t, scratch, "push", "--force", "origin", "main")
|
||||
|
||||
// gitshallow must recover — fetch+reset, not pull --ff-only.
|
||||
// Use a fresh instance: the same *Repo has a 1s debounce that would
|
||||
// skip the follow-up fetch in this test's wall-clock window.
|
||||
repo2 := gitshallow.New(upstream, clone, 1, "main")
|
||||
updated, err := repo2.Fetch()
|
||||
if err != nil {
|
||||
t.Fatalf("post-force-push Fetch: %v", err)
|
||||
}
|
||||
if !updated {
|
||||
t.Error("post-force-push Fetch: expected updated=true")
|
||||
}
|
||||
got, err = os.ReadFile(filepath.Join(clone, "data.txt"))
|
||||
if err != nil {
|
||||
t.Fatalf("read v2: %v", err)
|
||||
}
|
||||
if string(got) != "v2\n" {
|
||||
t.Fatalf("v2: got %q want %q", got, "v2\n")
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user