Merge branch 'jc/directory-attrs-regression-fix'
[gitweb.git] / commit.c
index 0ea441d13b1430231f30d9524aed88b9719290b6..b4512ab0b2ebd008aa90e0dfe00fbc1aa42a5c64 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -9,6 +9,8 @@
 #include "gpg-interface.h"
 #include "mergesort.h"
 
+static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
+
 int save_commit_buffer = 1;
 
 const char *commit_type = "commit";
@@ -461,14 +463,23 @@ static void clear_commit_marks_1(struct commit_list **plist,
        }
 }
 
-void clear_commit_marks(struct commit *commit, unsigned int mark)
+void clear_commit_marks_many(int nr, struct commit **commit, unsigned int mark)
 {
        struct commit_list *list = NULL;
-       commit_list_insert(commit, &list);
+
+       while (nr--) {
+               commit_list_insert(*commit, &list);
+               commit++;
+       }
        while (list)
                clear_commit_marks_1(&list, pop_commit(&list), mark);
 }
 
+void clear_commit_marks(struct commit *commit, unsigned int mark)
+{
+       clear_commit_marks_many(1, &commit, mark);
+}
+
 void clear_commit_marks_for_object_array(struct object_array *a, unsigned mark)
 {
        struct object *object;
@@ -607,6 +618,7 @@ static struct commit *interesting(struct commit_list *list)
        return NULL;
 }
 
+/* all input commits in one and twos[] must have been parsed! */
 static struct commit_list *paint_down_to_common(struct commit *one, int n, struct commit **twos)
 {
        struct commit_list *list = NULL;
@@ -615,6 +627,8 @@ static struct commit_list *paint_down_to_common(struct commit *one, int n, struc
 
        one->object.flags |= PARENT1;
        commit_list_insert_by_date(one, &list);
+       if (!n)
+               return list;
        for (i = 0; i < n; i++) {
                twos[i]->object.flags |= PARENT2;
                commit_list_insert_by_date(twos[i], &list);
@@ -735,6 +749,8 @@ static int remove_redundant(struct commit **array, int cnt)
        redundant = xcalloc(cnt, 1);
        filled_index = xmalloc(sizeof(*filled_index) * (cnt - 1));
 
+       for (i = 0; i < cnt; i++)
+               parse_commit(array[i]);
        for (i = 0; i < cnt; i++) {
                struct commit_list *common;
 
@@ -790,8 +806,7 @@ struct commit_list *get_merge_bases_many(struct commit *one,
        if (!result || !result->next) {
                if (cleanup) {
                        clear_commit_marks(one, all_flags);
-                       for (i = 0; i < n; i++)
-                               clear_commit_marks(twos[i], all_flags);
+                       clear_commit_marks_many(n, twos, all_flags);
                }
                return result;
        }
@@ -809,8 +824,7 @@ struct commit_list *get_merge_bases_many(struct commit *one,
        free_commit_list(result);
 
        clear_commit_marks(one, all_flags);
-       for (i = 0; i < n; i++)
-               clear_commit_marks(twos[i], all_flags);
+       clear_commit_marks_many(n, twos, all_flags);
 
        cnt = remove_redundant(rslt, cnt);
        result = NULL;
@@ -845,25 +859,36 @@ int is_descendant_of(struct commit *commit, struct commit_list *with_commit)
 }
 
 /*
- * Is "commit" an ancestor of (i.e. reachable from) the "reference"?
+ * Is "commit" an ancestor of one of the "references"?
  */
-int in_merge_bases(struct commit *commit, struct commit *reference)
+int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit **reference)
 {
        struct commit_list *bases;
-       int ret = 0;
+       int ret = 0, i;
 
-       if (parse_commit(commit) || parse_commit(reference))
+       if (parse_commit(commit))
                return ret;
+       for (i = 0; i < nr_reference; i++)
+               if (parse_commit(reference[i]))
+                       return ret;
 
-       bases = paint_down_to_common(commit, 1, &reference);
+       bases = paint_down_to_common(commit, nr_reference, reference);
        if (commit->object.flags & PARENT2)
                ret = 1;
        clear_commit_marks(commit, all_flags);
-       clear_commit_marks(reference, all_flags);
+       clear_commit_marks_many(nr_reference, reference, all_flags);
        free_commit_list(bases);
        return ret;
 }
 
+/*
+ * Is "commit" an ancestor of (i.e. reachable from) the "reference"?
+ */
+int in_merge_bases(struct commit *commit, struct commit *reference)
+{
+       return in_merge_bases_many(commit, 1, &reference);
+}
+
 struct commit_list *reduce_heads(struct commit_list *heads)
 {
        struct commit_list *p;
@@ -1073,8 +1098,9 @@ static int excluded_header_field(const char *field, size_t len, const char **exc
        return 0;
 }
 
-struct commit_extra_header *read_commit_extra_header_lines(const char *buffer, size_t size,
-                                                          const char **exclude)
+static struct commit_extra_header *read_commit_extra_header_lines(
+       const char *buffer, size_t size,
+       const char **exclude)
 {
        struct commit_extra_header *extra = NULL, **tail = &extra, *it = NULL;
        const char *line, *next, *eof, *eob;
@@ -1339,3 +1365,13 @@ struct commit_list **commit_list_append(struct commit *commit,
        new->next = NULL;
        return &new->next;
 }
+
+void print_commit_list(struct commit_list *list,
+                      const char *format_cur,
+                      const char *format_last)
+{
+       for ( ; list; list = list->next) {
+               const char *format = list->next ? format_cur : format_last;
+               printf(format, sha1_to_hex(list->item->object.sha1));
+       }
+}