2018-02-10 21:19:26 +03:00
// Copyright 2018 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
2020-12-17 17:00:47 +03:00
// +build !gogit
2018-02-10 21:19:26 +03:00
package git
import (
"bytes"
"fmt"
"strconv"
2021-02-18 00:32:25 +03:00
"strings"
2018-02-10 21:19:26 +03:00
)
2021-02-18 00:32:25 +03:00
// ParseTreeEntries parses the output of a `git ls-tree -l` command.
2018-02-10 21:19:26 +03:00
func ParseTreeEntries ( data [ ] byte ) ( [ ] * TreeEntry , error ) {
return parseTreeEntries ( data , nil )
}
func parseTreeEntries ( data [ ] byte , ptree * Tree ) ( [ ] * TreeEntry , error ) {
entries := make ( [ ] * TreeEntry , 0 , 10 )
for pos := 0 ; pos < len ( data ) ; {
2021-02-18 00:32:25 +03:00
// expect line to be of the form "<mode> <type> <sha> <space-padded-size>\t<filename>"
2018-02-10 21:19:26 +03:00
entry := new ( TreeEntry )
entry . ptree = ptree
if pos + 6 > len ( data ) {
return nil , fmt . Errorf ( "Invalid ls-tree output: %s" , string ( data ) )
}
switch string ( data [ pos : pos + 6 ] ) {
case "100644" :
2020-12-17 17:00:47 +03:00
entry . entryMode = EntryModeBlob
2018-02-10 21:19:26 +03:00
pos += 12 // skip over "100644 blob "
case "100755" :
2020-12-17 17:00:47 +03:00
entry . entryMode = EntryModeExec
2018-02-10 21:19:26 +03:00
pos += 12 // skip over "100755 blob "
case "120000" :
2020-12-17 17:00:47 +03:00
entry . entryMode = EntryModeSymlink
2018-02-10 21:19:26 +03:00
pos += 12 // skip over "120000 blob "
case "160000" :
2020-12-17 17:00:47 +03:00
entry . entryMode = EntryModeCommit
2018-02-10 21:19:26 +03:00
pos += 14 // skip over "160000 object "
case "040000" :
2020-12-17 17:00:47 +03:00
entry . entryMode = EntryModeTree
2018-02-10 21:19:26 +03:00
pos += 12 // skip over "040000 tree "
default :
return nil , fmt . Errorf ( "unknown type: %v" , string ( data [ pos : pos + 6 ] ) )
}
if pos + 40 > len ( data ) {
return nil , fmt . Errorf ( "Invalid ls-tree output: %s" , string ( data ) )
}
id , err := NewIDFromString ( string ( data [ pos : pos + 40 ] ) )
if err != nil {
return nil , fmt . Errorf ( "Invalid ls-tree output: %v" , err )
}
entry . ID = id
pos += 41 // skip over sha and trailing space
2021-02-18 00:32:25 +03:00
end := pos + bytes . IndexByte ( data [ pos : ] , '\t' )
if end < pos {
return nil , fmt . Errorf ( "Invalid ls-tree -l output: %s" , string ( data ) )
}
entry . size , _ = strconv . ParseInt ( strings . TrimSpace ( string ( data [ pos : end ] ) ) , 10 , 64 )
entry . sized = true
pos = end + 1
end = pos + bytes . IndexByte ( data [ pos : ] , '\n' )
2018-02-10 21:19:26 +03:00
if end < pos {
return nil , fmt . Errorf ( "Invalid ls-tree output: %s" , string ( data ) )
}
// In case entry name is surrounded by double quotes(it happens only in git-shell).
if data [ pos ] == '"' {
2020-12-17 17:00:47 +03:00
entry . name , err = strconv . Unquote ( string ( data [ pos : end ] ) )
2018-02-10 21:19:26 +03:00
if err != nil {
return nil , fmt . Errorf ( "Invalid ls-tree output: %v" , err )
}
} else {
2020-12-17 17:00:47 +03:00
entry . name = string ( data [ pos : end ] )
2018-02-10 21:19:26 +03:00
}
pos = end + 1
entries = append ( entries , entry )
}
return entries , nil
}