I have the following code:
branch, err := gR.LookupBranch(branchName, git.BranchLocal)
if err != nil {
return err
}
defer branch.Free()
commit, err := gR.LookupCommit(branch.Target())
if err != nil {
return err
}
defer commit.Free()
tree, err := gR.LookupTree(commit.TreeId())
if err != nil {
return err
}
defer tree.Free()
err = tree.Walk(func(td string, te *git.TreeEntry) int {
if te.Type == git.ObjectBlob {
fmt.Println(te.Name)
}
return 0
})
This recursively prints out all the files in the repository. For example, if we had the following files in our repo:
test_file.txt
test_file_2.txt
test_folder/test_subfile_1.txt
test_folder/test_subfolder/test_subfile_2.txt
Then it would print:
test_file.txt
test_file2.txt
test_subfile_1.txt
test_subfile_2.txt
Instead, my aim is to print:
test_file.txt
test_file_2.txt
test_folder
But then also be able to choose to start the walk from inside the folder, so be able to print:
test_subfile_1.txt
test_subfolder
How can I achieve this? (The aim is to lazy load a directory structure into a web client i.e. to allow the web client to load contents of folders when the user opens them - also note this is a bare repo)
To avoid entering a given directory, it's enough to return 1
from a function passed to Walk
.
You can save seen directories in an array or a channel.
Example:
func echoFilesCollectDirs(repo *git.Repository, tree *git.Tree, ch chan *git.Tree) {
tree.Walk(func(td string, te *git.TreeEntry) int {
fmt.Println(te.Name)
if te.Type == git.ObjectTree {
t, _ := repo.LookupTree(te.Id)
go func() { ch <- t }() // send tree into channel to process it later
return 1
}
return 0
})
}
func main() {
gR, tree := getRepoAndTree() // returns (*git.Repository, *git.Tree)
ch := make(chan *git.Tree)
echoFilesCollectDirs(gR, tree, ch)
// process next directory in a channel
// t := <-ch
// echoFilesCollectDirs(gR, t, ch)
}
Note: to make the code shorter, I've removed error handling and a boilerplate part that gets *git.Repository
and root *git.Tree
(function getRepoAndTree()
).