From 7b978176930366fb768aea0bff634dc166c7f3bf Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Fri, 8 Mar 2024 12:51:16 -0500 Subject: [PATCH] fix: unquote git quoted filenames Git core.quotePath is enabled by default and causes unicode in filenames to be quoted. Unquote filenames and requote them to escape control characters BUT not unicode characters. Fixes: https://github.com/charmbracelet/soft-serve/issues/457 --- pkg/ssh/cmd/tree.go | 3 ++- pkg/ui/common/format.go | 15 +++++++++++++++ pkg/ui/pages/repo/filesitem.go | 9 ++------- testscript/testdata/repo-tree.txtar | 16 +++++++++++++++- 4 files changed, 34 insertions(+), 9 deletions(-) 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