http-push: support for updating remote info/refs
[git.git] / revision.c
index 4885871..c8d93ff 100644 (file)
@@ -82,18 +82,20 @@ void mark_parents_uninteresting(struct commit *commit)
 
        while (parents) {
                struct commit *commit = parents->item;
-               commit->object.flags |= UNINTERESTING;
-
-               /*
-                * Normally we haven't parsed the parent
-                * yet, so we won't have a parent of a parent
-                * here. However, it may turn out that we've
-                * reached this commit some other way (where it
-                * wasn't uninteresting), in which case we need
-                * to mark its parents recursively too..
-                */
-               if (commit->parents)
-                       mark_parents_uninteresting(commit);
+               if (!(commit->object.flags & UNINTERESTING)) {
+                       commit->object.flags |= UNINTERESTING;
+
+                       /*
+                        * Normally we haven't parsed the parent
+                        * yet, so we won't have a parent of a parent
+                        * here. However, it may turn out that we've
+                        * reached this commit some other way (where it
+                        * wasn't uninteresting), in which case we need
+                        * to mark its parents recursively too..
+                        */
+                       if (commit->parents)
+                               mark_parents_uninteresting(commit);
+               }
 
                /*
                 * A missing commit is ok iff its parent is marked
@@ -280,6 +282,7 @@ static int same_tree_as_empty(struct tree *t1)
 static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
 {
        struct commit_list **pp, *parent;
+       int tree_changed = 0;
 
        if (!commit->tree)
                return;
@@ -294,14 +297,19 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
        while ((parent = *pp) != NULL) {
                struct commit *p = parent->item;
 
-               if (p->object.flags & UNINTERESTING) {
-                       pp = &parent->next;
-                       continue;
-               }
-
                parse_commit(p);
                switch (compare_tree(p->tree, commit->tree)) {
                case TREE_SAME:
+                       if (p->object.flags & UNINTERESTING) {
+                               /* Even if a merge with an uninteresting
+                                * side branch brought the entire change
+                                * we are interested in, we do not want
+                                * to lose the other branches of this
+                                * merge, so we just keep going.
+                                */
+                               pp = &parent->next;
+                               continue;
+                       }
                        parent->next = NULL;
                        commit->parents = parent;
                        return;
@@ -313,12 +321,14 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
                        }
                /* fallthrough */
                case TREE_DIFFERENT:
+                       tree_changed = 1;
                        pp = &parent->next;
                        continue;
                }
                die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
        }
-       commit->object.flags |= TREECHANGE;
+       if (tree_changed)
+               commit->object.flags |= TREECHANGE;
 }
 
 static void add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list)
@@ -482,6 +492,21 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                                revs->max_count = atoi(arg + 12);
                                continue;
                        }
+                       /* accept -<digit>, like traditilnal "head" */
+                       if ((*arg == '-') && isdigit(arg[1])) {
+                               revs->max_count = atoi(arg + 1);
+                               continue;
+                       }
+                       if (!strcmp(arg, "-n")) {
+                               if (argc <= i + 1)
+                                       die("-n requires an argument");
+                               revs->max_count = atoi(argv[++i]);
+                               continue;
+                       }
+                       if (!strncmp(arg,"-n",2)) {
+                               revs->max_count = atoi(arg + 2);
+                               continue;
+                       }
                        if (!strncmp(arg, "--max-age=", 10)) {
                                revs->max_age = atoi(arg + 10);
                                revs->limited = 1;
@@ -669,13 +694,11 @@ static void rewrite_parents(struct commit *commit)
 struct commit *get_revision(struct rev_info *revs)
 {
        struct commit_list *list = revs->commits;
-       struct commit *commit;
 
        if (!list)
                return NULL;
 
        /* Check the max_count ... */
-       commit = list->item;
        switch (revs->max_count) {
        case -1:
                break;
@@ -686,22 +709,28 @@ struct commit *get_revision(struct rev_info *revs)
        }
 
        do {
-               commit = pop_most_recent_commit(&revs->commits, SEEN);
+               struct commit *commit = revs->commits->item;
+
                if (commit->object.flags & (UNINTERESTING|SHOWN))
-                       continue;
+                       goto next;
                if (revs->min_age != -1 && (commit->date > revs->min_age))
-                       continue;
+                       goto next;
                if (revs->max_age != -1 && (commit->date < revs->max_age))
                        return NULL;
                if (revs->no_merges && commit->parents && commit->parents->next)
-                       continue;
+                       goto next;
                if (revs->paths && revs->dense) {
                        if (!(commit->object.flags & TREECHANGE))
-                               continue;
+                               goto next;
                        rewrite_parents(commit);
                }
+               /* More to go? */
+               if (revs->max_count)
+                       pop_most_recent_commit(&revs->commits, SEEN);
                commit->object.flags |= SHOWN;
                return commit;
+next:
+               pop_most_recent_commit(&revs->commits, SEEN);
        } while (revs->commits);
        return NULL;
 }