ref: 2e44bb34cf9b4d8b0ce809c4da29880633ba659a
parent: 397eb22166afa8cd273dbd0decdcb2ac7f2d34df
author: Runxi Yu <me@runxiyu.org>
date: Thu Jan 29 17:10:39 EST 2026
tree: Add InsertEntry and RemoveEntry
--- a/obj_tree.go
+++ b/obj_tree.go
@@ -4,6 +4,7 @@
"bytes"
"errors"
"fmt"
+ "sort"
"strconv"
)
@@ -216,6 +217,46 @@
}
}
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 {--
⑨