diff --git a/pkg/ssh/cmd/tree.go b/pkg/ssh/cmd/tree.go index 6399c3e3f8d021a81de54c734690b6282361053b..aec94e9165d6375058fa800a9474c6576579baf2 100644 --- a/pkg/ssh/cmd/tree.go +++ b/pkg/ssh/cmd/tree.go @@ -6,6 +6,7 @@ import ( "github.com/charmbracelet/soft-serve/git" "github.com/charmbracelet/soft-serve/pkg/backend" "github.com/charmbracelet/soft-serve/pkg/proto" + "github.com/charmbracelet/soft-serve/pkg/ui/common" "github.com/dustin/go-humanize" "github.com/spf13/cobra" ) @@ -93,7 +94,7 @@ func treeCommand() *cobra.Command { } else { ssize = humanize.Bytes(uint64(size)) } - cmd.Printf("%s\t%s\t %s\n", ent.Mode(), ssize, ent.Name()) + cmd.Printf("%s\t%s\t %s\n", ent.Mode(), ssize, common.UnquoteFilename(ent.Name())) } return nil }, diff --git a/pkg/ui/common/format.go b/pkg/ui/common/format.go index 8402737969c26740131a7c26f9fd762be4df76d9..4344e057d8cfba2478b977a34f01a1d28c1cc6d2 100644 --- a/pkg/ui/common/format.go +++ b/pkg/ui/common/format.go @@ -2,6 +2,7 @@ package common import ( "fmt" + "strconv" "strings" "github.com/alecthomas/chroma/v2/lexers" @@ -54,3 +55,17 @@ func FormatHighlight(p, c string) (string, error) { } return r.String(), nil } + +// UnquoteFilename unquotes a filename. +// When Git is with "core.quotePath" set to "true" (default), it will quote +// the filename with double quotes if it contains control characters or unicode. +// this function will unquote the filename. +func UnquoteFilename(s string) string { + name := s + if n, err := strconv.Unquote(`"` + s + `"`); err == nil { + name = n + } + + name = strconv.Quote(name) + return strings.Trim(name, `"`) +} diff --git a/pkg/ui/pages/repo/filesitem.go b/pkg/ui/pages/repo/filesitem.go index fde57de8c380a22932cf3992d6cc3b2cfd1f0e11..eb59313dba0b3356fe345dfa33b474a4a673474a 100644 --- a/pkg/ui/pages/repo/filesitem.go +++ b/pkg/ui/pages/repo/filesitem.go @@ -4,7 +4,6 @@ import ( "fmt" "io" "io/fs" - "strconv" "strings" "github.com/charmbracelet/bubbles/key" @@ -23,16 +22,12 @@ type FileItem struct { // ID returns the ID of the file item. func (i FileItem) ID() string { - name := i.entry.Name() - if n, err := strconv.Unquote(name); err == nil { - name = n - } - return name + return i.entry.Name() } // Title returns the title of the file item. func (i FileItem) Title() string { - return i.entry.Name() + return common.UnquoteFilename(i.entry.Name()) } // Description returns the description of the file item. diff --git a/testscript/testdata/repo-tree.txtar b/testscript/testdata/repo-tree.txtar index bc00ef03162484262b4f65707c95d4a7cfa8d94d..b3e6320de5f84429277f4f41829db9ee4544253f 100644 --- a/testscript/testdata/repo-tree.txtar +++ b/testscript/testdata/repo-tree.txtar @@ -1,7 +1,7 @@ # vi: set ft=conf # convert crlf to lf on windows -[windows] dos2unix tree1.txt tree2.txt tree3.txt +[windows] dos2unix tree1.txt tree2.txt tree3.txt tree4.txt # start soft serve exec soft serve & @@ -47,6 +47,18 @@ stderr 'file not found' ! stdout . stderr 'revision does not exist' +# test unicode file name issue #457 +soft repo create repo4 +git clone ssh://localhost:$SSH_PORT/repo4 repo4 +mkfile ./repo4/🍕.md '🍕' +git -C repo4 add -A +git -C repo4 commit -m 'unicode' +git -C repo4 push origin HEAD + +# print root tree +soft repo tree repo4 +cmp stdout tree4.txt + # stop the server [windows] stopserver @@ -59,3 +71,5 @@ drwxrwxrwx - folder -rw-r--r-- 5 B aa.md -- tree3.txt -- -rw-r--r-- 2 B b.md +-- tree4.txt -- +-rw-r--r-- 4 B 🍕.md