Extend index to save more flags
[gitweb.git] / revision.c
index 0aaa4c10b9692b39eb3dfb1cf0e45890d598550e..2f646deab09c423143185b7f7928ae46ab9f4c97 100644 (file)
@@ -782,6 +782,10 @@ void init_revisions(struct rev_info *revs, const char *prefix)
 
        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;
@@ -946,33 +950,12 @@ void read_revisions_from_stdin(struct rev_info *revs)
 
 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)
@@ -1163,23 +1146,19 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
         * 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"))
@@ -1354,9 +1333,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
        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");
@@ -1408,16 +1385,34 @@ static int remove_duplicate_parents(struct commit *commit)
        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;
 
        /*
@@ -1426,7 +1421,7 @@ static struct commit_list **simplify_one(struct commit *commit, struct commit_li
         * anyway.
         */
        if ((commit->object.flags & UNINTERESTING) || !commit->parents) {
-               commit->util = commit;
+               st->simplified = commit;
                return tail;
        }
 
@@ -1435,19 +1430,24 @@ static struct commit_list **simplify_one(struct commit *commit, struct commit_li
         * 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);
 
        /*
@@ -1482,9 +1482,11 @@ static struct commit_list **simplify_one(struct commit *commit, struct commit_li
            (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;
 }
 
@@ -1493,7 +1495,10 @@ static void simplify_merges(struct rev_info *revs)
        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;
@@ -1508,7 +1513,7 @@ static void simplify_merges(struct rev_info *revs)
                        struct commit_list *next = list->next;
                        free(list);
                        list = next;
-                       tail = simplify_one(commit, tail);
+                       tail = simplify_one(revs, commit, tail);
                }
        }
 
@@ -1519,9 +1524,11 @@ static void simplify_merges(struct rev_info *revs)
        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;
        }
 }
@@ -1622,9 +1629,9 @@ static int rewrite_parents(struct rev_info *revs, struct commit *commit)
 
 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));
 }
@@ -1786,26 +1793,6 @@ static struct commit *get_revision_internal(struct rev_info *revs)
                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
         */
@@ -1878,7 +1865,23 @@ static struct commit *get_revision_internal(struct rev_info *revs)
 
 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;