aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/object/tree.go
diff options
context:
space:
mode:
authoryiteng.nyt <yiteng.nyt@alibaba-inc.com>2023-12-13 12:04:51 +0800
committeryiteng.nyt <yiteng.nyt@alibaba-inc.com>2024-03-08 17:12:43 +0800
commit1d4bec06f4538a4f9f6000eaf5a17921dc1b5128 (patch)
tree884b98f8daf8297dff9b9f836aa8d03dd6a22206 /plumbing/object/tree.go
parentf5d118c19c0ff1f15e1f5cf9129d1837ecdeee39 (diff)
downloadgo-git-1d4bec06f4538a4f9f6000eaf5a17921dc1b5128.tar.gz
plumbing: object, check entry order in (*Tree).Encode, export TreeEntrySorter
Diffstat (limited to 'plumbing/object/tree.go')
-rw-r--r--plumbing/object/tree.go29
1 files changed, 29 insertions, 0 deletions
diff --git a/plumbing/object/tree.go b/plumbing/object/tree.go
index 7fe773d..0fd0e51 100644
--- a/plumbing/object/tree.go
+++ b/plumbing/object/tree.go
@@ -7,6 +7,7 @@ import (
"io"
"path"
"path/filepath"
+ "sort"
"strings"
"github.com/go-git/go-git/v5/plumbing"
@@ -27,6 +28,7 @@ var (
ErrFileNotFound = errors.New("file not found")
ErrDirectoryNotFound = errors.New("directory not found")
ErrEntryNotFound = errors.New("entry not found")
+ ErrEntriesNotSorted = errors.New("entries in tree are not sorted")
)
// Tree is basically like a directory - it references a bunch of other trees
@@ -270,6 +272,28 @@ func (t *Tree) Decode(o plumbing.EncodedObject) (err error) {
return nil
}
+type TreeEntrySorter []TreeEntry
+
+func (s TreeEntrySorter) Len() int {
+ return len(s)
+}
+
+func (s TreeEntrySorter) Less(i, j int) bool {
+ name1 := s[i].Name
+ name2 := s[j].Name
+ if s[i].Mode == filemode.Dir {
+ name1 += "/"
+ }
+ if s[j].Mode == filemode.Dir {
+ name2 += "/"
+ }
+ return name1 < name2
+}
+
+func (s TreeEntrySorter) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
// Encode transforms a Tree into a plumbing.EncodedObject.
func (t *Tree) Encode(o plumbing.EncodedObject) (err error) {
o.SetType(plumbing.TreeObject)
@@ -279,6 +303,11 @@ func (t *Tree) Encode(o plumbing.EncodedObject) (err error) {
}
defer ioutil.CheckClose(w, &err)
+
+ if !sort.IsSorted(TreeEntrySorter(t.Entries)) {
+ return ErrEntriesNotSorted
+ }
+
for _, entry := range t.Entries {
if strings.IndexByte(entry.Name, 0) != -1 {
return fmt.Errorf("malformed filename %q", entry.Name)