git-fetch: do not fail when remote branch disappears
authorJunio C Hamano <gitster@pobox.com>
Sat, 27 Oct 2007 06:09:48 +0000 (23:09 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 28 Oct 2007 21:06:39 +0000 (14:06 -0700)
When the branch named with branch.$name.merge is not covered by
the fetch configuration for the remote repository named with
branch.$name.remote, we automatically add that branch to the set
of branches to be fetched.  However, if the remote repository
does not have that branch (e.g. it used to exist, but got
removed), this is not a reason to fail the git-fetch itself.

The situation however will be noticed if git-fetch was called by
git-pull, as the resulting FETCH_HEAD would not have any entry
that is marked for merging.

Acked-By: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin-fetch.c
remote.c
remote.h

index b9d2b0c27e3c09dd2746db94c25c00eaa492ba7c..003ed76d16236ec6857a19d6223518e6e73bdc93 100644 (file)
@@ -48,15 +48,21 @@ static void add_merge_config(struct ref **head,
                if (rm)
                        continue;
 
-               /* Not fetched to a tracking branch?  We need to fetch
+               /*
+                * 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.
+                * 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
+                * there is no entry in the resulting FETCH_HEAD marked
+                * for merging.
                 */
                refspec.src = branch->merge[i]->src;
                refspec.dst = NULL;
                refspec.pattern = 0;
                refspec.force = 0;
-               get_fetch_map(remote_refs, &refspec, tail);
+               get_fetch_map(remote_refs, &refspec, tail, 1);
                for (rm = *old_tail; rm; rm = rm->next)
                        rm->merge = 1;
        }
@@ -75,7 +81,7 @@ static struct ref *get_ref_map(struct transport *transport,
 
        if (ref_count || tags) {
                for (i = 0; i < ref_count; i++) {
-                       get_fetch_map(remote_refs, &refs[i], &tail);
+                       get_fetch_map(remote_refs, &refs[i], &tail, 0);
                        if (refs[i].dst && refs[i].dst[0])
                                *autotags = 1;
                }
@@ -88,7 +94,7 @@ static struct ref *get_ref_map(struct transport *transport,
                        refspec.dst = "refs/tags/";
                        refspec.pattern = 1;
                        refspec.force = 0;
-                       get_fetch_map(remote_refs, &refspec, &tail);
+                       get_fetch_map(remote_refs, &refspec, &tail, 0);
                }
        } else {
                /* Use the defaults */
@@ -97,7 +103,7 @@ static struct ref *get_ref_map(struct transport *transport,
                int has_merge = branch_has_merge_config(branch);
                if (remote && (remote->fetch_refspec_nr || has_merge)) {
                        for (i = 0; i < remote->fetch_refspec_nr; i++) {
-                               get_fetch_map(remote_refs, &remote->fetch[i], &tail);
+                               get_fetch_map(remote_refs, &remote->fetch[i], &tail, 0);
                                if (remote->fetch[i].dst &&
                                    remote->fetch[i].dst[0])
                                        *autotags = 1;
@@ -110,11 +116,13 @@ static struct ref *get_ref_map(struct transport *transport,
                         * as given in branch.<name>.remote, we add the
                         * ref given in branch.<name>.merge, too.
                         */
-                       if (has_merge && !strcmp(branch->remote_name,
-                                               remote->name))
+                       if (has_merge &&
+                           !strcmp(branch->remote_name, remote->name))
                                add_merge_config(&ref_map, remote_refs, branch, &tail);
                } else {
                        ref_map = get_remote_ref(remote_refs, "HEAD");
+                       if (!ref_map)
+                               die("Couldn't find remote ref HEAD");
                        ref_map->merge = 1;
                }
        }
index 170015aabfc18d028b22a5200cbddc5a5ec3f042..bec2ba1adbed02af54572be924dcfbb47bf9c423 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -857,7 +857,7 @@ struct ref *get_remote_ref(struct ref *remote_refs, const char *name)
        struct ref *ref = find_ref_by_name_abbrev(remote_refs, name);
 
        if (!ref)
-               die("Couldn't find remote ref %s\n", name);
+               return NULL;
 
        return copy_ref(ref);
 }
@@ -889,20 +889,24 @@ static struct ref *get_local_ref(const char *name)
 
 int get_fetch_map(struct ref *remote_refs,
                  const struct refspec *refspec,
-                 struct ref ***tail)
+                 struct ref ***tail,
+                 int missing_ok)
 {
        struct ref *ref_map, *rm;
 
        if (refspec->pattern) {
                ref_map = get_expanded_map(remote_refs, refspec);
        } else {
-               ref_map = get_remote_ref(remote_refs,
-                                        refspec->src[0] ?
-                                        refspec->src : "HEAD");
-
-               ref_map->peer_ref = get_local_ref(refspec->dst);
-               if (ref_map->peer_ref && refspec->force)
-                       ref_map->peer_ref->force = 1;
+               const char *name = refspec->src[0] ? refspec->src : "HEAD";
+
+               ref_map = get_remote_ref(remote_refs, name);
+               if (!missing_ok && !ref_map)
+                       die("Couldn't find remote ref %s", name);
+               if (ref_map) {
+                       ref_map->peer_ref = get_local_ref(refspec->dst);
+                       if (ref_map->peer_ref && refspec->force)
+                               ref_map->peer_ref->force = 1;
+               }
        }
 
        for (rm = ref_map; rm; rm = rm->next) {
index c62636d78ef996b97aef73cf37cfb5de3f279145..878b4ecc32a2a4b5be4e0444ae4510e1a7ab01cb 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -67,9 +67,12 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
  * *tail is the pointer to the tail pointer of the list of results
  * beforehand, and will be set to the tail pointer of the list of
  * results afterward.
+ *
+ * missing_ok is usually false, but when we are adding branch.$name.merge
+ * it is Ok if the branch is not at the remote anymore.
  */
 int get_fetch_map(struct ref *remote_refs, const struct refspec *refspec,
-                 struct ref ***tail);
+                 struct ref ***tail, int missing_ok);
 
 struct ref *get_remote_ref(struct ref *remote_refs, const char *name);