send-pack: allow generic sha1 expression on the source side.
authorJunio C Hamano <junkio@cox.net>
Sat, 6 Aug 2005 17:12:03 +0000 (10:12 -0700)
committerJunio C Hamano <junkio@cox.net>
Sat, 6 Aug 2005 17:19:38 +0000 (10:19 -0700)
This extends the source side semantics to match what Linus
suggested.

An example:

$ git-send-pack kernel.org:/pub/scm/git/git.git pu^^:master pu

would allow me to push the current pu into pu, and the
commit two commits before it into master, on my public
repository.

The revised rule for updating remote heads is as follows.

$ git-send-pack [--all] <remote> [<ref>...]

- When no <ref> is specified:

- with '--all', it is the same as specifying the full refs/*
path for all local refs;

- without '--all', it is the same as specifying the full
refs/* path for refs that exist on both ends;

- When one or more <ref>s are specified:

- a single token <ref> (i.e. no colon) must be a pattern that
tail-matches refs/* path for an existing local ref. It is
an error for the pattern to match no local ref, or more
than one local refs. The matching ref is pushed to the
remote end under the same name.

- <src>:<dst> can have different cases. <src> is first tried
as the tail-matching pattern for refs/* path.

- If more than one matches are found, it is an error.

- If one match is found, <dst> must either match no remote
ref and start with "refs/", or match exactly one remote
ref. That remote ref is updated with the sha1 value
obtained from the <src> sha1.

- If no match is found, it is given to get_extended_sha1();
it is an error if get_extended_sha1() does not find an
object name. If it succeeds, <dst> must either match
no remote ref and start with "refs/" or match exactly
one remote ref. That remote ref is updated with the sha1
value.

Signed-off-by: Junio C Hamano <junkio@cox.net>
connect.c
index c872bfd45b815d12ba87d215cc157495b6a1e4aa..20b80a1b54b965d4af272aa7cb7c0009c737e4dd 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -133,6 +133,20 @@ static void link_dst_tail(struct ref *ref, struct ref ***tail)
        **tail = NULL;
 }
 
+static struct ref *try_explicit_object_name(const char *name)
+{
+       unsigned char sha1[20];
+       struct ref *ref;
+       int len;
+       if (get_sha1(name, sha1))
+               return NULL;
+       len = strlen(name) + 1;
+       ref = xcalloc(1, sizeof(*ref) + len);
+       memcpy(ref->name, name, len);
+       memcpy(ref->new_sha1, sha1, 20);
+       return ref;
+}
+
 static int match_explicit_refs(struct ref *src, struct ref *dst,
                               struct ref ***dst_tail, struct refspec *rs)
 {
@@ -145,6 +159,12 @@ static int match_explicit_refs(struct ref *src, struct ref *dst,
                case 1:
                        break;
                case 0:
+                       /* The source could be in the get_sha1() format
+                        * not a reference name.
+                        */
+                       matched_src = try_explicit_object_name(rs[i].src);
+                       if (matched_src)
+                               break;
                        errs = 1;
                        error("src refspec %s does not match any.");
                        break;