add nip34/git-natural-api, using the same approach as https://jsr.io/@fiatjaf/git-natural-api.
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
package gitnaturalapi
|
||||
|
||||
import "encoding/hex"
|
||||
|
||||
type TreeEntry struct {
|
||||
Path string
|
||||
Mode string
|
||||
IsDir bool
|
||||
Hash string
|
||||
}
|
||||
|
||||
type TreeFile struct {
|
||||
Name string
|
||||
Hash string
|
||||
Content []byte
|
||||
}
|
||||
|
||||
type TreeDirectory struct {
|
||||
Name string
|
||||
Hash string
|
||||
Content *Tree
|
||||
}
|
||||
|
||||
type Tree struct {
|
||||
Directories []TreeDirectory
|
||||
Files []TreeFile
|
||||
}
|
||||
|
||||
func LoadTree(obj *ParsedObject, objects map[string]*ParsedObject, depth *int) *Tree {
|
||||
directories := make([]TreeDirectory, 0)
|
||||
files := make([]TreeFile, 0)
|
||||
entries := ParseTree(obj.Data)
|
||||
|
||||
for _, entry := range entries {
|
||||
child := objects[entry.Hash]
|
||||
|
||||
if entry.IsDir {
|
||||
var content *Tree
|
||||
if child != nil && (depth == nil || *depth > 0) {
|
||||
var newDepth *int
|
||||
if depth != nil {
|
||||
d := *depth - 1
|
||||
newDepth = &d
|
||||
}
|
||||
content = LoadTree(child, objects, newDepth)
|
||||
}
|
||||
directories = append(directories, TreeDirectory{
|
||||
Name: entry.Path,
|
||||
Hash: entry.Hash,
|
||||
Content: content,
|
||||
})
|
||||
} else {
|
||||
var content []byte
|
||||
if child != nil {
|
||||
content = child.Data
|
||||
}
|
||||
files = append(files, TreeFile{
|
||||
Name: entry.Path,
|
||||
Hash: entry.Hash,
|
||||
Content: content,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &Tree{Directories: directories, Files: files}
|
||||
}
|
||||
|
||||
func ParseTree(treeData []byte) []TreeEntry {
|
||||
entries := make([]TreeEntry, 0)
|
||||
offset := 0
|
||||
|
||||
for offset < len(treeData) {
|
||||
modeEnd := offset
|
||||
for treeData[modeEnd] != 0x20 {
|
||||
modeEnd++
|
||||
}
|
||||
mode := string(treeData[offset:modeEnd])
|
||||
offset = modeEnd + 1
|
||||
|
||||
filenameEnd := offset
|
||||
for treeData[filenameEnd] != 0x00 {
|
||||
filenameEnd++
|
||||
}
|
||||
path := string(treeData[offset:filenameEnd])
|
||||
offset = filenameEnd + 1
|
||||
|
||||
hash := hex.EncodeToString(treeData[offset : offset+20])
|
||||
offset += 20
|
||||
|
||||
isDir := mode == "40000" || mode == "040000"
|
||||
|
||||
entries = append(entries, TreeEntry{
|
||||
Mode: mode,
|
||||
Path: path,
|
||||
Hash: hash,
|
||||
IsDir: isDir,
|
||||
})
|
||||
}
|
||||
|
||||
return entries
|
||||
}
|
||||
Reference in New Issue
Block a user