Add some fancy colors in the test library when terminal supports it.
[gitweb.git] / revision.c
index e43c6489785a61707b838df782d2859ec6654651..e76da0d448f81d8b6b496990bc2568fef3662671 100644 (file)
@@ -114,19 +114,20 @@ void mark_parents_uninteresting(struct commit *commit)
        }
 }
 
-void add_pending_object(struct rev_info *revs, struct object *obj, const char *name)
-{
-       add_pending_object_with_mode(revs, obj, name, S_IFINVALID);
-}
-
-void add_pending_object_with_mode(struct rev_info *revs, struct object *obj, const char *name, unsigned mode)
+static void add_pending_object_with_mode(struct rev_info *revs, struct object *obj, const char *name, unsigned mode)
 {
        if (revs->no_walk && (obj->flags & UNINTERESTING))
                die("object ranges do not make sense when not walking revisions");
+       if (revs->reflog_info && obj->type == OBJ_COMMIT &&
+                       add_reflog_for_walk(revs->reflog_info,
+                               (struct commit *)obj, name))
+               return;
        add_object_array_with_mode(obj, name, &revs->pending, mode);
-       if (revs->reflog_info && obj->type == OBJ_COMMIT)
-               add_reflog_for_walk(revs->reflog_info,
-                               (struct commit *)obj, name);
+}
+
+void add_pending_object(struct rev_info *revs, struct object *obj, const char *name)
+{
+       add_pending_object_with_mode(revs, obj, name, S_IFINVALID);
 }
 
 static struct object *get_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags)
@@ -262,7 +263,7 @@ static void file_change(struct diff_options *options,
        options->has_changes = 1;
 }
 
-int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree *t2)
+static int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree *t2)
 {
        if (!t1)
                return REV_TREE_NEW;
@@ -276,7 +277,7 @@ int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree *t2)
        return tree_difference;
 }
 
-int rev_same_tree_as_empty(struct rev_info *revs, struct tree *t1)
+static int rev_same_tree_as_empty(struct rev_info *revs, struct tree *t1)
 {
        int retval;
        void *tree;
@@ -437,7 +438,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit, str
        return 0;
 }
 
-static void cherry_pick_list(struct commit_list *list)
+static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
 {
        struct commit_list *p;
        int left_count = 0, right_count = 0;
@@ -458,6 +459,11 @@ static void cherry_pick_list(struct commit_list *list)
 
        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;
+       }
 
        /* Compute patch-ids for one side */
        for (p = list; p; p = p->next) {
@@ -546,7 +552,7 @@ static int limit_list(struct rev_info *revs)
                p = &commit_list_insert(commit, p)->next;
        }
        if (revs->cherry_pick)
-               cherry_pick_list(newlist);
+               cherry_pick_list(newlist, revs);
 
        revs->commits = newlist;
        return 0;
@@ -667,7 +673,6 @@ void init_revisions(struct rev_info *revs, const char *prefix)
        revs->min_age = -1;
        revs->skip_count = -1;
        revs->max_count = -1;
-       revs->subject_prefix = "PATCH";
 
        revs->prune_fn = NULL;
        revs->prune_data = NULL;
@@ -881,6 +886,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
        const char **unrecognized = argv + 1;
        int left = 1;
        int all_match = 0;
+       int regflags = 0;
 
        /* First, search for "--" */
        seen_dashdash = 0;
@@ -890,7 +896,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                        continue;
                argv[i] = NULL;
                argc = i;
-               revs->prune_data = get_pathspec(revs->prefix, argv + i + 1);
+               if (argv[i + 1])
+                       revs->prune_data = get_pathspec(revs->prefix, argv + i + 1);
                seen_dashdash = 1;
                break;
        }
@@ -1017,6 +1024,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                        }
                        if (!strcmp(arg, "--cherry-pick")) {
                                revs->cherry_pick = 1;
+                               revs->limited = 1;
                                continue;
                        }
                        if (!strcmp(arg, "--objects")) {
@@ -1126,14 +1134,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                                continue;
                        }
                        if (!strncmp(arg, "--date=", 7)) {
-                               if (!strcmp(arg + 7, "relative"))
-                                       revs->date_mode = DATE_RELATIVE;
-                               else if (!strcmp(arg + 7, "local"))
-                                       revs->date_mode = DATE_LOCAL;
-                               else if (!strcmp(arg + 7, "default"))
-                                       revs->date_mode = DATE_NORMAL;
-                               else
-                                       die("unknown date format %s", arg);
+                               revs->date_mode = parse_date_format(arg + 7);
+                               continue;
+                       }
+                       if (!strcmp(arg, "--log-size")) {
+                               revs->show_log_size = 1;
                                continue;
                        }
 
