X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=builtin-push.c;h=70b1168fa677fc889543e87b2a3f964b175375c6;hb=5b5fe9a526e3841ff6f61dda743b9624dc8f6426;hp=5f7eccf14b272fc108bcd49aece911ebde460b4f;hpb=c954d33da1c878788e7c01a50a5c1066622802c6;p=git.git diff --git a/builtin-push.c b/builtin-push.c index 5f7eccf14..70b1168fa 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; -static const char *execute; +static int all, tags, force, thin = 1, verbose; +static const char *receivepack; #define BUF_SIZE (2084) static char buffer[BUF_SIZE]; @@ -32,7 +32,7 @@ static int expand_one_ref(const char *ref, const unsigned char *sha1, int flag, /* Ignore the "refs/" at the beginning of the refname */ ref += 5; - if (!strncmp(ref, "tags/", 5)) + if (!prefixcmp(ref, "tags/")) add_refspec(xstrdup(ref)); return 0; } @@ -54,14 +54,85 @@ 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) { - size_t bytes = nr * sizeof(char *); - - refspec = xrealloc(refspec, bytes); - memcpy(refspec, refs, bytes); - refspec_nr = nr; + 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(); } @@ -78,10 +149,10 @@ static int get_remotes_uri(const char *repo, const char *uri[MAX_URI]) int is_refspec; char *s, *p; - if (!strncmp("URL:", buffer, 4)) { + if (!prefixcmp(buffer, "URL:")) { is_refspec = 0; s = buffer + 4; - } else if (!strncmp("Push:", buffer, 5)) { + } else if (!prefixcmp(buffer, "Push:")) { is_refspec = 1; s = buffer + 5; } else @@ -104,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) @@ -118,10 +191,11 @@ 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) { - if (!strncmp(key, "remote.", 7) && + if (!prefixcmp(key, "remote.") && !strncmp(key + 7, config_repo, config_repo_len)) { if (!strcmp(key + 7 + config_repo_len, ".url")) { if (config_current_uri < MAX_URI) @@ -130,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; } @@ -143,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; @@ -227,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++) { @@ -237,10 +323,10 @@ static int do_push(const char *repo) int dest_refspec_nr = refspec_nr; const char **dest_refspec = refspec; const char *dest = uri[i]; - const char *sender = "git-send-pack"; - if (!strncmp(dest, "http://", 7) || - !strncmp(dest, "https://", 8)) - sender = "git-http-push"; + const char *sender = "send-pack"; + if (!prefixcmp(dest, "http://") || + !prefixcmp(dest, "https://")) + sender = "http-push"; else if (thin) argv[dest_argc++] = "--thin"; argv[0] = sender; @@ -248,7 +334,9 @@ static int do_push(const char *repo) while (dest_refspec_nr--) argv[dest_argc++] = *dest_refspec++; argv[dest_argc] = NULL; - err = run_command_v(argc, argv); + if (verbose) + fprintf(stderr, "Pushing to %s\n", dest); + err = run_command_v_opt(argv, RUN_GIT_CMD); if (!err) continue; switch (err) { @@ -281,6 +369,14 @@ int cmd_push(int argc, const char **argv, const char *prefix) i++; break; } + if (!strcmp(arg, "-v")) { + verbose=1; + continue; + } + if (!prefixcmp(arg, "--repo=")) { + repo = arg+7; + continue; + } if (!strcmp(arg, "--all")) { all = 1; continue; @@ -301,8 +397,12 @@ int cmd_push(int argc, const char **argv, const char *prefix) thin = 0; continue; } - if (!strncmp(arg, "--exec=", 7)) { - execute = arg; + if (!prefixcmp(arg, "--receive-pack=")) { + receivepack = arg; + continue; + } + if (!prefixcmp(arg, "--exec=")) { + receivepack = arg; continue; } usage(push_usage);