Also fix a possible segfault in the refspec parser. Signed-off-by: Pierre Habouzit <madcoder@xxxxxxxxxx> --- builtin-fetch.c | 145 +++++++++++++++++++------------------------------------ 1 files changed, 50 insertions(+), 95 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index cf7498b..4a58955 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -8,11 +8,15 @@ #include "path-list.h" #include "remote.h" #include "transport.h" +#include "parse-options.h" -static const char fetch_usage[] = "git-fetch [-a | --append] [--upload-pack <upload-pack>] [-f | --force] [--no-tags] [-t | --tags] [-k | --keep] [-u | --update-head-ok] [--depth <depth>] [-v | --verbose] [<repository> <refspec>...]"; +static const char * const fetch_usage[] = { + "git-fetch [options] [<repository> <refspec>...]", + NULL +}; static int append, force, tags, no_tags, update_head_ok, verbose, quiet; -static char *default_rla = NULL; +static struct strbuf default_rla = STRBUF_INIT; static struct transport *transport; static void unlock_pack(void) @@ -131,7 +135,7 @@ static int s_update_ref(const char *action, static struct ref_lock *lock; if (!rla) - rla = default_rla; + rla = default_rla.buf; snprintf(msg, sizeof(msg), "%s: %s", rla, action); lock = lock_any_ref_for_update(ref->name, check_old ? ref->old_sha1 : NULL, 0); @@ -443,91 +447,47 @@ static void set_option(const char *name, const char *value) int cmd_fetch(int argc, const char **argv, const char *prefix) { struct remote *remote; - int i, j, rla_offset; + int count, i; static const char **refs = NULL; int ref_nr = 0; - int cmd_len = 0; const char *depth = NULL, *upload_pack = NULL; int keep = 0; - + struct option builtin_fetch_options[] = { + OPT_BOOLEAN('q', "quiet", &quiet, "be quiet"), + OPT_BOOLEAN('v', "verbose", &verbose, "be verbose"), + + OPT_GROUP(""), + OPT_BOOLEAN('a', "append", &append, "append in .git/FETCH_HEAD"), + OPT_BOOLEAN('f', "force", &force, "force non fast-forwards updates"), + OPT_BOOLEAN( 0 , "no-tags", &no_tags, "don't follow tags at all"), + OPT_BOOLEAN('t', "tags", &tags, "fetch all tags"), + OPT_STRING( 0 , "depth", &depth, + "depth", "deepen history of a shallow clone"), + + OPT_GROUP("Advanced Options"), + OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"), + OPT_BOOLEAN('u', "update-head-ok", &update_head_ok, + "allow to update the head in the current branch"), + OPT_STRING( 0 , "upload-pack", &upload_pack, "path", + "path to git-upload-pack on the remote"), + }; + + strbuf_grow(&default_rla, 8192); + strbuf_addstr(&default_rla, "fetch"); for (i = 1; i < argc; i++) { - const char *arg = argv[i]; - cmd_len += strlen(arg); - - if (arg[0] != '-') - break; - if (!strcmp(arg, "--append") || !strcmp(arg, "-a")) { - append = 1; - continue; - } - if (!prefixcmp(arg, "--upload-pack=")) { - upload_pack = arg + 14; - continue; - } - if (!strcmp(arg, "--upload-pack")) { - i++; - if (i == argc) - usage(fetch_usage); - upload_pack = argv[i]; - continue; - } - if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) { - force = 1; - continue; - } - if (!strcmp(arg, "--no-tags")) { - no_tags = 1; - continue; - } - if (!strcmp(arg, "--tags") || !strcmp(arg, "-t")) { - tags = 1; - continue; - } - if (!strcmp(arg, "--keep") || !strcmp(arg, "-k")) { - keep = 1; - continue; - } - if (!strcmp(arg, "--update-head-ok") || !strcmp(arg, "-u")) { - update_head_ok = 1; - continue; - } - if (!prefixcmp(arg, "--depth=")) { - depth = arg + 8; - continue; - } - if (!strcmp(arg, "--depth")) { - i++; - if (i == argc) - usage(fetch_usage); - depth = argv[i]; - continue; - } - if (!strcmp(arg, "--quiet")) { - quiet = 1; - continue; - } - if (!strcmp(arg, "--verbose") || !strcmp(arg, "-v")) { - verbose++; - continue; - } - usage(fetch_usage); - } - - for (j = i; j < argc; j++) - cmd_len += strlen(argv[j]); - - default_rla = xmalloc(cmd_len + 5 + argc + 1); - sprintf(default_rla, "fetch"); - rla_offset = strlen(default_rla); - for (j = 1; j < argc; j++) { - sprintf(default_rla + rla_offset, " %s", argv[j]); - rla_offset += strlen(argv[j]) + 1; + strbuf_addch(&default_rla, ' '); + strbuf_addstr(&default_rla, argv[i]); } - if (i == argc) + count = parse_options(argc, argv, builtin_fetch_options, + ARRAY_SIZE(builtin_fetch_options), + fetch_usage, 0); + if (count == 0) { remote = remote_get(NULL); - else - remote = remote_get(argv[i++]); + } else { + remote = remote_get(*argv++); + count--; + } transport = transport_get(remote, remote->url[0]); if (verbose >= 2) @@ -544,25 +504,20 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) if (!transport->url) die("Where do you want to fetch from today?"); - if (i < argc) { - int j = 0; - refs = xcalloc(argc - i + 1, sizeof(const char *)); - while (i < argc) { - if (!strcmp(argv[i], "tag")) { + if (count) { + refs = xcalloc(count + 1, sizeof(const char *)); + for (i = ref_nr = 0; i < count; i++) { + if (i + 1 < count && !strcmp(argv[i], "tag")) { char *ref; i++; ref = xmalloc(strlen(argv[i]) * 2 + 22); - strcpy(ref, "refs/tags/"); - strcat(ref, argv[i]); - strcat(ref, ":refs/tags/"); - strcat(ref, argv[i]); - refs[j++] = ref; - } else - refs[j++] = argv[i]; - i++; + sprintf(ref, "refs/tags/%s:refs/tags/%s", argv[i], argv[i]); + refs[ref_nr++] = ref; + } else { + refs[ref_nr++] = argv[i]; + } } - refs[j] = NULL; - ref_nr = j; + refs[ref_nr] = NULL; } signal(SIGINT, unlock_pack_on_signal); -- 1.5.3.GIT - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html