diff options
| author | 2025-11-20 08:00:00 +0800 | |
|---|---|---|
| committer | 2025-11-20 08:00:00 +0800 | |
| commit | a27bd4625f6e1f5153e5e654b09156cea48f82d2 (patch) | |
| tree | ba60075ebdda0b0238f02f52465ab5464541841f | |
| parent | refs: ResolveRef and ResolveRefFully, no HEAD split (diff) | |
| signature | No signature | |
refs: Support resolving hashes as refs
| -rw-r--r-- | refs.go | 8 | ||||
| -rw-r--r-- | refs_test.go | 52 |
2 files changed, 60 insertions, 0 deletions
@@ -156,6 +156,14 @@ func (repo *Repository) ResolveRef(path string) (Ref, error) { "HEAD", "ORIG_HEAD", "FETCH_HEAD", "MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "REBASE_HEAD", "BISECT_HEAD", }, path) { + id, err := repo.ParseHash(path) + if err == nil { + return Ref{ + Kind: RefKindDetached, + Hash: id, + }, nil + } + // For now let's keep this to prevent e.g., random users from // specifying something crazy like objects/... or ./config. // There may be other legal pseudo-refs in the future, diff --git a/refs_test.go b/refs_test.go index 58953b53..022a22c6 100644 --- a/refs_test.go +++ b/refs_test.go @@ -227,3 +227,55 @@ func TestResolveRefFullySymbolicCycle(t *testing.T) { t.Fatalf("unexpected error for symbolic cycle: %v", err) } } + +func TestResolveRefHashInput(t *testing.T) { + repoPath, cleanup := setupTestRepo(t) + defer cleanup() + + workDir, cleanupWork := setupWorkDir(t) + defer cleanupWork() + + err := os.WriteFile(filepath.Join(workDir, "file.txt"), []byte("content"), 0o644) + if err != nil { + t.Fatalf("failed to write file.txt: %v", err) + } + gitCmd(t, repoPath, "--work-tree="+workDir, "add", ".") + gitCmd(t, repoPath, "--work-tree="+workDir, "commit", "-m", "init") + + commitHash := gitCmd(t, repoPath, "rev-parse", "HEAD") + + repo, err := OpenRepository(repoPath) + if err != nil { + t.Fatalf("OpenRepository failed: %v", err) + } + defer repo.Close() + + hashObj, err := repo.ParseHash(commitHash) + if err != nil { + t.Fatalf("ParseHash failed: %v", err) + } + + ref, err := repo.ResolveRef(commitHash) + if err != nil { + t.Fatalf("ResolveRef(hash) failed: %v", err) + } + if ref.Kind != RefKindDetached { + t.Fatalf("expected RefKindDetached, got %v", ref.Kind) + } + if ref.Hash != hashObj { + t.Fatalf("hash mismatch: got %s, want %s", ref.Hash, hashObj) + } + + hash, err := repo.ResolveRefFully(commitHash) + if err != nil { + t.Fatalf("ResolveRefFully(hash) failed: %v", err) + } + if hash != hashObj { + t.Fatalf("hash mismatch: got %s, want %s", hash, hashObj) + } + + _, err = repo.ResolveRef("this_is_not_a_hash") + if err == nil { + t.Fatalf("expected error for invalid hash input") + } +} |
