Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPratik Karki <predatoramigo@gmail.com>2018-09-05 01:00:08 +0300
committerJunio C Hamano <gitster@pobox.com>2018-10-11 08:12:45 +0300
commit103148aad80ee7ab65b902d77d964260cfd3f6ea (patch)
treea9de3895ad9c7d80e66997a263c737731bf96abb /commit.c
parent3c3588c7d33456e76d0ed7b881378ee575f4dc45 (diff)
merge-base --fork-point: extract libified function
We need this functionality in the builtin rebase. Note: to make this function truly reusable, we have to switch the call get_merges_many_dirty() to get_merges_many() because we want the commit flags to be reset (otherwise, subsequent get_merge_bases() calls would obtain incorrect results). This did not matter when the function was called in `git rev-parse --fork-point` because in that command, the process definitely did not traverse any commits before exiting. Signed-off-by: Pratik Karki <predatoramigo@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'commit.c')
-rw-r--r--commit.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/commit.c b/commit.c
index 30d1af2b20..a3fc77a4eb 100644
--- a/commit.c
+++ b/commit.c
@@ -17,6 +17,7 @@
#include "sha1-lookup.h"
#include "wt-status.h"
#include "advice.h"
+#include "refs.h"
static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
@@ -958,6 +959,86 @@ static struct commit_list *merge_bases_many(struct commit *one, int n, struct co
return result;
}
+struct rev_collect {
+ struct commit **commit;
+ int nr;
+ int alloc;
+ unsigned int initial : 1;
+};
+
+static void add_one_commit(struct object_id *oid, struct rev_collect *revs)
+{
+ struct commit *commit;
+
+ if (is_null_oid(oid))
+ return;
+
+ commit = lookup_commit(the_repository, oid);
+ if (!commit ||
+ (commit->object.flags & TMP_MARK) ||
+ parse_commit(commit))
+ return;
+
+ ALLOC_GROW(revs->commit, revs->nr + 1, revs->alloc);
+ revs->commit[revs->nr++] = commit;
+ commit->object.flags |= TMP_MARK;
+}
+
+static int collect_one_reflog_ent(struct object_id *ooid, struct object_id *noid,
+ const char *ident, timestamp_t timestamp,
+ int tz, const char *message, void *cbdata)
+{
+ struct rev_collect *revs = cbdata;
+
+ if (revs->initial) {
+ revs->initial = 0;
+ add_one_commit(ooid, revs);
+ }
+ add_one_commit(noid, revs);
+ return 0;
+}
+
+struct commit *get_fork_point(const char *refname, struct commit *commit)
+{
+ struct object_id oid;
+ struct rev_collect revs;
+ struct commit_list *bases;
+ int i;
+ struct commit *ret = NULL;
+
+ memset(&revs, 0, sizeof(revs));
+ revs.initial = 1;
+ for_each_reflog_ent(refname, collect_one_reflog_ent, &revs);
+
+ if (!revs.nr && !get_oid(refname, &oid))
+ add_one_commit(&oid, &revs);
+
+ for (i = 0; i < revs.nr; i++)
+ revs.commit[i]->object.flags &= ~TMP_MARK;
+
+ bases = get_merge_bases_many(commit, revs.nr, revs.commit);
+
+ /*
+ * There should be one and only one merge base, when we found
+ * a common ancestor among reflog entries.
+ */
+ if (!bases || bases->next)
+ goto cleanup_return;
+
+ /* And the found one must be one of the reflog entries */
+ for (i = 0; i < revs.nr; i++)
+ if (&bases->item->object == &revs.commit[i]->object)
+ break; /* found */
+ if (revs.nr <= i)
+ goto cleanup_return;
+
+ ret = bases->item;
+
+cleanup_return:
+ free_commit_list(bases);
+ return ret;
+}
+
struct commit_list *get_octopus_merge_bases(struct commit_list *in)
{
struct commit_list *i, *j, *k, *ret = NULL;