Skip to content

Commit

Permalink
Merge pull request git-lfs#3190 from git-lfs/ttaylorr/lock-gitignored…
Browse files Browse the repository at this point in the history
…-files

locks: manage write permissions of ignored files
  • Loading branch information
ttaylorr authored Aug 23, 2018
2 parents 5d9d25b + a727fea commit 87e2474
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 2 deletions.
2 changes: 1 addition & 1 deletion locking/lockable.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func (c *Client) fixFileWriteFlags(absPath, workingDir string, lockable, unlocka
errs = append(errs, err)
}

tools.FastWalkGitRepo(absPath, func(parentDir string, fi os.FileInfo, err error) {
tools.FastWalkGitRepoAll(absPath, func(parentDir string, fi os.FileInfo, err error) {
if err != nil {
addErr(err)
return
Expand Down
24 changes: 24 additions & 0 deletions t/t-lock.sh
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,27 @@ begin_test "creating a lock (symlinked working directory)"
popd > /dev/null
)
end_test

begin_test "lock with .gitignore"
(
set -e

reponame="lock-with-gitignore"
setup_remote_repo_with_file "$reponame" "a.txt"
clone_repo "$reponame" "$reponame"

echo "*.txt filter=lfs diff=lfs merge=lfs -text lockable" > .gitattributes

git add .gitattributes
git commit -m ".gitattributes: mark 'a.txt' as lockable"

rm -f a.txt && git checkout a.txt
refute_file_writeable a.txt

echo "*.txt" > .gitignore
git add .gitignore
git commit -m ".gitignore: ignore 'a.txt'"
rm -f a.txt && git checkout a.txt
refute_file_writeable a.txt
)
end_test
14 changes: 13 additions & 1 deletion tools/filetools.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,19 @@ type FastWalkCallback func(parentDir string, info os.FileInfo, err error)
//
// rootDir - Absolute path to the top of the repository working directory
func FastWalkGitRepo(rootDir string, cb FastWalkCallback) {
walker := fastWalkWithExcludeFiles(rootDir, ".gitignore")
fastWalkCallback(fastWalkWithExcludeFiles(rootDir, ".gitignore"), cb)
}

// FastWalkGitRepoAll behaves as FastWalkGitRepo, with the additional caveat
// that it does not ignore paths and directories found in .gitignore file(s)
// throughout the repository.
func FastWalkGitRepoAll(rootDir string, cb FastWalkCallback) {
fastWalkCallback(fastWalkWithExcludeFiles(rootDir, ""), cb)
}

// fastWalkCallback calls the FastWalkCallback "cb" for all files found by the
// given *fastWalker, "walker".
func fastWalkCallback(walker *fastWalker, cb FastWalkCallback) {
for file := range walker.ch {
cb(file.ParentDir, file.Info, file.Err)
}
Expand Down
42 changes: 42 additions & 0 deletions tools/filetools_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,32 @@ thisisnot.txt
sort.Strings(gotEntries)
assert.Equal(t, expectedEntries, gotEntries)

// Go again using FastWalkGitRepoAll instead of FastWalkGitRepo to
// ensure that .gitingore'd files and directories are seen and
// traversed, respectively.
for _, ignore := range ignored {
expectedEntries = append(expectedEntries, join(mainDir, ignore))
}
gotEntries = make([]string, 0, 1000)

FastWalkGitRepoAll(mainDir, func(parent string, info os.FileInfo, err error) {
if err != nil {
gotErrors = append(gotErrors, err)
} else {
if len(parent) == 0 {
gotEntries = append(gotEntries, info.Name())
} else {
gotEntries = append(gotEntries, join(parent, info.Name()))
}
}
})

expectedEntries = uniq(expectedEntries)
gotEntries = uniq(gotEntries)

sort.Strings(expectedEntries)
sort.Strings(gotEntries)
assert.Equal(t, expectedEntries, gotEntries)
}

// Make test data - ensure you've Chdir'ed into a temp dir first
Expand Down Expand Up @@ -233,6 +259,22 @@ func getFileMode(filename string) os.FileMode {
return s.Mode()
}

// uniq creates an element-wise copy of "xs" containing only unique elements in
// the same order.
func uniq(xs []string) []string {
seen := make(map[string]struct{})
uniq := make([]string, 0, len(xs))

for _, x := range xs {
if _, ok := seen[x]; !ok {
seen[x] = struct{}{}
uniq = append(uniq, x)
}
}

return uniq
}

func TestSetWriteFlag(t *testing.T) {
f, err := ioutil.TempFile("", "lfstestwriteflag")
assert.Nil(t, err)
Expand Down

0 comments on commit 87e2474

Please sign in to comment.