Merge branch 'tr/rev-list-reverse'
authorJunio C Hamano <gitster@pobox.com>
Fri, 19 Sep 2008 03:18:37 +0000 (20:18 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 19 Sep 2008 03:18:37 +0000 (20:18 -0700)
* tr/rev-list-reverse:
t6013: replace use of 'tac' with equivalent Perl
rev-list: fix --reverse interaction with --parents

1  2 
revision.c
revision.h
diff --combined revision.c
index 499f0e0225c1e8e2289cbca1264923b6f4bfab71,d797f05c93abebddee4ca599f72841231b1426aa..2f646deab09c423143185b7f7928ae46ab9f4c97
@@@ -782,10 -782,6 +782,10 @@@ void init_revisions(struct rev_info *re
  
        revs->commit_format = CMIT_FMT_DEFAULT;
  
 +      revs->grep_filter.status_only = 1;
 +      revs->grep_filter.pattern_tail = &(revs->grep_filter.pattern_list);
 +      revs->grep_filter.regflags = REG_NEWLINE;
 +
        diff_setup(&revs->diffopt);
        if (prefix && !revs->diffopt.prefix) {
                revs->diffopt.prefix = prefix;
@@@ -950,12 -946,33 +950,12 @@@ void read_revisions_from_stdin(struct r
  
  static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what)
  {
 -      if (!revs->grep_filter) {
 -              struct grep_opt *opt = xcalloc(1, sizeof(*opt));
 -              opt->status_only = 1;
 -              opt->pattern_tail = &(opt->pattern_list);
 -              opt->regflags = REG_NEWLINE;
 -              revs->grep_filter = opt;
 -      }
 -      append_grep_pattern(revs->grep_filter, ptn,
 -                          "command line", 0, what);
 +      append_grep_pattern(&revs->grep_filter, ptn, "command line", 0, what);
  }
  
 -static void add_header_grep(struct rev_info *revs, const char *field, const char *pattern)
 +static void add_header_grep(struct rev_info *revs, enum grep_header_field field, const char *pattern)
  {
 -      char *pat;
 -      const char *prefix;
 -      int patlen, fldlen;
 -
 -      fldlen = strlen(field);
 -      patlen = strlen(pattern);
 -      pat = xmalloc(patlen + fldlen + 10);
 -      prefix = ".*";
 -      if (*pattern == '^') {
 -              prefix = "";
 -              pattern++;
 -      }
 -      sprintf(pat, "^%s %s%s", field, prefix, pattern);
 -      add_grep(revs, pat, GREP_PATTERN_HEAD);
 +      append_header_grep_pattern(&revs->grep_filter, field, pattern);
  }
  
  static void add_message_grep(struct rev_info *revs, const char *pattern)
@@@ -1146,19 -1163,23 +1146,19 @@@ static int handle_revision_opt(struct r
         * Grepping the commit log
         */
        else if (!prefixcmp(arg, "--author=")) {
 -              add_header_grep(revs, "author", arg+9);
 +              add_header_grep(revs, GREP_HEADER_AUTHOR, arg+9);
        } else if (!prefixcmp(arg, "--committer=")) {
 -              add_header_grep(revs, "committer", arg+12);
 +              add_header_grep(revs, GREP_HEADER_COMMITTER, arg+12);
        } else if (!prefixcmp(arg, "--grep=")) {
                add_message_grep(revs, arg+7);
        } else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
 -              if (revs->grep_filter)
 -                      revs->grep_filter->regflags |= REG_EXTENDED;
 +              revs->grep_filter.regflags |= REG_EXTENDED;
        } else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
 -              if (revs->grep_filter)
 -                      revs->grep_filter->regflags |= REG_ICASE;
 +              revs->grep_filter.regflags |= REG_ICASE;
        } else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
 -              if (revs->grep_filter)
 -                      revs->grep_filter->fixed = 1;
 +              revs->grep_filter.fixed = 1;
        } else if (!strcmp(arg, "--all-match")) {
 -              if (revs->grep_filter)
 -                      revs->grep_filter->all_match = 1;
 +              revs->grep_filter.all_match = 1;
        } else if (!prefixcmp(arg, "--encoding=")) {
                arg += 11;
                if (strcmp(arg, "none"))
@@@ -1333,7 -1354,9 +1333,7 @@@ int setup_revisions(int argc, const cha
        if (diff_setup_done(&revs->diffopt) < 0)
                die("diff_setup_done failed");
  
 -      if (revs->grep_filter) {
 -              compile_grep_patterns(revs->grep_filter);
 -      }
 +      compile_grep_patterns(&revs->grep_filter);
  
        if (revs->reverse && revs->reflog_info)
                die("cannot combine --reverse with --walk-reflogs");
@@@ -1385,34 -1408,16 +1385,34 @@@ static int remove_duplicate_parents(str
        return surviving_parents;
  }
  
 -static struct commit_list **simplify_one(struct commit *commit, struct commit_list **tail)
 +struct merge_simplify_state {
 +      struct commit *simplified;
 +};
 +
 +static struct merge_simplify_state *locate_simplify_state(struct rev_info *revs, struct commit *commit)
 +{
 +      struct merge_simplify_state *st;
 +
 +      st = lookup_decoration(&revs->merge_simplification, &commit->object);
 +      if (!st) {
 +              st = xcalloc(1, sizeof(*st));
 +              add_decoration(&revs->merge_simplification, &commit->object, st);
 +      }
 +      return st;
 +}
 +
 +static struct commit_list **simplify_one(struct rev_info *revs, struct commit *commit, struct commit_list **tail)
  {
        struct commit_list *p;
 +      struct merge_simplify_state *st, *pst;
        int cnt;
  
 +      st = locate_simplify_state(revs, commit);
 +
        /*
 -       * We store which commit each one simplifies to in its util field.
         * Have we handled this one?
         */
 -      if (commit->util)
 +      if (st->simplified)
                return tail;
  
        /*
         * anyway.
         */
        if ((commit->object.flags & UNINTERESTING) || !commit->parents) {
 -              commit->util = commit;
 +              st->simplified = commit;
                return tail;
        }
  
         * Otherwise we are not ready to rewrite this one yet.
         */
        for (cnt = 0, p = commit->parents; p; p = p->next) {
 -              if (!p->item->util) {
 +              pst = locate_simplify_state(revs, p->item);
 +              if (!pst->simplified) {
                        tail = &commit_list_insert(p->item, tail)->next;
                        cnt++;
                }
        }
 -      if (cnt)
 +      if (cnt) {
 +              tail = &commit_list_insert(commit, tail)->next;
                return tail;
 +      }
  
        /*
         * Rewrite our list of parents.
         */
 -      for (p = commit->parents; p; p = p->next)
 -              p->item = p->item->util;
 +      for (p = commit->parents; p; p = p->next) {
 +              pst = locate_simplify_state(revs, p->item);
 +              p->item = pst->simplified;
 +      }
        cnt = remove_duplicate_parents(commit);
  
        /*
            (commit->object.flags & UNINTERESTING) ||
            !(commit->object.flags & TREESAME) ||
            (1 < cnt))
 -              commit->util = commit;
 -      else
 -              commit->util = commit->parents->item->util;
 +              st->simplified = commit;
 +      else {
 +              pst = locate_simplify_state(revs, commit->parents->item);
 +              st->simplified = pst->simplified;
 +      }
        return tail;
  }
  
@@@ -1495,10 -1493,7 +1495,10 @@@ static void simplify_merges(struct rev_
        struct commit_list *list;
        struct commit_list *yet_to_do, **tail;
  
 -      sort_in_topological_order(&revs->commits, revs->lifo);
 +      if (!revs->topo_order)
 +              sort_in_topological_order(&revs->commits, revs->lifo);
 +      if (!revs->prune)
 +              return;
  
        /* feed the list reversed */
        yet_to_do = NULL;
                        struct commit_list *next = list->next;
                        free(list);
                        list = next;
 -                      tail = simplify_one(commit, tail);
 +                      tail = simplify_one(revs, commit, tail);
                }
        }
  
        while (list) {
                struct commit *commit = list->item;
                struct commit_list *next = list->next;
 +              struct merge_simplify_state *st;
                free(list);
                list = next;
 -              if (commit->util == commit)
 +              st = locate_simplify_state(revs, commit);
 +              if (st->simplified == commit)
                        tail = &commit_list_insert(commit, tail)->next;
        }
  }
@@@ -1629,9 -1622,9 +1629,9 @@@ static int rewrite_parents(struct rev_i
  
  static int commit_match(struct commit *commit, struct rev_info *opt)
  {
 -      if (!opt->grep_filter)
 +      if (!opt->grep_filter.pattern_list)
                return 1;
 -      return grep_buffer(opt->grep_filter,
 +      return grep_buffer(&opt->grep_filter,
                           NULL, /* we say nothing, not even filename */
                           commit->buffer, strlen(commit->buffer));
  }
@@@ -1793,26 -1786,6 +1793,6 @@@ static struct commit *get_revision_inte
                return c;
        }
  
-       if (revs->reverse) {
-               int limit = -1;
-               if (0 <= revs->max_count) {
-                       limit = revs->max_count;
-                       if (0 < revs->skip_count)
-                               limit += revs->skip_count;
-               }
-               l = NULL;
-               while ((c = get_revision_1(revs))) {
-                       commit_list_insert(c, &l);
-                       if ((0 < limit) && !--limit)
-                               break;
-               }
-               revs->commits = l;
-               revs->reverse = 0;
-               revs->max_count = -1;
-               c = NULL;
-       }
        /*
         * Now pick up what they want to give us
         */
  
  struct commit *get_revision(struct rev_info *revs)
  {
-       struct commit *c = get_revision_internal(revs);
+       struct commit *c;
+       struct commit_list *reversed;
+       if (revs->reverse) {
+               reversed = NULL;
+               while ((c = get_revision_internal(revs))) {
+                       commit_list_insert(c, &reversed);
+               }
+               revs->commits = reversed;
+               revs->reverse = 0;
+               revs->reverse_output_stage = 1;
+       }
+       if (revs->reverse_output_stage)
+               return pop_commit(&revs->commits);
+       c = get_revision_internal(revs);
        if (c && revs->graph)
                graph_update(revs->graph, c);
        return c;
diff --combined revision.h
index fc23522b3850edb3752181596fd83da8599e3d27,b818cea76bd31004888ff4c7eecaa798533c508f..2fdb2dd0ff3425b68b47aa8fd11155aa881d4a4a
@@@ -2,7 -2,6 +2,7 @@@
  #define REVISION_H
  
  #include "parse-options.h"
 +#include "grep.h"
  
  #define SEEN          (1u<<0)
  #define UNINTERESTING   (1u<<1)
@@@ -54,6 -53,7 +54,7 @@@ struct rev_info 
                        rewrite_parents:1,
                        print_parents:1,
                        reverse:1,
+                       reverse_output_stage:1,
                        cherry_pick:1,
                        first_parent_only:1;
  
@@@ -94,7 -94,7 +95,7 @@@
        int             show_log_size;
  
        /* Filter by commit log message */
 -      struct grep_opt *grep_filter;
 +      struct grep_opt grep_filter;
  
        /* Display history graph */
        struct git_graph *graph;
  
        struct reflog_walk_info *reflog_info;
        struct decoration children;
 +      struct decoration merge_simplification;
  };
  
  #define REV_TREE_SAME         0
  void read_revisions_from_stdin(struct rev_info *revs);
  
  typedef void (*show_early_output_fn_t)(struct rev_info *, struct commit_list *);
 -volatile show_early_output_fn_t show_early_output;
 +extern volatile show_early_output_fn_t show_early_output;
  
  extern void init_revisions(struct rev_info *revs, const char *prefix);
  extern int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def);