summaryrefslogtreecommitdiff
path: root/builtin/fetch.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/fetch.c')
-rw-r--r--builtin/fetch.c104
1 files changed, 60 insertions, 44 deletions
diff --git a/builtin/fetch.c b/builtin/fetch.c
index dfde96a435..f7abbc31ff 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -712,7 +712,7 @@ static void adjust_refcol_width(const struct ref *ref)
int max, rlen, llen, len;
/* uptodate lines are only shown on high verbosity level */
- if (!verbosity && oideq(&ref->peer_ref->old_oid, &ref->old_oid))
+ if (verbosity <= 0 && oideq(&ref->peer_ref->old_oid, &ref->old_oid))
return;
max = term_columns();
@@ -748,6 +748,9 @@ static void prepare_format_display(struct ref *ref_map)
struct ref *rm;
const char *format = "full";
+ if (verbosity < 0)
+ return;
+
git_config_get_string_tmp("fetch.output", &format);
if (!strcasecmp(format, "full"))
compact_format = 0;
@@ -827,7 +830,12 @@ static void format_display(struct strbuf *display, char code,
const char *remote, const char *local,
int summary_width)
{
- int width = (summary_width + strlen(summary) - gettext_width(summary));
+ int width;
+
+ if (verbosity < 0)
+ return;
+
+ width = (summary_width + strlen(summary) - gettext_width(summary));
strbuf_addf(display, "%c %-*s ", code, width, summary);
if (!compact_format)
@@ -846,13 +854,11 @@ static int update_local_ref(struct ref *ref,
int summary_width)
{
struct commit *current = NULL, *updated;
- enum object_type type;
struct branch *current_branch = branch_get(NULL);
const char *pretty_ref = prettify_refname(ref->name);
int fast_forward = 0;
- type = oid_object_info(the_repository, &ref->new_oid, NULL);
- if (type < 0)
+ if (!repo_has_object_file(the_repository, &ref->new_oid))
die(_("object %s not found"), oid_to_hex(&ref->new_oid));
if (oideq(&ref->old_oid, &ref->new_oid)) {
@@ -964,7 +970,7 @@ static int update_local_ref(struct ref *ref,
}
}
-static int iterate_ref_map(void *cb_data, struct object_id *oid)
+static const struct object_id *iterate_ref_map(void *cb_data)
{
struct ref **rm = cb_data;
struct ref *ref = *rm;
@@ -972,10 +978,9 @@ static int iterate_ref_map(void *cb_data, struct object_id *oid)
while (ref && ref->status == REF_STATUS_REJECT_SHALLOW)
ref = ref->next;
if (!ref)
- return -1; /* end of the list */
+ return NULL;
*rm = ref->next;
- oidcpy(oid, &ref->old_oid);
- return 0;
+ return &ref->old_oid;
}
struct fetch_head {
@@ -1074,7 +1079,6 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
int connectivity_checked, struct ref *ref_map)
{
struct fetch_head fetch_head;
- struct commit *commit;
int url_len, i, rc = 0;
struct strbuf note = STRBUF_INIT, err = STRBUF_INIT;
struct ref_transaction *transaction = NULL;
@@ -1122,20 +1126,33 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
want_status <= FETCH_HEAD_IGNORE;
want_status++) {
for (rm = ref_map; rm; rm = rm->next) {
+ struct commit *commit = NULL;
struct ref *ref = NULL;
if (rm->status == REF_STATUS_REJECT_SHALLOW) {
if (want_status == FETCH_HEAD_MERGE)
- warning(_("reject %s because shallow roots are not allowed to be updated"),
+ warning(_("rejected %s because shallow roots are not allowed to be updated"),
rm->peer_ref ? rm->peer_ref->name : rm->name);
continue;
}
- commit = lookup_commit_reference_gently(the_repository,
- &rm->old_oid,
- 1);
- if (!commit)
- rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE;
+ /*
+ * References in "refs/tags/" are often going to point
+ * to annotated tags, which are not part of the
+ * commit-graph. We thus only try to look up refs in
+ * the graph which are not in that namespace to not
+ * regress performance in repositories with many
+ * annotated tags.
+ */
+ if (!starts_with(rm->name, "refs/tags/"))
+ commit = lookup_commit_in_graph(the_repository, &rm->old_oid);
+ if (!commit) {
+ commit = lookup_commit_reference_gently(the_repository,
+ &rm->old_oid,
+ 1);
+ if (!commit)
+ rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE;
+ }
if (rm->fetch_head_status != want_status)
continue;
@@ -1202,13 +1219,12 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
"FETCH_HEAD", summary_width);
}
if (note.len) {
- if (verbosity >= 0 && !shown_url) {
+ if (!shown_url) {
fprintf(stderr, _("From %.*s\n"),
url_len, url);
shown_url = 1;
}
- if (verbosity >= 0)
- fprintf(stderr, " %s\n", note.buf);
+ fprintf(stderr, " %s\n", note.buf);
}
}
}
@@ -1229,7 +1245,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
" 'git remote prune %s' to remove any old, conflicting "
"branches"), remote_name);
- if (advice_fetch_show_forced_updates) {
+ if (advice_enabled(ADVICE_FETCH_SHOW_FORCED_UPDATES)) {
if (!fetch_show_forced_updates) {
warning(_(warn_show_forced_updates));
} else if (forced_updates_ms > FORCED_UPDATES_DELAY_WARNING_IN_MS) {
@@ -1282,37 +1298,35 @@ static int check_exist_and_connected(struct ref *ref_map)
return check_connected(iterate_ref_map, &rm, &opt);
}
-static int fetch_refs(struct transport *transport, struct ref *ref_map)
+static int fetch_and_consume_refs(struct transport *transport, struct ref *ref_map)
{
- int ret = check_exist_and_connected(ref_map);
+ int connectivity_checked = 1;
+ int ret;
+
+ /*
+ * We don't need to perform a fetch in case we can already satisfy all
+ * refs.
+ */
+ ret = check_exist_and_connected(ref_map);
if (ret) {
trace2_region_enter("fetch", "fetch_refs", the_repository);
ret = transport_fetch_refs(transport, ref_map);
trace2_region_leave("fetch", "fetch_refs", the_repository);
+ if (ret)
+ goto out;
+ connectivity_checked = transport->smart_options ?
+ transport->smart_options->connectivity_checked : 0;
}
- if (!ret)
- /*
- * Keep the new pack's ".keep" file around to allow the caller
- * time to update refs to reference the new objects.
- */
- return 0;
- transport_unlock_pack(transport);
- return ret;
-}
-/* Update local refs based on the ref values fetched from a remote */
-static int consume_refs(struct transport *transport, struct ref *ref_map)
-{
- int connectivity_checked = transport->smart_options
- ? transport->smart_options->connectivity_checked : 0;
- int ret;
trace2_region_enter("fetch", "consume_refs", the_repository);
ret = store_updated_refs(transport->url,
transport->remote->name,
connectivity_checked,
ref_map);
- transport_unlock_pack(transport);
trace2_region_leave("fetch", "consume_refs", the_repository);
+
+out:
+ transport_unlock_pack(transport);
return ret;
}
@@ -1428,7 +1442,9 @@ static void add_negotiation_tips(struct git_transport_options *smart_options)
if (!has_glob_specials(s)) {
struct object_id oid;
if (get_oid(s, &oid))
- die("%s is not a valid object", s);
+ die(_("%s is not a valid object"), s);
+ if (!has_object(the_repository, &oid, 0))
+ die(_("the object %s does not exist"), s);
oid_array_append(oids, &oid);
continue;
}
@@ -1499,8 +1515,7 @@ static void backfill_tags(struct transport *transport, struct ref *ref_map)
transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
transport_set_option(transport, TRANS_OPT_DEPTH, "0");
transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL);
- if (!fetch_refs(transport, ref_map))
- consume_refs(transport, ref_map);
+ fetch_and_consume_refs(transport, ref_map);
if (gsecondary) {
transport_disconnect(gsecondary);
@@ -1591,7 +1606,7 @@ static int do_fetch(struct transport *transport,
transport->url);
}
}
- if (fetch_refs(transport, ref_map) || consume_refs(transport, ref_map)) {
+ if (fetch_and_consume_refs(transport, ref_map)) {
free_refs(ref_map);
retcode = 1;
goto cleanup;
@@ -1990,6 +2005,9 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
fetch_config_from_gitmodules(sfjc, rs);
}
+ if (negotiate_only && !negotiation_tip.nr)
+ die(_("--negotiate-only needs one or more --negotiate-tip=*"));
+
if (deepen_relative) {
if (deepen_relative < 0)
die(_("Negative depth in --deepen is not supported"));
@@ -2130,8 +2148,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
NULL);
}
- close_object_store(the_repository->objects);
-
if (enable_auto_gc)
run_auto_maintenance(verbosity < 0);