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>
This commit is contained in:
parent
3c3588c7d3
commit
103148aad8
@ -110,54 +110,12 @@ static int handle_is_ancestor(int argc, const char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handle_fork_point(int argc, const char **argv)
|
static int handle_fork_point(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
struct object_id oid;
|
struct object_id oid;
|
||||||
char *refname;
|
char *refname;
|
||||||
|
struct commit *derived, *fork_point;
|
||||||
const char *commitname;
|
const char *commitname;
|
||||||
struct rev_collect revs;
|
|
||||||
struct commit *derived;
|
|
||||||
struct commit_list *bases;
|
|
||||||
int i, ret = 0;
|
|
||||||
|
|
||||||
switch (dwim_ref(argv[0], strlen(argv[0]), &oid, &refname)) {
|
switch (dwim_ref(argv[0], strlen(argv[0]), &oid, &refname)) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -173,41 +131,14 @@ static int handle_fork_point(int argc, const char **argv)
|
|||||||
die("Not a valid object name: '%s'", commitname);
|
die("Not a valid object name: '%s'", commitname);
|
||||||
|
|
||||||
derived = lookup_commit_reference(the_repository, &oid);
|
derived = lookup_commit_reference(the_repository, &oid);
|
||||||
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))
|
fork_point = get_fork_point(refname, derived);
|
||||||
add_one_commit(&oid, &revs);
|
|
||||||
|
|
||||||
for (i = 0; i < revs.nr; i++)
|
if (!fork_point)
|
||||||
revs.commit[i]->object.flags &= ~TMP_MARK;
|
return 1;
|
||||||
|
|
||||||
bases = get_merge_bases_many_dirty(derived, revs.nr, revs.commit);
|
printf("%s\n", oid_to_hex(&fork_point->object.oid));
|
||||||
|
return 0;
|
||||||
/*
|
|
||||||
* There should be one and only one merge base, when we found
|
|
||||||
* a common ancestor among reflog entries.
|
|
||||||
*/
|
|
||||||
if (!bases || bases->next) {
|
|
||||||
ret = 1;
|
|
||||||
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) {
|
|
||||||
ret = 1; /* not found */
|
|
||||||
goto cleanup_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s\n", oid_to_hex(&bases->item->object.oid));
|
|
||||||
|
|
||||||
cleanup_return:
|
|
||||||
free_commit_list(bases);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmd_merge_base(int argc, const char **argv, const char *prefix)
|
int cmd_merge_base(int argc, const char **argv, const char *prefix)
|
||||||
|
81
commit.c
81
commit.c
@ -17,6 +17,7 @@
|
|||||||
#include "sha1-lookup.h"
|
#include "sha1-lookup.h"
|
||||||
#include "wt-status.h"
|
#include "wt-status.h"
|
||||||
#include "advice.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 **);
|
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;
|
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 *get_octopus_merge_bases(struct commit_list *in)
|
||||||
{
|
{
|
||||||
struct commit_list *i, *j, *k, *ret = NULL;
|
struct commit_list *i, *j, *k, *ret = NULL;
|
||||||
|
2
commit.h
2
commit.h
@ -211,6 +211,8 @@ extern struct commit_list *get_octopus_merge_bases(struct commit_list *in);
|
|||||||
/* To be used only when object flags after this call no longer matter */
|
/* To be used only when object flags after this call no longer matter */
|
||||||
extern struct commit_list *get_merge_bases_many_dirty(struct commit *one, int n, struct commit **twos);
|
extern struct commit_list *get_merge_bases_many_dirty(struct commit *one, int n, struct commit **twos);
|
||||||
|
|
||||||
|
struct commit *get_fork_point(const char *refname, struct commit *commit);
|
||||||
|
|
||||||
/* largest positive number a signed 32-bit integer can contain */
|
/* largest positive number a signed 32-bit integer can contain */
|
||||||
#define INFINITE_DEPTH 0x7fffffff
|
#define INFINITE_DEPTH 0x7fffffff
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user