#include "refs.h"
#include "commit.h"
#include "builtin.h"
-#include "path-list.h"
+#include "string-list.h"
#include "remote.h"
#include "transport.h"
#include "run-command.h"
#include "parse-options.h"
static const char * const builtin_fetch_usage[] = {
- "git-fetch [options] [<repository> <refspec>...]",
+ "git fetch [options] [<repository> <refspec>...]",
NULL
};
/*
* Not fetched to a tracking branch? We need to fetch
* it anyway to allow this branch's "branch.$name.merge"
- * to be honored by git-pull, but we do not have to
+ * to be honored by 'git pull', but we do not have to
* fail if branch.$name.merge is misconfigured to point
* at a nonexisting branch. If we were indeed called by
- * git-pull, it will notice the misconfiguration because
+ * 'git pull', it will notice the misconfiguration because
* there is no entry in the resulting FETCH_HEAD marked
* for merging.
*/
/* Merge everything on the command line, but not --tags */
for (rm = ref_map; rm; rm = rm->next)
rm->merge = 1;
- if (tags == TAGS_SET) {
- struct refspec refspec;
- refspec.src = "refs/tags/";
- refspec.dst = "refs/tags/";
- refspec.pattern = 1;
- refspec.force = 0;
- get_fetch_map(remote_refs, &refspec, &tail, 0);
- }
+ if (tags == TAGS_SET)
+ get_fetch_map(remote_refs, tag_refspec, &tail, 0);
} else {
/* Use the defaults */
struct remote *remote = transport->remote;
lock = lock_any_ref_for_update(ref->name,
check_old ? ref->old_sha1 : NULL, 0);
if (!lock)
- return 1;
+ return 2;
if (write_ref_sha1(lock, ref->new_sha1, msg) < 0)
- return 1;
+ return 2;
return 0;
}
if (type < 0)
die("object %s not found", sha1_to_hex(ref->new_sha1));
- if (!*ref->name) {
- /* Not storing */
- if (verbose)
- sprintf(display, "* branch %s -> FETCH_HEAD", remote);
- return 0;
- }
-
if (!hashcmp(ref->old_sha1, ref->new_sha1)) {
if (verbose)
sprintf(display, "= %-*s %-*s -> %s", SUMMARY_WIDTH,
if (!is_null_sha1(ref->old_sha1) &&
!prefixcmp(ref->name, "refs/tags/")) {
- sprintf(display, "- %-*s %-*s -> %s",
+ int r;
+ r = s_update_ref("updating tag", ref, 0);
+ sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : '-',
SUMMARY_WIDTH, "[tag update]", REFCOL_WIDTH, remote,
- pretty_ref);
- return s_update_ref("updating tag", ref, 0);
+ pretty_ref, r ? " (unable to update local ref)" : "");
+ return r;
}
current = lookup_commit_reference_gently(ref->old_sha1, 1);
if (!current || !updated) {
const char *msg;
const char *what;
+ int r;
if (!strncmp(ref->name, "refs/tags/", 10)) {
msg = "storing tag";
what = "[new tag]";
what = "[new branch]";
}
- sprintf(display, "* %-*s %-*s -> %s", SUMMARY_WIDTH, what,
- REFCOL_WIDTH, remote, pretty_ref);
- return s_update_ref(msg, ref, 0);
+ r = s_update_ref(msg, ref, 0);
+ sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : '*',
+ SUMMARY_WIDTH, what, REFCOL_WIDTH, remote, pretty_ref,
+ r ? " (unable to update local ref)" : "");
+ return r;
}
if (in_merge_bases(current, &updated, 1)) {
char quickref[83];
+ int r;
strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
strcat(quickref, "..");
strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
- sprintf(display, " %-*s %-*s -> %s", SUMMARY_WIDTH, quickref,
- REFCOL_WIDTH, remote, pretty_ref);
- return s_update_ref("fast forward", ref, 1);
+ r = s_update_ref("fast forward", ref, 1);
+ sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : ' ',
+ SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
+ pretty_ref, r ? " (unable to update local ref)" : "");
+ return r;
} else if (force || ref->force) {
char quickref[84];
+ int r;
strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
strcat(quickref, "...");
strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
- sprintf(display, "+ %-*s %-*s -> %s (forced update)",
- SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote, pretty_ref);
- return s_update_ref("forced-update", ref, 1);
+ r = s_update_ref("forced-update", ref, 1);
+ sprintf(display, "%c %-*s %-*s -> %s (%s)", r ? '!' : '+',
+ SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
+ pretty_ref,
+ r ? "unable to update local ref" : "forced update");
+ return r;
} else {
sprintf(display, "! %-*s %-*s -> %s (non fast forward)",
SUMMARY_WIDTH, "[rejected]", REFCOL_WIDTH, remote,
}
}
-static int store_updated_refs(const char *url, struct ref *ref_map)
+static int store_updated_refs(const char *url, const char *remote_name,
+ struct ref *ref_map)
{
FILE *fp;
struct commit *commit;
- int url_len, i, note_len, shown_url = 0;
+ int url_len, i, note_len, shown_url = 0, rc = 0;
char note[1024];
const char *what, *kind;
struct ref *rm;
rm->merge ? "" : "not-for-merge",
note);
- if (ref) {
- update_local_ref(ref, what, verbose, note);
- if (*note) {
- if (!shown_url) {
- fprintf(stderr, "From %.*s\n",
- url_len, url);
- shown_url = 1;
- }
- fprintf(stderr, " %s\n", note);
+ if (ref)
+ rc |= update_local_ref(ref, what, verbose, note);
+ else
+ sprintf(note, "* %-*s %-*s -> FETCH_HEAD",
+ SUMMARY_WIDTH, *kind ? kind : "branch",
+ REFCOL_WIDTH, *what ? what : "HEAD");
+ if (*note) {
+ if (!shown_url) {
+ fprintf(stderr, "From %.*s\n",
+ url_len, url);
+ shown_url = 1;
}
+ fprintf(stderr, " %s\n", note);
}
}
fclose(fp);
- return 0;
+ if (rc & 2)
+ error("some local refs could not be updated; try running\n"
+ " 'git remote prune %s' to remove any old, conflicting "
+ "branches", remote_name);
+ return rc;
}
/*
* The refs we are going to fetch are in to_fetch (nr_heads in
* total). If running
*
- * $ git-rev-list --objects to_fetch[0] to_fetch[1] ... --not --all
+ * $ git rev-list --objects to_fetch[0] to_fetch[1] ... --not --all
*
* does not error out, that means everything reachable from the
* refs we are going to fetch exists and is connected to some of
if (ret)
ret = transport_fetch_refs(transport, ref_map);
if (!ret)
- ret |= store_updated_refs(transport->url, ref_map);
+ ret |= store_updated_refs(transport->url,
+ transport->remote->name,
+ ref_map);
transport_unlock_pack(transport);
return ret;
}
static int add_existing(const char *refname, const unsigned char *sha1,
int flag, void *cbdata)
{
- struct path_list *list = (struct path_list *)cbdata;
- path_list_insert(refname, list);
+ struct string_list *list = (struct string_list *)cbdata;
+ string_list_insert(refname, list);
return 0;
}
struct ref **head,
struct ref ***tail)
{
- struct path_list existing_refs = { NULL, 0, 0, 0 };
- struct path_list new_refs = { NULL, 0, 0, 1 };
+ struct string_list existing_refs = { NULL, 0, 0, 0 };
+ struct string_list new_refs = { NULL, 0, 0, 1 };
char *ref_name;
int ref_name_len;
const unsigned char *ref_sha1;
}
}
- if (!path_list_has_path(&existing_refs, ref_name) &&
- !path_list_has_path(&new_refs, ref_name) &&
+ if (!string_list_has_string(&existing_refs, ref_name) &&
+ !string_list_has_string(&new_refs, ref_name) &&
(has_sha1_file(ref->old_sha1) ||
will_fetch(head, ref->old_sha1))) {
- path_list_insert(ref_name, &new_refs);
+ string_list_insert(ref_name, &new_refs);
- rm = alloc_ref(strlen(ref_name) + 1);
- strcpy(rm->name, ref_name);
- rm->peer_ref = alloc_ref(strlen(ref_name) + 1);
- strcpy(rm->peer_ref->name, ref_name);
+ rm = alloc_ref_from_str(ref_name);
+ rm->peer_ref = alloc_ref_from_str(ref_name);
hashcpy(rm->old_sha1, ref_sha1);
**tail = rm;
}
free(ref_name);
}
- path_list_clear(&existing_refs, 0);
- path_list_clear(&new_refs, 0);
+ string_list_clear(&existing_refs, 0);
+ string_list_clear(&new_refs, 0);
}
static int do_fetch(struct transport *transport,
free_refs(ref_map);
}
- transport_disconnect(transport);
-
return 0;
}
int i;
static const char **refs = NULL;
int ref_nr = 0;
+ int exit_code;
/* Record the command line for the reflog */
strbuf_addstr(&default_rla, "fetch");
signal(SIGINT, unlock_pack_on_signal);
atexit(unlock_pack);
- return do_fetch(transport,
+ exit_code = do_fetch(transport,
parse_fetch_refspec(ref_nr, refs), ref_nr);
+ transport_disconnect(transport);
+ transport = NULL;
+ return exit_code;
}