Skip to content

Commit b0ab652

Browse files
stefanhallerjesseduffield
authored andcommitted
Escape special characters when git-ignoring files
1 parent 41f89d8 commit b0ab652

File tree

2 files changed

+9
-23
lines changed

2 files changed

+9
-23
lines changed

pkg/commands/git_commands/working_tree.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"os"
66
"path/filepath"
7+
"regexp"
78

89
"github.com/go-errors/errors"
910
"github.com/jesseduffield/lazygit/pkg/commands/models"
@@ -230,15 +231,21 @@ func (self *WorkingTreeCommands) DiscardUnstagedFileChanges(file *models.File) e
230231
return self.cmd.New(cmdArgs).Run()
231232
}
232233

234+
// Escapes special characters in a filename for gitignore and exclude files
235+
func escapeFilename(filename string) string {
236+
re := regexp.MustCompile(`^[!#]|[\[\]*]`)
237+
return re.ReplaceAllString(filename, `\${0}`)
238+
}
239+
233240
// Ignore adds a file to the gitignore for the repo
234241
func (self *WorkingTreeCommands) Ignore(filename string) error {
235-
return self.os.AppendLineToFile(".gitignore", filename)
242+
return self.os.AppendLineToFile(".gitignore", escapeFilename(filename))
236243
}
237244

238245
// Exclude adds a file to the .git/info/exclude for the repo
239246
func (self *WorkingTreeCommands) Exclude(filename string) error {
240247
excludeFile := filepath.Join(self.repoPaths.repoGitDirPath, "info", "exclude")
241-
return self.os.AppendLineToFile(excludeFile, filename)
248+
return self.os.AppendLineToFile(excludeFile, escapeFilename(filename))
242249
}
243250

244251
// WorktreeFileDiff returns the diff of a file

pkg/integration/tests/file/gitignore_special_characters.go

-21
Original file line numberDiff line numberDiff line change
@@ -55,33 +55,12 @@ var GitignoreSpecialCharacters = NewIntegrationTest(NewIntegrationTestArgs{
5555
excludeFile("file[x]")
5656

5757
t.Views().Files().
58-
/* EXPECTED:
5958
Lines(
6059
Equals("▼ /"),
6160
Equals(" ?? .gitignore"),
6261
Equals(" ?? abc_def"),
6362
)
64-
ACTUAL:
65-
As you can see, it did ignore the 'file!abc' and 'file#abc' files
66-
correctly. Those don't need to be quoted because # and ! are only
67-
special at the beginning.
6863

69-
Most of the other files are not ignored properly because their
70-
special characters need to be escaped. For * it's the other way
71-
round: while it does hide 'abc*def', it also hides 'abc_def',
72-
which we don't want.
73-
*/
74-
Lines(
75-
Equals("▼ /"),
76-
Equals(" ?? !file"),
77-
Equals(" ?? #file"),
78-
Equals(" ?? .gitignore"),
79-
Equals(" ?? file[x]"),
80-
)
81-
82-
/* EXPECTED:
8364
t.FileSystem().FileContent(".gitignore", Equals("\\#file\nfile#abc\n\\!file\nfile!abc\nabc\\*def\nfile\\[x\\]\n"))
84-
ACTUAL: */
85-
t.FileSystem().FileContent(".gitignore", Equals("#file\nfile#abc\n!file\nfile!abc\nabc*def\nfile[x]\n"))
8665
},
8766
})

0 commit comments

Comments
 (0)