aboutsummaryrefslogtreecommitdiff
path: root/object/tree.go
diff options
context:
space:
mode:
Diffstat (limited to 'object/tree.go')
-rw-r--r--object/tree.go163
1 files changed, 0 insertions, 163 deletions
diff --git a/object/tree.go b/object/tree.go
deleted file mode 100644
index 83dcb508..00000000
--- a/object/tree.go
+++ /dev/null
@@ -1,163 +0,0 @@
-package object
-
-import (
- "bytes"
- "fmt"
- "sort"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
- objecttype "codeberg.org/lindenii/furgit/object/type"
-)
-
-// FileMode represents the mode of a file in a Git tree.
-type FileMode uint32
-
-const (
- FileModeDir FileMode = 0o40000
- FileModeRegular FileMode = 0o100644
- FileModeExecutable FileMode = 0o100755
- FileModeSymlink FileMode = 0o120000
- FileModeGitlink FileMode = 0o160000
-)
-
-// TreeEntry represents a single entry in a tree.
-type TreeEntry struct {
- Mode FileMode
- Name []byte
- ID objectid.ObjectID
-}
-
-// Tree represents a Git tree object.
-type Tree struct {
- Entries []TreeEntry
-}
-
-// ObjectType returns TypeTree.
-func (tree *Tree) ObjectType() objecttype.Type {
- _ = tree
-
- return objecttype.TypeTree
-}
-
-// Entry looks up a tree entry by name.
-func (tree *Tree) Entry(name []byte) *TreeEntry {
- if len(tree.Entries) == 0 {
- return nil
- }
-
- if e := tree.entry(name, true); e != nil {
- return e
- }
-
- return tree.entry(name, false)
-}
-
-// InsertEntry inserts a tree entry while preserving Git ordering.
-func (tree *Tree) InsertEntry(newEntry TreeEntry) error {
- if tree.entry(newEntry.Name, true) != nil || tree.entry(newEntry.Name, false) != nil {
- return fmt.Errorf("object: 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.
-func (tree *Tree) RemoveEntry(name []byte) error {
- if len(tree.Entries) == 0 {
- return fmt.Errorf("object: tree: entry %q not found", name)
- }
-
- 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 fmt.Errorf("object: tree: entry %q not found", name)
-}
-
-func (tree *Tree) entry(name []byte, searchIsTree bool) *TreeEntry {
- low, high := 0, len(tree.Entries)-1
- for low <= high {
- mid := low + (high-low)/2
- entry := &tree.Entries[mid]
-
- cmp := TreeEntryNameCompare(entry.Name, entry.Mode, name, searchIsTree)
- if cmp == 0 {
- if bytes.Equal(entry.Name, name) {
- return entry
- }
-
- return nil
- }
-
- if cmp < 0 {
- low = mid + 1
- } else {
- high = mid - 1
- }
- }
-
- return nil
-}
-
-// TreeEntryNameCompare compares names using Git tree ordering rules.
-func TreeEntryNameCompare(entryName []byte, entryMode FileMode, searchName []byte, searchIsTree bool) int {
- isEntryTree := entryMode == FileModeDir
-
- entryLen := len(entryName)
- if isEntryTree {
- entryLen++
- }
-
- searchLen := len(searchName)
- if searchIsTree {
- searchLen++
- }
-
- n := min(searchLen, entryLen)
-
- for i := range n {
- var ec, sc byte
- if i < len(entryName) {
- ec = entryName[i]
- } else {
- ec = '/'
- }
-
- if i < len(searchName) {
- sc = searchName[i]
- } else {
- sc = '/'
- }
-
- if ec < sc {
- return -1
- }
-
- if ec > sc {
- return 1
- }
- }
-
- if entryLen < searchLen {
- return -1
- }
-
- if entryLen > searchLen {
- return 1
- }
-
- return 0
-}