ref: b82af688be4d94245c4a7eb730b12348b08b414b
parent: 3ce59c3248dec0eb0f918c42f37f53bc2ac20425
author: Runxi Yu <runxiyu@umich.edu>
date: Mon Mar 30 23:19:39 EDT 2026
reachability: Use fetcher and clean up some legacy helper stuff
--- a/reachability/domain.go
+++ b/reachability/domain.go
@@ -1,5 +1,7 @@
package reachability
+import "fmt"
+
// Domain specifies which graph edges are traversed.
type Domain uint8
@@ -9,3 +11,12 @@
// DomainObjects traverses full commit/tree/blob objects.
DomainObjects
)
+
+func validateDomain(domain Domain) error {+ switch domain {+ case DomainCommits, DomainObjects:
+ return nil
+ default:
+ return fmt.Errorf("reachability: invalid domain %d", domain)+ }
+}
--- a/reachability/helpers.go
+++ /dev/null
@@ -1,72 +1,0 @@
-package reachability
-
-import (
- "errors"
- "fmt"
-
- giterrors "codeberg.org/lindenii/furgit/errors"
- objectid "codeberg.org/lindenii/furgit/object/id"
- objectstore "codeberg.org/lindenii/furgit/object/store"
- objecttype "codeberg.org/lindenii/furgit/object/type"
-)
-
-func validateDomain(domain Domain) error {- switch domain {- case DomainCommits, DomainObjects:
- return nil
- default:
- return fmt.Errorf("reachability: invalid domain %d", domain)- }
-}
-
-func containsOID(set map[objectid.ObjectID]struct{}, id objectid.ObjectID) bool {- if len(set) == 0 {- return false
- }
-
- _, ok := set[id]
-
- return ok
-}
-
-// The following helpers exist because we don't have unified error handling across the entire project.
-// This will be fixed later.
-
-func (walk *Walk) readHeaderType(id objectid.ObjectID) (objecttype.Type, error) {- return walk.reachability.readHeaderType(id)
-}
-
-func (r *Reachability) readHeaderType(id objectid.ObjectID) (objecttype.Type, error) {- ty, _, err := r.store.ReadHeader(id)
- if err != nil {- if errors.Is(err, objectstore.ErrObjectNotFound) {- return objecttype.TypeInvalid, &giterrors.ObjectMissingError{OID: id}- }
-
- return objecttype.TypeInvalid, err
- }
-
- return ty, nil
-}
-
-func (walk *Walk) readBytesContent(id objectid.ObjectID) ([]byte, error) {- content, err := walk.reachability.readBytesContent(id)
- if err != nil {- return nil, err
- }
-
- return content, nil
-}
-
-func (r *Reachability) readBytesContent(id objectid.ObjectID) ([]byte, error) {- _, content, err := r.store.ReadBytesContent(id)
- if err != nil {- if errors.Is(err, objectstore.ErrObjectNotFound) {- return nil, &giterrors.ObjectMissingError{OID: id}- }
-
- return nil, err
- }
-
- return content, nil
-}
--- a/reachability/integration_test.go
+++ b/reachability/integration_test.go
@@ -11,6 +11,7 @@
giterrors "codeberg.org/lindenii/furgit/errors"
"codeberg.org/lindenii/furgit/internal/testgit"
+ objectfetch "codeberg.org/lindenii/furgit/object/fetch"
objectid "codeberg.org/lindenii/furgit/object/id"
"codeberg.org/lindenii/furgit/reachability"
)
@@ -249,7 +250,7 @@
func openReachabilityFromTestRepo(t *testing.T, testRepo *testgit.TestRepo) *reachability.Reachability {t.Helper()
- return reachability.New(testRepo.OpenObjectStore(t), nil)
+ return reachability.New(objectfetch.New(testRepo.OpenObjectStore(t)), nil)
}
func oidSetFromSeq(seq func(func(objectid.ObjectID) bool)) map[objectid.ObjectID]struct{} {--- a/reachability/reachability.go
+++ b/reachability/reachability.go
@@ -2,7 +2,7 @@
import (
commitgraphread "codeberg.org/lindenii/furgit/format/commitgraph/read"
- objectstore "codeberg.org/lindenii/furgit/object/store"
+ objectfetch "codeberg.org/lindenii/furgit/object/fetch"
)
// Reachability provides graph traversal over objects in one object store.
@@ -9,14 +9,14 @@
//
// Labels: MT-Safe.
type Reachability struct {- store objectstore.Reader
- graph *commitgraphread.Reader
+ fetcher *objectfetch.Fetcher
+ graph *commitgraphread.Reader
}
-// New builds a Reachability over one object store with an optional
+// New builds a Reachability over one object fetcher with an optional
// commit-graph reader for faster commit-domain traversal.
//
// Labels: Deps-Borrowed, Life-Parent.
-func New(store objectstore.Reader, graph *commitgraphread.Reader) *Reachability {- return &Reachability{store: store, graph: graph}+func New(fetcher *objectfetch.Fetcher, graph *commitgraphread.Reader) *Reachability {+ return &Reachability{fetcher: fetcher, graph: graph}}
--- a/reachability/unit_test.go
+++ b/reachability/unit_test.go
@@ -9,6 +9,7 @@
giterrors "codeberg.org/lindenii/furgit/errors"
"codeberg.org/lindenii/furgit/internal/testgit"
+ objectfetch "codeberg.org/lindenii/furgit/object/fetch"
objectid "codeberg.org/lindenii/furgit/object/id"
"codeberg.org/lindenii/furgit/object/store/memory"
"codeberg.org/lindenii/furgit/object/tree"
@@ -118,7 +119,7 @@
t.Fatal(err)
}
- r := reachability.New(store, nil)
+ r := reachability.New(objectfetch.New(store), nil)
walk := r.Walk(reachability.DomainCommits, nil, map[objectid.ObjectID]struct{}{tag2: {}})got := collectSeq(walk.Seq())
@@ -162,7 +163,7 @@
t.Fatal(err)
}
- r := reachability.New(store, nil)
+ r := reachability.New(objectfetch.New(store), nil)
walk := r.Walk(reachability.DomainCommits, map[objectid.ObjectID]struct{}{commit: {}}, map[objectid.ObjectID]struct{}{commit: {}})got := collectSeq(walk.Seq())
@@ -203,7 +204,7 @@
t.Fatal(err)
}
- r := reachability.New(store, nil)
+ r := reachability.New(objectfetch.New(store), nil)
walk := r.Walk(reachability.DomainCommits, nil, map[objectid.ObjectID]struct{}{tag: {}})_ = collectSeq(walk.Seq())
@@ -263,7 +264,7 @@
t.Fatal(err)
}
- r := reachability.New(store, nil)
+ r := reachability.New(objectfetch.New(store), nil)
walk := r.Walk(
reachability.DomainCommits,
map[objectid.ObjectID]struct{}{tag1: {}},@@ -327,7 +328,7 @@
t.Fatal(err)
}
- r := reachability.New(store, nil)
+ r := reachability.New(objectfetch.New(store), nil)
walk := r.Walk(reachability.DomainObjects, nil, map[objectid.ObjectID]struct{}{commit: {}})got := collectSeq(walk.Seq())
@@ -377,7 +378,7 @@
t.Fatal(err)
}
- r := reachability.New(store, nil)
+ r := reachability.New(objectfetch.New(store), nil)
err = r.CheckConnected(reachability.DomainCommits, nil, map[objectid.ObjectID]struct{}{commit: {}}) if err == nil {@@ -399,7 +400,7 @@
t.Parallel()
testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper- r := reachability.New(newCountingMemStore(algo), nil)
+ r := reachability.New(objectfetch.New(newCountingMemStore(algo)), nil)
walk := r.Walk(reachability.Domain(99), nil, nil)
_ = collectSeq(walk.Seq())
--- a/reachability/walk_expand_commits.go
+++ b/reachability/walk_expand_commits.go
@@ -4,8 +4,6 @@
"fmt"
"codeberg.org/lindenii/furgit/errors"
- objectcommit "codeberg.org/lindenii/furgit/object/commit"
- objecttag "codeberg.org/lindenii/furgit/object/tag"
objecttype "codeberg.org/lindenii/furgit/object/type"
)
@@ -28,7 +26,7 @@
}
}
- ty, err := walk.readHeaderType(item.id)
+ ty, _, err := walk.reachability.fetcher.Header(item.id)
if err != nil {return nil, err
}
@@ -35,34 +33,24 @@
switch ty {case objecttype.TypeCommit:
- content, err := walk.readBytesContent(item.id)
+ commit, err := walk.reachability.fetcher.ExactCommit(item.id)
if err != nil {return nil, err
}
- commit, err := objectcommit.Parse(content, item.id.Algorithm())
- if err != nil {- return nil, err
- }
-
- next := make([]walkItem, 0, len(commit.Parents))
- for _, parent := range commit.Parents {+ next := make([]walkItem, 0, len(commit.Object().Parents))
+ for _, parent := range commit.Object().Parents { next = append(next, walkItem{id: parent, want: objecttype.TypeInvalid})}
return next, nil
case objecttype.TypeTag:
- content, err := walk.readBytesContent(item.id)
+ tag, err := walk.reachability.fetcher.ExactTag(item.id)
if err != nil {return nil, err
}
- tag, err := objecttag.Parse(content, item.id.Algorithm())
- if err != nil {- return nil, err
- }
-
- return []walkItem{{id: tag.Target, want: objecttype.TypeInvalid}}, nil+ return []walkItem{{id: tag.Object().Target, want: objecttype.TypeInvalid}}, nilcase objecttype.TypeTree, objecttype.TypeBlob, objecttype.TypeInvalid,
objecttype.TypeFuture, objecttype.TypeOfsDelta, objecttype.TypeRefDelta:
return nil, &errors.ObjectTypeError{OID: item.id, Got: ty, Want: objecttype.TypeCommit}--- a/reachability/walk_expand_objects.go
+++ b/reachability/walk_expand_objects.go
@@ -4,14 +4,12 @@
"fmt"
"codeberg.org/lindenii/furgit/errors"
- objectcommit "codeberg.org/lindenii/furgit/object/commit"
- objecttag "codeberg.org/lindenii/furgit/object/tag"
objecttree "codeberg.org/lindenii/furgit/object/tree"
objecttype "codeberg.org/lindenii/furgit/object/type"
)
func (walk *Walk) expandObjects(item walkItem) ([]walkItem, error) {- ty, err := walk.readHeaderType(item.id)
+ ty, _, err := walk.reachability.fetcher.Header(item.id)
if err != nil {return nil, err
}
@@ -24,37 +22,27 @@
case objecttype.TypeBlob:
return nil, nil
case objecttype.TypeCommit:
- content, err := walk.readBytesContent(item.id)
+ commit, err := walk.reachability.fetcher.ExactCommit(item.id)
if err != nil {return nil, err
}
- commit, err := objectcommit.Parse(content, item.id.Algorithm())
- if err != nil {- return nil, err
- }
+ next := make([]walkItem, 0, len(commit.Object().Parents)+1)
- next := make([]walkItem, 0, len(commit.Parents)+1)
-
- next = append(next, walkItem{id: commit.Tree, want: objecttype.TypeTree})- for _, parent := range commit.Parents {+ next = append(next, walkItem{id: commit.Object().Tree, want: objecttype.TypeTree})+ for _, parent := range commit.Object().Parents { next = append(next, walkItem{id: parent, want: objecttype.TypeCommit})}
return next, nil
case objecttype.TypeTree:
- content, err := walk.readBytesContent(item.id)
+ tree, err := walk.reachability.fetcher.ExactTree(item.id)
if err != nil {return nil, err
}
- tree, err := objecttree.Parse(content, item.id.Algorithm())
- if err != nil {- return nil, err
- }
-
- next := make([]walkItem, 0, len(tree.Entries))
- for _, entry := range tree.Entries {+ next := make([]walkItem, 0, len(tree.Object().Entries))
+ for _, entry := range tree.Object().Entries { switch entry.Mode {case objecttree.FileModeGitlink:
continue
@@ -67,17 +55,12 @@
return next, nil
case objecttype.TypeTag:
- content, err := walk.readBytesContent(item.id)
+ tag, err := walk.reachability.fetcher.ExactTag(item.id)
if err != nil {return nil, err
}
- tag, err := objecttag.Parse(content, item.id.Algorithm())
- if err != nil {- return nil, err
- }
-
- return []walkItem{{id: tag.Target, want: tag.TargetType}}, nil+ return []walkItem{{id: tag.Object().Target, want: tag.Object().TargetType}}, nilcase objecttype.TypeInvalid, objecttype.TypeFuture, objecttype.TypeOfsDelta, objecttype.TypeRefDelta:
return nil, &errors.ObjectTypeError{OID: item.id, Got: ty, Want: item.want}}
--- a/reachability/walk_seq.go
+++ b/reachability/walk_seq.go
@@ -37,7 +37,7 @@
item := stack[len(stack)-1]
stack = stack[:len(stack)-1]
- if containsOID(walk.haves, item.id) {+ if _, ok := walk.haves[item.id]; ok {continue
}
--- a/reachability/walk_verify.go
+++ b/reachability/walk_verify.go
@@ -2,13 +2,12 @@
import (
"codeberg.org/lindenii/furgit/errors"
- objectcommit "codeberg.org/lindenii/furgit/object/commit"
objectid "codeberg.org/lindenii/furgit/object/id"
objecttype "codeberg.org/lindenii/furgit/object/type"
)
func (walk *Walk) validateCommitObject(id objectid.ObjectID) error {- ty, err := walk.readHeaderType(id)
+ ty, _, err := walk.reachability.fetcher.Header(id)
if err != nil {return err
}
@@ -17,12 +16,7 @@
return &errors.ObjectTypeError{OID: id, Got: ty, Want: objecttype.TypeCommit}}
- content, err := walk.readBytesContent(id)
- if err != nil {- return err
- }
-
- _, err = objectcommit.Parse(content, id.Algorithm())
+ _, err = walk.reachability.fetcher.ExactCommit(id)
return err
}
--
⑨