Skip to content

Commit fc421da

Browse files
committed
track: provide an option to handle paths literally
Normally, the arguments to "git lfs track" are taken as glob patterns. This is generally useful, but sometimes there are filenames that contain special characters. Add a "--filename" option that forces arguments to be taken as literal paths instead of glob patterns to make handling these files easier. In the test helpers, pass -F to grep so that our unusual file names don't trigger undesired pattern matching. This has no effect on other tests, as they all pass a literal filename here.
1 parent 277940a commit fc421da

File tree

4 files changed

+51
-1
lines changed

4 files changed

+51
-1
lines changed

commands/command_track.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ var (
2727
trackDryRunFlag bool
2828
trackNoModifyAttrsFlag bool
2929
trackNoExcludedFlag bool
30+
trackFilenameFlag bool
3031
)
3132

3233
func trackCommand(cmd *cobra.Command, args []string) {
@@ -95,6 +96,13 @@ ArgsLoop:
9596
lockableArg = " " + git.LockableAttrib
9697
}
9798

99+
if trackFilenameFlag {
100+
// We need to do this after escapeAttrPattern since that
101+
// function turns backslashes into slashes.
102+
encodedArg = escapeGlobCharacters(encodedArg)
103+
pattern = escapeGlobCharacters(pattern)
104+
}
105+
98106
changedAttribLines[pattern] = fmt.Sprintf("%s filter=lfs diff=lfs merge=lfs -text%v%s", encodedArg, lockableArg, lineEnd)
99107

100108
if trackLockableFlag {
@@ -290,8 +298,16 @@ var (
290298
" ": "[[:space:]]",
291299
"#": "\\#",
292300
}
301+
trackEscapeStrings = []string{"*", "[", "]", "?"}
293302
)
294303

304+
func escapeGlobCharacters(s string) string {
305+
for _, ch := range trackEscapeStrings {
306+
s = strings.Replace(s, ch, fmt.Sprintf("\\%s", ch), -1)
307+
}
308+
return s
309+
}
310+
295311
func escapeAttrPattern(unescaped string) string {
296312
var escaped string = strings.Replace(unescaped, `\`, "/", -1)
297313

@@ -320,5 +336,6 @@ func init() {
320336
cmd.Flags().BoolVarP(&trackDryRunFlag, "dry-run", "d", false, "preview results of running `git lfs track`")
321337
cmd.Flags().BoolVarP(&trackNoModifyAttrsFlag, "no-modify-attrs", "", false, "skip modifying .gitattributes file")
322338
cmd.Flags().BoolVarP(&trackNoExcludedFlag, "no-excluded", "", false, "skip listing excluded paths")
339+
cmd.Flags().BoolVarP(&trackFilenameFlag, "filename", "", false, "treat this pattern as a literal filename")
323340
})
324341
}

docs/man/git-lfs-track.1.ronn

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ to match paths.
3131

3232
Disabled by default.
3333

34+
* `--filename`
35+
Treat the arguments as literal filenames, not as patterns. Any special glob
36+
characters in the filename will be escaped when writing the `.gitattributes`
37+
file.
38+
3439
* `--lockable` `-l`
3540
Make the paths 'lockable', meaning they should be locked to edit them, and
3641
will be made read-only in the working copy when not locked.

t/t-track.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,3 +653,31 @@ begin_test "track: escaped pattern in .gitattributes"
653653
fi
654654
)
655655
end_test
656+
657+
begin_test "track: escaped glob pattern in .gitattributes"
658+
(
659+
set -e
660+
661+
# None of these characters are valid in the Win32 subsystem.
662+
[ "$IS_WINDOWS" -eq 1 ] && exit 0
663+
664+
reponame="track-escaped-glob"
665+
git init "$reponame"
666+
cd "$reponame"
667+
668+
filename='*[foo]bar?.txt'
669+
contents='I need escaping'
670+
contents_oid=$(calc_oid "$contents")
671+
672+
git lfs track --filename "$filename"
673+
git add .
674+
cat .gitattributes
675+
676+
printf "%s" "$contents" > "$filename"
677+
git add .
678+
git commit -m 'Add unusually named file'
679+
680+
# If Git understood our escaping, we'll have a pointer. Otherwise, we won't.
681+
assert_pointer "master" "$filename" "$contents_oid" 15
682+
)
683+
end_test

t/testhelpers.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ assert_pointer() {
1414
while read -r -d $'\0' x; do
1515
echo $x
1616
done |
17-
grep "$path" | cut -f 3 -d " ")
17+
grep -F "$path" | cut -f 3 -d " ")
1818

1919
actual=$(git cat-file -p $gitblob)
2020
expected=$(pointer $oid $size)

0 commit comments

Comments
 (0)