7b978176930366fb768aea0bff634dc166c7f3bf

Author
Ayman Bagabas <ayman.bagabas@gmail.com>
Committer
Ayman Bagabas <ayman.bagabas@gmail.com>
Date

Message

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

Diff

  1diff --git a/pkg/ssh/cmd/tree.go b/pkg/ssh/cmd/tree.go
  2index 6399c3e3f8d021a81de54c734690b6282361053b..aec94e9165d6375058fa800a9474c6576579baf2 100644
  3--- a/pkg/ssh/cmd/tree.go
  4+++ b/pkg/ssh/cmd/tree.go
  5@@ -6,6 +6,7 @@ import (
  6 	"github.com/charmbracelet/soft-serve/git"
  7 	"github.com/charmbracelet/soft-serve/pkg/backend"
  8 	"github.com/charmbracelet/soft-serve/pkg/proto"
  9+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 10 	"github.com/dustin/go-humanize"
 11 	"github.com/spf13/cobra"
 12 )
 13@@ -93,7 +94,7 @@ func treeCommand() *cobra.Command {
 14 				} else {
 15 					ssize = humanize.Bytes(uint64(size))
 16 				}
 17-				cmd.Printf("%s\t%s\t %s\n", ent.Mode(), ssize, ent.Name())
 18+				cmd.Printf("%s\t%s\t %s\n", ent.Mode(), ssize, common.UnquoteFilename(ent.Name()))
 19 			}
 20 			return nil
 21 		},
 22diff --git a/pkg/ui/common/format.go b/pkg/ui/common/format.go
 23index 8402737969c26740131a7c26f9fd762be4df76d9..4344e057d8cfba2478b977a34f01a1d28c1cc6d2 100644
 24--- a/pkg/ui/common/format.go
 25+++ b/pkg/ui/common/format.go
 26@@ -2,6 +2,7 @@ package common
 27 
 28 import (
 29 	"fmt"
 30+	"strconv"
 31 	"strings"
 32 
 33 	"github.com/alecthomas/chroma/v2/lexers"
 34@@ -54,3 +55,17 @@ func FormatHighlight(p, c string) (string, error) {
 35 	}
 36 	return r.String(), nil
 37 }
 38+
 39+// UnquoteFilename unquotes a filename.
 40+// When Git is with "core.quotePath" set to "true" (default), it will quote
 41+// the filename with double quotes if it contains control characters or unicode.
 42+// this function will unquote the filename.
 43+func UnquoteFilename(s string) string {
 44+	name := s
 45+	if n, err := strconv.Unquote(`"` + s + `"`); err == nil {
 46+		name = n
 47+	}
 48+
 49+	name = strconv.Quote(name)
 50+	return strings.Trim(name, `"`)
 51+}
 52diff --git a/pkg/ui/pages/repo/filesitem.go b/pkg/ui/pages/repo/filesitem.go
 53index fde57de8c380a22932cf3992d6cc3b2cfd1f0e11..eb59313dba0b3356fe345dfa33b474a4a673474a 100644
 54--- a/pkg/ui/pages/repo/filesitem.go
 55+++ b/pkg/ui/pages/repo/filesitem.go
 56@@ -4,7 +4,6 @@ import (
 57 	"fmt"
 58 	"io"
 59 	"io/fs"
 60-	"strconv"
 61 	"strings"
 62 
 63 	"github.com/charmbracelet/bubbles/key"
 64@@ -23,16 +22,12 @@ type FileItem struct {
 65 
 66 // ID returns the ID of the file item.
 67 func (i FileItem) ID() string {
 68-	name := i.entry.Name()
 69-	if n, err := strconv.Unquote(name); err == nil {
 70-		name = n
 71-	}
 72-	return name
 73+	return i.entry.Name()
 74 }
 75 
 76 // Title returns the title of the file item.
 77 func (i FileItem) Title() string {
 78-	return i.entry.Name()
 79+	return common.UnquoteFilename(i.entry.Name())
 80 }
 81 
 82 // Description returns the description of the file item.
 83diff --git a/testscript/testdata/repo-tree.txtar b/testscript/testdata/repo-tree.txtar
 84index bc00ef03162484262b4f65707c95d4a7cfa8d94d..b3e6320de5f84429277f4f41829db9ee4544253f 100644
 85--- a/testscript/testdata/repo-tree.txtar
 86+++ b/testscript/testdata/repo-tree.txtar
 87@@ -1,7 +1,7 @@
 88 # vi: set ft=conf
 89 
 90 # convert crlf to lf on windows
 91-[windows] dos2unix tree1.txt tree2.txt tree3.txt
 92+[windows] dos2unix tree1.txt tree2.txt tree3.txt tree4.txt
 93 
 94 # start soft serve
 95 exec soft serve &
 96@@ -47,6 +47,18 @@ stderr 'file not found'
 97 ! stdout .
 98 stderr 'revision does not exist'
 99 
100+# test unicode file name issue #457
101+soft repo create repo4
102+git clone ssh://localhost:$SSH_PORT/repo4 repo4
103+mkfile ./repo4/๐Ÿ•.md '๐Ÿ•'
104+git -C repo4 add -A
105+git -C repo4 commit -m 'unicode'
106+git -C repo4 push origin HEAD
107+
108+# print root tree
109+soft repo tree repo4
110+cmp stdout tree4.txt
111+
112 # stop the server
113 [windows] stopserver
114 
115@@ -59,3 +71,5 @@ drwxrwxrwx	-	 folder
116 -rw-r--r--	5 B	 aa.md
117 -- tree3.txt --
118 -rw-r--r--	2 B	 b.md
119+-- tree4.txt --
120+-rw-r--r--	4 B	 ๐Ÿ•.md