#include "diff.h"
#include "refs.h"
#include "revision.h"
-#include <regex.h>
#include "grep.h"
static char *path_name(struct name_path *path, const char *name)
static void add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list)
{
struct commit_list *parent = commit->parents;
+ unsigned left_flag;
if (commit->object.flags & ADDED)
return;
if (revs->no_walk)
return;
+ left_flag = (commit->object.flags & SYMMETRIC_LEFT);
parent = commit->parents;
while (parent) {
struct commit *p = parent->item;
parent = parent->next;
parse_commit(p);
+ p->object.flags |= left_flag;
if (p->object.flags & SEEN)
continue;
p->object.flags |= SEEN;
if (revs->max_age != -1 && (commit->date < revs->max_age))
obj->flags |= UNINTERESTING;
- if (revs->unpacked &&
- has_sha1_pack(obj->sha1, revs->ignore_packed))
- obj->flags |= UNINTERESTING;
add_parents_to_list(revs, commit, &list);
if (obj->flags & UNINTERESTING) {
mark_parents_uninteresting(commit);
static int all_flags;
static struct rev_info *all_revs;
-static int handle_one_ref(const char *path, const unsigned char *sha1)
+static int handle_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
{
struct object *object = get_reference(all_revs, path, sha1, all_flags);
add_pending_object(all_revs, object, "");
{
all_revs = revs;
all_flags = flags;
- for_each_ref(handle_one_ref);
+ for_each_ref(handle_one_ref, NULL);
}
static int add_parents_only(struct rev_info *revs, const char *arg, int flags)
revs->prefix = prefix;
revs->max_age = -1;
revs->min_age = -1;
+ revs->skip_count = -1;
revs->max_count = -1;
revs->prune_fn = NULL;
add_pending_commit_list(revs, exclude,
flags_exclude);
free_commit_list(exclude);
- a->object.flags |= flags;
+ a->object.flags |= flags | SYMMETRIC_LEFT;
} else
a->object.flags |= flags_exclude;
b->object.flags |= flags;
return 0;
*dotdot = '^';
}
+ dotdot = strstr(arg, "^!");
+ if (dotdot && !dotdot[2]) {
+ *dotdot = 0;
+ if (!add_parents_only(revs, arg, flags ^ UNINTERESTING))
+ *dotdot = '^';
+ }
+
local_flags = 0;
if (*arg == '^') {
local_flags = UNINTERESTING;
int i, flags, seen_dashdash, show_merge;
const char **unrecognized = argv + 1;
int left = 1;
+ int all_match = 0;
/* First, search for "--" */
seen_dashdash = 0;
revs->max_count = atoi(arg + 12);
continue;
}
+ if (!strncmp(arg, "--skip=", 7)) {
+ revs->skip_count = atoi(arg + 7);
+ continue;
+ }
/* accept -<digit>, like traditional "head" */
if ((*arg == '-') && isdigit(arg[1])) {
revs->max_count = atoi(arg + 1);
revs->boundary = 1;
continue;
}
+ if (!strcmp(arg, "--left-right")) {
+ revs->left_right = 1;
+ continue;
+ }
if (!strcmp(arg, "--objects")) {
revs->tag_objects = 1;
revs->tree_objects = 1;
add_message_grep(revs, arg+7);
continue;
}
+ if (!strcmp(arg, "--all-match")) {
+ all_match = 1;
+ continue;
+ }
opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
if (opts > 0) {
add_pending_object(revs, object, def);
}
- if (revs->topo_order || revs->unpacked)
+ if (revs->topo_order)
revs->limited = 1;
if (revs->prune_data) {
if (diff_setup_done(&revs->diffopt) < 0)
die("diff_setup_done failed");
- if (revs->grep_filter)
+ if (revs->grep_filter) {
+ revs->grep_filter->all_match = all_match;
compile_grep_patterns(revs->grep_filter);
+ }
return left;
}
commit->buffer, strlen(commit->buffer));
}
-struct commit *get_revision(struct rev_info *revs)
+static struct commit *get_revision_1(struct rev_info *revs)
{
- struct commit_list *list = revs->commits;
-
- if (!list)
+ if (!revs->commits)
return NULL;
- /* Check the max_count ... */
- switch (revs->max_count) {
- case -1:
- break;
- case 0:
- return NULL;
- default:
- revs->max_count--;
- }
-
do {
struct commit_list *entry = revs->commits;
struct commit *commit = entry->item;
* that we'd otherwise have done in limit_list().
*/
if (!revs->limited) {
- if ((revs->unpacked &&
- has_sha1_pack(commit->object.sha1,
- revs->ignore_packed)) ||
- (revs->max_age != -1 &&
- (commit->date < revs->max_age)))
+ if (revs->max_age != -1 &&
+ (commit->date < revs->max_age))
continue;
add_parents_to_list(revs, commit, &revs->commits);
}
if (commit->object.flags & SHOWN)
continue;
+ if (revs->unpacked && has_sha1_pack(commit->object.sha1,
+ revs->ignore_packed))
+ continue;
+
/* We want to show boundary commits only when their
* children are shown. When path-limiter is in effect,
* rewrite_parents() drops some commits from getting shown,
} while (revs->commits);
return NULL;
}
+
+struct commit *get_revision(struct rev_info *revs)
+{
+ struct commit *c = NULL;
+
+ if (0 < revs->skip_count) {
+ while ((c = get_revision_1(revs)) != NULL) {
+ if (revs->skip_count-- <= 0)
+ break;
+ }
+ }
+
+ /* Check the max_count ... */
+ switch (revs->max_count) {
+ case -1:
+ break;
+ case 0:
+ return NULL;
+ default:
+ revs->max_count--;
+ }
+ if (c)
+ return c;
+ return get_revision_1(revs);
+}