aboutsummaryrefslogtreecommitdiffstats
path: root/builtin/fetch.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/fetch.c')
-rw-r--r--builtin/fetch.c126
1 files changed, 59 insertions, 67 deletions
diff --git a/builtin/fetch.c b/builtin/fetch.c
index fe2b26c74a..5279997c96 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -14,7 +14,7 @@
#include "refs.h"
#include "refspec.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "oidset.h"
#include "oid-array.h"
#include "commit.h"
@@ -586,7 +586,7 @@ static struct ref *get_ref_map(struct remote *remote,
struct refspec_item tag_refspec;
/* also fetch all tags */
- refspec_item_init(&tag_refspec, TAG_REFSPEC, 0);
+ refspec_item_init_push(&tag_refspec, TAG_REFSPEC);
get_fetch_map(remote_refs, &tag_refspec, &tail, 0);
refspec_item_clear(&tag_refspec);
} else if (tags == TAGS_DEFAULT && *autotags) {
@@ -687,7 +687,7 @@ static int s_update_ref(const char *action,
switch (ref_transaction_commit(our_transaction, &err)) {
case 0:
break;
- case TRANSACTION_NAME_CONFLICT:
+ case REF_TRANSACTION_ERROR_NAME_CONFLICT:
ret = STORE_REF_ERROR_DF_CONFLICT;
goto out;
default:
@@ -1617,13 +1617,13 @@ static void report_set_head(const char *remote, const char *head_name,
strbuf_release(&buf_prefix);
}
-static int set_head(const struct ref *remote_refs, int follow_remote_head,
- const char *no_warn_branch)
+static int set_head(const struct ref *remote_refs, struct remote *remote)
{
- int result = 0, create_only, is_bare, was_detached;
+ int result = 0, create_only, baremirror, was_detached;
struct strbuf b_head = STRBUF_INIT, b_remote_head = STRBUF_INIT,
b_local_head = STRBUF_INIT;
- const char *remote = gtransport->remote->name;
+ int follow_remote_head = remote->follow_remote_head;
+ const char *no_warn_branch = remote->no_warn_branch;
char *head_name = NULL;
struct ref *ref, *matches;
struct ref *fetch_map = NULL, **fetch_map_tail = &fetch_map;
@@ -1638,14 +1638,11 @@ static int set_head(const struct ref *remote_refs, int follow_remote_head,
get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0);
matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
- fetch_map, 1);
+ fetch_map, REMOTE_GUESS_HEAD_ALL);
for (ref = matches; ref; ref = ref->next) {
string_list_append(&heads, strip_refshead(ref->name));
}
- if (follow_remote_head == FOLLOW_REMOTE_NEVER)
- goto cleanup;
-
if (!heads.nr)
result = 1;
else if (heads.nr > 1)
@@ -1655,17 +1652,17 @@ static int set_head(const struct ref *remote_refs, int follow_remote_head,
if (!head_name)
goto cleanup;
- is_bare = is_bare_repository();
- create_only = follow_remote_head == FOLLOW_REMOTE_ALWAYS ? 0 : !is_bare;
- if (is_bare) {
+ baremirror = is_bare_repository() && remote->mirror;
+ create_only = follow_remote_head == FOLLOW_REMOTE_ALWAYS ? 0 : !baremirror;
+ if (baremirror) {
strbuf_addstr(&b_head, "HEAD");
strbuf_addf(&b_remote_head, "refs/heads/%s", head_name);
} else {
- strbuf_addf(&b_head, "refs/remotes/%s/HEAD", remote);
- strbuf_addf(&b_remote_head, "refs/remotes/%s/%s", remote, head_name);
+ strbuf_addf(&b_head, "refs/remotes/%s/HEAD", remote->name);
+ strbuf_addf(&b_remote_head, "refs/remotes/%s/%s", remote->name, head_name);
}
/* make sure it's valid */
- if (!is_bare && !refs_ref_exists(refs, b_remote_head.buf)) {
+ if (!baremirror && !refs_ref_exists(refs, b_remote_head.buf)) {
result = 1;
goto cleanup;
}
@@ -1678,7 +1675,7 @@ static int set_head(const struct ref *remote_refs, int follow_remote_head,
if (verbosity >= 0 &&
follow_remote_head == FOLLOW_REMOTE_WARN &&
(!no_warn_branch || strcmp(no_warn_branch, head_name)))
- report_set_head(remote, head_name, &b_local_head, was_detached);
+ report_set_head(remote->name, head_name, &b_local_head, was_detached);
cleanup:
free(head_name);
@@ -1691,21 +1688,6 @@ cleanup:
return result;
}
-static int uses_remote_tracking(struct transport *transport, struct refspec *rs)
-{
- if (!remote_is_configured(transport->remote, 0))
- return 0;
-
- if (!rs->nr)
- rs = &transport->remote->fetch;
-
- for (int i = 0; i < rs->nr; i++)
- if (rs->items[i].dst)
- return 1;
-
- return 0;
-}
-
static int do_fetch(struct transport *transport,
struct refspec *rs,
const struct fetch_config *config)
@@ -1718,9 +1700,9 @@ static int do_fetch(struct transport *transport,
const struct ref *remote_refs;
struct transport_ls_refs_options transport_ls_refs_options =
TRANSPORT_LS_REFS_OPTIONS_INIT;
- int must_list_refs = 1;
struct fetch_head fetch_head = { 0 };
struct strbuf err = STRBUF_INIT;
+ int do_set_head = 0;
if (tags == TAGS_DEFAULT) {
if (transport->remote->fetch_tags == 2)
@@ -1737,27 +1719,16 @@ static int do_fetch(struct transport *transport,
}
if (rs->nr) {
- int i;
-
refspec_ref_prefixes(rs, &transport_ls_refs_options.ref_prefixes);
-
- /*
- * We can avoid listing refs if all of them are exact
- * OIDs
- */
- must_list_refs = 0;
- for (i = 0; i < rs->nr; i++) {
- if (!rs->items[i].exact_sha1) {
- must_list_refs = 1;
- break;
- }
- }
} else {
struct branch *branch = branch_get(NULL);
- if (transport->remote->fetch.nr)
+ if (transport->remote->fetch.nr) {
refspec_ref_prefixes(&transport->remote->fetch,
&transport_ls_refs_options.ref_prefixes);
+ if (transport->remote->follow_remote_head != FOLLOW_REMOTE_NEVER)
+ do_set_head = 1;
+ }
if (branch_has_merge_config(branch) &&
!strcmp(branch->remote_name, transport->remote->name)) {
int i;
@@ -1766,21 +1737,29 @@ static int do_fetch(struct transport *transport,
branch->merge[i]->src);
}
}
- }
- if (tags == TAGS_SET || tags == TAGS_DEFAULT) {
- must_list_refs = 1;
- if (transport_ls_refs_options.ref_prefixes.nr)
+ /*
+ * If there are no refs specified to fetch, then we just
+ * fetch HEAD; mention that to narrow the advertisement.
+ */
+ if (!transport_ls_refs_options.ref_prefixes.nr)
strvec_push(&transport_ls_refs_options.ref_prefixes,
- "refs/tags/");
+ "HEAD");
}
- if (uses_remote_tracking(transport, rs)) {
- must_list_refs = 1;
- strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
- }
+ if (tags == TAGS_SET || tags == TAGS_DEFAULT)
+ strvec_push(&transport_ls_refs_options.ref_prefixes,
+ "refs/tags/");
+
+ if (do_set_head)
+ strvec_push(&transport_ls_refs_options.ref_prefixes,
+ "HEAD");
- if (must_list_refs) {
+ /*
+ * Only initiate ref listing if we have at least one ref we want to
+ * know about.
+ */
+ if (transport_ls_refs_options.ref_prefixes.nr) {
trace2_region_enter("fetch", "remote_refs", the_repository);
remote_refs = transport_get_remote_refs(transport,
&transport_ls_refs_options);
@@ -1865,8 +1844,15 @@ static int do_fetch(struct transport *transport,
goto cleanup;
retcode = ref_transaction_commit(transaction, &err);
- if (retcode)
+ if (retcode) {
+ /*
+ * Explicitly handle transaction cleanup to avoid
+ * aborting an already closed transaction.
+ */
+ ref_transaction_free(transaction);
+ transaction = NULL;
goto cleanup;
+ }
}
commit_fetch_head(&fetch_head);
@@ -1924,13 +1910,13 @@ static int do_fetch(struct transport *transport,
"you need to specify exactly one branch with the --set-upstream option"));
}
}
- if (set_head(remote_refs, transport->remote->follow_remote_head,
- transport->remote->no_warn_branch))
- ;
+ if (do_set_head) {
/*
- * Way too many cases where this can go wrong
- * so let's just fail silently for now.
+ * Way too many cases where this can go wrong so let's just
+ * ignore errors and fail silently for now.
*/
+ set_head(remote_refs, transport->remote);
+ }
cleanup:
if (retcode) {
@@ -2366,8 +2352,14 @@ int cmd_fetch(int argc,
OPT_SET_INT_F(0, "refetch", &refetch,
N_("re-fetch without negotiating common commits"),
1, PARSE_OPT_NONEG),
- { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
- N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
+ {
+ .type = OPTION_STRING,
+ .long_name = "submodule-prefix",
+ .value = &submodule_prefix,
+ .argh = N_("dir"),
+ .help = N_("prepend this to submodule path output"),
+ .flags = PARSE_OPT_HIDDEN,
+ },
OPT_CALLBACK_F(0, "recurse-submodules-default",
&recurse_submodules_default, N_("on-demand"),
N_("default for recursive fetching of submodules "