Merge branch 'jc/maint-1.7.4-pathspec-stdin-and-cmdline'
authorJunio C Hamano <gitster@pobox.com>
Wed, 11 May 2011 22:05:01 +0000 (15:05 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 11 May 2011 23:09:25 +0000 (16:09 -0700)
Update the fix for 1.7.5 maintenance track.

* jc/maint-1.7.4-pathspec-stdin-and-cmdline:
setup_revisions(): take pathspec from command line and --stdin correctly

1  2 
revision.c
diff --combined revision.c
index 0f38364cf3f81a9088305ca802adf8b7c9260e91,073173eb9c48ec08a8fb30adf6bbd8b6ce54b1cc..707a703a09d6c7ffc1adfcd89da83d5b97da397f
@@@ -323,7 -323,7 +323,7 @@@ static int rev_compare_tree(struct rev_
                 * tagged commit by specifying both --simplify-by-decoration
                 * and pathspec.
                 */
 -              if (!revs->prune_data)
 +              if (!revs->prune_data.nr)
                        return REV_TREE_SAME;
        }
  
@@@ -535,7 -535,6 +535,7 @@@ static void cherry_pick_list(struct com
        int left_count = 0, right_count = 0;
        int left_first;
        struct patch_ids ids;
 +      unsigned cherry_flag;
  
        /* First count the commits on the left and on the right */
        for (p = list; p; p = p->next) {
  
        left_first = left_count < right_count;
        init_patch_ids(&ids);
 -      if (revs->diffopt.nr_paths) {
 -              ids.diffopts.nr_paths = revs->diffopt.nr_paths;
 -              ids.diffopts.paths = revs->diffopt.paths;
 -              ids.diffopts.pathlens = revs->diffopt.pathlens;
 -      }
 +      ids.diffopts.pathspec = revs->diffopt.pathspec;
  
        /* Compute patch-ids for one side */
        for (p = list; p; p = p->next) {
                commit->util = add_commit_patch_id(commit, &ids);
        }
  
 +      /* either cherry_mark or cherry_pick are true */
 +      cherry_flag = revs->cherry_mark ? PATCHSAME : SHOWN;
 +
        /* Check the other side */
        for (p = list; p; p = p->next) {
                struct commit *commit = p->item;
                if (!id)
                        continue;
                id->seen = 1;
 -              commit->object.flags |= SHOWN;
 +              commit->object.flags |= cherry_flag;
        }
  
        /* Now check the original side for seen ones */
                if (!ent)
                        continue;
                if (ent->seen)
 -                      commit->object.flags |= SHOWN;
 +                      commit->object.flags |= cherry_flag;
                commit->util = NULL;
        }
  
@@@ -733,23 -733,6 +733,23 @@@ static struct commit_list *collect_bott
        return bottom;
  }
  
 +/* Assumes either left_only or right_only is set */
 +static void limit_left_right(struct commit_list *list, struct rev_info *revs)
 +{
 +      struct commit_list *p;
 +
 +      for (p = list; p; p = p->next) {
 +              struct commit *commit = p->item;
 +
 +              if (revs->right_only) {
 +                      if (commit->object.flags & SYMMETRIC_LEFT)
 +                              commit->object.flags |= SHOWN;
 +              } else  /* revs->left_only is set */
 +                      if (!(commit->object.flags & SYMMETRIC_LEFT))
 +                              commit->object.flags |= SHOWN;
 +      }
 +}
 +
  static int limit_list(struct rev_info *revs)
  {
        int slop = SLOP;
                show(revs, newlist);
                show_early_output = NULL;
        }
 -      if (revs->cherry_pick)
 +      if (revs->cherry_pick || revs->cherry_mark)
                cherry_pick_list(newlist, revs);
  
 +      if (revs->left_only || revs->right_only)
 +              limit_left_right(newlist, revs);
 +
        if (bottom) {
                limit_to_ancestry(bottom, newlist);
                free_commit_list(bottom);
@@@ -941,7 -921,6 +941,7 @@@ void init_revisions(struct rev_info *re
        revs->min_age = -1;
        revs->skip_count = -1;
        revs->max_count = -1;
 +      revs->max_parents = -1;
  
        revs->commit_format = CMIT_FMT_DEFAULT;
  
@@@ -994,7 -973,7 +994,7 @@@ static void prepare_show_merge(struct r
                struct cache_entry *ce = active_cache[i];
                if (!ce_stage(ce))
                        continue;
 -              if (ce_path_match(ce, revs->prune_data)) {
 +              if (ce_path_match(ce, &revs->prune_data)) {
                        prune_num++;
                        prune = xrealloc(prune, sizeof(*prune) * prune_num);
                        prune[prune_num-2] = ce->name;
                       ce_same_name(ce, active_cache[i+1]))
                        i++;
        }
 -      revs->prune_data = prune;
 +      free_pathspec(&revs->prune_data);
 +      init_pathspec(&revs->prune_data, prune);
        revs->limited = 1;
  }
  
@@@ -1096,35 -1074,34 +1096,34 @@@ int handle_revision_arg(const char *arg
        return 0;
  }
  
- static void read_pathspec_from_stdin(struct rev_info *revs, struct strbuf *sb, const char ***prune_data)
- {
-       const char **prune = *prune_data;
-       int prune_nr;
      int prune_alloc;
+ struct cmdline_pathspec {
+       int alloc;
+       int nr;
+       const char **path;
};
  
-       /* count existing ones */
-       if (!prune)
-               prune_nr = 0;
-       else
-               for (prune_nr = 0; prune[prune_nr]; prune_nr++)
-                       ;
-       prune_alloc = prune_nr; /* not really, but we do not know */
+ 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, prune_nr+1, prune_alloc);
-               prune[prune_nr++] = xstrdup(sb->buf);
+               ALLOC_GROW(prune->path, prune->nr+1, prune->alloc);
+               prune->path[prune->nr++] = xstrdup(sb->buf);
        }
-       if (prune) {
-               ALLOC_GROW(prune, prune_nr+1, prune_alloc);
-               prune[prune_nr] = NULL;
-       }
-       *prune_data = prune;
  }
  
- static void read_revisions_from_stdin(struct rev_info *revs, const char ***prune)
+ static void read_revisions_from_stdin(struct rev_info *revs,
+                                     struct cmdline_pathspec *prune)
  {
        struct strbuf sb;
        int seen_dashdash = 0;
@@@ -1278,47 -1255,16 +1277,47 @@@ static int handle_revision_opt(struct r
        } else if (!strcmp(arg, "--remove-empty")) {
                revs->remove_empty_trees = 1;
        } else if (!strcmp(arg, "--merges")) {
 -              revs->merges_only = 1;
 +              revs->min_parents = 2;
        } else if (!strcmp(arg, "--no-merges")) {
 -              revs->no_merges = 1;
 +              revs->max_parents = 1;
 +      } else if (!prefixcmp(arg, "--min-parents=")) {
 +              revs->min_parents = atoi(arg+14);
 +      } else if (!prefixcmp(arg, "--no-min-parents")) {
 +              revs->min_parents = 0;
 +      } else if (!prefixcmp(arg, "--max-parents=")) {
 +              revs->max_parents = atoi(arg+14);
 +      } else if (!prefixcmp(arg, "--no-max-parents")) {
 +              revs->max_parents = -1;
        } else if (!strcmp(arg, "--boundary")) {
                revs->boundary = 1;
        } else if (!strcmp(arg, "--left-right")) {
                revs->left_right = 1;
 +      } else if (!strcmp(arg, "--left-only")) {
 +              if (revs->right_only)
 +                      die("--left-only is incompatible with --right-only"
 +                          " or --cherry");
 +              revs->left_only = 1;
 +      } else if (!strcmp(arg, "--right-only")) {
 +              if (revs->left_only)
 +                      die("--right-only is incompatible with --left-only");
 +              revs->right_only = 1;
 +      } else if (!strcmp(arg, "--cherry")) {
 +              if (revs->left_only)
 +                      die("--cherry is incompatible with --left-only");
 +              revs->cherry_mark = 1;
 +              revs->right_only = 1;
 +              revs->max_parents = 1;
 +              revs->limited = 1;
        } else if (!strcmp(arg, "--count")) {
                revs->count = 1;
 +      } else if (!strcmp(arg, "--cherry-mark")) {
 +              if (revs->cherry_pick)
 +                      die("--cherry-mark is incompatible with --cherry-pick");
 +              revs->cherry_mark = 1;
 +              revs->limited = 1; /* needs limit_list() */
        } else if (!strcmp(arg, "--cherry-pick")) {
 +              if (revs->cherry_mark)
 +                      die("--cherry-pick is incompatible with --cherry-mark");
                revs->cherry_pick = 1;
                revs->limited = 1;
        } else if (!strcmp(arg, "--objects")) {
@@@ -1498,34 -1444,6 +1497,6 @@@ static int for_each_good_bisect_ref(con
        return for_each_ref_in_submodule(submodule, "refs/bisect/good", fn, cb_data);
  }
  
- static void append_prune_data(const char ***prune_data, const char **av)
- {
-       const char **prune = *prune_data;
-       int prune_nr;
-       int prune_alloc;
-       if (!prune) {
-               *prune_data = av;
-               return;
-       }
-       /* count existing ones */
-       for (prune_nr = 0; prune[prune_nr]; prune_nr++)
-               ;
-       prune_alloc = prune_nr; /* not really, but we do not know */
-       while (*av) {
-               ALLOC_GROW(prune, prune_nr+1, prune_alloc);
-               prune[prune_nr++] = *av;
-               av++;
-       }
-       if (prune) {
-               ALLOC_GROW(prune, prune_nr+1, prune_alloc);
-               prune[prune_nr] = NULL;
-       }
-       *prune_data = prune;
- }
  /*
   * Parse revision information, filling in the "rev_info" structure,
   * and removing the used arguments from the argument list.
  int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct setup_revision_opt *opt)
  {
        int i, flags, left, seen_dashdash, read_from_stdin, got_rev_arg = 0;
-       const char **prune_data = NULL;
+       struct cmdline_pathspec prune_data;
        const char *submodule = NULL;
        const char *optarg;
        int argcount;
  
 -
+       memset(&prune_data, 0, sizeof(prune_data));
        if (opt)
                submodule = opt->submodule;
  
                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;
        }
                        got_rev_arg = 1;
        }
  
-       if (prune_data)
-               init_pathspec(&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);
++              init_pathspec(&revs->prune_data,
++                            get_pathspec(revs->prefix, prune_data.path));
+       }
  
        if (revs->def == NULL)
                revs->def = opt ? opt->def : NULL;
        if (revs->topo_order)
                revs->limited = 1;
  
 -      if (revs->prune_data) {
 -              diff_tree_setup_paths(revs->prune_data, &revs->pruning);
 +      if (revs->prune_data.nr) {
 +              diff_tree_setup_paths(revs->prune_data.raw, &revs->pruning);
                /* Can't prune commits with rename following: the paths change.. */
                if (!DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES))
                        revs->prune = 1;
                if (!revs->full_diff)
 -                      diff_tree_setup_paths(revs->prune_data, &revs->diffopt);
 +                      diff_tree_setup_paths(revs->prune_data.raw, &revs->diffopt);
        }
        if (revs->combine_merges)
                revs->ignore_merges = 0;
@@@ -2038,15 -1961,10 +2014,15 @@@ enum commit_action get_commit_action(st
                return commit_ignore;
        if (revs->min_age != -1 && (commit->date > revs->min_age))
                return commit_ignore;
 -      if (revs->no_merges && commit->parents && commit->parents->next)
 -              return commit_ignore;
 -      if (revs->merges_only && !(commit->parents && commit->parents->next))
 -              return commit_ignore;
 +      if (revs->min_parents || (revs->max_parents >= 0)) {
 +              int n = 0;
 +              struct commit_list *p;
 +              for (p = commit->parents; p; p = p->next)
 +                      n++;
 +              if ((n < revs->min_parents) ||
 +                  ((revs->max_parents >= 0) && (n > revs->max_parents)))
 +                      return commit_ignore;
 +      }
        if (!commit_match(commit, revs))
                return commit_ignore;
        if (revs->prune && revs->dense) {
@@@ -2293,32 -2211,3 +2269,32 @@@ struct commit *get_revision(struct rev_
                graph_update(revs->graph, c);
        return c;
  }
 +
 +char *get_revision_mark(const struct rev_info *revs, const struct commit *commit)
 +{
 +      if (commit->object.flags & BOUNDARY)
 +              return "-";
 +      else if (commit->object.flags & UNINTERESTING)
 +              return "^";
 +      else if (commit->object.flags & PATCHSAME)
 +              return "=";
 +      else if (!revs || revs->left_right) {
 +              if (commit->object.flags & SYMMETRIC_LEFT)
 +                      return "<";
 +              else
 +                      return ">";
 +      } else if (revs->graph)
 +              return "*";
 +      else if (revs->cherry_mark)
 +              return "+";
 +      return "";
 +}
 +
 +void put_revision_mark(const struct rev_info *revs, const struct commit *commit)
 +{
 +      char *mark = get_revision_mark(revs, commit);
 +      if (!strlen(mark))
 +              return;
 +      fputs(mark, stdout);
 +      putchar(' ');
 +}