Merge pull request #4835 from chrisd8088/migrate-gitattrs-exec-fix

fix merging of `.gitattributes` with execute file mode during migration
This commit is contained in:
Chris Darroch 2022-01-25 09:27:51 -08:00 committed by GitHub
commit 02448f5fde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 126 additions and 19 deletions

2
go.mod

@ -5,7 +5,7 @@ module github.com/git-lfs/git-lfs/v3
require (
github.com/avast/retry-go v2.4.2+incompatible
github.com/dpotapov/go-spnego v0.0.0-20210315154721-298b63a54430
github.com/git-lfs/gitobj/v2 v2.0.2
github.com/git-lfs/gitobj/v2 v2.1.0
github.com/git-lfs/go-netrc v0.0.0-20210914205454-f0c862dd687a
github.com/git-lfs/pktline v0.0.0-20210330133718-06e9096e2825
github.com/git-lfs/wildmatch/v2 v2.0.1

4
go.sum

@ -7,8 +7,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dpotapov/go-spnego v0.0.0-20210315154721-298b63a54430 h1:oempk9HjNt6rVKyKmpdnoN7XABQv3SXLWu3pxUI7Vlk=
github.com/dpotapov/go-spnego v0.0.0-20210315154721-298b63a54430/go.mod h1:AVSs/gZKt1bOd2AhkhbS7Qh56Hv7klde22yXVbwYJhc=
github.com/git-lfs/gitobj/v2 v2.0.2 h1:p8rWlhEyiSsC+4Qc+EdufySatf8sDtvJIrHAHgf7Ar8=
github.com/git-lfs/gitobj/v2 v2.0.2/go.mod h1:q6aqxl6Uu3gWsip5GEKpw+7459F97er8COmU45ncAxw=
github.com/git-lfs/gitobj/v2 v2.1.0 h1:5BUDAMga0Sv9msMXolrn6xplkiG5RaVEkOir2HSznog=
github.com/git-lfs/gitobj/v2 v2.1.0/go.mod h1:q6aqxl6Uu3gWsip5GEKpw+7459F97er8COmU45ncAxw=
github.com/git-lfs/go-netrc v0.0.0-20210914205454-f0c862dd687a h1:6pskVZacdMUL93pCpMAYnMDLjH1yDFhssPYGe32sjdk=
github.com/git-lfs/go-netrc v0.0.0-20210914205454-f0c862dd687a/go.mod h1:70O4NAtvWn1jW8V8V+OKrJJYcxDLTmIozfi2fmSz5SI=
github.com/git-lfs/pktline v0.0.0-20210330133718-06e9096e2825 h1:riQhgheTL7tMF4d5raz9t3+IzoR1i1wqxE1kZC6dY+U=

@ -25,10 +25,13 @@ assert_ref_unmoved() {
# refs/heads/main
#
# - Commit 'A' has 120, in a.txt, and a corresponding entry in .gitattributes.
#
# If "0755" is passed as an argument, the .gitattributes file is created
# with that permissions mode.
setup_local_branch_with_gitattrs() {
set -e
reponame="migrate-single-remote-branch-with-attrs"
reponame="migrate-single-local-branch-with-attrs"
remove_and_create_local_repo "$reponame"
@ -40,6 +43,10 @@ setup_local_branch_with_gitattrs() {
git lfs track "*.txt"
git lfs track "*.other"
if [[ $1 == "0755" ]]; then
chmod +x .gitattributes
fi
git add .gitattributes
git commit -m "add .gitattributes"
}
@ -56,7 +63,7 @@ setup_local_branch_with_gitattrs() {
setup_local_branch_with_nested_gitattrs() {
set -e
reponame="nested-attrs"
reponame="migrate-single-local-branch-nested-attrs"
remove_and_create_local_repo "$reponame"
@ -97,7 +104,7 @@ setup_single_local_branch_untracked() {
local name="${1:-a.md}"
reponame="single-local-branch-untracked"
reponame="migrate-single-local-branch-untracked"
remove_and_create_local_repo "$reponame"
@ -118,16 +125,23 @@ setup_single_local_branch_untracked() {
#
# - Commit 'A' has 120, in a.txt and 140 in a.md, with both files tracked as
# pointers in Git LFS
#
# If "0755" is passed as an argument, the .gitattributes file is created
# with that permissions mode.
setup_single_local_branch_tracked() {
set -e
reponame="migrate-single-remote-branch-with-attrs"
reponame="migrate-single-local-branch-tracked"
remove_and_create_local_repo "$reponame"
echo "*.txt filter=lfs diff=lfs merge=lfs -text" > .gitattributes
echo "*.md filter=lfs diff=lfs merge=lfs -text" >> .gitattributes
if [[ $1 == "0755" ]]; then
chmod +x .gitattributes
fi
git add .gitattributes
git commit -m "initial commit"

@ -367,6 +367,52 @@ begin_test "migrate export (include/exclude ref)"
)
end_test
begin_test "migrate export (.gitattributes with different permissions)"
(
set -e
# Windows lacks POSIX permissions.
[ "$IS_WINDOWS" -eq 1 ] && exit 0
setup_single_local_branch_tracked 0755
md_oid="$(calc_oid "$(cat a.md)")"
txt_oid="$(calc_oid "$(cat a.txt)")"
assert_pointer "refs/heads/main" "a.txt" "$txt_oid" "120"
assert_pointer "refs/heads/main" "a.md" "$md_oid" "140"
[ -x .gitattributes ]
git lfs migrate export --include="*.txt"
[ ! -x .gitattributes ]
refute_pointer "refs/heads/main" "a.txt"
assert_pointer "refs/heads/main" "a.md" "$md_oid" "140"
refute_local_object "$txt_oid" "120"
assert_local_object "$md_oid" "140"
main="$(git rev-parse refs/heads/main)"
main_attrs="$(git cat-file -p "$main:.gitattributes")"
echo "$main_attrs" | grep -q "*.txt !text !filter !merge !diff"
attrs_main_sha="$(git show $main:.gitattributes | git hash-object --stdin)"
md_main_sha="$(git show $main:a.md | git hash-object --stdin)"
txt_main_sha="$(git show $main:a.txt | git hash-object --stdin)"
diff -u <(git ls-tree $main) <(cat <<-EOF
100644 blob $attrs_main_sha .gitattributes
100644 blob $md_main_sha a.md
100644 blob $txt_main_sha a.txt
EOF
)
)
end_test
begin_test "migrate export (--object-map)"
(
set -e

@ -502,7 +502,6 @@ begin_test "migrate import (above with include or exclude)"
)
end_test
begin_test "migrate import (existing .gitattributes)"
(
set -e
@ -561,6 +560,52 @@ EOF)
)
end_test
begin_test "migrate import (existing .gitattributes with different permissions)"
(
set -e
# Windows lacks POSIX permissions.
[ "$IS_WINDOWS" -eq 1 ] && exit 0
setup_local_branch_with_gitattrs 0755
main="$(git rev-parse refs/heads/main)"
txt_main_oid="$(calc_oid "$(git cat-file -p "$main:a.txt")")"
[ -x .gitattributes ]
git lfs migrate import --yes --include-ref=refs/heads/main --include="*.txt"
[ ! -x .gitattributes ]
assert_local_object "$txt_main_oid" "120"
main="$(git rev-parse refs/heads/main)"
prev="$(git rev-parse refs/heads/main^1)"
diff -u <(git cat-file -p $main:.gitattributes) <(cat <<-EOF
*.txt filter=lfs diff=lfs merge=lfs -text
*.other filter=lfs diff=lfs merge=lfs -text
EOF
)
diff -u <(git cat-file -p $prev:.gitattributes) <(cat <<-EOF
*.txt filter=lfs diff=lfs merge=lfs -text
EOF
)
attrs_main_sha="$(git show $main:.gitattributes | git hash-object --stdin)"
txt_main_sha="$(git show $main:a.txt | git hash-object --stdin)"
diff -u <(git ls-tree $main) <(cat <<-EOF
100644 blob $attrs_main_sha .gitattributes
100644 blob $txt_main_sha a.txt
EOF
)
)
end_test
begin_test "migrate import (identical contents, different permissions)"
(
set -e
@ -580,12 +625,12 @@ begin_test "migrate import (identical contents, different permissions)"
git commit -m "make file executable"
# Verify we have executable permissions.
ls -la foo.dat | grep 'rwx'
[ -x foo.dat ]
git lfs migrate import --everything --include="*.dat"
# Verify we have executable permissions.
ls -la foo.dat | grep 'rwx'
[ -x foo.dat ]
)
end_test

@ -115,22 +115,18 @@ func (t *Tree) Encode(to io.Writer) (n int, err error) {
func (t *Tree) Merge(others ...*TreeEntry) *Tree {
unseen := make(map[string]*TreeEntry)
// Build a cache of name+filemode to *TreeEntry.
// Build a cache of name to *TreeEntry.
for _, other := range others {
key := fmt.Sprintf("%s\x00%o", other.Name, other.Filemode)
unseen[key] = other
unseen[other.Name] = other
}
// Map the existing entries ("t.Entries") into a new set by either
// copying an existing entry, or replacing it with a new one.
entries := make([]*TreeEntry, 0, len(t.Entries))
for _, entry := range t.Entries {
key := fmt.Sprintf("%s\x00%o", entry.Name, entry.Filemode)
if other, ok := unseen[key]; ok {
if other, ok := unseen[entry.Name]; ok {
entries = append(entries, other)
delete(unseen, key)
delete(unseen, entry.Name)
} else {
oid := make([]byte, len(entry.Oid))
copy(oid, entry.Oid)
@ -234,6 +230,12 @@ func (e *TreeEntry) Type() ObjectType {
}
}
// IsLink returns true if the given TreeEntry is a blob which represents a
// symbolic link (i.e., with a filemode of 0120000.
func (e *TreeEntry) IsLink() bool {
return e.Filemode & sIFMT == sIFLNK
}
// SubtreeOrder is an implementation of sort.Interface that sorts a set of
// `*TreeEntry`'s according to "subtree" order. This ordering is required to
// write trees in a correct, readable format to the Git object database.

2
vendor/modules.txt vendored

@ -8,7 +8,7 @@ github.com/avast/retry-go
github.com/davecgh/go-spew/spew
# github.com/dpotapov/go-spnego v0.0.0-20210315154721-298b63a54430
github.com/dpotapov/go-spnego
# github.com/git-lfs/gitobj/v2 v2.0.2
# github.com/git-lfs/gitobj/v2 v2.1.0
github.com/git-lfs/gitobj/v2
github.com/git-lfs/gitobj/v2/errors
github.com/git-lfs/gitobj/v2/pack