7
7
"io"
8
8
"path"
9
9
"path/filepath"
10
+ "sort"
10
11
"strings"
11
12
12
13
"github.com/go-git/go-git/v5/plumbing"
27
28
ErrFileNotFound = errors .New ("file not found" )
28
29
ErrDirectoryNotFound = errors .New ("directory not found" )
29
30
ErrEntryNotFound = errors .New ("entry not found" )
31
+ ErrEntriesNotSorted = errors .New ("entries in tree are not sorted" )
30
32
)
31
33
32
34
// 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) {
270
272
return nil
271
273
}
272
274
275
+ type TreeEntrySorter []TreeEntry
276
+
277
+ func (s TreeEntrySorter ) Len () int {
278
+ return len (s )
279
+ }
280
+
281
+ func (s TreeEntrySorter ) Less (i , j int ) bool {
282
+ name1 := s [i ].Name
283
+ name2 := s [j ].Name
284
+ if s [i ].Mode == filemode .Dir {
285
+ name1 += "/"
286
+ }
287
+ if s [j ].Mode == filemode .Dir {
288
+ name2 += "/"
289
+ }
290
+ return name1 < name2
291
+ }
292
+
293
+ func (s TreeEntrySorter ) Swap (i , j int ) {
294
+ s [i ], s [j ] = s [j ], s [i ]
295
+ }
296
+
273
297
// Encode transforms a Tree into a plumbing.EncodedObject.
274
298
func (t * Tree ) Encode (o plumbing.EncodedObject ) (err error ) {
275
299
o .SetType (plumbing .TreeObject )
@@ -279,7 +303,15 @@ func (t *Tree) Encode(o plumbing.EncodedObject) (err error) {
279
303
}
280
304
281
305
defer ioutil .CheckClose (w , & err )
306
+
307
+ if ! sort .IsSorted (TreeEntrySorter (t .Entries )) {
308
+ return ErrEntriesNotSorted
309
+ }
310
+
282
311
for _ , entry := range t .Entries {
312
+ if strings .IndexByte (entry .Name , 0 ) != - 1 {
313
+ return fmt .Errorf ("malformed filename %q" , entry .Name )
314
+ }
283
315
if _ , err = fmt .Fprintf (w , "%o %s" , entry .Mode , entry .Name ); err != nil {
284
316
return err
285
317
}
0 commit comments