aboutsummaryrefslogtreecommitdiff
path: root/repository
diff options
context:
space:
mode:
Diffstat (limited to 'repository')
-rw-r--r--repository/resolver.go11
-rw-r--r--repository/stored.go76
-rw-r--r--repository/stored_test.go66
-rw-r--r--repository/traversal_test.go2
-rw-r--r--repository/tree.go53
5 files changed, 35 insertions, 173 deletions
diff --git a/repository/resolver.go b/repository/resolver.go
new file mode 100644
index 00000000..faeb8837
--- /dev/null
+++ b/repository/resolver.go
@@ -0,0 +1,11 @@
+package repository
+
+import "codeberg.org/lindenii/furgit/object/resolve"
+
+// Resolver returns an object resolver backed by the repository's object store.
+//
+// The returned resolver is ready for use and does not take ownership of the
+// repository or its underlying object store.
+func (repo *Repository) Resolver() *resolve.Resolver {
+ return resolve.New(repo.objects)
+}
diff --git a/repository/stored.go b/repository/stored.go
deleted file mode 100644
index 92a3f0ad..00000000
--- a/repository/stored.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package repository
-
-import (
- "fmt"
-
- "codeberg.org/lindenii/furgit/object"
- "codeberg.org/lindenii/furgit/object/stored"
- "codeberg.org/lindenii/furgit/objectid"
- "codeberg.org/lindenii/furgit/objecttype"
-)
-
-// ReadStored reads, parses, and wraps one object by ID.
-func (repo *Repository) ReadStored(id objectid.ObjectID) (*stored.Stored[object.Object], error) {
- parsed, err := repo.readParsedObject(id)
- if err != nil {
- return nil, err
- }
-
- return stored.New(id, parsed), nil
-}
-
-// ReadStoredBlob reads and parses a blob object by ID.
-func (repo *Repository) ReadStoredBlob(id objectid.ObjectID) (*stored.Stored[*object.Blob], error) {
- return readStoredAs[*object.Blob](repo, id)
-}
-
-// ReadStoredTree reads and parses a tree object by ID.
-func (repo *Repository) ReadStoredTree(id objectid.ObjectID) (*stored.Stored[*object.Tree], error) {
- return readStoredAs[*object.Tree](repo, id)
-}
-
-// ReadStoredCommit reads and parses a commit object by ID.
-func (repo *Repository) ReadStoredCommit(id objectid.ObjectID) (*stored.Stored[*object.Commit], error) {
- return readStoredAs[*object.Commit](repo, id)
-}
-
-// ReadStoredTag reads and parses a tag object by ID.
-func (repo *Repository) ReadStoredTag(id objectid.ObjectID) (*stored.Stored[*object.Tag], error) {
- return readStoredAs[*object.Tag](repo, id)
-}
-
-// readParsedObject reads bytes content from storage and parses one object.
-//
-//nolint:ireturn
-func (repo *Repository) readParsedObject(id objectid.ObjectID) (object.Object, error) {
- ty, content, err := repo.objects.ReadBytesContent(id)
- if err != nil {
- return nil, err
- }
-
- parsed, err := object.ParseObjectWithoutHeader(ty, content, repo.algo)
- if err != nil {
- tyName, ok := objecttype.Name(ty)
- if !ok {
- tyName = fmt.Sprintf("type %d", ty)
- }
-
- return nil, fmt.Errorf("repository: parse object %s (%s): %w", id, tyName, err)
- }
-
- return parsed, nil
-}
-
-func readStoredAs[T object.Object](repo *Repository, id objectid.ObjectID) (*stored.Stored[T], error) {
- parsed, err := repo.readParsedObject(id)
- if err != nil {
- return nil, err
- }
-
- typed, ok := parsed.(T)
- if !ok {
- return nil, fmt.Errorf("repository: expected %T object %s, got %v", *new(T), id, parsed.ObjectType())
- }
-
- return stored.New(id, typed), nil
-}
diff --git a/repository/stored_test.go b/repository/stored_test.go
index fdae3f5a..47b61fe9 100644
--- a/repository/stored_test.go
+++ b/repository/stored_test.go
@@ -24,9 +24,9 @@ func TestReadStoredTyped(t *testing.T) {
repo := repoHarness.OpenRepository(t)
- blob, err := repo.ReadStoredBlob(blobID)
+ blob, err := repo.Resolver().ExactBlob(blobID)
if err != nil {
- t.Fatalf("ReadStoredBlob: %v", err)
+ t.Fatalf("ExactBlob: %v", err)
}
if blob.ID() != blobID {
@@ -37,9 +37,9 @@ func TestReadStoredTyped(t *testing.T) {
t.Fatalf("blob body = %q, want %q", blob.Object().Data, "commit-body\n")
}
- tree, err := repo.ReadStoredTree(treeID)
+ tree, err := repo.Resolver().ExactTree(treeID)
if err != nil {
- t.Fatalf("ReadStoredTree: %v", err)
+ t.Fatalf("ExactTree: %v", err)
}
if tree.ID() != treeID {
@@ -50,9 +50,9 @@ func TestReadStoredTyped(t *testing.T) {
t.Fatalf("tree entries = %d, want 1", len(tree.Object().Entries))
}
- commit, err := repo.ReadStoredCommit(commitID)
+ commit, err := repo.Resolver().ExactCommit(commitID)
if err != nil {
- t.Fatalf("ReadStoredCommit: %v", err)
+ t.Fatalf("ExactCommit: %v", err)
}
if commit.ID() != commitID {
@@ -65,7 +65,7 @@ func TestReadStoredTyped(t *testing.T) {
})
}
-func TestResolveTreeEntry(t *testing.T) {
+func TestResolverPath(t *testing.T) {
t.Parallel()
testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
@@ -81,27 +81,22 @@ func TestResolveTreeEntry(t *testing.T) {
repo := repoHarness.OpenRepository(t)
- rootTree, err := repo.ReadStoredTree(rootTreeID)
+ entry, err := repo.Resolver().Path(rootTreeID, [][]byte{[]byte("dir"), []byte("leaf.txt")})
if err != nil {
- t.Fatalf("ReadStoredTree(root): %v", err)
- }
-
- entry, err := repo.ResolveTreeEntry(rootTree, [][]byte{[]byte("dir"), []byte("leaf.txt")})
- if err != nil {
- t.Fatalf("ResolveTreeEntry: %v", err)
+ t.Fatalf("Path: %v", err)
}
if entry.Mode != object.FileModeRegular {
- t.Fatalf("ResolveTreeEntry mode = %o, want %o", entry.Mode, object.FileModeRegular)
+ t.Fatalf("Path mode = %o, want %o", entry.Mode, object.FileModeRegular)
}
if entry.ID != blobID {
- t.Fatalf("ResolveTreeEntry id = %s, want %s", entry.ID, blobID)
+ t.Fatalf("Path id = %s, want %s", entry.ID, blobID)
}
})
}
-func TestResolveTreeEntryErrors(t *testing.T) {
+func TestResolverPathErrors(t *testing.T) {
t.Parallel()
testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
@@ -117,14 +112,9 @@ func TestResolveTreeEntryErrors(t *testing.T) {
repo := repoHarness.OpenRepository(t)
- rootTree, err := repo.ReadStoredTree(rootTreeID)
- if err != nil {
- t.Fatalf("ReadStoredTree(root): %v", err)
- }
-
- _, err = repo.ResolveTreeEntry(rootTree, [][]byte{[]byte("missing")})
+ _, err := repo.Resolver().Path(rootTreeID, [][]byte{[]byte("missing")})
if err == nil || !strings.Contains(err.Error(), "not found") {
- t.Fatalf("ResolveTreeEntry missing: err = %v, want not found error", err)
+ t.Fatalf("Path missing: err = %v, want not found error", err)
}
})
@@ -140,20 +130,15 @@ func TestResolveTreeEntryErrors(t *testing.T) {
repo := repoHarness.OpenRepository(t)
- rootTree, err := repo.ReadStoredTree(rootTreeID)
- if err != nil {
- t.Fatalf("ReadStoredTree(root): %v", err)
- }
-
- _, err = repo.ResolveTreeEntry(rootTree, [][]byte{[]byte("dir"), []byte("leaf")})
+ _, err := repo.Resolver().Path(rootTreeID, [][]byte{[]byte("dir"), []byte("leaf")})
if err == nil || !strings.Contains(err.Error(), "is not a tree") {
- t.Fatalf("ResolveTreeEntry non-tree: err = %v, want non-tree error", err)
+ t.Fatalf("Path non-tree: err = %v, want non-tree error", err)
}
})
})
}
-func TestResolveTreeEntryDeepPath(t *testing.T) {
+func TestResolverPathDeepPath(t *testing.T) {
t.Parallel()
testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
@@ -179,22 +164,17 @@ func TestResolveTreeEntryDeepPath(t *testing.T) {
repo := repoHarness.OpenRepository(t)
- rootTree, err := repo.ReadStoredTree(currentTree)
- if err != nil {
- t.Fatalf("ReadStoredTree(root): %v", err)
- }
-
- entry, err := repo.ResolveTreeEntry(rootTree, parts)
+ entry, err := repo.Resolver().Path(currentTree, parts)
if err != nil {
- t.Fatalf("ResolveTreeEntry(deep): %v", err)
+ t.Fatalf("Path(deep): %v", err)
}
if entry.Mode != object.FileModeRegular {
- t.Fatalf("ResolveTreeEntry(deep) mode = %o, want %o", entry.Mode, object.FileModeRegular)
+ t.Fatalf("Path(deep) mode = %o, want %o", entry.Mode, object.FileModeRegular)
}
if entry.ID != leafBlobID {
- t.Fatalf("ResolveTreeEntry(deep) id = %s, want %s", entry.ID, leafBlobID)
+ t.Fatalf("Path(deep) id = %s, want %s", entry.ID, leafBlobID)
}
})
}
@@ -227,9 +207,9 @@ func TestReadStoredTreeMixedModes(t *testing.T) {
repo := repoHarness.OpenRepository(t)
- rootTree, err := repo.ReadStoredTree(rootTreeID)
+ rootTree, err := repo.Resolver().ExactTree(rootTreeID)
if err != nil {
- t.Fatalf("ReadStoredTree(root): %v", err)
+ t.Fatalf("ExactTree(root): %v", err)
}
expect := map[string]object.FileMode{
diff --git a/repository/traversal_test.go b/repository/traversal_test.go
index 7472250e..791db9d0 100644
--- a/repository/traversal_test.go
+++ b/repository/traversal_test.go
@@ -175,7 +175,7 @@ func traverseReachableIter(repo *repository.Repository, root objectid.ObjectID)
visited[id] = struct{}{}
- stored, err := repo.ReadStored(id)
+ stored, err := repo.Resolver().ExactObject(id)
if err != nil {
return 0, err
}
diff --git a/repository/tree.go b/repository/tree.go
deleted file mode 100644
index c9d635ad..00000000
--- a/repository/tree.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package repository
-
-import (
- "errors"
- "fmt"
-
- "codeberg.org/lindenii/furgit/object"
- "codeberg.org/lindenii/furgit/object/stored"
-)
-
-// ResolveTreeEntry resolves one path within a stored root tree.
-//
-// parts must contain at least one path segment. Intermediate segments must be
-// tree entries.
-func (repo *Repository) ResolveTreeEntry(tree *stored.Stored[*object.Tree], parts [][]byte) (object.TreeEntry, error) {
- if tree == nil {
- return object.TreeEntry{}, errors.New("repository: nil root tree")
- }
-
- if len(parts) == 0 {
- return object.TreeEntry{}, errors.New("repository: empty tree path")
- }
-
- current := tree
-
- for i, part := range parts {
- if len(part) == 0 {
- return object.TreeEntry{}, errors.New("repository: empty tree path segment")
- }
-
- entry := current.Object().Entry(part)
- if entry == nil {
- return object.TreeEntry{}, fmt.Errorf("repository: tree entry %q not found", part)
- }
-
- if i == len(parts)-1 {
- return *entry, nil
- }
-
- if entry.Mode != object.FileModeDir {
- return object.TreeEntry{}, fmt.Errorf("repository: path segment %q is not a tree", part)
- }
-
- next, err := repo.ReadStoredTree(entry.ID)
- if err != nil {
- return object.TreeEntry{}, err
- }
-
- current = next
- }
-
- return object.TreeEntry{}, fmt.Errorf("repository: tree entry not found")
-}