commands/track: teach --no-modify-attrs

This commit is contained in:
Taylor Blau 2017-04-24 09:22:33 -06:00
parent d57e97ce28
commit 5af2ba3cc9
3 changed files with 90 additions and 43 deletions

@ -26,6 +26,7 @@ var (
trackNotLockableFlag bool trackNotLockableFlag bool
trackVerboseLoggingFlag bool trackVerboseLoggingFlag bool
trackDryRunFlag bool trackDryRunFlag bool
trackNoModifyAttrsFlag bool
) )
func trackCommand(cmd *cobra.Command, args []string) { func trackCommand(cmd *cobra.Command, args []string) {
@ -66,13 +67,15 @@ func trackCommand(cmd *cobra.Command, args []string) {
ArgsLoop: ArgsLoop:
for _, unsanitizedPattern := range args { for _, unsanitizedPattern := range args {
pattern := cleanRootPath(unsanitizedPattern) pattern := cleanRootPath(unsanitizedPattern)
for _, known := range knownPatterns { if !trackNoModifyAttrsFlag {
if known.Path == filepath.Join(relpath, pattern) && for _, known := range knownPatterns {
((trackLockableFlag && known.Lockable) || // enabling lockable & already lockable (no change) if known.Path == filepath.Join(relpath, pattern) &&
(trackNotLockableFlag && !known.Lockable) || // disabling lockable & not lockable (no change) ((trackLockableFlag && known.Lockable) || // enabling lockable & already lockable (no change)
(!trackLockableFlag && !trackNotLockableFlag)) { // leave lockable as-is in all cases (trackNotLockableFlag && !known.Lockable) || // disabling lockable & not lockable (no change)
Print("%q already supported", pattern) (!trackLockableFlag && !trackNotLockableFlag)) { // leave lockable as-is in all cases
continue ArgsLoop Print("%q already supported", pattern)
continue ArgsLoop
}
} }
} }
@ -98,49 +101,57 @@ ArgsLoop:
// replacing any lines where the values have changed, and appending new lines // replacing any lines where the values have changed, and appending new lines
// change this: // change this:
attribContents, err := ioutil.ReadFile(".gitattributes") var (
// it's fine for file to not exist attribContents []byte
if err != nil && !os.IsNotExist(err) { attributesFile *os.File
Print("Error reading .gitattributes file") )
return if !trackNoModifyAttrsFlag {
} attribContents, err = ioutil.ReadFile(".gitattributes")
// Re-generate the file with merge of old contents and new (to deal with changes) // it's fine for file to not exist
attributesFile, err := os.OpenFile(".gitattributes", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0660) if err != nil && !os.IsNotExist(err) {
if err != nil { Print("Error reading .gitattributes file")
Print("Error opening .gitattributes file") return
return
}
defer attributesFile.Close()
if len(attribContents) > 0 {
scanner := bufio.NewScanner(bytes.NewReader(attribContents))
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
if len(fields) < 1 {
continue
}
pattern := fields[0]
if newline, ok := changedAttribLines[pattern]; ok {
// Replace this line (newline already embedded)
attributesFile.WriteString(newline)
// Remove from map so we know we don't have to add it to the end
delete(changedAttribLines, pattern)
} else {
// Write line unchanged (replace newline)
attributesFile.WriteString(line + lineEnd)
}
} }
// Re-generate the file with merge of old contents and new (to deal with changes)
attributesFile, err = os.OpenFile(".gitattributes", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0660)
if err != nil {
Print("Error opening .gitattributes file")
return
}
defer attributesFile.Close()
// Our method of writing also made sure there's always a newline at end if len(attribContents) > 0 {
scanner := bufio.NewScanner(bytes.NewReader(attribContents))
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
if len(fields) < 1 {
continue
}
pattern := fields[0]
if newline, ok := changedAttribLines[pattern]; ok {
// Replace this line (newline already embedded)
attributesFile.WriteString(newline)
// Remove from map so we know we don't have to add it to the end
delete(changedAttribLines, pattern)
} else {
// Write line unchanged (replace newline)
attributesFile.WriteString(line + lineEnd)
}
}
// Our method of writing also made sure there's always a newline at end
}
} }
// Any items left in the map, write new lines at the end of the file // Any items left in the map, write new lines at the end of the file
// Note this is only new patterns, not ones which changed locking flags // Note this is only new patterns, not ones which changed locking flags
for pattern, newline := range changedAttribLines { for pattern, newline := range changedAttribLines {
// Newline already embedded if !trackNoModifyAttrsFlag {
attributesFile.WriteString(newline) // Newline already embedded
attributesFile.WriteString(newline)
}
// Also, for any new patterns we've added, make sure any existing git // Also, for any new patterns we've added, make sure any existing git
// tracked files have their timestamp updated so they will now show as // tracked files have their timestamp updated so they will now show as
@ -272,5 +283,6 @@ func init() {
cmd.Flags().BoolVarP(&trackNotLockableFlag, "not-lockable", "", false, "remove lockable attribute from pattern") cmd.Flags().BoolVarP(&trackNotLockableFlag, "not-lockable", "", false, "remove lockable attribute from pattern")
cmd.Flags().BoolVarP(&trackVerboseLoggingFlag, "verbose", "v", false, "log which files are being tracked and modified") cmd.Flags().BoolVarP(&trackVerboseLoggingFlag, "verbose", "v", false, "log which files are being tracked and modified")
cmd.Flags().BoolVarP(&trackDryRunFlag, "dry-run", "d", false, "preview results of running `git lfs track`") cmd.Flags().BoolVarP(&trackDryRunFlag, "dry-run", "d", false, "preview results of running `git lfs track`")
cmd.Flags().BoolVarP(&trackNoModifyAttrsFlag, "no-modify-attrs", "", false, "skip modifying .gitattributes file")
}) })
} }

@ -39,6 +39,10 @@ to match paths.
Remove the lockable flag from the paths so they are no longer read-only unless Remove the lockable flag from the paths so they are no longer read-only unless
locked. locked.
* `--no-modify-attrs`
Makes matched entries stat-dirty so that Git can re-index files you wish to
convert to LFS. Does not modify any `.gitattributes` file(s).
## EXAMPLES ## EXAMPLES
* List the patterns that Git LFS is currently tracking: * List the patterns that Git LFS is currently tracking:

@ -463,3 +463,34 @@ begin_test "track escaped pattern"
assert_attributes_count "\\#" "filter=lfs" 1 assert_attributes_count "\\#" "filter=lfs" 1
) )
end_test end_test
begin_test "track (--no-modify-attrs)"
(
set -e
reponame="track-no-modify-attrs"
git init "$reponame"
cd "$reponame"
echo "contents" > a.dat
git add a.dat
# Git assumes that identical results from `stat(1)` between the index and
# working copy are stat dirty. To prevent this, wait at least one second to
# yield different `stat(1)` results.
sleep 1
git commit -m "add a.dat"
echo "*.dat filter=lfs diff=lfs merge=lfs -text" > .gitattributes
git add .gitattributes
git commit -m "asdf"
[ -z "$(git status --porcelain)" ]
git lfs track --no-modify-attrs "*.dat"
[ " M a.dat" = "$(git status --porcelain)" ]
)
end_test