Skip to content

Commit 9b5f5e0

Browse files
committed
Merge branch 'kn/fix-fetch-backfill-tag-with-batched-ref-updates' into seen
"git fetch" that involves fetching tags, when a tag being fetched needs to overwrite existing one, failed to fetch other tags, which has been corrected. * kn/fix-fetch-backfill-tag-with-batched-ref-updates: fetch: fix non-conflicting tags not being committed fetch: extract out reference committing logic
2 parents 4f96afa + 456f6a4 commit 9b5f5e0

File tree

2 files changed

+103
-26
lines changed

2 files changed

+103
-26
lines changed

builtin/fetch.c

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,6 +1681,36 @@ static void ref_transaction_rejection_handler(const char *refname,
16811681
*data->retcode = 1;
16821682
}
16831683

1684+
/*
1685+
* Commit the reference transaction. If it isn't an atomic transaction, handle
1686+
* rejected updates as part of using batched updates.
1687+
*/
1688+
static int commit_ref_transaction(struct ref_transaction **transaction,
1689+
bool is_atomic, const char *remote_name,
1690+
struct strbuf *err)
1691+
{
1692+
int retcode = ref_transaction_commit(*transaction, err);
1693+
if (retcode)
1694+
goto out;
1695+
1696+
if (!is_atomic) {
1697+
struct ref_rejection_data data = {
1698+
.conflict_msg_shown = 0,
1699+
.remote_name = remote_name,
1700+
.retcode = &retcode,
1701+
};
1702+
1703+
ref_transaction_for_each_rejected_update(*transaction,
1704+
ref_transaction_rejection_handler,
1705+
&data);
1706+
}
1707+
1708+
out:
1709+
ref_transaction_free(*transaction);
1710+
*transaction = NULL;
1711+
return retcode;
1712+
}
1713+
16841714
static int do_fetch(struct transport *transport,
16851715
struct refspec *rs,
16861716
const struct fetch_config *config)
@@ -1853,33 +1883,10 @@ static int do_fetch(struct transport *transport,
18531883
if (retcode)
18541884
goto cleanup;
18551885

1856-
retcode = ref_transaction_commit(transaction, &err);
1857-
if (retcode) {
1858-
/*
1859-
* Explicitly handle transaction cleanup to avoid
1860-
* aborting an already closed transaction.
1861-
*/
1862-
ref_transaction_free(transaction);
1863-
transaction = NULL;
1886+
retcode = commit_ref_transaction(&transaction, atomic_fetch,
1887+
transport->remote->name, &err);
1888+
if (retcode)
18641889
goto cleanup;
1865-
}
1866-
1867-
if (!atomic_fetch) {
1868-
struct ref_rejection_data data = {
1869-
.retcode = &retcode,
1870-
.conflict_msg_shown = 0,
1871-
.remote_name = transport->remote->name,
1872-
};
1873-
1874-
ref_transaction_for_each_rejected_update(transaction,
1875-
ref_transaction_rejection_handler,
1876-
&data);
1877-
if (retcode) {
1878-
ref_transaction_free(transaction);
1879-
transaction = NULL;
1880-
goto cleanup;
1881-
}
1882-
}
18831890

18841891
commit_fetch_head(&fetch_head);
18851892

@@ -1945,6 +1952,14 @@ static int do_fetch(struct transport *transport,
19451952
}
19461953

19471954
cleanup:
1955+
/*
1956+
* When using batched updates, we want to commit the non-rejected
1957+
* updates and also handle the rejections.
1958+
*/
1959+
if (retcode && !atomic_fetch && transaction)
1960+
commit_ref_transaction(&transaction, false,
1961+
transport->remote->name, &err);
1962+
19481963
if (retcode) {
19491964
if (err.len) {
19501965
error("%s", err.buf);

t/t5510-fetch.sh

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,6 +1552,7 @@ test_expect_success CASE_INSENSITIVE_FS,REFFILES 'D/F conflict on case insensiti
15521552
'
15531553

15541554
test_expect_success REFFILES 'D/F conflict on case sensitive filesystem with lock' '
1555+
test_when_finished rm -rf base repo &&
15551556
(
15561557
git init --ref-format=reftable base &&
15571558
cd base &&
@@ -1577,6 +1578,67 @@ test_expect_success REFFILES 'D/F conflict on case sensitive filesystem with loc
15771578
)
15781579
'
15791580

1581+
test_expect_success 'fetch --tags fetches existing tags' '
1582+
test_when_finished rm -rf base repo &&
1583+
1584+
git init base &&
1585+
git -C base commit --allow-empty -m "empty-commit" &&
1586+
1587+
git clone --bare base repo &&
1588+
1589+
git -C base tag tag-1 &&
1590+
git -C repo for-each-ref >out &&
1591+
test_grep ! "tag-1" out &&
1592+
git -C repo fetch --tags &&
1593+
git -C repo for-each-ref >out &&
1594+
test_grep "tag-1" out
1595+
'
1596+
1597+
test_expect_success 'fetch --tags fetches non-conflicting tags' '
1598+
test_when_finished rm -rf base repo &&
1599+
1600+
git init base &&
1601+
git -C base commit --allow-empty -m "empty-commit" &&
1602+
git -C base tag tag-1 &&
1603+
1604+
git clone --bare base repo &&
1605+
1606+
git -C base tag tag-2 &&
1607+
git -C repo for-each-ref >out &&
1608+
test_grep ! "tag-2" out &&
1609+
1610+
git -C base commit --allow-empty -m "second empty-commit" &&
1611+
git -C base tag -f tag-1 &&
1612+
1613+
test_must_fail git -C repo fetch --tags 2>out &&
1614+
test_grep "tag-1 (would clobber existing tag)" out &&
1615+
git -C repo for-each-ref >out &&
1616+
test_grep "tag-2" out
1617+
'
1618+
1619+
test_expect_success "backfill tags when providing a refspec" '
1620+
test_when_finished rm -rf source target &&
1621+
1622+
git init source &&
1623+
git -C source commit --allow-empty --message common &&
1624+
git clone file://"$(pwd)"/source target &&
1625+
(
1626+
cd source &&
1627+
test_commit history &&
1628+
test_commit fetch-me
1629+
) &&
1630+
1631+
# The "history" tag is backfilled eventhough we requested
1632+
# to only fetch HEAD
1633+
git -C target fetch origin HEAD:branch &&
1634+
git -C target tag -l >actual &&
1635+
cat >expect <<-\EOF &&
1636+
fetch-me
1637+
history
1638+
EOF
1639+
test_cmp expect actual
1640+
'
1641+
15801642
. "$TEST_DIRECTORY"/lib-httpd.sh
15811643
start_httpd
15821644

0 commit comments

Comments
 (0)