Merge branch 'xx/db-refspec-vs-js-remote'
authorJunio C Hamano <gitster@pobox.com>
Fri, 20 Mar 2009 21:30:00 +0000 (14:30 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 20 Mar 2009 21:30:00 +0000 (14:30 -0700)
* xx/db-refspec-vs-js-remote:
Support '*' in the middle of a refspec
Keep '*' in pattern refspecs
Use the matching function to generate the match results
Use a single function to match names against patterns
Make clone parse the default refspec with the normal code

1  2 
builtin-clone.c
builtin-remote.c
remote.c
diff --combined builtin-clone.c
index 7fbfbf973c79494fe20a7d25cb3383da31574829,b385b97828fa3973494666a16f939578209fdef7..0031b5f51cd96525a265dab02494700e9d36fce8
@@@ -20,9 -20,7 +20,9 @@@
  #include "dir.h"
  #include "pack-refs.h"
  #include "sigchain.h"
 +#include "branch.h"
  #include "remote.h"
 +#include "run-command.h"
  
  /*
   * Overall FIXMEs:
@@@ -316,8 -314,23 +316,8 @@@ static struct ref *write_remote_refs(co
        return local_refs;
  }
  
 -static void install_branch_config(const char *local,
 -                                const char *origin,
 -                                const char *remote)
 -{
 -      struct strbuf key = STRBUF_INIT;
 -      strbuf_addf(&key, "branch.%s.remote", local);
 -      git_config_set(key.buf, origin);
 -      strbuf_reset(&key);
 -      strbuf_addf(&key, "branch.%s.merge", local);
 -      git_config_set(key.buf, remote);
 -      strbuf_release(&key);
 -}
 -
  int cmd_clone(int argc, const char **argv, const char *prefix)
  {
 -      int use_local_hardlinks = 1;
 -      int use_separate_remote = 1;
        int is_bundle = 0;
        struct stat buf;
        const char *repo_name, *repo, *work_tree, *git_dir;
        struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
        struct transport *transport = NULL;
        char *src_ref_prefix = "refs/heads/";
 +      int err = 0;
  
-       struct refspec refspec;
+       struct refspec *refspec;
+       const char *fetch_pattern;
  
        junk_pid = getpid();
  
        if (argc == 0)
                die("You must specify a repository to clone.");
  
 -      if (option_no_hardlinks)
 -              use_local_hardlinks = 0;
 -
        if (option_mirror)
                option_bare = 1;
  
                        die("--bare and --origin %s options are incompatible.",
                            option_origin);
                option_no_checkout = 1;
 -              use_separate_remote = 0;
        }
  
        if (!option_origin)
                strbuf_addf(&branch_top, "refs/remotes/%s/", option_origin);
        }
  
+       strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top.buf);
        if (option_mirror || !option_bare) {
                /* Configure the remote */
+               strbuf_addf(&key, "remote.%s.fetch", option_origin);
+               git_config_set_multivar(key.buf, value.buf, "^$", 0);
+               strbuf_reset(&key);
                if (option_mirror) {
                        strbuf_addf(&key, "remote.%s.mirror", option_origin);
                        git_config_set(key.buf, "true");
  
                strbuf_addf(&key, "remote.%s.url", option_origin);
                git_config_set(key.buf, repo);
-                       strbuf_reset(&key);
-               strbuf_addf(&key, "remote.%s.fetch", option_origin);
-               strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top.buf);
-               git_config_set_multivar(key.buf, value.buf, "^$", 0);
                strbuf_reset(&key);
-               strbuf_reset(&value);
        }
  
