a6bc4781a63d118d989599241057ec95fa39da5b
   1#include "cache.h"
   2#include "commit.h"
   3#include "decorate.h"
   4#include "prio-queue.h"
   5#include "tree.h"
   6#include "revision.h"
   7#include "tag.h"
   8#include "commit-reach.h"
   9
  10/* Remember to update object flag allocation in object.h */
  11#define PARENT1         (1u<<16)
  12#define PARENT2         (1u<<17)
  13#define STALE           (1u<<18)
  14#define RESULT          (1u<<19)
  15
  16static const unsigned all_flags = (PARENT1 | PARENT2 | STALE | RESULT);
  17
  18static int queue_has_nonstale(struct prio_queue *queue)
  19{
  20        int i;
  21        for (i = 0; i < queue->nr; i++) {
  22                struct commit *commit = queue->array[i].data;
  23                if (!(commit->object.flags & STALE))
  24                        return 1;
  25        }
  26        return 0;
  27}
  28
  29/* all input commits in one and twos[] must have been parsed! */
  30static struct commit_list *paint_down_to_common(struct commit *one, int n,
  31                                                struct commit **twos,
  32                                                int min_generation)
  33{
  34        struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
  35        struct commit_list *result = NULL;
  36        int i;
  37        uint32_t last_gen = GENERATION_NUMBER_INFINITY;
  38
  39        one->object.flags |= PARENT1;
  40        if (!n) {
  41                commit_list_append(one, &result);
  42                return result;
  43        }
  44        prio_queue_put(&queue, one);
  45
  46        for (i = 0; i < n; i++) {
  47                twos[i]->object.flags |= PARENT2;
  48                prio_queue_put(&queue, twos[i]);
  49        }
  50
  51        while (queue_has_nonstale(&queue)) {
  52                struct commit *commit = prio_queue_get(&queue);
  53                struct commit_list *parents;
  54                int flags;
  55
  56                if (commit->generation > last_gen)
  57                        BUG("bad generation skip %8x > %8x at %s",
  58                            commit->generation, last_gen,
  59                            oid_to_hex(&commit->object.oid));
  60                last_gen = commit->generation;
  61
  62                if (commit->generation < min_generation)
  63                        break;
  64
  65                flags = commit->object.flags & (PARENT1 | PARENT2 | STALE);
  66                if (flags == (PARENT1 | PARENT2)) {
  67                        if (!(commit->object.flags & RESULT)) {
  68                                commit->object.flags |= RESULT;
  69                                commit_list_insert_by_date(commit, &result);
  70                        }
  71                        /* Mark parents of a found merge stale */
  72                        flags |= STALE;
  73                }
  74                parents = commit->parents;
  75                while (parents) {
  76                        struct commit *p = parents->item;
  77                        parents = parents->next;
  78                        if ((p->object.flags & flags) == flags)
  79                                continue;
  80                        if (parse_commit(p))
  81                                return NULL;
  82                        p->object.flags |= flags;
  83                        prio_queue_put(&queue, p);
  84                }
  85        }
  86
  87        clear_prio_queue(&queue);
  88        return result;
  89}
  90
  91static struct commit_list *merge_bases_many(struct commit *one, int n, struct commit **twos)
  92{
  93        struct commit_list *list = NULL;
  94        struct commit_list *result = NULL;
  95        int i;
  96
  97        for (i = 0; i < n; i++) {
  98                if (one == twos[i])
  99                        /*
 100                         * We do not mark this even with RESULT so we do not
 101                         * have to clean it up.
 102                         */
 103                        return commit_list_insert(one, &result);
 104        }
 105
 106        if (parse_commit(one))
 107                return NULL;
 108        for (i = 0; i < n; i++) {
 109                if (parse_commit(twos[i]))
 110                        return NULL;
 111        }
 112
 113        list = paint_down_to_common(one, n, twos, 0);
 114
 115        while (list) {
 116                struct commit *commit = pop_commit(&list);
 117                if (!(commit->object.flags & STALE))
 118                        commit_list_insert_by_date(commit, &result);
 119        }
 120        return result;
 121}
 122
 123struct commit_list *get_octopus_merge_bases(struct commit_list *in)
 124{
 125        struct commit_list *i, *j, *k, *ret = NULL;
 126
 127        if (!in)
 128                return ret;
 129
 130        commit_list_insert(in->item, &ret);
 131
 132        for (i = in->next; i; i = i->next) {
 133                struct commit_list *new_commits = NULL, *end = NULL;
 134
 135                for (j = ret; j; j = j->next) {
 136                        struct commit_list *bases;
 137                        bases = get_merge_bases(i->item, j->item);
 138                        if (!new_commits)
 139                                new_commits = bases;
 140                        else
 141                                end->next = bases;
 142                        for (k = bases; k; k = k->next)
 143                                end = k;
 144                }
 145                ret = new_commits;
 146        }
 147        return ret;
 148}
 149
 150static int remove_redundant(struct commit **array, int cnt)
 151{
 152        /*
 153         * Some commit in the array may be an ancestor of
 154         * another commit.  Move such commit to the end of
 155         * the array, and return the number of commits that
 156         * are independent from each other.
 157         */
 158        struct commit **work;
 159        unsigned char *redundant;
 160        int *filled_index;
 161        int i, j, filled;
 162
 163        work = xcalloc(cnt, sizeof(*work));
 164        redundant = xcalloc(cnt, 1);
 165        ALLOC_ARRAY(filled_index, cnt - 1);
 166
 167        for (i = 0; i < cnt; i++)
 168                parse_commit(array[i]);
 169        for (i = 0; i < cnt; i++) {
 170                struct commit_list *common;
 171                uint32_t min_generation = array[i]->generation;
 172
 173                if (redundant[i])
 174                        continue;
 175                for (j = filled = 0; j < cnt; j++) {
 176                        if (i == j || redundant[j])
 177                                continue;
 178                        filled_index[filled] = j;
 179                        work[filled++] = array[j];
 180
 181                        if (array[j]->generation < min_generation)
 182                                min_generation = array[j]->generation;
 183                }
 184                common = paint_down_to_common(array[i], filled, work,
 185                                              min_generation);
 186                if (array[i]->object.flags & PARENT2)
 187                        redundant[i] = 1;
 188                for (j = 0; j < filled; j++)
 189                        if (work[j]->object.flags & PARENT1)
 190                                redundant[filled_index[j]] = 1;
 191                clear_commit_marks(array[i], all_flags);
 192                clear_commit_marks_many(filled, work, all_flags);
 193                free_commit_list(common);
 194        }
 195
 196        /* Now collect the result */
 197        COPY_ARRAY(work, array, cnt);
 198        for (i = filled = 0; i < cnt; i++)
 199                if (!redundant[i])
 200                        array[filled++] = work[i];
 201        for (j = filled, i = 0; i < cnt; i++)
 202                if (redundant[i])
 203                        array[j++] = work[i];
 204        free(work);
 205        free(redundant);
 206        free(filled_index);
 207        return filled;
 208}
 209
 210static struct commit_list *get_merge_bases_many_0(struct commit *one,
 211                                                  int n,
 212                                                  struct commit **twos,
 213                                                  int cleanup)
 214{
 215        struct commit_list *list;
 216        struct commit **rslt;
 217        struct commit_list *result;
 218        int cnt, i;
 219
 220        result = merge_bases_many(one, n, twos);
 221        for (i = 0; i < n; i++) {
 222                if (one == twos[i])
 223                        return result;
 224        }
 225        if (!result || !result->next) {
 226                if (cleanup) {
 227                        clear_commit_marks(one, all_flags);
 228                        clear_commit_marks_many(n, twos, all_flags);
 229                }
 230                return result;
 231        }
 232
 233        /* There are more than one */
 234        cnt = commit_list_count(result);
 235        rslt = xcalloc(cnt, sizeof(*rslt));
 236        for (list = result, i = 0; list; list = list->next)
 237                rslt[i++] = list->item;
 238        free_commit_list(result);
 239
 240        clear_commit_marks(one, all_flags);
 241        clear_commit_marks_many(n, twos, all_flags);
 242
 243        cnt = remove_redundant(rslt, cnt);
 244        result = NULL;
 245        for (i = 0; i < cnt; i++)
 246                commit_list_insert_by_date(rslt[i], &result);
 247        free(rslt);
 248        return result;
 249}
 250
 251struct commit_list *get_merge_bases_many(struct commit *one,
 252                                         int n,
 253                                         struct commit **twos)
 254{
 255        return get_merge_bases_many_0(one, n, twos, 1);
 256}
 257
 258struct commit_list *get_merge_bases_many_dirty(struct commit *one,
 259                                               int n,
 260                                               struct commit **twos)
 261{
 262        return get_merge_bases_many_0(one, n, twos, 0);
 263}
 264
 265struct commit_list *get_merge_bases(struct commit *one, struct commit *two)
 266{
 267        return get_merge_bases_many_0(one, 1, &two, 1);
 268}
 269
 270/*
 271 * Is "commit" a descendant of one of the elements on the "with_commit" list?
 272 */
 273int is_descendant_of(struct commit *commit, struct commit_list *with_commit)
 274{
 275        if (!with_commit)
 276                return 1;
 277        while (with_commit) {
 278                struct commit *other;
 279
 280                other = with_commit->item;
 281                with_commit = with_commit->next;
 282                if (in_merge_bases(other, commit))
 283                        return 1;
 284        }
 285        return 0;
 286}
 287
 288/*
 289 * Is "commit" an ancestor of one of the "references"?
 290 */
 291int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit **reference)
 292{
 293        struct commit_list *bases;
 294        int ret = 0, i;
 295        uint32_t min_generation = GENERATION_NUMBER_INFINITY;
 296
 297        if (parse_commit(commit))
 298                return ret;
 299        for (i = 0; i < nr_reference; i++) {
 300                if (parse_commit(reference[i]))
 301                        return ret;
 302                if (reference[i]->generation < min_generation)
 303                        min_generation = reference[i]->generation;
 304        }
 305
 306        if (commit->generation > min_generation)
 307                return ret;
 308
 309        bases = paint_down_to_common(commit, nr_reference, reference, commit->generation);
 310        if (commit->object.flags & PARENT2)
 311                ret = 1;
 312        clear_commit_marks(commit, all_flags);
 313        clear_commit_marks_many(nr_reference, reference, all_flags);
 314        free_commit_list(bases);
 315        return ret;
 316}
 317
 318/*
 319 * Is "commit" an ancestor of (i.e. reachable from) the "reference"?
 320 */
 321int in_merge_bases(struct commit *commit, struct commit *reference)
 322{
 323        return in_merge_bases_many(commit, 1, &reference);
 324}
 325
 326struct commit_list *reduce_heads(struct commit_list *heads)
 327{
 328        struct commit_list *p;
 329        struct commit_list *result = NULL, **tail = &result;
 330        struct commit **array;
 331        int num_head, i;
 332
 333        if (!heads)
 334                return NULL;
 335
 336        /* Uniquify */
 337        for (p = heads; p; p = p->next)
 338                p->item->object.flags &= ~STALE;
 339        for (p = heads, num_head = 0; p; p = p->next) {
 340                if (p->item->object.flags & STALE)
 341                        continue;
 342                p->item->object.flags |= STALE;
 343                num_head++;
 344        }
 345        array = xcalloc(num_head, sizeof(*array));
 346        for (p = heads, i = 0; p; p = p->next) {
 347                if (p->item->object.flags & STALE) {
 348                        array[i++] = p->item;
 349                        p->item->object.flags &= ~STALE;
 350                }
 351        }
 352        num_head = remove_redundant(array, num_head);
 353        for (i = 0; i < num_head; i++)
 354                tail = &commit_list_insert(array[i], tail)->next;
 355        free(array);
 356        return result;
 357}
 358
 359void reduce_heads_replace(struct commit_list **heads)
 360{
 361        struct commit_list *result = reduce_heads(*heads);
 362        free_commit_list(*heads);
 363        *heads = result;
 364}
 365
 366static void unmark_and_free(struct commit_list *list, unsigned int mark)
 367{
 368        while (list) {
 369                struct commit *commit = pop_commit(&list);
 370                commit->object.flags &= ~mark;
 371        }
 372}
 373
 374int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid)
 375{
 376        struct object *o;
 377        struct commit *old_commit, *new_commit;
 378        struct commit_list *list, *used;
 379        int found = 0;
 380
 381        /*
 382         * Both new_commit and old_commit must be commit-ish and new_commit is descendant of
 383         * old_commit.  Otherwise we require --force.
 384         */
 385        o = deref_tag(the_repository, parse_object(the_repository, old_oid),
 386                      NULL, 0);
 387        if (!o || o->type != OBJ_COMMIT)
 388                return 0;
 389        old_commit = (struct commit *) o;
 390
 391        o = deref_tag(the_repository, parse_object(the_repository, new_oid),
 392                      NULL, 0);
 393        if (!o || o->type != OBJ_COMMIT)
 394                return 0;
 395        new_commit = (struct commit *) o;
 396
 397        if (parse_commit(new_commit) < 0)
 398                return 0;
 399
 400        used = list = NULL;
 401        commit_list_insert(new_commit, &list);
 402        while (list) {
 403                new_commit = pop_most_recent_commit(&list, TMP_MARK);
 404                commit_list_insert(new_commit, &used);
 405                if (new_commit == old_commit) {
 406                        found = 1;
 407                        break;
 408                }
 409        }
 410        unmark_and_free(list, TMP_MARK);
 411        unmark_and_free(used, TMP_MARK);
 412        return found;
 413}