aboutsummaryrefslogtreecommitdiff
path: root/reachability/walk_expand_objects.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-06 10:59:53 +0800
committerGravatar Runxi Yu2026-03-06 10:59:53 +0800
commit95f8f3d45fe077042df4fd4afa73d4e419bc9974 (patch)
tree1e650b788eb4fbe5fc61ad0df700de58ebba40c5 /reachability/walk_expand_objects.go
parentformat/commitgraph: Split layer files (diff)
signatureNo signature
reachability: Split walk files
Diffstat (limited to 'reachability/walk_expand_objects.go')
-rw-r--r--reachability/walk_expand_objects.go83
1 files changed, 83 insertions, 0 deletions
diff --git a/reachability/walk_expand_objects.go b/reachability/walk_expand_objects.go
new file mode 100644
index 00000000..97cab79c
--- /dev/null
+++ b/reachability/walk_expand_objects.go
@@ -0,0 +1,83 @@
+package reachability
+
+import (
+ "fmt"
+
+ "codeberg.org/lindenii/furgit/object"
+ "codeberg.org/lindenii/furgit/objecttype"
+)
+
+func (walk *Walk) expandObjects(item walkItem) ([]walkItem, error) {
+ ty, err := walk.readHeaderType(item.id)
+ if err != nil {
+ return nil, err
+ }
+
+ if item.want != objecttype.TypeInvalid && ty != item.want {
+ return nil, &ErrObjectType{OID: item.id, Got: ty, Want: item.want}
+ }
+
+ switch ty {
+ case objecttype.TypeBlob:
+ return nil, nil
+ case objecttype.TypeCommit:
+ content, err := walk.readBytesContent(item.id)
+ if err != nil {
+ return nil, err
+ }
+
+ commit, err := object.ParseCommit(content, item.id.Algorithm())
+ if err != nil {
+ return nil, err
+ }
+
+ 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: parent, want: objecttype.TypeCommit})
+ }
+
+ return next, nil
+ case objecttype.TypeTree:
+ content, err := walk.readBytesContent(item.id)
+ if err != nil {
+ return nil, err
+ }
+
+ tree, err := object.ParseTree(content, item.id.Algorithm())
+ if err != nil {
+ return nil, err
+ }
+
+ next := make([]walkItem, 0, len(tree.Entries))
+ for _, entry := range tree.Entries {
+ switch entry.Mode {
+ case object.FileModeGitlink:
+ continue
+ case object.FileModeDir:
+ next = append(next, walkItem{id: entry.ID, want: objecttype.TypeTree})
+ case object.FileModeRegular, object.FileModeExecutable, object.FileModeSymlink:
+ next = append(next, walkItem{id: entry.ID, want: objecttype.TypeBlob})
+ }
+ }
+
+ return next, nil
+ case objecttype.TypeTag:
+ content, err := walk.readBytesContent(item.id)
+ if err != nil {
+ return nil, err
+ }
+
+ tag, err := object.ParseTag(content, item.id.Algorithm())
+ if err != nil {
+ return nil, err
+ }
+
+ return []walkItem{{id: tag.Target, want: tag.TargetType}}, nil
+ case objecttype.TypeInvalid, objecttype.TypeFuture, objecttype.TypeOfsDelta, objecttype.TypeRefDelta:
+ return nil, &ErrObjectType{OID: item.id, Got: ty, Want: item.want}
+ }
+
+ return nil, fmt.Errorf("reachability: unreachable object type %d", ty)
+}