revision traversal: --children option
This adds a new --children option to the revision machinery. In addition to the list of parents, child commits of each commit are computed and stored as a decoration to each commit. Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
f43e2fd43b
commit
f35f5603f4
40
revision.c
40
revision.c
@ -9,6 +9,7 @@
|
|||||||
#include "grep.h"
|
#include "grep.h"
|
||||||
#include "reflog-walk.h"
|
#include "reflog-walk.h"
|
||||||
#include "patch-ids.h"
|
#include "patch-ids.h"
|
||||||
|
#include "decorate.h"
|
||||||
|
|
||||||
volatile show_early_output_fn_t show_early_output;
|
volatile show_early_output_fn_t show_early_output;
|
||||||
|
|
||||||
@ -1310,6 +1311,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
|
|||||||
revs->no_walk = 0;
|
revs->no_walk = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(arg, "--children")) {
|
||||||
|
revs->children.name = "children";
|
||||||
|
revs->limited = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
|
opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
|
||||||
if (opts > 0) {
|
if (opts > 0) {
|
||||||
@ -1395,10 +1401,31 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
|
|||||||
|
|
||||||
if (revs->reverse && revs->reflog_info)
|
if (revs->reverse && revs->reflog_info)
|
||||||
die("cannot combine --reverse with --walk-reflogs");
|
die("cannot combine --reverse with --walk-reflogs");
|
||||||
|
if (revs->parents && revs->children.name)
|
||||||
|
die("cannot combine --parents and --children");
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_child(struct rev_info *revs, struct commit *parent, struct commit *child)
|
||||||
|
{
|
||||||
|
struct commit_list *l = xcalloc(1, sizeof(*l));
|
||||||
|
|
||||||
|
l->item = child;
|
||||||
|
l->next = add_decoration(&revs->children, &parent->object, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_children(struct rev_info *revs)
|
||||||
|
{
|
||||||
|
struct commit_list *l;
|
||||||
|
for (l = revs->commits; l; l = l->next) {
|
||||||
|
struct commit *commit = l->item;
|
||||||
|
struct commit_list *p;
|
||||||
|
|
||||||
|
for (p = commit->parents; p; p = p->next)
|
||||||
|
add_child(revs, p->item, commit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int prepare_revision_walk(struct rev_info *revs)
|
int prepare_revision_walk(struct rev_info *revs)
|
||||||
{
|
{
|
||||||
int nr = revs->pending.nr;
|
int nr = revs->pending.nr;
|
||||||
@ -1427,6 +1454,8 @@ int prepare_revision_walk(struct rev_info *revs)
|
|||||||
return -1;
|
return -1;
|
||||||
if (revs->topo_order)
|
if (revs->topo_order)
|
||||||
sort_in_topological_order(&revs->commits, revs->lifo);
|
sort_in_topological_order(&revs->commits, revs->lifo);
|
||||||
|
if (revs->children.name)
|
||||||
|
set_children(revs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1504,6 +1533,11 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
|
|||||||
commit->buffer, strlen(commit->buffer));
|
commit->buffer, strlen(commit->buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int want_ancestry(struct rev_info *revs)
|
||||||
|
{
|
||||||
|
return (revs->parents || revs->children.name);
|
||||||
|
}
|
||||||
|
|
||||||
enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
|
enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
|
||||||
{
|
{
|
||||||
if (commit->object.flags & SHOWN)
|
if (commit->object.flags & SHOWN)
|
||||||
@ -1524,13 +1558,13 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
|
|||||||
/* Commit without changes? */
|
/* Commit without changes? */
|
||||||
if (commit->object.flags & TREESAME) {
|
if (commit->object.flags & TREESAME) {
|
||||||
/* drop merges unless we want parenthood */
|
/* drop merges unless we want parenthood */
|
||||||
if (!revs->parents)
|
if (!want_ancestry(revs))
|
||||||
return commit_ignore;
|
return commit_ignore;
|
||||||
/* non-merge - always ignore it */
|
/* non-merge - always ignore it */
|
||||||
if (!commit->parents || !commit->parents->next)
|
if (!commit->parents || !commit->parents->next)
|
||||||
return commit_ignore;
|
return commit_ignore;
|
||||||
}
|
}
|
||||||
if (revs->parents && rewrite_parents(revs, commit) < 0)
|
if (want_ancestry(revs) && rewrite_parents(revs, commit) < 0)
|
||||||
return commit_error;
|
return commit_error;
|
||||||
}
|
}
|
||||||
return commit_show;
|
return commit_show;
|
||||||
|
@ -98,6 +98,7 @@ struct rev_info {
|
|||||||
struct diff_options pruning;
|
struct diff_options pruning;
|
||||||
|
|
||||||
struct reflog_walk_info *reflog_info;
|
struct reflog_walk_info *reflog_info;
|
||||||
|
struct decoration children;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define REV_TREE_SAME 0
|
#define REV_TREE_SAME 0
|
||||||
|
Loading…
Reference in New Issue
Block a user