aboutsummaryrefslogtreecommitdiff
path: root/obj_tree.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-01-29 22:10:39 +0100
committerGravatar Runxi Yu2026-01-29 22:10:39 +0100
commit2e44bb34cf9b4d8b0ce809c4da29880633ba659a (patch)
tree8eed0dfa789cc8016fe3807d1a534c554bce6dcb /obj_tree.go
parentobj, loose: Add Object.Serialize() interface (diff)
signatureNo signature
tree: Add InsertEntry and RemoveEntry
Diffstat (limited to 'obj_tree.go')
-rw-r--r--obj_tree.go41
1 files changed, 41 insertions, 0 deletions
diff --git a/obj_tree.go b/obj_tree.go
index 07c77441..2475b237 100644
--- a/obj_tree.go
+++ b/obj_tree.go
@@ -4,6 +4,7 @@ import (
"bytes"
"errors"
"fmt"
+ "sort"
"strconv"
)
@@ -218,6 +219,46 @@ func (tree *Tree) entry(name []byte, searchIsTree bool) *TreeEntry {
return nil
}
+// InsertEntry inserts a tree entry while preserving Git's name ordering.
+// It returns an error if an entry with the same name already exists.
+func (tree *Tree) InsertEntry(newEntry TreeEntry) error {
+ if tree == nil {
+ return ErrInvalidObject
+ }
+ for _, entry := range tree.Entries {
+ if bytes.Equal(entry.Name, newEntry.Name) {
+ return fmt.Errorf("furgit: tree: entry %q already exists", newEntry.Name)
+ }
+ }
+ newIsTree := newEntry.Mode == FileModeDir
+ insertAt := sort.Search(len(tree.Entries), func(i int) bool {
+ return TreeEntryNameCompare(tree.Entries[i].Name, tree.Entries[i].Mode, newEntry.Name, newIsTree) >= 0
+ })
+ tree.Entries = append(tree.Entries, TreeEntry{})
+ copy(tree.Entries[insertAt+1:], tree.Entries[insertAt:])
+ tree.Entries[insertAt] = newEntry
+ return nil
+}
+
+// RemoveEntry removes a tree entry by name.
+// It returns ErrNotFound if no matching entry exists.
+func (tree *Tree) RemoveEntry(name []byte) error {
+ if tree == nil {
+ return ErrInvalidObject
+ }
+ if len(tree.Entries) == 0 {
+ return ErrNotFound
+ }
+ for i := range tree.Entries {
+ if bytes.Equal(tree.Entries[i].Name, name) {
+ copy(tree.Entries[i:], tree.Entries[i+1:])
+ tree.Entries = tree.Entries[:len(tree.Entries)-1]
+ return nil
+ }
+ }
+ return ErrNotFound
+}
+
func TreeEntryNameCompare(entryName []byte, entryMode FileMode, searchName []byte, searchIsTree bool) int {
isEntryTree := entryMode == FileModeDir