git-lfs/t/t-pre-push.sh
Chris Darroch ec219b27d4 commands,t: use Git LFS project name in messages
We convert a few messages output by the various commands to use
the full "Git LFS" project name instead of the shorter "LFS" variant,
which will make them consistent with how the project name appears
in other messages elsewhere.

Note that we leave the status messages in the transfer queue
using the shorter variant as they are intended to be brief, are
checked extensively in the test suite, and are familiar to users
at this point.
2022-01-29 22:30:22 -08:00

1344 lines
38 KiB
Bash
Executable File

#!/usr/bin/env bash
. "$(dirname "$0")/testlib.sh"
begin_test "pre-push with good ref"
(
set -e
reponame="pre-push-main-branch-required"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git config "lfs.$(repo_endpoint "$GITSERVER" "$reponame").locksverify" false
git lfs track "*.dat"
echo "hi" > a.dat
git add .gitattributes a.dat
git commit -m "add a.dat"
refute_server_object "$reponame" 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 "refs/heads/main"
# for some reason, using 'tee' and $PIPESTATUS does not work here
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push origin "$GITSERVER/$reponame" 2>&1 > push.log
assert_server_object "$reponame" 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 "refs/heads/main"
)
end_test
begin_test "pre-push with tracked ref"
(
set -e
reponame="pre-push-tracked-branch-required"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git config "lfs.$(repo_endpoint "$GITSERVER" "$reponame").locksverify" false
git lfs track "*.dat"
echo "hi" > a.dat
git add .gitattributes a.dat
git commit -m "add a.dat"
refute_server_object "$reponame" 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 "refs/heads/tracked"
# for some reason, using 'tee' and $PIPESTATUS does not work here
echo "refs/heads/main main refs/heads/tracked 0000000000000000000000000000000000000000" |
git lfs pre-push origin main 2>&1 > push.log
assert_server_object "$reponame" 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 "refs/heads/tracked"
)
end_test
begin_test "pre-push with bad ref"
(
set -e
reponame="pre-push-other-branch-required"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git config "lfs.$(repo_endpoint "$GITSERVER" "$reponame").locksverify" false
git lfs track "*.dat"
echo "hi" > a.dat
git add .gitattributes a.dat
git commit -m "add a.dat"
refute_server_object "$reponame" 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 "refs/heads/other"
# for some reason, using 'tee' and $PIPESTATUS does not work here
set +e
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push origin "$GITSERVER/$reponame" 2> push.log
pushcode=$?
set -e
if [ "0" -eq "$pushcode" ]; then
echo "expected command to fail"
exit 1
fi
grep 'Expected ref "refs/heads/other", got "refs/heads/main"' push.log
refute_server_object "$reponame" 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 "refs/heads/other"
)
end_test
begin_test "pre-push"
(
set -e
reponame="$(basename "$0" ".sh")"
setup_remote_repo "$reponame"
clone_repo "$reponame" repo
git lfs track "*.dat"
git add .gitattributes
git commit -m "add git attributes"
git config "lfs.$(repo_endpoint $GITSERVER $reponame).locksverify" true
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push origin "$GITSERVER/$reponame" |
tee push.log
# no output if nothing to do
[ "$(du -k push.log | cut -f 1)" == "0" ]
git lfs track "*.dat"
echo "hi" > hi.dat
git add hi.dat
git commit -m "add hi.dat"
git show
refute_server_object "$reponame" 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4
# push file to the git lfs server
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push origin "$GITSERVER/$reponame" 2>&1 |
tee push.log
grep "Uploading LFS objects: 100% (1/1), 3 B" push.log
assert_server_object "$reponame" 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4
)
end_test
begin_test "pre-push dry-run"
(
set -e
reponame="$(basename "$0" ".sh")-dry-run"
setup_remote_repo "$reponame"
clone_repo "$reponame" repo-dry-run
git lfs track "*.dat"
git add .gitattributes
git commit -m "add git attributes"
git config "lfs.$(repo_endpoint $GITSERVER $reponame).locksverify" true
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push --dry-run origin "$GITSERVER/$reponame" |
tee push.log
[ "" = "$(cat push.log)" ]
git lfs track "*.dat"
echo "dry" > hi.dat
git add hi.dat
git commit -m "add hi.dat"
git show
refute_server_object "$reponame" 2840e0eafda1d0760771fe28b91247cf81c76aa888af28a850b5648a338dc15b
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push --dry-run origin "$GITSERVER/$reponame" |
tee push.log
grep "push 2840e0eafda1d0760771fe28b91247cf81c76aa888af28a850b5648a338dc15b => hi.dat" push.log
cat push.log
[ `wc -l < push.log` = 1 ]
refute_server_object "$reponame" 2840e0eafda1d0760771fe28b91247cf81c76aa888af28a850b5648a338dc15b
)
end_test
begin_test "pre-push skip-push"
(
set -e
reponame="$(basename "$0" ".sh")-skip-push"
setup_remote_repo "$reponame"
clone_repo "$reponame" repo-skip-push
git lfs track "*.dat"
git add .gitattributes
git commit -m "add git attributes"
git config "lfs.$(repo_endpoint $GITSERVER $reponame).locksverify" true
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
GIT_LFS_SKIP_PUSH=true git lfs pre-push origin "$GITSERVER/$reponame" |
tee push.log
[ "" = "$(cat push.log)" ]
git lfs track "*.dat"
echo "dry" > hi.dat
git add hi.dat
git commit -m "add hi.dat"
git show
refute_server_object "$reponame" 2840e0eafda1d0760771fe28b91247cf81c76aa888af28a850b5648a338dc15b
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
GIT_LFS_SKIP_PUSH=true git lfs pre-push origin "$GITSERVER/$reponame" |
tee push.log
[ "" = "$(cat push.log)" ]
refute_server_object "$reponame" 2840e0eafda1d0760771fe28b91247cf81c76aa888af28a850b5648a338dc15b
)
end_test
begin_test "pre-push 307 redirects"
(
set -e
reponame="$(basename "$0" ".sh")"
setup_remote_repo "$reponame"
clone_repo "$reponame" repo-307
git lfs track "*.dat"
git add .gitattributes
git commit -m "add git attributes"
# relative redirect
git config remote.origin.lfsurl "$GITSERVER/redirect307/rel/$reponame.git/info/lfs"
git lfs track "*.dat"
echo "hi" > hi.dat
git add hi.dat
git commit -m "add hi.dat"
git show
# push file to the git lfs server
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push origin "$GITSERVER/redirect307/rel/$reponame.git/info/lfs" 2>&1 |
tee push.log
grep "Uploading LFS objects: 100% (1/1), 3 B" push.log
assert_server_object "$reponame" 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4
# absolute redirect
git config remote.origin.lfsurl "$GITSERVER/redirect307/abs/$reponame.git/info/lfs"
echo "hi" > hi2.dat
git add hi2.dat
git commit -m "add hi2.dat"
git show
# push file to the git lfs server
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push origin "$GITSERVER/redirect307/abs/$reponame.git/info/lfs" 2>&1 |
tee push.log
grep "Uploading LFS objects: 100% (1/1), 3 B" push.log
)
end_test
begin_test "pre-push with existing file"
(
set -e
reponame="$(basename "$0" ".sh")-existing-file"
setup_remote_repo "$reponame"
clone_repo "$reponame" existing-file
echo "existing" > existing.dat
git add existing.dat
git commit -m "add existing dat"
git lfs track "*.dat"
echo "new" > new.dat
git add new.dat
git add .gitattributes
git commit -m "add new file through git lfs"
# push file to the git lfs server
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push origin "$GITSERVER/$reponame" 2>&1 |
tee push.log
grep "Uploading LFS objects: 100% (1/1), 4 B" push.log
# now the file exists
assert_server_object "$reponame" 7aa7a5359173d05b63cfd682e3c38487f3cb4f7f1d60659fe59fab1505977d4c
)
end_test
begin_test "pre-push with existing pointer"
(
set -e
reponame="$(basename "$0" ".sh")-existing-pointer"
setup_remote_repo "$reponame"
clone_repo "$reponame" existing-pointer
echo "$(pointer "7aa7a5359173d05b63cfd682e3c38487f3cb4f7f1d60659fe59fab1505977d4c" 4)" > new.dat
git add new.dat
git commit -m "add new pointer"
mkdir -p .git/lfs/objects/7a/a7
echo "new" > .git/lfs/objects/7a/a7/7aa7a5359173d05b63cfd682e3c38487f3cb4f7f1d60659fe59fab1505977d4c
# push file to the git lfs server
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push origin "$GITSERVER/$reponame" 2>&1 |
tee push.log
grep "Uploading LFS objects: 100% (1/1), 4 B" push.log
)
end_test
begin_test "pre-push with missing pointer not on server"
(
set -e
reponame="$(basename "$0" ".sh")-missing-pointer"
setup_remote_repo "$reponame"
clone_repo "$reponame" missing-pointer
oid="7aa7a5359173d05b63cfd682e3c38487f3cb4f7f1d60659fe59fab1505977d4c"
echo "$(pointer "$oid" 4)" > new.dat
git add new.dat
git commit -m "add new pointer"
# assert that push fails
set +e
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push origin "$GITSERVER/$reponame" 2>&1 |
tee push.log
set -e
grep " (missing) new.dat ($oid)" push.log
)
end_test
begin_test "pre-push with missing pointer which is on server"
(
# should permit push if files missing locally but are on server, shouldn't
# require client to have every file (prune)
set -e
reponame="$(basename "$0" ".sh")-missing-but-on-server"
setup_remote_repo "$reponame"
clone_repo "$reponame" missing-but-on-server
contents="common data"
contents_oid=$(calc_oid "$contents")
git lfs track "*.dat"
printf "%s" "$contents" > common1.dat
git add common1.dat
git add .gitattributes
git commit -m "add first file"
# push file to the git lfs server
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push origin "$GITSERVER/$reponame" 2>&1 |
tee push.log
grep "Uploading LFS objects: 100% (1/1), 11 B" push.log
# now the file exists
assert_server_object "$reponame" "$contents_oid"
# create another commit referencing same oid, then delete local data & push
printf "%s" "$contents" > common2.dat
git add common2.dat
git commit -m "add second file, same content"
rm -rf .git/lfs/objects
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push origin "$GITSERVER/$reponame" 2>&1 |
tee push.log
# make sure there were no errors reported
[ -z "$(grep -i 'Error' push.log)" ]
)
end_test
begin_test "pre-push with missing and present pointers (lfs.allowincompletepush true)"
(
set -e
reponame="pre-push-missing-and-present"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git lfs track "*.dat"
git add .gitattributes
git commit -m "initial commit"
present="present"
present_oid="$(calc_oid "$present")"
printf "%s" "$present" > present.dat
missing="missing"
missing_oid="$(calc_oid "$missing")"
printf "%s" "$missing" > missing.dat
git add present.dat missing.dat
git commit -m "add present.dat and missing.dat"
git rm missing.dat
git commit -m "remove missing"
# :fire: the "missing" object
missing_oid_part_1="$(echo "$missing_oid" | cut -b 1-2)"
missing_oid_part_2="$(echo "$missing_oid" | cut -b 3-4)"
missing_oid_path=".git/lfs/objects/$missing_oid_part_1/$missing_oid_part_2/$missing_oid"
rm "$missing_oid_path"
git config lfs.allowincompletepush true
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push origin "$GITSERVER/$reponame" 2>&1 |
tee push.log
if [ "0" -ne "${PIPESTATUS[1]}" ]; then
echo >&2 "fatal: expected \`git lfs pre-push origin $GITSERVER/$reponame\` to succeed..."
exit 1
fi
grep "LFS upload missing objects" push.log
grep " (missing) missing.dat ($missing_oid)" push.log
assert_server_object "$reponame" "$present_oid"
refute_server_object "$reponame" "$missing_oid"
)
end_test
begin_test "pre-push reject missing pointers (lfs.allowincompletepush default)"
(
set -e
reponame="pre-push-reject-missing-and-present"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git lfs track "*.dat"
git add .gitattributes
git commit -m "initial commit"
present="present"
present_oid="$(calc_oid "$present")"
printf "%s" "$present" > present.dat
missing="missing"
missing_oid="$(calc_oid "$missing")"
printf "%s" "$missing" > missing.dat
git add present.dat missing.dat
git commit -m "add present.dat and missing.dat"
git rm missing.dat
git commit -m "remove missing"
# :fire: the "missing" object
missing_oid_part_1="$(echo "$missing_oid" | cut -b 1-2)"
missing_oid_part_2="$(echo "$missing_oid" | cut -b 3-4)"
missing_oid_path=".git/lfs/objects/$missing_oid_part_1/$missing_oid_part_2/$missing_oid"
rm "$missing_oid_path"
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push origin "$GITSERVER/$reponame" 2>&1 |
tee push.log
if [ "2" -ne "${PIPESTATUS[1]}" ]; then
echo >&2 "fatal: expected \`git lfs pre-push origin $GITSERVER/$reponame\` to fail..."
exit 1
fi
grep 'Unable to find source' push.log
refute_server_object "$reponame" "$present_oid"
refute_server_object "$reponame" "$missing_oid"
)
end_test
begin_test "pre-push multiple branches"
(
set -e
reponame="$(basename "$0" ".sh")-multiple-branches"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git lfs track "*.dat" 2>&1 | tee track.log
grep "Tracking \"\*.dat\"" track.log
NUMFILES=6
# generate content we'll use
for ((a=0; a < NUMFILES ; a++))
do
content[$a]="filecontent$a"
oid[$a]=$(calc_oid "${content[$a]}")
done
echo "[
{
\"CommitDate\":\"$(get_date -10d)\",
\"Files\":[
{\"Filename\":\"file1.dat\",\"Size\":${#content[0]}, \"Data\":\"${content[0]}\"},
{\"Filename\":\"file2.dat\",\"Size\":${#content[1]}, \"Data\":\"${content[1]}\"}]
},
{
\"NewBranch\":\"branch1\",
\"CommitDate\":\"$(get_date -5d)\",
\"Files\":[
{\"Filename\":\"file2.dat\",\"Size\":${#content[2]}, \"Data\":\"${content[2]}\"}]
},
{
\"ParentBranches\":[\"main\"],
\"NewBranch\":\"branch2\",
\"CommitDate\":\"$(get_date -5d)\",
\"Files\":[
{\"Filename\":\"file3.dat\",\"Size\":${#content[3]}, \"Data\":\"${content[3]}\"}]
},
{
\"ParentBranches\":[\"main\"],
\"NewBranch\":\"branch3\",
\"CommitDate\":\"$(get_date -2d)\",
\"Files\":[
{\"Filename\":\"file1.dat\",\"Size\":${#content[4]}, \"Data\":\"${content[4]}\"}]
},
{
\"ParentBranches\":[\"main\"],
\"NewBranch\":\"branch4\",
\"CommitDate\":\"$(get_date -1d)\",
\"Files\":[
{\"Filename\":\"file4.dat\",\"Size\":${#content[5]}, \"Data\":\"${content[5]}\"}]
}
]" | lfstest-testutils addcommits
# make sure when called via git push all branches are updated
git push origin main branch1 branch2 branch3 branch4
for ((a=0; a < NUMFILES ; a++))
do
assert_server_object "$reponame" "${oid[$a]}"
done
)
end_test
begin_test "pre-push with bad remote"
(
set -e
cd repo
echo "refs/heads/main main refs/heads/main 0000000000000000000000000000000000000000" |
git lfs pre-push not-a-remote "$GITSERVER/$reponame" 2>&1 |
tee pre-push.log
grep "Invalid remote name" pre-push.log
)
end_test
begin_test "pre-push unfetched deleted remote branch & server GC"
(
# point of this is to simulate the case where the local cache of the remote
# branch state contains a branch which has actually been deleted on the remote,
# the client just doesn't know yet (hasn't done 'git fetch origin --prune')
# If the server GC'd the objects that deleted branch contained, but they were
# referenced by a branch being pushed (earlier commit), push might assume it
# doesn't have to push it, but it does. Tests that we check the real remote refs
# before making an assumption about the diff we need to push
set -e
reponame="$(basename "$0" ".sh")-server-deleted-branch-gc"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git lfs track "*.dat" 2>&1 | tee track.log
grep "Tracking \"\*.dat\"" track.log
NUMFILES=4
# generate content we'll use
for ((a=0; a < NUMFILES ; a++))
do
content[$a]="filecontent$a"
oid[$a]=$(calc_oid "${content[$a]}")
done
echo "[
{
\"CommitDate\":\"$(get_date -10d)\",
\"Files\":[
{\"Filename\":\"file1.dat\",\"Size\":${#content[0]}, \"Data\":\"${content[0]}\"},
{\"Filename\":\"file2.dat\",\"Size\":${#content[1]}, \"Data\":\"${content[1]}\"}]
},
{
\"NewBranch\":\"branch-to-delete\",
\"CommitDate\":\"$(get_date -5d)\",
\"Files\":[
{\"Filename\":\"file3.dat\",\"Size\":${#content[2]}, \"Data\":\"${content[2]}\"}]
},
{
\"NewBranch\":\"branch-to-push-after\",
\"CommitDate\":\"$(get_date -2d)\",
\"Files\":[
{\"Filename\":\"file4.dat\",\"Size\":${#content[3]}, \"Data\":\"${content[3]}\"}]
}
]" | lfstest-testutils addcommits
# push only the first 2 branches
git push origin main branch-to-delete
for ((a=0; a < 3 ; a++))
do
assert_server_object "$reponame" "${oid[$a]}"
done
# confirm we haven't pushed the last one yet
refute_server_object "$reponame" "${oid[3]}"
# copy the cached remote ref for the branch we're going to delete remotely
cp .git/refs/remotes/origin/branch-to-delete branch-to-delete.ref
# now delete the branch on the server
git push origin --delete branch-to-delete
# remove the OID in it, as if GC'd
delete_server_object "$reponame" "${oid[2]}"
refute_server_object "$reponame" "${oid[2]}"
# Now put the cached remote ref back, as if someone else had deleted it but
# we hadn't done git fetch --prune yet
mv branch-to-delete.ref .git/refs/remotes/origin/branch-to-delete
# Confirm that local cache of remote branch is back
git branch -r 2>&1 | tee branch-r.log
grep "origin/branch-to-delete" branch-r.log
# Now push later branch which should now need to re-push previous commits LFS too
git push origin branch-to-push-after
# all objects should now be there even though cached remote branch claimed it already had file3.dat
for ((a=0; a < NUMFILES ; a++))
do
assert_server_object "$reponame" "${oid[$a]}"
done
)
end_test
begin_test "pre-push delete branch"
(
set -e
reponame="$(basename "$0" ".sh")-delete-branch"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git lfs track "*.dat" 2>&1 | tee track.log
grep "Tracking \"\*.dat\"" track.log
NUMFILES=4
# generate content we'll use
for ((a=0; a < NUMFILES ; a++))
do
content[$a]="filecontent$a"
oid[$a]=$(calc_oid "${content[$a]}")
done
echo "[
{
\"CommitDate\":\"$(get_date -2d)\",
\"Files\":[
{\"Filename\":\"file1.dat\",\"Size\":${#content[0]}, \"Data\":\"${content[0]}\"},
{\"Filename\":\"file2.dat\",\"Size\":${#content[1]}, \"Data\":\"${content[1]}\"}]
},
{
\"NewBranch\":\"branch-to-delete\",
\"CommitDate\":\"$(get_date -1d)\",
\"Files\":[
{\"Filename\":\"file3.dat\",\"Size\":${#content[2]}, \"Data\":\"${content[2]}\"}]
},
{
\"ParentBranches\":[\"main\"],
\"CommitDate\":\"$(get_date -0d)\",
\"Files\":[
{\"Filename\":\"file4.dat\",\"Size\":${#content[3]}, \"Data\":\"${content[3]}\"}]
}
]" | lfstest-testutils addcommits
# push all branches
git push origin main branch-to-delete
for ((a=0; a < NUMFILES ; a++))
do
assert_server_object "$reponame" "${oid[$a]}"
done
# deleting a branch with git push should not fail
# (requires correct special casing of "(delete) 0000000000.." in hook)
git push origin --delete branch-to-delete
)
end_test
begin_test "pre-push with our lock"
(
set -e
reponame="pre_push_owned_locks"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git lfs track "*.dat"
git add .gitattributes
git commit -m "initial commit"
contents="locked contents"
printf "%s" "$contents" > locked.dat
git add locked.dat
git commit -m "add locked.dat"
git push origin main
git lfs lock --json "locked.dat" | tee lock.log
id=$(assert_lock lock.log locked.dat)
assert_server_lock $id
printf "authorized changes" >> locked.dat
git add locked.dat
git commit -m "add unauthorized changes"
GIT_CURL_VERBOSE=1 git push origin main 2>&1 | tee push.log
grep "Consider unlocking your own locked files" push.log
grep "* locked.dat" push.log
assert_server_lock "$id"
)
end_test
begin_test "pre-push with their lock on lfs file"
(
set -e
reponame="pre_push_unowned_lock"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git lfs track "*.dat"
git add .gitattributes
git commit -m "initial commit"
contents="locked contents"
# any lock path with "theirs" is returned as "their" lock by /locks/verify
printf "%s" "$contents" > locked_theirs.dat
git add locked_theirs.dat
git commit -m "add locked_theirs.dat"
git push origin main
git lfs lock --json "locked_theirs.dat" | tee lock.log
id=$(assert_lock lock.log locked_theirs.dat)
assert_server_lock $id
pushd "$TRASHDIR" >/dev/null
clone_repo "$reponame" "$reponame-assert"
git config lfs.locksverify true
printf "unauthorized changes" >> locked_theirs.dat
git add locked_theirs.dat
# --no-verify is used to avoid the pre-commit hook which is not under test
git commit --no-verify -m "add unauthorized changes"
git push origin main 2>&1 | tee push.log
res="${PIPESTATUS[0]}"
if [ "0" -eq "$res" ]; then
echo "push should fail"
exit 1
fi
grep "Unable to push locked files" push.log
grep "* locked_theirs.dat - Git LFS Tests" push.log
grep "Cannot update locked files." push.log
refute_server_object "$reponame" "$(calc_oid_file locked_theirs.dat)"
popd >/dev/null
)
end_test
begin_test "pre-push with their lock on non-lfs lockable file"
(
set -e
reponame="pre_push_unowned_lock_not_lfs"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
echo "*.dat lockable" > .gitattributes
git add .gitattributes
git commit -m "initial commit"
# any lock path with "theirs" is returned as "their" lock by /locks/verify
echo "hi" > readme.txt
echo "tiny" > tiny_locked_theirs.dat
git help > large_locked_theirs.dat
git add readme.txt tiny_locked_theirs.dat large_locked_theirs.dat
git commit -m "add initial files"
git push origin main
git lfs lock --json "tiny_locked_theirs.dat" | tee lock.log
id=$(assert_lock lock.log tiny_locked_theirs.dat)
assert_server_lock $id
git lfs lock --json "large_locked_theirs.dat" | tee lock.log
id=$(assert_lock lock.log large_locked_theirs.dat)
assert_server_lock $id
pushd "$TRASHDIR" >/dev/null
clone_repo "$reponame" "$reponame-assert"
git config lfs.locksverify true
git lfs update # manually add pre-push hook, since lfs clean hook is not used
echo "other changes" >> readme.txt
echo "unauthorized changes" >> large_locked_theirs.dat
echo "unauthorized changes" >> tiny_locked_theirs.dat
# --no-verify is used to avoid the pre-commit hook which is not under test
git commit --no-verify -am "add unauthorized changes"
git push origin main 2>&1 | tee push.log
res="${PIPESTATUS[0]}"
if [ "0" -eq "$res" ]; then
echo "push should fail"
exit 1
fi
grep "Unable to push locked files" push.log
grep "* large_locked_theirs.dat - Git LFS Tests" push.log
grep "* tiny_locked_theirs.dat - Git LFS Tests" push.log
grep "Cannot update locked files." push.log
refute_server_object "$reponame" "$(calc_oid_file large_locked_theirs.dat)"
refute_server_object "$reponame" "$(calc_oid_file tiny_locked_theirs.dat)"
popd >/dev/null
)
end_test
begin_test "pre-push locks verify 5xx with verification enabled"
(
set -e
reponame="lock-enabled-verify-5xx"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
endpoint="$(repo_endpoint $GITSERVER $reponame)"
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
git config "lfs.$endpoint.locksverify" true
git push origin main 2>&1 | tee push.log
grep "\"origin\" does not support the Git LFS locking API" push.log
grep "git config lfs.$endpoint.locksverify false" push.log
refute_server_object "$reponame" "$contents_oid"
)
end_test
begin_test "pre-push disable locks verify on exact url"
(
set -e
reponame="lock-disabled-verify-5xx"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
endpoint="$(repo_endpoint $GITSERVER $reponame)"
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
git config "lfs.$endpoint.locksverify" false
git push origin main 2>&1 | tee push.log
[ "0" -eq "$(grep -c "\"origin\" does not support the Git LFS locking API" push.log)" ]
assert_server_object "$reponame" "$contents_oid"
)
end_test
begin_test "pre-push disable locks verify on partial url"
(
set -e
reponame="lock-disabled-verify-5xx-partial"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
endpoint="$server/$repo"
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
git config "lfs.$endpoint.locksverify" false
git push origin main 2>&1 | tee push.log
[ "0" -eq "$(grep -c "\"origin\" does not support the Git LFS locking API" push.log)" ]
assert_server_object "$reponame" "$contents_oid"
)
end_test
begin_test "pre-push locks verify 403 with good ref"
(
set -e
reponame="lock-verify-main-branch-required"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
git config "lfs.$GITSERVER/$reponame.git.locksverify" true
git push origin main 2>&1 | tee push.log
assert_server_object "$reponame" "$contents_oid" "refs/heads/main"
)
end_test
begin_test "pre-push locks verify 403 with good tracked ref"
(
set -e
reponame="lock-verify-tracked-branch-required"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
git config push.default upstream
git config branch.main.merge refs/heads/tracked
git config branch.main.remote origin
git config "lfs.$GITSERVER/$reponame.git.locksverify" true
git push 2>&1 | tee push.log
assert_server_object "$reponame" "$contents_oid" "refs/heads/tracked"
)
end_test
begin_test "pre-push locks verify 403 with explicit ref"
(
set -e
reponame="lock-verify-explicit-branch-required"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
git config "lfs.$GITSERVER/$reponame.git.locksverify" true
git push origin main:explicit 2>&1 | tee push.log
assert_server_object "$reponame" "$contents_oid" "refs/heads/explicit"
)
end_test
begin_test "pre-push locks verify 403 with bad ref"
(
set -e
reponame="lock-verify-other-branch-required"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
git config "lfs.$GITSERVER/$reponame.git.locksverify" true
git push origin main 2>&1 | tee push.log
grep "failed to push some refs" push.log
refute_server_object "$reponame" "$contents_oid" "refs/heads/other"
)
end_test
begin_test "pre-push locks verify 5xx with verification unset"
(
set -e
reponame="lock-unset-verify-5xx"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
endpoint="$(repo_endpoint $GITSERVER $reponame)"
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
[ -z "$(git config "lfs.$endpoint.locksverify")" ]
git push origin main 2>&1 | tee push.log
grep "\"origin\" does not support the Git LFS locking API" push.log
assert_server_object "$reponame" "$contents_oid"
)
end_test
begin_test "pre-push locks verify 501 with verification enabled"
(
set -e
reponame="lock-enabled-verify-501"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
endpoint="$(repo_endpoint $GITSERVER $reponame)"
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
git config "lfs.$endpoint.locksverify" true
git push origin main 2>&1 | tee push.log
assert_server_object "$reponame" "$contents_oid"
[ "false" = "$(git config "lfs.$endpoint.locksverify")" ]
)
end_test
begin_test "pre-push locks verify 501 with verification disabled"
(
set -e
reponame="lock-disabled-verify-501"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
endpoint="$(repo_endpoint $GITSERVER $reponame)"
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
git config "lfs.$endpoint.locksverify" false
git push origin main 2>&1 | tee push.log
assert_server_object "$reponame" "$contents_oid"
[ "false" = "$(git config "lfs.$endpoint.locksverify")" ]
)
end_test
begin_test "pre-push locks verify 501 with verification unset"
(
set -e
reponame="lock-unset-verify-501"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
endpoint="$(repo_endpoint $GITSERVER $reponame)"
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
[ -z "$(git config "lfs.$endpoint.locksverify")" ]
git push origin main 2>&1 | tee push.log
assert_server_object "$reponame" "$contents_oid"
[ "false" = "$(git config "lfs.$endpoint.locksverify")" ]
)
end_test
begin_test "pre-push locks verify 200"
(
set -e
reponame="lock-verify-200"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
endpoint="$(repo_endpoint $GITSERVER $reponame)"
[ -z "$(git config "lfs.$endpoint.locksverify")" ]
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
git push origin main 2>&1 | tee push.log
grep "Locking support detected on remote \"origin\"." push.log
grep "git config lfs.$endpoint.locksverify true" push.log
assert_server_object "$reponame" "$contents_oid"
)
end_test
begin_test "pre-push locks verify 403 with verification enabled"
(
set -e
reponame="lock-enabled-verify-403"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
endpoint="$(repo_endpoint $GITSERVER $reponame)"
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
git config "lfs.$endpoint.locksverify" true
git push origin main 2>&1 | tee push.log
grep "error: Authentication error" push.log
refute_server_object "$reponame" "$contents_oid"
[ "true" = "$(git config "lfs.$endpoint.locksverify")" ]
)
end_test
begin_test "pre-push locks verify 403 with verification disabled"
(
set -e
reponame="lock-disabled-verify-403"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
endpoint="$(repo_endpoint $GITSERVER $reponame)"
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
git config "lfs.$endpoint.locksverify" false
git push origin main 2>&1 | tee push.log
assert_server_object "$reponame" "$contents_oid"
[ "false" = "$(git config "lfs.$endpoint.locksverify")" ]
)
end_test
begin_test "pre-push locks verify 403 with verification unset"
(
set -e
reponame="lock-unset-verify-403"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
endpoint="$(repo_endpoint $GITSERVER $reponame)"
contents="example"
contents_oid="$(calc_oid "$contents")"
printf "%s" "$contents" > a.dat
git lfs track "*.dat"
git add .gitattributes a.dat
git commit --message "initial commit"
[ -z "$(git config "lfs.$endpoint.locksverify")" ]
git push origin main 2>&1 | tee push.log
grep "warning: Authentication error" push.log
assert_server_object "$reponame" "$contents_oid"
[ -z "$(git config "lfs.$endpoint.locksverify")" ]
)
end_test
begin_test "pre-push with pushDefault and explicit remote"
(
set -e
reponame="pre-push-pushdefault-explicit"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git remote add wrong "$(repo_endpoint "$GITSERVER" "wrong-url")"
git config "lfs.$(repo_endpoint "$GITSERVER" "$reponame").locksverify" false
git config remote.pushDefault wrong
git lfs track "*.dat"
echo "hi" > a.dat
git add .gitattributes a.dat
git commit -m "add a.dat"
refute_server_object "$reponame" 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 "refs/heads/main"
GIT_TRACE=1 GIT_TRANSFER_TRACE=1 git push origin main 2>&1 | tee push.log
assert_server_object "$reponame" 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 "refs/heads/main"
! grep wrong-url push.log
)
end_test
begin_test "pre-push uses optimization if remote URL matches"
(
set -e
reponame="pre-push-remote-url-optimization"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
endpoint=$(git config remote.origin.url)
contents_oid=$(calc_oid 'hi\n')
git config "lfs.$endpoint.locksverify" false
git lfs track "*.dat"
echo "hi" > a.dat
git add .gitattributes a.dat
git commit -m "add a.dat"
refute_server_object "$reponame" $contents_oid "refs/heads/main"
GIT_TRACE=1 GIT_TRANSFER_TRACE=1 git push "$endpoint" main 2>&1 | tee push.log
grep 'rev-list.*--not --remotes=origin' push.log
)
end_test
begin_test "pre-push does not traverse Git objects server has"
(
set -e
reponame="pre-push-traverse-server-objects"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
endpoint=$(git config remote.origin.url)
contents_oid=$(calc_oid 'hi\n')
git config "lfs.$endpoint.locksverify" false
git lfs track "*.dat"
echo "hi" > a.dat
git add .gitattributes a.dat
git commit -m "add a.dat"
refute_server_object "$reponame" $contents_oid "refs/heads/main"
# We use a different URL instead of a named remote or the remote URL so that
# we can't make use of the optimization that ignores objects we already have
# in remote tracking branches.
GIT_TRACE=1 GIT_TRANSFER_TRACE=1 git push "$endpoint.git" main 2>&1 | tee push.log
assert_server_object "$reponame" $contents_oid "refs/heads/main"
contents2_oid=$(calc_oid 'hello\n')
echo "hello" > b.dat
git add .gitattributes b.dat
git commit -m "add b.dat"
refute_server_object "$reponame" $contents2_oid "refs/heads/main"
GIT_TRACE=1 GIT_TRANSFER_TRACE=1 git push "$endpoint.git" main 2>&1 | tee push.log
assert_server_object "$reponame" $contents2_oid "refs/heads/main"
# Verify that we haven't tried to push or query for the object we already
# pushed before; i.e., we didn't see it because we ignored its Git object
# during traversal.
! grep $contents_oid push.log
)
end_test
begin_test "pre-push with force-pushed ref"
(
set -e
reponame="pre-push-force-pushed-ref"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git config "lfs.$(repo_endpoint "$GITSERVER" "$reponame").locksverify" false
git lfs track "*.dat"
echo "hi" > a.dat
git add .gitattributes a.dat
git commit -m "add a.dat"
git tag -a -m tagname tagname
refute_server_object "$reponame" 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 "refs/heads/main"
git push origin main tagname
assert_server_object "$reponame" 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 "refs/heads/main"
# We pick a different message so that we get different object IDs even if both
# commands run in the same second.
git tag -f -a -m tagname2 tagname
# Prune the old tag object.
git reflog expire --all --expire=now
git gc --prune=now
# Make sure we deal with us missing the object for the old value of the tag ref.
git push origin +tagname
)
end_test
begin_test "pre-push with local path"
(
set -e
reponame="pre-push-local-path"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame-2"
cd ..
clone_repo "$reponame" "$reponame"
git lfs track "*.dat"
echo "hi" > a.dat
git add .gitattributes a.dat
git commit -m "add a.dat"
# Push to the other repo.
git push "../$reponame-2" main:foo
# Push to . to make sure that works.
git push "." main:foo
git lfs fsck
cd "../$reponame-2"
git checkout foo
git lfs fsck
)
end_test