Support +<src>:<dst> format in push as well.
authorJunio C Hamano <junkio@cox.net>
Wed, 24 Aug 2005 07:40:14 +0000 (00:40 -0700)
committerJunio C Hamano <junkio@cox.net>
Wed, 24 Aug 2005 23:50:53 +0000 (16:50 -0700)
Signed-off-by: Junio C Hamano <junkio@cox.net>
cache.h
connect.c
send-pack.c

diff --git a/cache.h b/cache.h
index ba5c4ab7eea18ac4782d5f31a80330f8b487f1b0..1478631b40bf122556e50d19686868b1fb03b712 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -309,6 +309,7 @@ struct ref {
        struct ref *next;
        unsigned char old_sha1[20];
        unsigned char new_sha1[20];
+       unsigned char force;
        struct ref *peer_ref; /* when renaming */
        char name[0];
 };
index a6657b13848b5474ffde7edb0ad60ed969f22852..7cd587357e31ece5451df7ff5616a924de601af3 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -82,15 +82,26 @@ int path_match(const char *path, int nr, char **match)
 struct refspec {
        char *src;
        char *dst;
+       char force;
 };
 
+/*
+ * A:B means fast forward remote B with local A.
+ * +A:B means overwrite remote B with local A.
+ * +A is a shorthand for +A:A.
+ * A is a shorthand for A:A.
+ */
 static struct refspec *parse_ref_spec(int nr_refspec, char **refspec)
 {
        int i;
-       struct refspec *rs = xmalloc(sizeof(*rs) * (nr_refspec + 1));
+       struct refspec *rs = xcalloc(sizeof(*rs), (nr_refspec + 1));
        for (i = 0; i < nr_refspec; i++) {
                char *sp, *dp, *ep;
                sp = refspec[i];
+               if (*sp == '+') {
+                       rs[i].force = 1;
+                       sp++;
+               }
                ep = strchr(sp, ':');
                if (ep) {
                        dp = ep + 1;
@@ -216,8 +227,10 @@ static int match_explicit_refs(struct ref *src, struct ref *dst,
                        error("dst ref %s receives from more than one src.",
                              matched_dst->name);
                }
-               else
+               else {
                        matched_dst->peer_ref = matched_src;
+                       matched_dst->force = rs[i].force;
+               }
        }
        return -errs;
 }
index 0ab135c9881c4d9fa6b82ea80f5e62d2fbf17d28..55d8ff7e102fa6cc369c993035c0579c2d33b775 100644 (file)
@@ -206,7 +206,8 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec)
                /* This part determines what can overwrite what.
                 * The rules are:
                 *
-                * (0) you can always use --force.
+                * (0) you can always use --force or +A:B notation to
+                *     selectively force individual ref pairs.
                 *
                 * (1) if the old thing does not exist, it is OK.
                 *
@@ -218,16 +219,19 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec)
                 *     descendant of old, it is OK.
                 */
 
-               if (!force_update && !is_zero_sha1(ref->old_sha1)) {
+               if (!force_update &&
+                   !is_zero_sha1(ref->old_sha1) &&
+                   !ref->force) {
                        if (!has_sha1_file(ref->old_sha1)) {
                                error("remote '%s' object %s does not "
                                      "exist on local",
                                      ref->name, sha1_to_hex(ref->old_sha1));
                                continue;
                        }
+
                        /* We assume that local is fsck-clean.  Otherwise
-                        * you _could_ have a old tag which points at
-                        * something you do not have which may or may not
+                        * you _could_ have an old tag which points at
+                        * something you do not have, which may or may not
                         * be a commit.
                         */
                        if (!ref_newer(ref->peer_ref->new_sha1,