Merge branch 'bk/ancestry-path' into jc/branch-desc

* bk/ancestry-path:
  t6019: avoid refname collision on case-insensitive systems
  revision: do not include sibling history in --ancestry-path output
  revision: keep track of the end-user input from the command line
  rev-list: Demonstrate breakage with --ancestry-path --all
This commit is contained in:
Junio C Hamano 2011-09-21 20:13:08 -07:00
commit 3bcad5a23d
3 changed files with 101 additions and 10 deletions

View file

@ -729,12 +729,16 @@ static void limit_to_ancestry(struct commit_list *bottom, struct commit_list *li
* to filter the result of "A..B" further to the ones that can actually
* reach A.
*/
static struct commit_list *collect_bottom_commits(struct commit_list *list)
static struct commit_list *collect_bottom_commits(struct rev_info *revs)
{
struct commit_list *elem, *bottom = NULL;
for (elem = list; elem; elem = elem->next)
if (elem->item->object.flags & UNINTERESTING)
commit_list_insert(elem->item, &bottom);
struct commit_list *bottom = NULL;
int i;
for (i = 0; i < revs->cmdline.nr; i++) {
struct rev_cmdline_entry *elem = &revs->cmdline.rev[i];
if ((elem->flags & UNINTERESTING) &&
elem->item->type == OBJ_COMMIT)
commit_list_insert((struct commit *)elem->item, &bottom);
}
return bottom;
}
@ -765,7 +769,7 @@ static int limit_list(struct rev_info *revs)
struct commit_list *bottom = NULL;
if (revs->ancestry_path) {
bottom = collect_bottom_commits(list);
bottom = collect_bottom_commits(revs);
if (!bottom)
die("--ancestry-path given but there are no bottom commits");
}
@ -822,6 +826,23 @@ static int limit_list(struct rev_info *revs)
return 0;
}
static void add_rev_cmdline(struct rev_info *revs,
struct object *item,
const char *name,
int whence,
unsigned flags)
{
struct rev_cmdline_info *info = &revs->cmdline;
int nr = info->nr;
ALLOC_GROW(info->rev, nr + 1, info->alloc);
info->rev[nr].item = item;
info->rev[nr].name = name;
info->rev[nr].whence = whence;
info->rev[nr].flags = flags;
info->nr++;
}
struct all_refs_cb {
int all_flags;
int warned_bad_reflog;
@ -834,6 +855,7 @@ static int handle_one_ref(const char *path, const unsigned char *sha1, int flag,
struct all_refs_cb *cb = cb_data;
struct object *object = get_reference(cb->all_revs, path, sha1,
cb->all_flags);
add_rev_cmdline(cb->all_revs, object, path, REV_CMD_REF, cb->all_flags);
add_pending_object(cb->all_revs, object, path);
return 0;
}
@ -860,6 +882,7 @@ static void handle_one_reflog_commit(unsigned char *sha1, void *cb_data)
struct object *o = parse_object(sha1);
if (o) {
o->flags |= cb->all_flags;
/* ??? CMDLINEFLAGS ??? */
add_pending_object(cb->all_revs, o, "");
}
else if (!cb->warned_bad_reflog) {
@ -896,12 +919,13 @@ static void handle_reflog(struct rev_info *revs, unsigned flags)
for_each_reflog(handle_one_reflog, &cb);
}
static int add_parents_only(struct rev_info *revs, const char *arg, int flags)
static int add_parents_only(struct rev_info *revs, const char *arg_, int flags)
{
unsigned char sha1[20];
struct object *it;
struct commit *commit;
struct commit_list *parents;
const char *arg = arg_;
if (*arg == '^') {
flags ^= UNINTERESTING;
@ -925,6 +949,7 @@ static int add_parents_only(struct rev_info *revs, const char *arg, int flags)
for (parents = commit->parents; parents; parents = parents->next) {
it = &parents->item->object;
it->flags |= flags;
add_rev_cmdline(revs, it, arg_, REV_CMD_PARENTS_ONLY, flags);
add_pending_object(revs, it, arg);
}
return 1;
@ -1018,7 +1043,7 @@ static void prepare_show_merge(struct rev_info *revs)
revs->limited = 1;
}
int handle_revision_arg(const char *arg, struct rev_info *revs,
int handle_revision_arg(const char *arg_, struct rev_info *revs,
int flags,
int cant_be_filename)
{
@ -1027,6 +1052,7 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
struct object *object;
unsigned char sha1[20];
int local_flags;
const char *arg = arg_;
dotdot = strstr(arg, "..");
if (dotdot) {
@ -1035,6 +1061,7 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
const char *this = arg;
int symmetric = *next == '.';
unsigned int flags_exclude = flags ^ UNINTERESTING;
unsigned int a_flags;
*dotdot = 0;
next += symmetric;
@ -1069,10 +1096,15 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
add_pending_commit_list(revs, exclude,
flags_exclude);
free_commit_list(exclude);
a->object.flags |= flags | SYMMETRIC_LEFT;
a_flags = flags | SYMMETRIC_LEFT;
} else
a->object.flags |= flags_exclude;
a_flags = flags_exclude;
a->object.flags |= a_flags;
b->object.flags |= flags;
add_rev_cmdline(revs, &a->object, this,
REV_CMD_LEFT, a_flags);
add_rev_cmdline(revs, &b->object, next,
REV_CMD_RIGHT, flags);
add_pending_object(revs, &a->object, this);
add_pending_object(revs, &b->object, next);
return 0;
@ -1103,6 +1135,7 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
if (!cant_be_filename)
verify_non_filename(revs->prefix, arg);
object = get_reference(revs, arg, sha1, flags ^ local_flags);
add_rev_cmdline(revs, object, arg_, REV_CMD_REV, flags ^ local_flags);
add_pending_object_with_mode(revs, object, arg, mode);
return 0;
}

View file

@ -24,6 +24,23 @@ struct rev_info;
struct log_info;
struct string_list;
struct rev_cmdline_info {
unsigned int nr;
unsigned int alloc;
struct rev_cmdline_entry {
struct object *item;
const char *name;
enum {
REV_CMD_REF,
REV_CMD_PARENTS_ONLY,
REV_CMD_LEFT,
REV_CMD_RIGHT,
REV_CMD_REV
} whence;
unsigned flags;
} *rev;
};
struct rev_info {
/* Starting list */
struct commit_list *commits;
@ -32,6 +49,9 @@ struct rev_info {
/* Parents of shown commits */
struct object_array boundary_commits;
/* The end-points specified by the end user */
struct rev_cmdline_info cmdline;
/* Basic information */
const char *prefix;
const char *def;

View file

@ -70,4 +70,42 @@ test_expect_success 'rev-list --ancestry-patch D..M -- M.t' '
test_cmp expect actual
'
# b---bc
# / \ /
# a X
# \ / \
# c---cb
#
# All refnames prefixed with 'x' to avoid confusion with the tags
# generated by test_commit on case-insensitive systems.
test_expect_success 'setup criss-cross' '
mkdir criss-cross &&
(cd criss-cross &&
git init &&
test_commit A &&
git checkout -b xb master &&
test_commit B &&
git checkout -b xc master &&
test_commit C &&
git checkout -b xbc xb -- &&
git merge xc &&
git checkout -b xcb xc -- &&
git merge xb &&
git checkout master)
'
# no commits in bc descend from cb
test_expect_success 'criss-cross: rev-list --ancestry-path cb..bc' '
(cd criss-cross &&
git rev-list --ancestry-path xcb..xbc > actual &&
test -z "$(cat actual)")
'
# no commits in repository descend from cb
test_expect_success 'criss-cross: rev-list --ancestry-path --all ^cb' '
(cd criss-cross &&
git rev-list --ancestry-path --all ^xcb > actual &&
test -z "$(cat actual)")
'
test_done