Skip to content

Commit 832e719

Browse files
committed
Merge branch 'cb/maint-update-ref-fix' into maint
* cb/maint-update-ref-fix: push: fix local refs update if already up-to-date do not force write of packed refs
2 parents 2819854 + 16ed2f4 commit 832e719

File tree

4 files changed

+50
-17
lines changed

4 files changed

+50
-17
lines changed

builtin-send-pack.c

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref)
222222
{
223223
struct refspec rs;
224224

225-
if (ref->status != REF_STATUS_OK)
225+
if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE)
226226
return;
227227

228228
rs.src = ref->name;
@@ -424,24 +424,19 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
424424
*/
425425
new_refs = 0;
426426
for (ref = remote_refs; ref; ref = ref->next) {
427-
const unsigned char *new_sha1;
428-
429-
if (!ref->peer_ref) {
430-
if (!args.send_mirror)
431-
continue;
432-
new_sha1 = null_sha1;
433-
}
434-
else
435-
new_sha1 = ref->peer_ref->new_sha1;
436427

428+
if (ref->peer_ref)
429+
hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
430+
else if (!args.send_mirror)
431+
continue;
437432

438-
ref->deletion = is_null_sha1(new_sha1);
433+
ref->deletion = is_null_sha1(ref->new_sha1);
439434
if (ref->deletion && !allow_deleting_refs) {
440435
ref->status = REF_STATUS_REJECT_NODELETE;
441436
continue;
442437
}
443438
if (!ref->deletion &&
444-
!hashcmp(ref->old_sha1, new_sha1)) {
439+
!hashcmp(ref->old_sha1, ref->new_sha1)) {
445440
ref->status = REF_STATUS_UPTODATE;
446441
continue;
447442
}
@@ -469,14 +464,13 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
469464
!ref->deletion &&
470465
!is_null_sha1(ref->old_sha1) &&
471466
(!has_sha1_file(ref->old_sha1)
472-
|| !ref_newer(new_sha1, ref->old_sha1));
467+
|| !ref_newer(ref->new_sha1, ref->old_sha1));
473468

474469
if (ref->nonfastforward && !ref->force && !args.force_update) {
475470
ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
476471
continue;
477472
}
478473

479-
hashcpy(ref->new_sha1, new_sha1);
480474
if (!ref->deletion)
481475
new_refs++;
482476

refs.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -789,10 +789,10 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
789789
char *ref_file;
790790
const char *orig_ref = ref;
791791
struct ref_lock *lock;
792-
struct stat st;
793792
int last_errno = 0;
794793
int type, lflags;
795794
int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
795+
int missing = 0;
796796

797797
lock = xcalloc(1, sizeof(struct ref_lock));
798798
lock->lock_fd = -1;
@@ -820,12 +820,13 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
820820
orig_ref, strerror(errno));
821821
goto error_return;
822822
}
823+
missing = is_null_sha1(lock->old_sha1);
823824
/* When the ref did not exist and we are creating it,
824825
* make sure there is no existing ref that is packed
825826
* whose name begins with our refname, nor a ref whose
826827
* name is a proper prefix of our refname.
827828
*/
828-
if (is_null_sha1(lock->old_sha1) &&
829+
if (missing &&
829830
!is_refname_available(ref, NULL, get_packed_refs(), 0))
830831
goto error_return;
831832

@@ -839,7 +840,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
839840
lock->ref_name = xstrdup(ref);
840841
lock->orig_ref_name = xstrdup(orig_ref);
841842
ref_file = git_path("%s", ref);
842-
if (lstat(ref_file, &st) && errno == ENOENT)
843+
if (missing)
843844
lock->force_write = 1;
844845
if ((flags & REF_NODEREF) && (type & REF_ISSYMREF))
845846
lock->force_write = 1;

t/t3210-pack-refs.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ test_expect_success \
9696
git branch -d n/o/p &&
9797
git branch n'
9898

99+
test_expect_success \
100+
'see if up-to-date packed refs are preserved' \
101+
'git branch q &&
102+
git pack-refs --all --prune &&
103+
git update-ref refs/heads/q refs/heads/q &&
104+
! test -f .git/refs/heads/q'
105+
99106
test_expect_success 'pack, prune and repack' '
100107
git tag foo &&
101108
git pack-refs --all --prune &&

t/t5516-fetch-push.sh

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,37 @@ test_expect_success 'push updates local refs' '
437437
438438
'
439439

440+
test_expect_success 'push updates up-to-date local refs' '
441+
442+
rm -rf parent child &&
443+
mkdir parent &&
444+
(cd parent && git init &&
445+
echo one >foo && git add foo && git commit -m one) &&
446+
git clone parent child1 &&
447+
git clone parent child2 &&
448+
(cd child1 &&
449+
echo two >foo && git commit -a -m two &&
450+
git push) &&
451+
(cd child2 &&
452+
git pull ../child1 master &&
453+
git push &&
454+
test $(git rev-parse master) = $(git rev-parse remotes/origin/master))
455+
456+
'
457+
458+
test_expect_success 'push preserves up-to-date packed refs' '
459+
460+
rm -rf parent child &&
461+
mkdir parent &&
462+
(cd parent && git init &&
463+
echo one >foo && git add foo && git commit -m one) &&
464+
git clone parent child &&
465+
(cd child &&
466+
git push &&
467+
! test -f .git/refs/remotes/origin/master)
468+
469+
'
470+
440471
test_expect_success 'push does not update local refs on failure' '
441472
442473
rm -rf parent child &&

0 commit comments

Comments
 (0)