push: don't fetch commit object when checking existence

If we're checking to see whether to tell the user to do a fetch before pushing there's no need for us to actually fetch the object from the remote if the clone is partial. Because the promisor doesn't do negotiation actually trying to do the fetch of the new head can be very expensive as it will try and include history that we already have and it just results in rejecting the push with a different message, and in behavior that is different to a clone that is not partial. Signed-off-by: Tom Hughes <tom@compton.nu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Tom Hughes committed May 22, 2024 at 21:15 UTC 6549c41ead833c8d8c4098806a29399433065516
2 files changed +20 -1
remote.c
+1 -1
@@ -1773,7 +1773,7 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
1773 if (!reject_reason && !ref->deletion && !is_null_oid(&ref->old_oid)) {
1774 if (starts_with(ref->name, "refs/tags/"))
1775 reject_reason = REF_STATUS_REJECT_ALREADY_EXISTS;
1776 - else if (!repo_has_object_file(the_repository, &ref->old_oid))
1776 + else if (!repo_has_object_file_with_flags(the_repository, &ref->old_oid, OBJECT_INFO_SKIP_FETCH_OBJECT))
1777 reject_reason = REF_STATUS_REJECT_FETCH_FIRST;
1778 else if (!lookup_commit_reference_gently(the_repository, &ref->old_oid, 1) ||
1779 !lookup_commit_reference_gently(the_repository, &ref->new_oid, 1))
t/t0410-partial-clone.sh
+19
@@ -689,6 +689,25 @@ test_expect_success 'lazy-fetch when accessing object not in the_repository' '
689 ! grep "[?]$FILE_HASH" out
690 '
691
692 +test_expect_success 'push should not fetch new commit objects' '
693 + rm -rf server client &&
694 + test_create_repo server &&
695 + test_config -C server uploadpack.allowfilter 1 &&
696 + test_config -C server uploadpack.allowanysha1inwant 1 &&
697 + test_commit -C server server1 &&
698 +
699 + git clone --filter=blob:none "file://$(pwd)/server" client &&
700 + test_commit -C client client1 &&
701 +
702 + test_commit -C server server2 &&
703 + COMMIT=$(git -C server rev-parse server2) &&
704 +
705 + test_must_fail git -C client push 2>err &&
706 + grep "fetch first" err &&
707 + git -C client rev-list --objects --missing=print "$COMMIT" >objects &&
708 + grep "^[?]$COMMIT" objects
709 +'
710 +
711 . "$TEST_DIRECTORY"/lib-httpd.sh
712 start_httpd
713