@ -116,21 +116,27 @@ static void add_pending_object(struct rev_info *revs, struct object *obj, const
@@ -116,21 +116,27 @@ static void add_pending_object(struct rev_info *revs, struct object *obj, const
add_object(obj, &revs->pending_objects, NULL, name);
}
static struct commit *get_commit_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags)
static struct object *get_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags)
{
struct object *object;
object = parse_object(sha1);
if (!object)
die("bad object %s", name);
object->flags |= flags;
return object;
}
static struct commit *handle_commit(struct rev_info *revs, struct object *object, const char *name)
{
unsigned long flags = object->flags;
/*
* Tag object? Look what it points to..
*/
while (object->type == tag_type) {
struct tag *tag = (struct tag *) object;
object->flags |= flags;
if (revs->tag_objects && !(object->flags & UNINTERESTING))
if (revs->tag_objects && !(flags & UNINTERESTING))
add_pending_object(revs, object, tag->tag);
object = parse_object(tag->tagged->sha1);
if (!object)
@ -143,7 +149,6 @@ static struct commit *get_commit_reference(struct rev_info *revs, const char *na
@@ -143,7 +149,6 @@ static struct commit *get_commit_reference(struct rev_info *revs, const char *na
*/
if (object->type == commit_type) {
struct commit *commit = (struct commit *)object;
object->flags |= flags;
if (parse_commit(commit) < 0)
die("unable to parse commit %s", name);
if (flags & UNINTERESTING) {
@ -241,7 +246,7 @@ int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree *t2)
@@ -241,7 +246,7 @@ int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree *t2)
return REV_TREE_DIFFERENT;
tree_difference = REV_TREE_SAME;
if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "",
&revs->diffopt) < 0)
&revs->pruning) < 0)
return REV_TREE_DIFFERENT;
return tree_difference;
}
@ -264,7 +269,7 @@ int rev_same_tree_as_empty(struct rev_info *revs, struct tree *t1)
@@ -264,7 +269,7 @@ int rev_same_tree_as_empty(struct rev_info *revs, struct tree *t1)
empty.size = 0;
tree_difference = 0;
retval = diff_tree(&empty, &real, "", &revs->diffopt);
retval = diff_tree(&empty, &real, "", &revs->pruning);
free(tree);
return retval >= 0 && !tree_difference;
@ -375,6 +380,9 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st
@@ -375,6 +380,9 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st
if (revs->prune_fn)
revs->prune_fn(revs, commit);
if (revs->no_walk)
return;
parent = commit->parents;
while (parent) {
struct commit *p = parent->item;
@ -451,21 +459,13 @@ static void limit_list(struct rev_info *revs)
@@ -451,21 +459,13 @@ static void limit_list(struct rev_info *revs)
revs->commits = newlist;
}
static void add_one_commit(struct commit *commit, struct rev_info *revs)
{
if (!commit || (commit->object.flags & SEEN))
return;
commit->object.flags |= SEEN;
commit_list_insert(commit, &revs->commits);
}
static int all_flags;
static struct rev_info *all_revs;
static int handle_one_ref(const char *path, const unsigned char *sha1)
{
struct commit *commit = get_commit_reference(all_revs, path, sha1, all_flags);
add_one_commit(commit, all_revs);
struct object *object = get_reference(all_revs, path, sha1, all_flags);
add_pending_object(all_revs, object, "");
return 0;
}
@ -479,9 +479,12 @@ static void handle_all(struct rev_info *revs, unsigned flags)
@@ -479,9 +479,12 @@ static void handle_all(struct rev_info *revs, unsigned flags)
void init_revisions(struct rev_info *revs)
{
memset(revs, 0, sizeof(*revs));
revs->diffopt.recursive = 1;
revs->diffopt.add_remove = file_add_remove;
revs->diffopt.change = file_change;
revs->abbrev = DEFAULT_ABBREV;
revs->ignore_merges = 1;
revs->pruning.recursive = 1;
revs->pruning.add_remove = file_add_remove;
revs->pruning.change = file_change;
revs->lifo = 1;
revs->dense = 1;
revs->prefix = setup_git_directory();
@ -494,6 +497,10 @@ void init_revisions(struct rev_info *revs)
@@ -494,6 +497,10 @@ void init_revisions(struct rev_info *revs)
revs->topo_setter = topo_sort_default_setter;
revs->topo_getter = topo_sort_default_getter;
revs->commit_format = CMIT_FMT_DEFAULT;
diff_setup(&revs->diffopt);
}
/*
@ -509,8 +516,6 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
@@ -509,8 +516,6 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
const char **unrecognized = argv + 1;
int left = 1;
init_revisions(revs);
/* First, search for "--" */
seen_dashdash = 0;
for (i = 1; i < argc; i++) {
@ -526,13 +531,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
@@ -526,13 +531,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
flags = 0;
for (i = 1; i < argc; i++) {
struct commit *commit;
struct object *object;
const char *arg = argv[i];
unsigned char sha1[20];
char *dotdot;
int local_flags;
if (*arg == '-') {
int opts;
if (!strncmp(arg, "--max-count=", 12)) {
revs->max_count = atoi(arg + 12);
continue;
@ -640,6 +646,76 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
@@ -640,6 +646,76 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->unpacked = 1;
continue;
}
if (!strcmp(arg, "-r")) {
revs->diff = 1;
revs->diffopt.recursive = 1;
continue;
}
if (!strcmp(arg, "-t")) {
revs->diff = 1;
revs->diffopt.recursive = 1;
revs->diffopt.tree_in_recursive = 1;
continue;
}
if (!strcmp(arg, "-m")) {
revs->ignore_merges = 0;
continue;
}
if (!strcmp(arg, "-c")) {
revs->diff = 1;
revs->combine_merges = 1;
continue;
}
if (!strcmp(arg, "--cc")) {
revs->diff = 1;
revs->dense_combined_merges = 1;
revs->combine_merges = 1;
continue;
}
if (!strcmp(arg, "-v")) {
revs->verbose_header = 1;
continue;
}
if (!strncmp(arg, "--pretty", 8)) {
revs->verbose_header = 1;
revs->commit_format = get_commit_format(arg+8);
continue;
}
if (!strcmp(arg, "--root")) {
revs->show_root_diff = 1;
continue;
}
if (!strcmp(arg, "--no-commit-id")) {
revs->no_commit_id = 1;
continue;
}
if (!strcmp(arg, "--always")) {
revs->always_show_header = 1;
continue;
}
if (!strcmp(arg, "--no-abbrev")) {
revs->abbrev = 0;
continue;
}
if (!strcmp(arg, "--abbrev")) {
revs->abbrev = DEFAULT_ABBREV;
continue;
}
if (!strcmp(arg, "--abbrev-commit")) {
revs->abbrev_commit = 1;
continue;
}
if (!strcmp(arg, "--full-diff")) {
revs->diff = 1;
revs->full_diff = 1;
continue;
}
opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
if (opts > 0) {
revs->diff = 1;
i += opts - 1;
continue;
}
*unrecognized++ = arg;
left++;
continue;
@ -656,15 +732,15 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
@@ -656,15 +732,15 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
this = "HEAD";
if (!get_sha1(this, from_sha1) &&
!get_sha1(next, sha1)) {
struct commit *exclude;
struct commit *include;
struct object *exclude;
struct object *include;
exclude = get_commit_reference(revs, this, from_sha1, flags ^ UNINTERESTING);
include = get_commit_reference(revs, next, sha1, flags);
exclude = get_reference(revs, this, from_sha1, flags ^ UNINTERESTING);
include = get_reference(revs, next, sha1, flags);
if (!exclude || !include)
die("Invalid revision range %s..%s", arg, next);
add_one_commit(exclude, revs);
add_one_commit(include, revs);
add_pending_object(revs, exclude, this);
add_pending_object(revs, include, next);
continue;
}
*dotdot = '.';
@ -689,32 +765,57 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
@@ -689,32 +765,57 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->prune_data = get_pathspec(revs->prefix, argv + i);
break;
}
commit = get_commit_reference(revs, arg, sha1, flags ^ local_flags);
add_one_commit(commit, revs);
object = get_reference(revs, arg, sha1, flags ^ local_flags);
add_pending_object(revs, object, arg);
}
if (def && !revs->commits) {
if (def && !revs->pending_objects) {
unsigned char sha1[20];
struct commit *commit;
struct object *object;
if (get_sha1(def, sha1) < 0)
die("bad default revision '%s'", def);
commit = get_commit_reference(revs, def, sha1, 0);
add_one_commit(commit, revs);
object = get_reference(revs, def, sha1, 0);
add_pending_object(revs, object, def);
}
if (revs->topo_order || revs->unpacked)
revs->limited = 1;
if (revs->prune_data) {
diff_tree_setup_paths(revs->prune_data, &revs->diffopt);
diff_tree_setup_paths(revs->prune_data, &revs->pruning);
revs->prune_fn = try_to_simplify_commit;
if (!revs->full_diff)
diff_tree_setup_paths(revs->prune_data, &revs->diffopt);
}
if (revs->combine_merges) {
revs->ignore_merges = 0;
if (revs->dense_combined_merges)
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
}
revs->diffopt.abbrev = revs->abbrev;
diff_setup_done(&revs->diffopt);
return left;
}
void prepare_revision_walk(struct rev_info *revs)
{
sort_by_date(&revs->commits);
struct object_list *list;
list = revs->pending_objects;
revs->pending_objects = NULL;
while (list) {
struct commit *commit = handle_commit(revs, list->item, list->name);
if (commit) {
if (!(commit->object.flags & SEEN)) {
commit->object.flags |= SEEN;
insert_by_date(commit, &revs->commits);
}
}
list = list->next;
}
if (revs->no_walk)
return;
if (revs->limited)
limit_list(revs);
if (revs->topo_order)