X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=builtin-push.c;h=c45649e26cf5284323aa80a5fe73b5842346eb14;hb=ffa84ffb77b06f9793967fb4f4dd5c946da8e341;hp=b7412e82937a240776cdda07da05797b0b2acb0b;hpb=f5c589f1dfff428a05b8783688513fe9f98309a2;p=git.git diff --git a/builtin-push.c b/builtin-push.c index b7412e829..c45649e26 100644 --- a/builtin-push.c +++ b/builtin-push.c @@ -8,10 +8,10 @@ #define MAX_URI (16) -static const char push_usage[] = "git-push [--all] [--tags] [-f | --force] [...]"; +static const char push_usage[] = "git-push [--all] [--tags] [--receive-pack=] [--repo=all] [-f | --force] [-v] [ ...]"; static int all, tags, force, thin = 1, verbose; -static const char *execute; +static const char *receivepack; #define BUF_SIZE (2084) static char buffer[BUF_SIZE]; @@ -54,38 +54,84 @@ static void expand_refspecs(void) for_each_ref(expand_one_ref, NULL); } +struct wildcard_cb { + const char *from_prefix; + int from_prefix_len; + const char *to_prefix; + int to_prefix_len; + int force; +}; + +static int expand_wildcard_ref(const char *ref, const unsigned char *sha1, int flag, void *cb_data) +{ + struct wildcard_cb *cb = cb_data; + int len = strlen(ref); + char *expanded, *newref; + + if (len < cb->from_prefix_len || + memcmp(cb->from_prefix, ref, cb->from_prefix_len)) + return 0; + expanded = xmalloc(len * 2 + cb->force + + (cb->to_prefix_len - cb->from_prefix_len) + 2); + newref = expanded + cb->force; + if (cb->force) + expanded[0] = '+'; + memcpy(newref, ref, len); + newref[len] = ':'; + memcpy(newref + len + 1, cb->to_prefix, cb->to_prefix_len); + strcpy(newref + len + 1 + cb->to_prefix_len, + ref + cb->from_prefix_len); + add_refspec(expanded); + return 0; +} + +static int wildcard_ref(const char *ref) +{ + int len; + const char *colon; + struct wildcard_cb cb; + + memset(&cb, 0, sizeof(cb)); + if (ref[0] == '+') { + cb.force = 1; + ref++; + } + len = strlen(ref); + colon = strchr(ref, ':'); + if (! (colon && ref < colon && + colon[-2] == '/' && colon[-1] == '*' && + /* "/:/" is at least 7 bytes */ + 7 <= len && + ref[len-2] == '/' && ref[len-1] == '*') ) + return 0 ; + cb.from_prefix = ref; + cb.from_prefix_len = colon - ref - 1; + cb.to_prefix = colon + 1; + cb.to_prefix_len = len - (colon - ref) - 2; + for_each_ref(expand_wildcard_ref, &cb); + return 1; +} + static void set_refspecs(const char **refs, int nr) { if (nr) { - int pass; - for (pass = 0; pass < 2; pass++) { - /* pass 0 counts and allocates, pass 1 fills */ - int i, cnt; - for (i = cnt = 0; i < nr; i++) { - if (!strcmp("tag", refs[i])) { - int len; - char *tag; - if (nr <= ++i) - die("tag shorthand without "); - if (pass) { - len = strlen(refs[i]) + 11; - tag = xmalloc(len); - strcpy(tag, "refs/tags/"); - strcat(tag, refs[i]); - refspec[cnt] = tag; - } - cnt++; - continue; - } - if (pass) - refspec[cnt] = refs[i]; - cnt++; - } - if (!pass) { - size_t bytes = cnt * sizeof(char *); - refspec_nr = cnt; - refspec = xrealloc(refspec, bytes); + int i; + for (i = 0; i < nr; i++) { + const char *ref = refs[i]; + if (!strcmp("tag", ref)) { + char *tag; + int len; + if (nr <= ++i) + die("tag shorthand without "); + len = strlen(refs[i]) + 11; + tag = xmalloc(len); + strcpy(tag, "refs/tags/"); + strcat(tag, refs[i]); + ref = tag; } + else if (wildcard_ref(ref)) + continue; + add_refspec(ref); } } expand_refspecs(); @@ -129,8 +175,10 @@ static int get_remotes_uri(const char *repo, const char *uri[MAX_URI]) else error("more than %d URL's specified, ignoring the rest", MAX_URI); } - else if (is_refspec && !has_explicit_refspec) - add_refspec(xstrdup(s)); + else if (is_refspec && !has_explicit_refspec) { + if (!wildcard_ref(s)) + add_refspec(xstrdup(s)); + } } fclose(f); if (!n) @@ -143,6 +191,7 @@ static const char *config_repo; static int config_repo_len; static int config_current_uri; static int config_get_refspecs; +static int config_get_receivepack; static int get_remote_config(const char* key, const char* value) { @@ -155,8 +204,19 @@ static int get_remote_config(const char* key, const char* value) error("more than %d URL's specified, ignoring the rest", MAX_URI); } else if (config_get_refspecs && - !strcmp(key + 7 + config_repo_len, ".push")) - add_refspec(xstrdup(value)); + !strcmp(key + 7 + config_repo_len, ".push")) { + if (!wildcard_ref(value)) + add_refspec(xstrdup(value)); + } + else if (config_get_receivepack && + !strcmp(key + 7 + config_repo_len, ".receivepack")) { + if (!receivepack) { + char *rp = xmalloc(strlen(value) + 16); + sprintf(rp, "--receive-pack=%s", value); + receivepack = rp; + } else + error("more than one receivepack given, using the first"); + } } return 0; } @@ -168,6 +228,7 @@ static int get_config_remotes_uri(const char *repo, const char *uri[MAX_URI]) config_current_uri = 0; config_uri = uri; config_get_refspecs = !(refspec_nr || all || tags); + config_get_receivepack = (receivepack == NULL); git_config(get_remote_config); return config_current_uri; @@ -252,8 +313,8 @@ static int do_push(const char *repo) argv[argc++] = "--all"; if (force) argv[argc++] = "--force"; - if (execute) - argv[argc++] = execute; + if (receivepack) + argv[argc++] = receivepack; common_argc = argc; for (i = 0; i < n; i++) { @@ -275,7 +336,7 @@ static int do_push(const char *repo) argv[dest_argc] = NULL; if (verbose) fprintf(stderr, "Pushing to %s\n", dest); - err = run_command_v(argc, argv); + err = run_command_v(argv); if (!err) continue; switch (err) { @@ -336,8 +397,12 @@ int cmd_push(int argc, const char **argv, const char *prefix) thin = 0; continue; } + if (!strncmp(arg, "--receive-pack=", 15)) { + receivepack = arg; + continue; + } if (!strncmp(arg, "--exec=", 7)) { - execute = arg; + receivepack = arg; continue; } usage(push_usage);