Convert octal notation file names in Git (#380)

This commit is contained in:
Thomas Miceli 2024-11-17 18:09:44 +01:00 committed by GitHub
parent 92bac3bf8c
commit c1e046f428
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 64 additions and 11 deletions

View file

@ -6,6 +6,7 @@ import (
"context"
"fmt"
"io"
"net/url"
"os"
"os/exec"
"path"
@ -115,6 +116,9 @@ func GetFilesOfRepository(user string, gist string, revision string) ([]string,
}
slice := strings.Split(string(stdout), "\n")
for i, s := range slice {
slice[i] = convertOctalToUTF8(s)
}
return slice[:len(slice)-1], nil
}
@ -153,7 +157,7 @@ func CatFileBatch(user string, gist string, revision string, truncate bool) ([]*
fileMap = append(fileMap, &catFileBatch{
Hash: hash,
Size: size,
Name: name,
Name: convertOctalToUTF8(name),
})
}
@ -249,7 +253,7 @@ func GetFileContent(user string, gist string, revision string, filename string,
"git",
"--no-pager",
"show",
revision+":"+filename,
revision+":"+convertURLToOctal(filename),
)
cmd.Dir = repositoryPath
@ -273,7 +277,7 @@ func GetFileSize(user string, gist string, revision string, filename string) (ui
"git",
"cat-file",
"-s",
revision+":"+filename,
revision+":"+convertURLToOctal(filename),
)
cmd.Dir = repositoryPath
@ -565,6 +569,48 @@ func removeFilesExceptGit(dir string) error {
})
}
func convertOctalToUTF8(name string) string {
name = strings.Trim(name, `"`)
utf8Name, err := strconv.Unquote(name)
if err != nil {
utf8Name, err = strconv.Unquote(`"` + name + `"`)
if err != nil {
return name
}
}
return utf8Name
}
func convertUTF8ToOctal(name string) string {
if strings.Contains(name, "\\") {
return name
}
needsQuoting := false
for _, r := range name {
if r > 127 {
needsQuoting = true
break
}
}
if !needsQuoting {
return name
}
quoted := fmt.Sprintf("%q", name)
return strings.Trim(quoted, `"`)
}
func convertURLToOctal(name string) string {
decoded, err := url.QueryUnescape(name)
if err != nil {
return name
}
return convertUTF8ToOctal(decoded)
}
const hookTemplate = `#!/bin/sh
"$OG_OPENGIST_HOME_INTERNAL/symlinks/opengist" --config=$OG_OPENGIST_HOME_INTERNAL/symlinks/config.yml hook %s
`

View file

@ -61,11 +61,12 @@ func TestContent(t *testing.T) {
"my_other_file.txt": `I really
hate Opengist`,
"rip.txt": "byebye",
"中文名.txt": "中文内容",
})
files, err := GetFilesOfRepository("thomas", "gist1", "HEAD")
require.NoError(t, err, "Could not get files of repository")
require.Subset(t, []string{"my_file.txt", "my_other_file.txt", "rip.txt"}, files, "Files are not correct")
require.Subset(t, []string{"my_file.txt", "my_other_file.txt", "rip.txt", "中文名.txt"}, files, "Files are not correct")
content, truncated, err := GetFileContent("thomas", "gist1", "HEAD", "my_file.txt", false)
require.NoError(t, err, "Could not get content")
@ -77,16 +78,22 @@ hate Opengist`,
require.False(t, truncated, "Content should not be truncated")
require.Equal(t, "I really\nhate Opengist", content, "Content is not correct")
content, truncated, err = GetFileContent("thomas", "gist1", "HEAD", "中文名.txt", false)
require.NoError(t, err, "Could not get content")
require.False(t, truncated, "Content should not be truncated")
require.Equal(t, "中文内容", content, "Content is not correct")
CommitToBare(t, "thomas", "gist1", map[string]string{
"my_renamed_file.txt": "I love Opengist\n",
"my_other_file.txt": `I really
like Opengist actually`,
"new_file.txt": "Wait now there is a new file",
"中文名.txt": "中文内容",
})
files, err = GetFilesOfRepository("thomas", "gist1", "HEAD")
require.NoError(t, err, "Could not get files of repository")
require.Subset(t, []string{"my_renamed_file.txt", "my_other_file.txt", "new_file.txt"}, files, "Files are not correct")
require.Subset(t, []string{"my_renamed_file.txt", "my_other_file.txt", "new_file.txt", "中文名.txt"}, files, "Files are not correct")
content, truncated, err = GetFileContent("thomas", "gist1", "HEAD", "my_other_file.txt", false)
require.NoError(t, err, "Could not get content")

View file

@ -193,28 +193,28 @@ loopLog:
case strings.HasPrefix(line, "dissimilarity index"):
continue
case strings.HasPrefix(line, "rename from "):
currentFile.OldFilename = line[12 : len(line)-1]
currentFile.OldFilename = convertOctalToUTF8(line[12 : len(line)-1])
case strings.HasPrefix(line, "rename to "):
currentFile.Filename = line[10 : len(line)-1]
currentFile.Filename = convertOctalToUTF8(line[10 : len(line)-1])
parseRename = false
case strings.HasPrefix(line, "copy from "):
currentFile.OldFilename = line[10 : len(line)-1]
currentFile.OldFilename = convertOctalToUTF8(line[10 : len(line)-1])
case strings.HasPrefix(line, "copy to "):
currentFile.Filename = line[8 : len(line)-1]
currentFile.Filename = convertOctalToUTF8(line[8 : len(line)-1])
parseRename = false
case strings.HasPrefix(line, "new file"):
currentFile.IsCreated = true
case strings.HasPrefix(line, "deleted file"):
currentFile.IsDeleted = true
case strings.HasPrefix(line, "--- "):
name := line[4 : len(line)-1]
name := convertOctalToUTF8(line[4 : len(line)-1])
if parseRename && currentFile.IsDeleted {
currentFile.Filename = name[2:]
} else if parseRename && strings.HasPrefix(name, "a/") {
currentFile.OldFilename = name[2:]
}
case strings.HasPrefix(line, "+++ "):
name := line[4 : len(line)-1]
name := convertOctalToUTF8(line[4 : len(line)-1])
if parseRename && strings.HasPrefix(name, "b/") {
currentFile.Filename = name[2:]
}