Merge branch 'jc/blame' (early part) into HEAD
* 'jc/blame' (early part): git-blame --reverse builtin-blame.c: allow more than 16 parents builtin-blame.c: move prepare_final() into a separate function. rev-list --children revision traversal: --children option Conflicts: Documentation/rev-list-options.txt revision.c
This commit is contained in:
commit
8bb65883d1
@ -45,6 +45,10 @@ endif::git-rev-list[]
|
|||||||
|
|
||||||
Print the parents of the commit.
|
Print the parents of the commit.
|
||||||
|
|
||||||
|
--children::
|
||||||
|
|
||||||
|
Print the children of the commit.
|
||||||
|
|
||||||
ifdef::git-rev-list[]
|
ifdef::git-rev-list[]
|
||||||
--timestamp::
|
--timestamp::
|
||||||
Print the raw commit timestamp.
|
Print the raw commit timestamp.
|
||||||
|
204
builtin-blame.c
204
builtin-blame.c
@ -43,6 +43,7 @@ static int max_orig_digits;
|
|||||||
static int max_digits;
|
static int max_digits;
|
||||||
static int max_score_digits;
|
static int max_score_digits;
|
||||||
static int show_root;
|
static int show_root;
|
||||||
|
static int reverse;
|
||||||
static int blank_boundary;
|
static int blank_boundary;
|
||||||
static int incremental;
|
static int incremental;
|
||||||
static int cmd_is_annotate;
|
static int cmd_is_annotate;
|
||||||
@ -91,7 +92,7 @@ struct origin {
|
|||||||
* Given an origin, prepare mmfile_t structure to be used by the
|
* Given an origin, prepare mmfile_t structure to be used by the
|
||||||
* diff machinery
|
* diff machinery
|
||||||
*/
|
*/
|
||||||
static char *fill_origin_blob(struct origin *o, mmfile_t *file)
|
static void fill_origin_blob(struct origin *o, mmfile_t *file)
|
||||||
{
|
{
|
||||||
if (!o->file.ptr) {
|
if (!o->file.ptr) {
|
||||||
enum object_type type;
|
enum object_type type;
|
||||||
@ -106,7 +107,6 @@ static char *fill_origin_blob(struct origin *o, mmfile_t *file)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
*file = o->file;
|
*file = o->file;
|
||||||
return file->ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -178,7 +178,7 @@ struct blame_entry {
|
|||||||
struct scoreboard {
|
struct scoreboard {
|
||||||
/* the final commit (i.e. where we started digging from) */
|
/* the final commit (i.e. where we started digging from) */
|
||||||
struct commit *final;
|
struct commit *final;
|
||||||
|
struct rev_info *revs;
|
||||||
const char *path;
|
const char *path;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1192,18 +1192,48 @@ static void pass_whole_blame(struct scoreboard *sb,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAXPARENT 16
|
/*
|
||||||
|
* We pass blame from the current commit to its parents. We keep saying
|
||||||
|
* "parent" (and "porigin"), but what we mean is to find scapegoat to
|
||||||
|
* exonerate ourselves.
|
||||||
|
*/
|
||||||
|
static struct commit_list *first_scapegoat(struct rev_info *revs, struct commit *commit)
|
||||||
|
{
|
||||||
|
if (!reverse)
|
||||||
|
return commit->parents;
|
||||||
|
return lookup_decoration(&revs->children, &commit->object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int num_scapegoats(struct rev_info *revs, struct commit *commit)
|
||||||
|
{
|
||||||
|
int cnt;
|
||||||
|
struct commit_list *l = first_scapegoat(revs, commit);
|
||||||
|
for (cnt = 0; l; l = l->next)
|
||||||
|
cnt++;
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAXSG 16
|
||||||
|
|
||||||
static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
|
static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
|
||||||
{
|
{
|
||||||
int i, pass;
|
struct rev_info *revs = sb->revs;
|
||||||
|
int i, pass, num_sg;
|
||||||
struct commit *commit = origin->commit;
|
struct commit *commit = origin->commit;
|
||||||
struct commit_list *parent;
|
struct commit_list *sg;
|
||||||
struct origin *parent_origin[MAXPARENT], *porigin;
|
struct origin *sg_buf[MAXSG];
|
||||||
|
struct origin *porigin, **sg_origin = sg_buf;
|
||||||
|
|
||||||
memset(parent_origin, 0, sizeof(parent_origin));
|
num_sg = num_scapegoats(revs, commit);
|
||||||
|
if (!num_sg)
|
||||||
|
goto finish;
|
||||||
|
else if (num_sg < ARRAY_SIZE(sg_buf))
|
||||||
|
memset(sg_buf, 0, sizeof(sg_buf));
|
||||||
|
else
|
||||||
|
sg_origin = xcalloc(num_sg, sizeof(*sg_origin));
|
||||||
|
|
||||||
/* The first pass looks for unrenamed path to optimize for
|
/*
|
||||||
|
* The first pass looks for unrenamed path to optimize for
|
||||||
* common cases, then we look for renames in the second pass.
|
* common cases, then we look for renames in the second pass.
|
||||||
*/
|
*/
|
||||||
for (pass = 0; pass < 2; pass++) {
|
for (pass = 0; pass < 2; pass++) {
|
||||||
@ -1211,13 +1241,13 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
|
|||||||
struct commit *, struct origin *);
|
struct commit *, struct origin *);
|
||||||
find = pass ? find_rename : find_origin;
|
find = pass ? find_rename : find_origin;
|
||||||
|
|
||||||
for (i = 0, parent = commit->parents;
|
for (i = 0, sg = first_scapegoat(revs, commit);
|
||||||
i < MAXPARENT && parent;
|
i < num_sg && sg;
|
||||||
parent = parent->next, i++) {
|
sg = sg->next, i++) {
|
||||||
struct commit *p = parent->item;
|
struct commit *p = sg->item;
|
||||||
int j, same;
|
int j, same;
|
||||||
|
|
||||||
if (parent_origin[i])
|
if (sg_origin[i])
|
||||||
continue;
|
continue;
|
||||||
if (parse_commit(p))
|
if (parse_commit(p))
|
||||||
continue;
|
continue;
|
||||||
@ -1230,24 +1260,24 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
|
|||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
for (j = same = 0; j < i; j++)
|
for (j = same = 0; j < i; j++)
|
||||||
if (parent_origin[j] &&
|
if (sg_origin[j] &&
|
||||||
!hashcmp(parent_origin[j]->blob_sha1,
|
!hashcmp(sg_origin[j]->blob_sha1,
|
||||||
porigin->blob_sha1)) {
|
porigin->blob_sha1)) {
|
||||||
same = 1;
|
same = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!same)
|
if (!same)
|
||||||
parent_origin[i] = porigin;
|
sg_origin[i] = porigin;
|
||||||
else
|
else
|
||||||
origin_decref(porigin);
|
origin_decref(porigin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
num_commits++;
|
num_commits++;
|
||||||
for (i = 0, parent = commit->parents;
|
for (i = 0, sg = first_scapegoat(revs, commit);
|
||||||
i < MAXPARENT && parent;
|
i < num_sg && sg;
|
||||||
parent = parent->next, i++) {
|
sg = sg->next, i++) {
|
||||||
struct origin *porigin = parent_origin[i];
|
struct origin *porigin = sg_origin[i];
|
||||||
if (!porigin)
|
if (!porigin)
|
||||||
continue;
|
continue;
|
||||||
if (pass_blame_to_parent(sb, origin, porigin))
|
if (pass_blame_to_parent(sb, origin, porigin))
|
||||||
@ -1258,10 +1288,10 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
|
|||||||
* Optionally find moves in parents' files.
|
* Optionally find moves in parents' files.
|
||||||
*/
|
*/
|
||||||
if (opt & PICKAXE_BLAME_MOVE)
|
if (opt & PICKAXE_BLAME_MOVE)
|
||||||
for (i = 0, parent = commit->parents;
|
for (i = 0, sg = first_scapegoat(revs, commit);
|
||||||
i < MAXPARENT && parent;
|
i < num_sg && sg;
|
||||||
parent = parent->next, i++) {
|
sg = sg->next, i++) {
|
||||||
struct origin *porigin = parent_origin[i];
|
struct origin *porigin = sg_origin[i];
|
||||||
if (!porigin)
|
if (!porigin)
|
||||||
continue;
|
continue;
|
||||||
if (find_move_in_parent(sb, origin, porigin))
|
if (find_move_in_parent(sb, origin, porigin))
|
||||||
@ -1272,23 +1302,25 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
|
|||||||
* Optionally find copies from parents' files.
|
* Optionally find copies from parents' files.
|
||||||
*/
|
*/
|
||||||
if (opt & PICKAXE_BLAME_COPY)
|
if (opt & PICKAXE_BLAME_COPY)
|
||||||
for (i = 0, parent = commit->parents;
|
for (i = 0, sg = first_scapegoat(revs, commit);
|
||||||
i < MAXPARENT && parent;
|
i < num_sg && sg;
|
||||||
parent = parent->next, i++) {
|
sg = sg->next, i++) {
|
||||||
struct origin *porigin = parent_origin[i];
|
struct origin *porigin = sg_origin[i];
|
||||||
if (find_copy_in_parent(sb, origin, parent->item,
|
if (find_copy_in_parent(sb, origin, sg->item,
|
||||||
porigin, opt))
|
porigin, opt))
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
for (i = 0; i < MAXPARENT; i++) {
|
for (i = 0; i < num_sg; i++) {
|
||||||
if (parent_origin[i]) {
|
if (sg_origin[i]) {
|
||||||
drop_origin_blob(parent_origin[i]);
|
drop_origin_blob(sg_origin[i]);
|
||||||
origin_decref(parent_origin[i]);
|
origin_decref(sg_origin[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drop_origin_blob(origin);
|
drop_origin_blob(origin);
|
||||||
|
if (sg_buf != sg_origin)
|
||||||
|
free(sg_origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1487,8 +1519,10 @@ static void found_guilty_entry(struct blame_entry *ent)
|
|||||||
* is still unknown, pick one blame_entry, and allow its current
|
* is still unknown, pick one blame_entry, and allow its current
|
||||||
* suspect to pass blames to its parents.
|
* suspect to pass blames to its parents.
|
||||||
*/
|
*/
|
||||||
static void assign_blame(struct scoreboard *sb, struct rev_info *revs, int opt)
|
static void assign_blame(struct scoreboard *sb, int opt)
|
||||||
{
|
{
|
||||||
|
struct rev_info *revs = sb->revs;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
struct blame_entry *ent;
|
struct blame_entry *ent;
|
||||||
struct commit *commit;
|
struct commit *commit;
|
||||||
@ -1509,8 +1543,9 @@ static void assign_blame(struct scoreboard *sb, struct rev_info *revs, int opt)
|
|||||||
commit = suspect->commit;
|
commit = suspect->commit;
|
||||||
if (!commit->object.parsed)
|
if (!commit->object.parsed)
|
||||||
parse_commit(commit);
|
parse_commit(commit);
|
||||||
if (!(commit->object.flags & UNINTERESTING) &&
|
if (reverse ||
|
||||||
!(revs->max_age != -1 && commit->date < revs->max_age))
|
(!(commit->object.flags & UNINTERESTING) &&
|
||||||
|
!(revs->max_age != -1 && commit->date < revs->max_age)))
|
||||||
pass_blame(sb, suspect, opt);
|
pass_blame(sb, suspect, opt);
|
||||||
else {
|
else {
|
||||||
commit->object.flags |= UNINTERESTING;
|
commit->object.flags |= UNINTERESTING;
|
||||||
@ -2006,6 +2041,10 @@ static int git_blame_config(const char *var, const char *value, void *cb)
|
|||||||
return git_default_config(var, value, cb);
|
return git_default_config(var, value, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare a dummy commit that represents the work tree (or staged) item.
|
||||||
|
* Note that annotating work tree item never works in the reverse.
|
||||||
|
*/
|
||||||
static struct commit *fake_working_tree_commit(const char *path, const char *contents_from)
|
static struct commit *fake_working_tree_commit(const char *path, const char *contents_from)
|
||||||
{
|
{
|
||||||
struct commit *commit;
|
struct commit *commit;
|
||||||
@ -2122,6 +2161,64 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
|
|||||||
return commit;
|
return commit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *prepare_final(struct scoreboard *sb)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char *final_commit_name = NULL;
|
||||||
|
struct rev_info *revs = sb->revs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There must be one and only one positive commit in the
|
||||||
|
* revs->pending array.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < revs->pending.nr; i++) {
|
||||||
|
struct object *obj = revs->pending.objects[i].item;
|
||||||
|
if (obj->flags & UNINTERESTING)
|
||||||
|
continue;
|
||||||
|
while (obj->type == OBJ_TAG)
|
||||||
|
obj = deref_tag(obj, NULL, 0);
|
||||||
|
if (obj->type != OBJ_COMMIT)
|
||||||
|
die("Non commit %s?", revs->pending.objects[i].name);
|
||||||
|
if (sb->final)
|
||||||
|
die("More than one commit to dig from %s and %s?",
|
||||||
|
revs->pending.objects[i].name,
|
||||||
|
final_commit_name);
|
||||||
|
sb->final = (struct commit *) obj;
|
||||||
|
final_commit_name = revs->pending.objects[i].name;
|
||||||
|
}
|
||||||
|
return final_commit_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *prepare_initial(struct scoreboard *sb)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char *final_commit_name = NULL;
|
||||||
|
struct rev_info *revs = sb->revs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There must be one and only one negative commit, and it must be
|
||||||
|
* the boundary.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < revs->pending.nr; i++) {
|
||||||
|
struct object *obj = revs->pending.objects[i].item;
|
||||||
|
if (!(obj->flags & UNINTERESTING))
|
||||||
|
continue;
|
||||||
|
while (obj->type == OBJ_TAG)
|
||||||
|
obj = deref_tag(obj, NULL, 0);
|
||||||
|
if (obj->type != OBJ_COMMIT)
|
||||||
|
die("Non commit %s?", revs->pending.objects[i].name);
|
||||||
|
if (sb->final)
|
||||||
|
die("More than one commit to dig down to %s and %s?",
|
||||||
|
revs->pending.objects[i].name,
|
||||||
|
final_commit_name);
|
||||||
|
sb->final = (struct commit *) obj;
|
||||||
|
final_commit_name = revs->pending.objects[i].name;
|
||||||
|
}
|
||||||
|
if (!final_commit_name)
|
||||||
|
die("No commit to dig down to?");
|
||||||
|
return final_commit_name;
|
||||||
|
}
|
||||||
|
|
||||||
int cmd_blame(int argc, const char **argv, const char *prefix)
|
int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
struct rev_info revs;
|
struct rev_info revs;
|
||||||
@ -2154,6 +2251,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
|||||||
blank_boundary = 1;
|
blank_boundary = 1;
|
||||||
else if (!strcmp("--root", arg))
|
else if (!strcmp("--root", arg))
|
||||||
show_root = 1;
|
show_root = 1;
|
||||||
|
else if (!strcmp("--reverse", arg)) {
|
||||||
|
argv[unk++] = "--children";
|
||||||
|
reverse = 1;
|
||||||
|
}
|
||||||
else if (!strcmp(arg, "--show-stats"))
|
else if (!strcmp(arg, "--show-stats"))
|
||||||
show_stats = 1;
|
show_stats = 1;
|
||||||
else if (!strcmp("-c", arg))
|
else if (!strcmp("-c", arg))
|
||||||
@ -2327,26 +2428,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
|||||||
setup_revisions(unk, argv, &revs, NULL);
|
setup_revisions(unk, argv, &revs, NULL);
|
||||||
memset(&sb, 0, sizeof(sb));
|
memset(&sb, 0, sizeof(sb));
|
||||||
|
|
||||||
/*
|
sb.revs = &revs;
|
||||||
* There must be one and only one positive commit in the
|
if (!reverse)
|
||||||
* revs->pending array.
|
final_commit_name = prepare_final(&sb);
|
||||||
*/
|
else if (contents_from)
|
||||||
for (i = 0; i < revs.pending.nr; i++) {
|
die("--contents and --children do not blend well.");
|
||||||
struct object *obj = revs.pending.objects[i].item;
|
else
|
||||||
if (obj->flags & UNINTERESTING)
|
final_commit_name = prepare_initial(&sb);
|
||||||
continue;
|
|
||||||
while (obj->type == OBJ_TAG)
|
|
||||||
obj = deref_tag(obj, NULL, 0);
|
|
||||||
if (obj->type != OBJ_COMMIT)
|
|
||||||
die("Non commit %s?",
|
|
||||||
revs.pending.objects[i].name);
|
|
||||||
if (sb.final)
|
|
||||||
die("More than one commit to dig from %s and %s?",
|
|
||||||
revs.pending.objects[i].name,
|
|
||||||
final_commit_name);
|
|
||||||
sb.final = (struct commit *) obj;
|
|
||||||
final_commit_name = revs.pending.objects[i].name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sb.final) {
|
if (!sb.final) {
|
||||||
/*
|
/*
|
||||||
@ -2425,7 +2513,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
|||||||
if (!incremental)
|
if (!incremental)
|
||||||
setup_pager();
|
setup_pager();
|
||||||
|
|
||||||
assign_blame(&sb, &revs, opt);
|
assign_blame(&sb, opt);
|
||||||
|
|
||||||
if (incremental)
|
if (incremental)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -37,6 +37,7 @@ static const char rev_list_usage[] =
|
|||||||
" --reverse\n"
|
" --reverse\n"
|
||||||
" formatting output:\n"
|
" formatting output:\n"
|
||||||
" --parents\n"
|
" --parents\n"
|
||||||
|
" --children\n"
|
||||||
" --objects | --objects-edge\n"
|
" --objects | --objects-edge\n"
|
||||||
" --unpacked\n"
|
" --unpacked\n"
|
||||||
" --header | --pretty\n"
|
" --header | --pretty\n"
|
||||||
@ -90,6 +91,15 @@ static void show_commit(struct commit *commit)
|
|||||||
parents = parents->next;
|
parents = parents->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (revs.children.name) {
|
||||||
|
struct commit_list *children;
|
||||||
|
|
||||||
|
children = lookup_decoration(&revs.children, &commit->object);
|
||||||
|
while (children) {
|
||||||
|
printf(" %s", sha1_to_hex(children->item->object.sha1));
|
||||||
|
children = children->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
show_decorations(commit);
|
show_decorations(commit);
|
||||||
if (revs.commit_format == CMIT_FMT_ONELINE)
|
if (revs.commit_format == CMIT_FMT_ONELINE)
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
|
39
revision.c
39
revision.c
@ -10,6 +10,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;
|
||||||
|
|
||||||
@ -1321,6 +1322,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) {
|
||||||
@ -1406,6 +1412,8 @@ 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->rewrite_parents && revs->children.name)
|
||||||
|
die("cannot combine --parents and --children");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Limitations on the graph functionality
|
* Limitations on the graph functionality
|
||||||
@ -1419,6 +1427,26 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
|
|||||||
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;
|
||||||
@ -1447,6 +1475,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1524,6 +1554,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->rewrite_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)
|
||||||
@ -1544,13 +1579,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->rewrite_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->rewrite_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;
|
||||||
|
@ -104,6 +104,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…
x
Reference in New Issue
Block a user