git: walk the path in 'cat' splitting only on '/', the api treats a backslash as a separator and returned a different file's contents.

This commit is contained in:
Yasuhiro Matsumoto
2026-08-29 00:08:11 +09:00
parent 6fe511be6c
commit 99c4b52a9a

38
git.go
View File

@@ -717,19 +717,43 @@ aside from those, there is also:
continue
}
entry, err := gitnaturalapi.GetObjectByPath(url, commit, path)
// the path is walked here instead of with GetObjectByPath()
// because that also treats '\' as a separator, while in git
// path names a backslash is just a regular character
segments := strings.Split(strings.Trim(path, "/"), "/")
name := segments[len(segments)-1]
depth := len(segments)
tree, err := gitnaturalapi.GetDirectoryTreeAt(url, commit, &depth)
if err != nil {
lastErr = err
continue
}
if entry == nil {
return fmt.Errorf("path '%s' not found", path)
}
if entry.IsDir {
return fmt.Errorf("path '%s' is a directory", path)
if len(segments) > 1 {
tree, err = gitTreeAtPath(tree, strings.Join(segments[:len(segments)-1], "/"))
if err != nil {
return err
}
}
obj, err := gitnaturalapi.GetObject(url, entry.Hash)
hash := ""
for _, file := range tree.Files {
if file.Name == name {
hash = file.Hash
break
}
}
if hash == "" {
for _, dir := range tree.Directories {
if dir.Name == name {
return fmt.Errorf("path '%s' is a directory", path)
}
}
return fmt.Errorf("path '%s' not found", path)
}
obj, err := gitnaturalapi.GetObject(url, hash)
if err != nil {
lastErr = fmt.Errorf("download error: %s", err)
continue