#!/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 && exit 1 true ) 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 && exit 1 true ) 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