-       refspec.force = 0;
-       refspec.pattern = 1;
-       refspec.src = src_ref_prefix;
-       refspec.dst = branch_top.buf;
+       fetch_pattern = value.buf;
+       refspec = parse_fetch_refspec(1, &fetch_pattern);
+       strbuf_reset(&value);
  
        if (path && !is_bundle)
                refs = clone_local(path, git_dir);
        if (refs) {
                clear_extra_refs();
  
-               mapped_refs = write_remote_refs(refs, &refspec, reflog_msg.buf);
+               mapped_refs = write_remote_refs(refs, refspec, reflog_msg.buf);
  
                remote_head = find_ref_by_name(refs, "HEAD");
                head_points_at = guess_remote_head(remote_head, mapped_refs, 0);
                remote_head = NULL;
                option_no_checkout = 1;
                if (!option_bare)
 -                      install_branch_config("master", option_origin,
 +                      install_branch_config(0, "master", option_origin,
                                              "refs/heads/master");
        }
  
                                      head_points_at->peer_ref->name,
                                      reflog_msg.buf);
  
 -                      install_branch_config(head, option_origin,
 +                      install_branch_config(0, head, option_origin,
                                              head_points_at->name);
                }
        } else if (remote_head) {
                if (write_cache(fd, active_cache, active_nr) ||
                    commit_locked_index(lock_file))
                        die("unable to write new index file");
 +
 +              err |= run_hook(NULL, "post-checkout", sha1_to_hex(null_sha1),
 +                              sha1_to_hex(remote_head->old_sha1), "1", NULL);
        }
  
        strbuf_release(&reflog_msg);
        strbuf_release(&key);
        strbuf_release(&value);
        junk_pid = 0;
 -      return 0;
 +      return err;
  }
diff --combined builtin-remote.c
index e445b8ba38372f538e618578548fc765a9ec7d17,3e4a41b11bbb5b30bec52b239708ad244fa95b88..993acd6a09869e23b3f8e67f0dddbddc946e6c5f
@@@ -358,14 -358,9 +358,9 @@@ static int get_push_ref_states_noquery(
        }
        for (i = 0; i < remote->push_refspec_nr; i++) {
                struct refspec *spec = remote->push + i;
-               char buf[PATH_MAX];
                if (spec->matching)
                        item = string_list_append("(matching)", &states->push);
-               else if (spec->pattern) {
-                       snprintf(buf, (sizeof(buf)), "%s*", spec->src);
-                       item = string_list_append(buf, &states->push);
-                       snprintf(buf, (sizeof(buf)), "%s*", spec->dst);
-               } else if (strlen(spec->src))
+               else if (strlen(spec->src))
                        item = string_list_append(spec->src, &states->push);
                else
                        item = string_list_append("(delete)", &states->push);
                info = item->util = xcalloc(sizeof(struct push_info), 1);
                info->forced = spec->force;
                info->status = PUSH_STATUS_NOTQUERIED;
-               if (spec->pattern)
-                       info->dest = xstrdup(buf);
-               else
-                       info->dest = xstrdup(spec->dst ? spec->dst : item->string);
+               info->dest = xstrdup(spec->dst ? spec->dst : item->string);
        }
        return 0;
  }
@@@ -389,7 -381,7 +381,7 @@@ static int get_head_names(const struct 
  
        refspec.force = 0;
        refspec.pattern = 1;
-       refspec.src = refspec.dst = "refs/heads/";
+       refspec.src = refspec.dst = "refs/heads/*";
        states->heads.strdup_strings = 1;
        get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0);
        matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
@@@ -616,8 -608,9 +608,8 @@@ static int mv(int argc, const char **ar
                struct string_list_item *item = remote_branches.items + i;
                int flag = 0;
                unsigned char sha1[20];
 -              const char *symref;
  
 -              symref = resolve_ref(item->string, sha1, 1, &flag);
 +              resolve_ref(item->string, sha1, 1, &flag);
                if (!(flag & REF_ISSYMREF))
                        continue;
                if (delete_ref(item->string, NULL, REF_NODEREF))
diff --combined remote.c
index baa50aab6573738059a9a71a224acb6877257255,f0acfb5c8642ea521fb9672c5c49759dfd2a3d82..e5d6b100d738c388bff91bff68b14f69dea87166
+++ b/remote.c
@@@ -11,8 -11,8 +11,8 @@@ static struct refspec s_tag_refspec = 
        0,
        1,
        0,
-       "refs/tags/",
-       "refs/tags/"
+       "refs/tags/*",
+       "refs/tags/*"
  };
  
  const struct refspec *tag_refspec = &s_tag_refspec;
