diff.c: replace a 'strdup' with 'xstrdup'.
[gitweb.git] / revision.c
index 931f978af91786abcdb0ce6b2ae819c9e4e15902..6e85aaa3fb30e98f3b02f094af7f1763577cdb8d 100644 (file)
@@ -67,10 +67,17 @@ void mark_tree_uninteresting(struct tree *tree)
 
        init_tree_desc(&desc, tree->buffer, tree->size);
        while (tree_entry(&desc, &entry)) {
-               if (S_ISDIR(entry.mode))
+               switch (object_type(entry.mode)) {
+               case OBJ_TREE:
                        mark_tree_uninteresting(lookup_tree(entry.sha1));
-               else
+                       break;
+               case OBJ_BLOB:
                        mark_blob_uninteresting(lookup_blob(entry.sha1));
+                       break;
+               default:
+                       /* Subproject commit - not in this repository */
+                       break;
+               }
        }
 
        /*
@@ -132,6 +139,18 @@ void add_pending_object(struct rev_info *revs, struct object *obj, const char *n
        add_pending_object_with_mode(revs, obj, name, S_IFINVALID);
 }
 
+void add_head_to_pending(struct rev_info *revs)
+{
+       unsigned char sha1[20];
+       struct object *obj;
+       if (get_sha1("HEAD", sha1))
+               return;
+       obj = parse_object(sha1);
+       if (!obj)
+               return;
+       add_pending_object(revs, obj, "HEAD");
+}
+
 static struct object *get_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags)
 {
        struct object *object;
@@ -252,7 +271,7 @@ static void file_add_remove(struct diff_options *options,
        }
        tree_difference = diff;
        if (tree_difference == REV_TREE_DIFFERENT)
-               options->has_changes = 1;
+               DIFF_OPT_SET(options, HAS_CHANGES);
 }
 
 static void file_change(struct diff_options *options,
@@ -262,7 +281,7 @@ static void file_change(struct diff_options *options,
                 const char *base, const char *path)
 {
        tree_difference = REV_TREE_DIFFERENT;
-       options->has_changes = 1;
+       DIFF_OPT_SET(options, HAS_CHANGES);
 }
 
 static int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree *t2)
@@ -272,7 +291,7 @@ static int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree
        if (!t2)
                return REV_TREE_DIFFERENT;
        tree_difference = REV_TREE_SAME;
-       revs->pruning.has_changes = 0;
+       DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
        if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "",
                           &revs->pruning) < 0)
                return REV_TREE_DIFFERENT;
@@ -296,7 +315,7 @@ static int rev_same_tree_as_empty(struct rev_info *revs, struct tree *t1)
        init_tree_desc(&empty, "", 0);
 
        tree_difference = REV_TREE_SAME;
-       revs->pruning.has_changes = 0;
+       DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
        retval = diff_tree(&empty, &real, "", &revs->pruning);
        free(tree);
 
@@ -311,17 +330,15 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
        /*
         * If we don't do pruning, everything is interesting
         */
-       if (!revs->prune) {
-               commit->object.flags |= TREECHANGE;
+       if (!revs->prune)
                return;
-       }
 
        if (!commit->tree)
                return;
 
        if (!commit->parents) {
-               if (!rev_same_tree_as_empty(revs, commit->tree))
-                       commit->object.flags |= TREECHANGE;
+               if (rev_same_tree_as_empty(revs, commit->tree))
+                       commit->object.flags |= TREESAME;
                return;
        }
 
@@ -329,10 +346,8 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
         * Normal non-merge commit? If we don't want to make the
         * history dense, we consider it always to be a change..
         */
-       if (!revs->dense && !commit->parents->next) {
-               commit->object.flags |= TREECHANGE;
+       if (!revs->dense && !commit->parents->next)
                return;
-       }
 
        pp = &commit->parents;
        while ((parent = *pp) != NULL) {
@@ -357,6 +372,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
                        }
                        parent->next = NULL;
                        commit->parents = parent;
+                       commit->object.flags |= TREESAME;
                        return;
 
                case REV_TREE_NEW:
@@ -385,7 +401,8 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
                die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
        }
        if (tree_changed && !tree_same)
-               commit->object.flags |= TREECHANGE;
+               return;
+       commit->object.flags |= TREESAME;
 }
 
 static int add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list)
@@ -688,8 +705,8 @@ void init_revisions(struct rev_info *revs, const char *prefix)
        revs->abbrev = DEFAULT_ABBREV;
        revs->ignore_merges = 1;
        revs->simplify_history = 1;
-       revs->pruning.recursive = 1;
-       revs->pruning.quiet = 1;
+       DIFF_OPT_SET(&revs->pruning, RECURSIVE);
+       DIFF_OPT_SET(&revs->pruning, QUIET);
        revs->pruning.add_remove = file_add_remove;
        revs->pruning.change = file_change;
        revs->lifo = 1;
@@ -1086,13 +1103,13 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                        }
                        if (!strcmp(arg, "-r")) {
                                revs->diff = 1;
-                               revs->diffopt.recursive = 1;
+                               DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
                                continue;
                        }
                        if (!strcmp(arg, "-t")) {
                                revs->diff = 1;
-                               revs->diffopt.recursive = 1;
-                               revs->diffopt.tree_in_recursive = 1;
+                               DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
+                               DIFF_OPT_SET(&revs->diffopt, TREE_IN_RECURSIVE);
                                continue;
                        }
                        if (!strcmp(arg, "-m")) {
@@ -1273,8 +1290,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
        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)
+       /* Pickaxe, diff-filter and rename following need diffs */
+       if (revs->diffopt.pickaxe ||
+           revs->diffopt.filter ||
+           DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES))
                revs->diff = 1;
 
        if (revs->topo_order)
@@ -1283,7 +1302,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
        if (revs->prune_data) {
                diff_tree_setup_paths(revs->prune_data, &revs->pruning);
                /* Can't prune commits with rename following: the paths change.. */
-               if (!revs->diffopt.follow_renames)
+               if (!DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES))
                        revs->prune = 1;
                if (!revs->full_diff)
                        diff_tree_setup_paths(revs->prune_data, &revs->diffopt);
@@ -1354,7 +1373,9 @@ static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp
                                return rewrite_one_error;
                if (p->parents && p->parents->next)
                        return rewrite_one_ok;
-               if (p->object.flags & (TREECHANGE | UNINTERESTING))
+               if (p->object.flags & UNINTERESTING)
+                       return rewrite_one_ok;
+               if (!(p->object.flags & TREESAME))
                        return rewrite_one_ok;
                if (!p->parents)
                        return rewrite_one_noparents;
@@ -1427,7 +1448,7 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
                return commit_ignore;
        if (revs->prune && revs->dense) {
                /* Commit without changes? */
-               if (!(commit->object.flags & TREECHANGE)) {
+               if (commit->object.flags & TREESAME) {
                        /* drop merges unless we want parenthood */
                        if (!revs->parents)
                                return commit_ignore;