@@ -1152,6 +1157,16 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                                add_message_grep(revs, arg+7);
                                continue;
                        }
+                       if (!strcmp(arg, "--extended-regexp") ||
+                           !strcmp(arg, "-E")) {
+                               regflags |= REG_EXTENDED;
+                               continue;
+                       }
+                       if (!strcmp(arg, "--regexp-ignore-case") ||
+                           !strcmp(arg, "-i")) {
+                               regflags |= REG_ICASE;
+                               continue;
+                       }
                        if (!strcmp(arg, "--all-match")) {
                                all_match = 1;
                                continue;
@@ -1168,11 +1183,17 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                                revs->reverse ^= 1;
                                continue;
                        }
+                       if (!strcmp(arg, "--no-walk")) {
+                               revs->no_walk = 1;
+                               continue;
+                       }
+                       if (!strcmp(arg, "--do-walk")) {
+                               revs->no_walk = 0;
+                               continue;
+                       }
 
                        opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
                        if (opts > 0) {
-                               if (strcmp(argv[i], "-z"))
-                                       revs->diff = 1;
                                i += opts - 1;
                                continue;
                        }
@@ -1201,6 +1222,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                }
        }
 
+       if (revs->grep_filter)
+               revs->grep_filter->regflags |= regflags;
+
        if (show_merge)
                prepare_show_merge(revs);
        if (def && !revs->pending.nr) {
@@ -1213,12 +1237,22 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                add_pending_object_with_mode(revs, object, def, mode);
        }
 
+       /* Did the user ask for any diff output? Run the diff! */
+       if (revs->diffopt.output_format & ~DIFF_FORMAT_NO_OUTPUT)
+               revs->diff = 1;
+
+       /* Pickaxe and rename following needs diffs */
+       if (revs->diffopt.pickaxe || revs->diffopt.follow_renames)
+               revs->diff = 1;
+
        if (revs->topo_order)
                revs->limited = 1;
 
        if (revs->prune_data) {
                diff_tree_setup_paths(revs->prune_data, &revs->pruning);
-               revs->prune_fn = try_to_simplify_commit;
+               /* Can't prune commits with rename following: the paths change.. */
+               if (!revs->diffopt.follow_renames)
+                       revs->prune_fn = try_to_simplify_commit;
                if (!revs->full_diff)
                        diff_tree_setup_paths(revs->prune_data, &revs->diffopt);
        }
@@ -1236,6 +1270,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                compile_grep_patterns(revs->grep_filter);
        }
 
+       if (revs->reverse && revs->reflog_info)
+               die("cannot combine --reverse with --walk-reflogs");
+
        return left;
 }
 
@@ -1295,6 +1332,26 @@ static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp
        }
 }
 
+static void remove_duplicate_parents(struct commit *commit)
+{
+       struct commit_list **pp, *p;
+
+       /* Examine existing parents while marking ones we have seen... */
+       pp = &commit->parents;
+       while ((p = *pp) != NULL) {
+               struct commit *parent = p->item;
+               if (parent->object.flags & TMP_MARK) {
+                       *pp = p->next;
+                       continue;
+               }
+               parent->object.flags |= TMP_MARK;
+               pp = &p->next;
+       }
+       /* ... and clear the temporary mark */
+       for (p = commit->parents; p; p = p->next)
+               p->item->object.flags &= ~TMP_MARK;
+}
+
 static int rewrite_parents(struct rev_info *revs, struct commit *commit)
 {
        struct commit_list **pp = &commit->parents;
@@ -1311,6 +1368,7 @@ static int rewrite_parents(struct rev_info *revs, struct commit *commit)
                }
                pp = &parent->next;
        }
+       remove_duplicate_parents(commit);
        return 0;
 }