cmd_fetch_pack(): combine the loop termination conditions
[gitweb.git] / builtin / fetch-pack.c
index 6207ecd2982761a47474b57cc945a2fc66ed84a1..dc4b1dcec039e5dc8bc067188b95c36b0e6ca35a 100644 (file)
@@ -23,7 +23,9 @@ static struct fetch_pack_args args = {
 };
 
 static const char fetch_pack_usage[] =
-"git fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]";
+"git fetch-pack [--all] [--stdin] [--quiet|-q] [--keep|-k] [--thin] "
+"[--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] "
+"[--no-progress] [-v] [<host>:]<directory> [<refs>...]";
 
 #define COMPLETE       (1U << 0)
 #define COMMON         (1U << 1)
@@ -898,7 +900,8 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 {
        int i, ret, nr_heads;
        struct ref *ref = NULL;
-       char *dest = NULL, **heads;
+       const char *dest = NULL;
+       char **heads;
        int fd[2];
        char *pack_lockfile = NULL;
        char **pack_lockfile_ptr = NULL;
@@ -906,78 +909,115 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 
        packet_trace_identity("fetch-pack");
 
-       nr_heads = 0;
        heads = NULL;
-       for (i = 1; i < argc; i++) {
+       for (i = 1; i < argc && *argv[i] == '-'; i++) {
                const char *arg = argv[i];
 
-               if (*arg == '-') {
-                       if (!prefixcmp(arg, "--upload-pack=")) {
-                               args.uploadpack = arg + 14;
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--exec=")) {
-                               args.uploadpack = arg + 7;
-                               continue;
-                       }
-                       if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
-                               args.quiet = 1;
-                               continue;
-                       }
-                       if (!strcmp("--keep", arg) || !strcmp("-k", arg)) {
-                               args.lock_pack = args.keep_pack;
-                               args.keep_pack = 1;
-                               continue;
-                       }
-                       if (!strcmp("--thin", arg)) {
-                               args.use_thin_pack = 1;
-                               continue;
-                       }
-                       if (!strcmp("--include-tag", arg)) {
-                               args.include_tag = 1;
-                               continue;
-                       }
-                       if (!strcmp("--all", arg)) {
-                               args.fetch_all = 1;
-                               continue;
-                       }
-                       if (!strcmp("-v", arg)) {
-                               args.verbose = 1;
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--depth=")) {
-                               args.depth = strtol(arg + 8, NULL, 0);
-                               continue;
-                       }
-                       if (!strcmp("--no-progress", arg)) {
-                               args.no_progress = 1;
-                               continue;
-                       }
-                       if (!strcmp("--stateless-rpc", arg)) {
-                               args.stateless_rpc = 1;
-                               continue;
+               if (!prefixcmp(arg, "--upload-pack=")) {
+                       args.uploadpack = arg + 14;
+                       continue;
+               }
+               if (!prefixcmp(arg, "--exec=")) {
+                       args.uploadpack = arg + 7;
+                       continue;
+               }
+               if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
+                       args.quiet = 1;
+                       continue;
+               }
+               if (!strcmp("--keep", arg) || !strcmp("-k", arg)) {
+                       args.lock_pack = args.keep_pack;
+                       args.keep_pack = 1;
+                       continue;
+               }
+               if (!strcmp("--thin", arg)) {
+                       args.use_thin_pack = 1;
+                       continue;
+               }
+               if (!strcmp("--include-tag", arg)) {
+                       args.include_tag = 1;
+                       continue;
+               }
+               if (!strcmp("--all", arg)) {
+                       args.fetch_all = 1;
+                       continue;
+               }
+               if (!strcmp("--stdin", arg)) {
+                       args.stdin_refs = 1;
+                       continue;
+               }
+               if (!strcmp("-v", arg)) {
+                       args.verbose = 1;
+                       continue;
+               }
+               if (!prefixcmp(arg, "--depth=")) {
+                       args.depth = strtol(arg + 8, NULL, 0);
+                       continue;
+               }
+               if (!strcmp("--no-progress", arg)) {
+                       args.no_progress = 1;
+                       continue;
+               }
+               if (!strcmp("--stateless-rpc", arg)) {
+                       args.stateless_rpc = 1;
+                       continue;
+               }
+               if (!strcmp("--lock-pack", arg)) {
+                       args.lock_pack = 1;
+                       pack_lockfile_ptr = &pack_lockfile;
+                       continue;
+               }
+               usage(fetch_pack_usage);
+       }
+
+       if (i < argc)
+               dest = argv[i++];
+       else
+               usage(fetch_pack_usage);
+
+       heads = (char **)(argv + i);
+       nr_heads = argc - i;
+
+       if (args.stdin_refs) {
+               /*
+                * Copy refs from cmdline to new growable list, then
+                * append the refs from the standard input.
+                */
+               int alloc_heads = nr_heads;
+               int size = nr_heads * sizeof(*heads);
+               heads = memcpy(xmalloc(size), heads, size);
+               if (args.stateless_rpc) {
+                       /* in stateless RPC mode we use pkt-line to read
+                        * from stdin, until we get a flush packet
+                        */
+                       static char line[1000];
+                       for (;;) {
+                               int n = packet_read_line(0, line, sizeof(line));
+                               if (!n)
+                                       break;
+                               if (line[n-1] == '\n')
+                                       n--;
+                               ALLOC_GROW(heads, nr_heads + 1, alloc_heads);
+                               heads[nr_heads++] = xmemdupz(line, n);
                        }
-                       if (!strcmp("--lock-pack", arg)) {
-                               args.lock_pack = 1;
-                               pack_lockfile_ptr = &pack_lockfile;
-                               continue;
+               }
+               else {
+                       /* read from stdin one ref per line, until EOF */
+                       struct strbuf line = STRBUF_INIT;
+                       while (strbuf_getline(&line, stdin, '\n') != EOF) {
+                               ALLOC_GROW(heads, nr_heads + 1, alloc_heads);
+                               heads[nr_heads++] = strbuf_detach(&line, NULL);
                        }
-                       usage(fetch_pack_usage);
+                       strbuf_release(&line);
                }
-               dest = (char *)arg;
-               heads = (char **)(argv + i + 1);
-               nr_heads = argc - i - 1;
-               break;
        }
-       if (!dest)
-               usage(fetch_pack_usage);
 
        if (args.stateless_rpc) {
                conn = NULL;
                fd[0] = 0;
                fd[1] = 1;
        } else {
-               conn = git_connect(fd, (char *)dest, args.uploadpack,
+               conn = git_connect(fd, dest, args.uploadpack,
                                   args.verbose ? CONNECT_VERBOSE : 0);
        }