/* * Returns common ancesstor for two branches. * Any two commits should have a common ancestor. * So returning NULL indicates an error, for e.g. corupt commit. */ SeafCommit * get_merge_base (SeafCommit *head, SeafCommit *remote) { GList *result, *iter; SeafCommit *one, **twos; int n, i; SeafCommit *ret = NULL; one = head; twos = (SeafCommit **) calloc (1, sizeof(SeafCommit *)); twos[0] = remote; n = 1; result = merge_bases_many (one, n, twos); free (twos); if (!result || !result->next) goto done; /* * More than one common ancestors. * Loop until the oldest common ancestor is found. */ while (1) { n = g_list_length (result) - 1; g_assert (n > 0); one = result->data; twos = calloc (n, sizeof(SeafCommit *)); for (iter = result->next, i = 0; i < n; iter = iter->next, i++) { twos[i] = iter->data; } g_list_free (result); result = merge_bases_many (one, n, twos); free (twos); if (!result || !result->next) break; } done: if (result) ret = result->data; g_list_free (result); return ret; }
static GList * get_independent_commits (GList *commits) { SeafCommit **rslt; GList *list, *result; int cnt, i, j; SeafCommit *c; g_debug ("Get independent commits.\n"); cnt = g_list_length (commits); rslt = calloc(cnt, sizeof(*rslt)); for (list = commits, i = 0; list; list = list->next) rslt[i++] = list->data; g_list_free (commits); for (i = 0; i < cnt - 1; i++) { for (j = i+1; j < cnt; j++) { if (!rslt[i] || !rslt[j]) continue; result = merge_bases_many(rslt[i], 1, &rslt[j]); for (list = result; list; list = list->next) { c = list->data; /* If two commits have fast-forward relationship, * drop the older one. */ if (strcmp (rslt[i]->commit_id, c->commit_id) == 0) { seaf_commit_unref (rslt[i]); rslt[i] = NULL; } if (strcmp (rslt[j]->commit_id, c->commit_id) == 0) { seaf_commit_unref (rslt[j]); rslt[j] = NULL; } seaf_commit_unref (c); } } } /* Surviving ones in rslt[] are the independent results */ result = NULL; for (i = 0; i < cnt; i++) { if (rslt[i]) result = g_list_insert_sorted_with_data (result, rslt[i], compare_commit_by_time, NULL); } free(rslt); return result; }