@@@ -39,7 -39,6 +39,7 @@@ static int branches_nr
  
  static struct branch *current_branch;
  static const char *default_remote_name;
 +static int explicit_default_remote_name;
  
  static struct rewrite **rewrite;
  static int rewrite_alloc;
@@@ -332,10 -331,8 +332,10 @@@ static int handle_config(const char *ke
                        if (!value)
                                return config_error_nonbool(key);
                        branch->remote_name = xstrdup(value);
 -                      if (branch == current_branch)
 +                      if (branch == current_branch) {
                                default_remote_name = branch->remote_name;
 +                              explicit_default_remote_name = 1;
 +                      }
                } else if (!strcmp(subkey, ".merge")) {
                        if (!value)
                                return config_error_nonbool(key);
@@@ -455,16 -452,11 +455,11 @@@ static void read_config(void
   */
  static int verify_refname(char *name, int is_glob)
  {
-       int result, len = -1;
+       int result;
  
-       if (is_glob) {
-               len = strlen(name);
-               assert(name[len - 1] == '/');
-               name[len - 1] = '\0';
-       }
        result = check_ref_format(name);
-       if (is_glob)
-               name[len - 1] = '/';
+       if (is_glob && result == CHECK_REF_FORMAT_WILDCARD)
+               result = CHECK_REF_FORMAT_OK;
        return result;
  }
  
@@@ -499,7 -491,7 +494,7 @@@ static struct refspec *parse_refspec_in
                int is_glob;
                const char *lhs, *rhs;
  
 -              llen = is_glob = 0;
 +              is_glob = 0;
  
                lhs = refspec[i];
                if (*lhs == '+') {
  
                if (rhs) {
                        size_t rlen = strlen(++rhs);
-                       is_glob = (2 <= rlen && !strcmp(rhs + rlen - 2, "/*"));
-                       rs[i].dst = xstrndup(rhs, rlen - is_glob);
+                       is_glob = (1 <= rlen && strchr(rhs, '*'));
+                       rs[i].dst = xstrndup(rhs, rlen);
                }
  
                llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
-               if (2 <= llen && !memcmp(lhs + llen - 2, "/*", 2)) {
+               if (1 <= llen && memchr(lhs, '*', llen)) {
                        if ((rhs && !is_glob) || (!rhs && fetch))
                                goto invalid;
                        is_glob = 1;
-                       llen--;
                } else if (rhs && is_glob) {
                        goto invalid;
                }
@@@ -647,16 -638,10 +641,16 @@@ static int valid_remote_nick(const cha
  struct remote *remote_get(const char *name)
  {
        struct remote *ret;
 +      int name_given = 0;
  
        read_config();
 -      if (!name)
 +      if (name)
 +              name_given = 1;
 +      else {
                name = default_remote_name;
 +              name_given = explicit_default_remote_name;
 +      }
 +
        ret = make_remote(name, 0);
        if (valid_remote_nick(name)) {
                if (!ret->url)
                if (!ret->url)
                        read_branches_file(ret);
        }
 -      if (!ret->url)
 +      if (name_given && !ret->url)
                add_url_alias(ret, name);
        if (!ret->url)
                return NULL;
@@@ -729,6 -714,41 +723,41 @@@ int remote_has_url(struct remote *remot
        return 0;
  }
  
+ static int match_name_with_pattern(const char *key, const char *name,
+                                  const char *value, char **result)
+ {
+       const char *kstar = strchr(key, '*');
+       size_t klen;
+       size_t ksuffixlen;
+       size_t namelen;
+       int ret;
+       if (!kstar)
+               die("Key '%s' of pattern had no '*'", key);
+       klen = kstar - key;
+       ksuffixlen = strlen(kstar + 1);
+       namelen = strlen(name);
+       ret = !strncmp(name, key, klen) && namelen >= klen + ksuffixlen &&
+               !memcmp(name + namelen - ksuffixlen, kstar + 1, ksuffixlen);
+       if (ret && value) {
+               const char *vstar = strchr(value, '*');
+               size_t vlen;
+               size_t vsuffixlen;
+               if (!vstar)
+                       die("Value '%s' of pattern has no '*'", value);
+               vlen = vstar - value;
+               vsuffixlen = strlen(vstar + 1);
+               *result = xmalloc(vlen + vsuffixlen +
+                                 strlen(name) -
+                                 klen - ksuffixlen + 1);
+               strncpy(*result, value, vlen);
+               strncpy(*result + vlen,
+                       name + klen, namelen - klen - ksuffixlen);
+               strcpy(*result + vlen + namelen - klen - ksuffixlen,
+                      vstar + 1);
+       }
+       return ret;
+ }
  int remote_find_tracking(struct remote *remote, struct refspec *refspec)
  {
        int find_src = refspec->src == NULL;
                if (!fetch->dst)
                        continue;
                if (fetch->pattern) {
-                       if (!prefixcmp(needle, key)) {
-                               *result = xmalloc(strlen(value) +
-                                                 strlen(needle) -
-                                                 strlen(key) + 1);
-                               strcpy(*result, value);
-                               strcpy(*result + strlen(value),
-                                      needle + strlen(key));
+                       if (match_name_with_pattern(key, needle, value, result)) {
                                refspec->force = fetch->force;
                                return 0;
                        }
@@@ -1041,7 -1055,8 +1064,8 @@@ static const struct refspec *check_patt
                        continue;
                }
  
-               if (rs[i].pattern && !prefixcmp(src->name, rs[i].src))
+               if (rs[i].pattern && match_name_with_pattern(rs[i].src, src->name,
+                                                            NULL, NULL))
                        return rs + i;
        }
        if (matching_refs != -1)
@@@ -1095,11 -1110,9 +1119,9 @@@ int match_refs(struct ref *src, struct 
  
                } else {
                        const char *dst_side = pat->dst ? pat->dst : pat->src;
-                       dst_name = xmalloc(strlen(dst_side) +
-                                          strlen(src->name) -
-                                          strlen(pat->src) + 2);
-                       strcpy(dst_name, dst_side);
-                       strcat(dst_name, src->name + strlen(pat->src));
+                       if (!match_name_with_pattern(pat->src, src->name,
+                                                    dst_side, &dst_name))
+                               die("Didn't think it matches any more");
                }
                dst_peer = find_ref_by_name(dst, dst_name);
                if (dst_peer) {
@@@ -1177,19 -1190,17 +1199,17 @@@ static struct ref *get_expanded_map(con
        struct ref *ret = NULL;
        struct ref **tail = &ret;
  
-       int remote_prefix_len = strlen(refspec->src);
-       int local_prefix_len = strlen(refspec->dst);
+       char *expn_name;
  
        for (ref = remote_refs; ref; ref = ref->next) {
                if (strchr(ref->name, '^'))
                        continue; /* a dereference item */
-               if (!prefixcmp(ref->name, refspec->src)) {
-                       const char *match;
+               if (match_name_with_pattern(refspec->src, ref->name,
+                                           refspec->dst, &expn_name)) {
                        struct ref *cpy = copy_ref(ref);
-                       match = ref->name + remote_prefix_len;
  
-                       cpy->peer_ref = alloc_ref_with_prefix(refspec->dst,
-                                       local_prefix_len, match);
+                       cpy->peer_ref = alloc_ref(expn_name);
+                       free(expn_name);
                        if (refspec->force)
                                cpy->peer_ref->force = 1;
                        *tail = cpy;