setup_revisions(): take pathspec from command line and --stdin correctly
[gitweb.git] / revision.c
index 4410a45a023f61774652420a7b8d430fd34a3ea8..047e0170056e236e4d096f45de4a56cc461308c6 100644 (file)
@@ -953,9 +953,37 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
        return 0;
 }
 
-static void read_revisions_from_stdin(struct rev_info *revs)
+struct cmdline_pathspec {
+       int alloc;
+       int nr;
+       const char **path;
+};
+
+static void append_prune_data(struct cmdline_pathspec *prune, const char **av)
+{
+       while (*av) {
+               ALLOC_GROW(prune->path, prune->nr+1, prune->alloc);
+               prune->path[prune->nr++] = *(av++);
+       }
+}
+
+static void read_pathspec_from_stdin(struct rev_info *revs, struct strbuf *sb,
+                                    struct cmdline_pathspec *prune)
+{
+       while (strbuf_getwholeline(sb, stdin, '\n') != EOF) {
+               int len = sb->len;
+               if (len && sb->buf[len - 1] == '\n')
+                       sb->buf[--len] = '\0';
+               ALLOC_GROW(prune->path, prune->nr+1, prune->alloc);
+               prune->path[prune->nr++] = xstrdup(sb->buf);
+       }
+}
+
+static void read_revisions_from_stdin(struct rev_info *revs,
+                                     struct cmdline_pathspec *prune)
 {
        struct strbuf sb;
+       int seen_dashdash = 0;
 
        strbuf_init(&sb, 1000);
        while (strbuf_getwholeline(&sb, stdin, '\n') != EOF) {
@@ -964,11 +992,18 @@ static void read_revisions_from_stdin(struct rev_info *revs)
                        sb.buf[--len] = '\0';
                if (!len)
                        break;
-               if (sb.buf[0] == '-')
+               if (sb.buf[0] == '-') {
+                       if (len == 2 && sb.buf[1] == '-') {
+                               seen_dashdash = 1;
+                               break;
+                       }
                        die("options not supported in --stdin mode");
+               }
                if (handle_revision_arg(sb.buf, revs, 0, 1))
                        die("bad revision '%s'", sb.buf);
        }
+       if (seen_dashdash)
+               read_pathspec_from_stdin(revs, &sb, prune);
        strbuf_release(&sb);
 }
 
@@ -996,7 +1031,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
        if (!strcmp(arg, "--all") || !strcmp(arg, "--branches") ||
            !strcmp(arg, "--tags") || !strcmp(arg, "--remotes") ||
            !strcmp(arg, "--reflog") || !strcmp(arg, "--not") ||
-           !strcmp(arg, "--no-walk") || !strcmp(arg, "--do-walk"))
+           !strcmp(arg, "--no-walk") || !strcmp(arg, "--do-walk") ||
+           !strcmp(arg, "--bisect"))
        {
                unkv[(*unkc)++] = arg;
                return 1;
@@ -1220,6 +1256,16 @@ void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
        ctx->argc -= n;
 }
 
+static int for_each_bad_bisect_ref(each_ref_fn fn, void *cb_data)
+{
+       return for_each_ref_in("refs/bisect/bad", fn, cb_data);
+}
+
+static int for_each_good_bisect_ref(each_ref_fn fn, void *cb_data)
+{
+       return for_each_ref_in("refs/bisect/good", fn, cb_data);
+}
+
 /*
  * Parse revision information, filling in the "rev_info" structure,
  * and removing the used arguments from the argument list.
@@ -1230,7 +1276,9 @@ void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
 int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def)
 {
        int i, flags, left, seen_dashdash, read_from_stdin;
-       const char **prune_data = NULL;
+       struct cmdline_pathspec prune_data;
+
+       memset(&prune_data, 0, sizeof(prune_data));
 
        /* First, search for "--" */
        seen_dashdash = 0;
@@ -1241,7 +1289,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                argv[i] = NULL;
                argc = i;
                if (argv[i + 1])
-                       prune_data = argv + i + 1;
+                       append_prune_data(&prune_data, argv + i + 1);
                seen_dashdash = 1;
                break;
        }
@@ -1263,6 +1311,12 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                                handle_refs(revs, flags, for_each_branch_ref);
                                continue;
                        }
+                       if (!strcmp(arg, "--bisect")) {
+                               handle_refs(revs, flags, for_each_bad_bisect_ref);
+                               handle_refs(revs, flags ^ UNINTERESTING, for_each_good_bisect_ref);
+                               revs->bisect = 1;
+                               continue;
+                       }
                        if (!strcmp(arg, "--tags")) {
                                handle_refs(revs, flags, for_each_tag_ref);
                                continue;
@@ -1294,7 +1348,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                                }
                                if (read_from_stdin++)
                                        die("--stdin given twice?");
-                               read_revisions_from_stdin(revs);
+                               read_revisions_from_stdin(revs, &prune_data);
                                continue;
                        }
 
@@ -1322,13 +1376,16 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                        for (j = i; j < argc; j++)
                                verify_filename(revs->prefix, argv[j]);
 
-                       prune_data = argv + i;
+                       append_prune_data(&prune_data, argv + i);
                        break;
                }
        }
 
-       if (prune_data)
-               revs->prune_data = get_pathspec(revs->prefix, prune_data);
+       if (prune_data.nr) {
+               ALLOC_GROW(prune_data.path, prune_data.nr+1, prune_data.alloc);
+               prune_data.path[prune_data.nr++] = NULL;
+               revs->prune_data = get_pathspec(revs->prefix, prune_data.path);
+       }
 
        if (revs->def == NULL)
                revs->def = def;