aboutsummaryrefslogtreecommitdiff
path: root/repository
diff options
context:
space:
mode:
Diffstat (limited to 'repository')
-rw-r--r--repository/read_stored_passthrough_test.go9
-rw-r--r--repository/refs_test.go25
-rw-r--r--repository/repository.go46
-rw-r--r--repository/repository_test.go17
-rw-r--r--repository/stored_test.go49
-rw-r--r--repository/traversal_bench_test.go12
-rw-r--r--repository/traversal_test.go10
-rw-r--r--repository/write_loose_test.go25
8 files changed, 143 insertions, 50 deletions
diff --git a/repository/read_stored_passthrough_test.go b/repository/read_stored_passthrough_test.go
index f320907a..3adcc103 100644
--- a/repository/read_stored_passthrough_test.go
+++ b/repository/read_stored_passthrough_test.go
@@ -3,6 +3,7 @@ package repository_test
import (
"bytes"
"io"
+ "os"
"testing"
"codeberg.org/lindenii/furgit/internal/testgit"
@@ -23,7 +24,13 @@ func TestReadStoredPassThroughs(t *testing.T) {
_, _, commitID := repoHarness.MakeCommit(t, "pass-through")
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}
diff --git a/repository/refs_test.go b/repository/refs_test.go
index 8ebf93a6..d0cb216b 100644
--- a/repository/refs_test.go
+++ b/repository/refs_test.go
@@ -1,6 +1,7 @@
package repository_test
import (
+ "os"
"strings"
"testing"
@@ -25,7 +26,13 @@ func TestRefConvenienceMethods(t *testing.T) {
repoHarness.SymbolicRef(t, "HEAD", "refs/heads/main")
repoHarness.UpdateRef(t, "refs/tags/v1", commitID)
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}
@@ -79,7 +86,13 @@ func TestResolveRefErrorSurface(t *testing.T) {
RefFormat: "files",
})
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}
@@ -114,7 +127,13 @@ func TestListRefsLooseOverridesPacked(t *testing.T) {
_, _, commit2 := repoHarness.MakeCommit(t, "commit-two")
repoHarness.UpdateRef(t, "refs/heads/main", commit2)
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}
diff --git a/repository/repository.go b/repository/repository.go
index bd5ac8f3..418941a0 100644
--- a/repository/repository.go
+++ b/repository/repository.go
@@ -21,7 +21,7 @@ import (
// Repository is a thin composition root for repository-local stores.
//
-// Open expects path to be the Git directory itself:
+// Open expects a root for the Git directory itself:
// a bare repository root or a non-bare ".git" directory.
type Repository struct {
config *config.Config
@@ -33,13 +33,9 @@ type Repository struct {
}
// Open opens a repository and wires object/ref stores from its on-disk format.
-func Open(path string) (repo *Repository, err error) {
- setupRoot, err := os.OpenRoot(path)
- if err != nil {
- return nil, err
- }
- defer func() { _ = setupRoot.Close() }()
-
+//
+// Open borrows root during construction and does not close it.
+func Open(root *os.Root) (repo *Repository, err error) {
repo = &Repository{}
defer func() {
if err != nil {
@@ -47,7 +43,7 @@ func Open(path string) (repo *Repository, err error) {
}
}()
- cfg, err := parseRepositoryConfig(setupRoot)
+ cfg, err := parseRepositoryConfig(root)
if err != nil {
return nil, err
}
@@ -59,14 +55,14 @@ func Open(path string) (repo *Repository, err error) {
}
repo.algo = algo
- objects, objectsLooseForWritingOnly, err := openObjectStore(path, algo)
+ objects, objectsLooseForWritingOnly, err := openObjectStore(root, algo)
if err != nil {
return nil, err
}
repo.objects = objects
repo.objectsLooseForWritingOnly = objectsLooseForWritingOnly
- refs, err := openRefStore(path, algo)
+ refs, err := openRefStore(root, algo)
if err != nil {
return nil, err
}
@@ -148,14 +144,8 @@ func detectObjectAlgorithm(cfg *config.Config) (objectid.Algorithm, error) {
return algo, nil
}
-func openObjectStore(path string, algo objectid.Algorithm) (objectstore.Store, *objectloose.Store, error) {
- repoRoot, err := os.OpenRoot(path)
- if err != nil {
- return nil, nil, fmt.Errorf("repository: open root: %w", err)
- }
- defer func() { _ = repoRoot.Close() }()
-
- objectsRoot, err := repoRoot.OpenRoot("objects")
+func openObjectStore(root *os.Root, algo objectid.Algorithm) (objectstore.Store, *objectloose.Store, error) {
+ objectsRoot, err := root.OpenRoot("objects")
if err != nil {
return nil, nil, fmt.Errorf("repository: open objects: %w", err)
}
@@ -182,7 +172,7 @@ func openObjectStore(path string, algo objectid.Algorithm) (objectstore.Store, *
objectsChain := objectchain.New(backends...)
- objectsRootForWriting, err := repoRoot.OpenRoot("objects")
+ objectsRootForWriting, err := root.OpenRoot("objects")
if err != nil {
_ = objectsChain.Close()
return nil, nil, fmt.Errorf("repository: open objects for loose writing: %w", err)
@@ -197,19 +187,13 @@ func openObjectStore(path string, algo objectid.Algorithm) (objectstore.Store, *
return objectsChain, objectsLooseForWritingOnly, nil
}
-func openRefStore(path string, algo objectid.Algorithm) (out refstore.Store, err error) {
- metaRoot, err := os.OpenRoot(path)
- if err != nil {
- return nil, fmt.Errorf("repository: open root: %w", err)
- }
- defer func() { _ = metaRoot.Close() }()
-
- hasReftable, err := hasReftableStack(metaRoot)
+func openRefStore(root *os.Root, algo objectid.Algorithm) (out refstore.Store, err error) {
+ hasReftable, err := hasReftableStack(root)
if err != nil {
return nil, err
}
if hasReftable {
- reftableRoot, err := metaRoot.OpenRoot("reftable")
+ reftableRoot, err := root.OpenRoot("reftable")
if err != nil {
return nil, fmt.Errorf("repository: open reftable: %w", err)
}
@@ -221,7 +205,7 @@ func openRefStore(path string, algo objectid.Algorithm) (out refstore.Store, err
return reftableStore, nil
}
- looseRoot, err := os.OpenRoot(path)
+ looseRoot, err := root.OpenRoot(".")
if err != nil {
return nil, fmt.Errorf("repository: open root for loose refs: %w", err)
}
@@ -232,7 +216,7 @@ func openRefStore(path string, algo objectid.Algorithm) (out refstore.Store, err
}
backends := []refstore.Store{looseStore}
- packedRefsFile, err := metaRoot.Open("packed-refs")
+ packedRefsFile, err := root.Open("packed-refs")
if err == nil {
packedStore, packedErr := refpacked.New(packedRefsFile, algo)
_ = packedRefsFile.Close()
diff --git a/repository/repository_test.go b/repository/repository_test.go
index de6b8428..f8b33c8a 100644
--- a/repository/repository_test.go
+++ b/repository/repository_test.go
@@ -1,6 +1,7 @@
package repository_test
import (
+ "os"
"testing"
"codeberg.org/lindenii/furgit/internal/testgit"
@@ -24,7 +25,13 @@ func TestOpenFilesRefFormat(t *testing.T) {
repoHarness.UpdateRef(t, "refs/heads/main", commitID)
repoHarness.SymbolicRef(t, "HEAD", "refs/heads/main")
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}
@@ -108,7 +115,13 @@ func writeMainAndHead(t *testing.T, repoHarness *testgit.TestRepo) objectid.Obje
func assertResolveFully(t *testing.T, repoHarness *testgit.TestRepo, name string, want objectid.ObjectID) {
t.Helper()
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}
diff --git a/repository/stored_test.go b/repository/stored_test.go
index 3768d450..e3e2266d 100644
--- a/repository/stored_test.go
+++ b/repository/stored_test.go
@@ -2,6 +2,7 @@ package repository_test
import (
"fmt"
+ "os"
"strings"
"testing"
@@ -23,7 +24,13 @@ func TestReadStoredTyped(t *testing.T) {
blobID, treeID, commitID := repoHarness.MakeCommit(t, "stored types")
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}
@@ -78,7 +85,13 @@ func TestResolveTreeEntry(t *testing.T) {
childTreeID := repoHarness.Mktree(t, fmt.Sprintf("100644 blob %s\tleaf.txt\n", blobID))
rootTreeID := repoHarness.Mktree(t, fmt.Sprintf("040000 tree %s\tdir\n", childTreeID))
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}
@@ -116,7 +129,13 @@ func TestResolveTreeEntryErrors(t *testing.T) {
blobID := repoHarness.HashObject(t, "blob", []byte("body\n"))
rootTreeID := repoHarness.Mktree(t, fmt.Sprintf("100644 blob %s\tfile.txt\n", blobID))
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}
@@ -143,7 +162,13 @@ func TestResolveTreeEntryErrors(t *testing.T) {
blobID := repoHarness.HashObject(t, "blob", []byte("body\n"))
rootTreeID := repoHarness.Mktree(t, fmt.Sprintf("100644 blob %s\tdir\n", blobID))
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}
@@ -185,7 +210,13 @@ func TestResolveTreeEntryDeepPath(t *testing.T) {
}
parts = append(parts, []byte("leaf.txt"))
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}
@@ -235,7 +266,13 @@ func TestReadStoredTreeMixedModes(t *testing.T) {
),
)
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}
diff --git a/repository/traversal_bench_test.go b/repository/traversal_bench_test.go
index da49c639..63e131de 100644
--- a/repository/traversal_bench_test.go
+++ b/repository/traversal_bench_test.go
@@ -21,9 +21,17 @@ func BenchmarkTraverseHeadTree(b *testing.B) {
b.Fatalf("missing %s", benchRepoPathEnv)
}
- repo, err := repository.Open(repoPath)
+ root, err := os.OpenRoot(repoPath)
if err != nil {
- b.Fatalf("repository.Open(%q): %v", repoPath, err)
+ b.Fatalf("os.OpenRoot(%q): %v", repoPath, err)
+ }
+ b.Cleanup(func() {
+ _ = root.Close()
+ })
+
+ repo, err := repository.Open(root)
+ if err != nil {
+ b.Fatalf("repository.Open(root for %q): %v", repoPath, err)
}
b.Cleanup(func() {
_ = repo.Close()
diff --git a/repository/traversal_test.go b/repository/traversal_test.go
index e6e3445a..28c03a2c 100644
--- a/repository/traversal_test.go
+++ b/repository/traversal_test.go
@@ -92,9 +92,15 @@ func TestRepositoryDepthFirstEnumerationCurrentWorktree(t *testing.T) {
func walkRepositoryFromHead(t *testing.T, repoPath string) {
t.Helper()
- repo, err := repository.Open(repoPath)
+ root, err := os.OpenRoot(repoPath)
if err != nil {
- t.Fatalf("repository.Open(%q): %v", repoPath, err)
+ t.Fatalf("os.OpenRoot(%q): %v", repoPath, err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
+ if err != nil {
+ t.Fatalf("repository.Open(root for %q): %v", repoPath, err)
}
defer func() { _ = repo.Close() }()
diff --git a/repository/write_loose_test.go b/repository/write_loose_test.go
index aae118e2..603b3a88 100644
--- a/repository/write_loose_test.go
+++ b/repository/write_loose_test.go
@@ -2,6 +2,7 @@ package repository_test
import (
"bytes"
+ "os"
"testing"
"codeberg.org/lindenii/furgit/internal/testgit"
@@ -20,7 +21,13 @@ func TestWriteLooseBytesContent(t *testing.T) {
RefFormat: "files",
})
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}
@@ -60,7 +67,13 @@ func TestWriteLooseReaderContent(t *testing.T) {
RefFormat: "files",
})
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}
@@ -90,7 +103,13 @@ func TestWriteLooseFull(t *testing.T) {
})
_, _, commitID := repoHarness.MakeCommit(t, "write-loose-full")
- repo, err := repository.Open(repoHarness.Dir())
+ root, err := os.OpenRoot(repoHarness.Dir())
+ if err != nil {
+ t.Fatalf("os.OpenRoot: %v", err)
+ }
+ defer func() { _ = root.Close() }()
+
+ repo, err := repository.Open(root)
if err != nil {
t.Fatalf("repository.Open: %v", err)
}