X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=revision.c;h=f1e0caaae3d2a96de6cf9bad12e8641c19d788dd;hb=ce4231ffa80da1888a668cc7c33f5349800ab4a3;hp=5a91d06b980d710e30a80c353a636ca1ca6b9a55;hpb=72ee96c0f1861fcdb9eaf39e78d86888437a27a9;p=git.git diff --git a/revision.c b/revision.c index 5a91d06b9..f1e0caaae 100644 --- a/revision.c +++ b/revision.c @@ -6,6 +6,8 @@ #include "diff.h" #include "refs.h" #include "revision.h" +#include +#include "grep.h" static char *path_name(struct name_path *path, const char *name) { @@ -416,7 +418,8 @@ static void limit_list(struct rev_info *revs) if (revs->max_age != -1 && (commit->date < revs->max_age)) obj->flags |= UNINTERESTING; - if (revs->unpacked && has_sha1_pack(obj->sha1)) + 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) { @@ -496,7 +499,7 @@ static int add_parents_only(struct rev_info *revs, const char *arg, int flags) it = get_reference(revs, arg, sha1, 0); if (it->type != OBJ_TAG) break; - memcpy(sha1, ((struct tag*)it)->tagged->sha1, 20); + hashcpy(sha1, ((struct tag*)it)->tagged->sha1); } if (it->type != OBJ_COMMIT) return 0; @@ -592,6 +595,131 @@ static void prepare_show_merge(struct rev_info *revs) revs->prune_data = prune; } +int handle_revision_arg(const char *arg, struct rev_info *revs, + int flags, + int cant_be_filename) +{ + char *dotdot; + struct object *object; + unsigned char sha1[20]; + int local_flags; + + dotdot = strstr(arg, ".."); + if (dotdot) { + unsigned char from_sha1[20]; + const char *next = dotdot + 2; + const char *this = arg; + int symmetric = *next == '.'; + unsigned int flags_exclude = flags ^ UNINTERESTING; + + *dotdot = 0; + next += symmetric; + + if (!*next) + next = "HEAD"; + if (dotdot == arg) + this = "HEAD"; + if (!get_sha1(this, from_sha1) && + !get_sha1(next, sha1)) { + struct commit *a, *b; + struct commit_list *exclude; + + a = lookup_commit_reference(from_sha1); + b = lookup_commit_reference(sha1); + if (!a || !b) { + die(symmetric ? + "Invalid symmetric difference expression %s...%s" : + "Invalid revision range %s..%s", + arg, next); + } + + if (!cant_be_filename) { + *dotdot = '.'; + verify_non_filename(revs->prefix, arg); + } + + if (symmetric) { + exclude = get_merge_bases(a, b, 1); + add_pending_commit_list(revs, exclude, + flags_exclude); + free_commit_list(exclude); + a->object.flags |= flags; + } else + a->object.flags |= flags_exclude; + b->object.flags |= flags; + add_pending_object(revs, &a->object, this); + add_pending_object(revs, &b->object, next); + return 0; + } + *dotdot = '.'; + } + dotdot = strstr(arg, "^@"); + if (dotdot && !dotdot[2]) { + *dotdot = 0; + if (add_parents_only(revs, arg, flags)) + return 0; + *dotdot = '^'; + } + local_flags = 0; + if (*arg == '^') { + local_flags = UNINTERESTING; + arg++; + } + if (get_sha1(arg, sha1)) + return -1; + if (!cant_be_filename) + verify_non_filename(revs->prefix, arg); + object = get_reference(revs, arg, sha1, flags ^ local_flags); + add_pending_object(revs, object, arg); + return 0; +} + +static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what) +{ + if (!revs->grep_filter) { + struct grep_opt *opt = xcalloc(1, sizeof(*opt)); + opt->status_only = 1; + opt->pattern_tail = &(opt->pattern_list); + opt->regflags = REG_NEWLINE; + revs->grep_filter = opt; + } + append_grep_pattern(revs->grep_filter, ptn, + "command line", 0, what); +} + +static void add_header_grep(struct rev_info *revs, const char *field, const char *pattern) +{ + char *pat; + const char *prefix; + int patlen, fldlen; + + fldlen = strlen(field); + patlen = strlen(pattern); + pat = xmalloc(patlen + fldlen + 10); + prefix = ".*"; + if (*pattern == '^') { + prefix = ""; + pattern++; + } + sprintf(pat, "^%s %s%s", field, prefix, pattern); + add_grep(revs, pat, GREP_PATTERN_HEAD); +} + +static void add_message_grep(struct rev_info *revs, const char *pattern) +{ + add_grep(revs, pattern, GREP_PATTERN_BODY); +} + +static void add_ignore_packed(struct rev_info *revs, const char *name) +{ + int num = ++revs->num_ignore_packed; + + revs->ignore_packed = xrealloc(revs->ignore_packed, + sizeof(const char **) * (num + 1)); + revs->ignore_packed[num-1] = name; + revs->ignore_packed[num] = NULL; +} + /* * Parse revision information, filling in the "rev_info" structure, * and removing the used arguments from the argument list. @@ -604,6 +732,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch 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; @@ -620,12 +749,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch flags = show_merge = 0; for (i = 1; i < argc; i++) { - 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)) { @@ -737,6 +861,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch } if (!strcmp(arg, "--unpacked")) { revs->unpacked = 1; + free(revs->ignore_packed); + revs->ignore_packed = NULL; + revs->num_ignore_packed = 0; + continue; + } + if (!strncmp(arg, "--unpacked=", 11)) { + revs->unpacked = 1; + add_ignore_packed(revs, arg+11); continue; } if (!strcmp(arg, "-r")) { @@ -816,6 +948,31 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch revs->simplify_history = 0; continue; } + if (!strcmp(arg, "--relative-date")) { + revs->relative_date = 1; + continue; + } + + /* + * Grepping the commit log + */ + if (!strncmp(arg, "--author=", 9)) { + add_header_grep(revs, "author", arg+9); + continue; + } + if (!strncmp(arg, "--committer=", 12)) { + add_header_grep(revs, "committer", arg+12); + continue; + } + if (!strncmp(arg, "--grep=", 7)) { + 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) { revs->diff = 1; @@ -826,71 +983,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch left++; continue; } - dotdot = strstr(arg, ".."); - if (dotdot) { - unsigned char from_sha1[20]; - const char *next = dotdot + 2; - const char *this = arg; - int symmetric = *next == '.'; - unsigned int flags_exclude = flags ^ UNINTERESTING; - - *dotdot = 0; - next += symmetric; - - if (!*next) - next = "HEAD"; - if (dotdot == arg) - this = "HEAD"; - if (!get_sha1(this, from_sha1) && - !get_sha1(next, sha1)) { - struct commit *a, *b; - struct commit_list *exclude; - - a = lookup_commit_reference(from_sha1); - b = lookup_commit_reference(sha1); - if (!a || !b) { - die(symmetric ? - "Invalid symmetric difference expression %s...%s" : - "Invalid revision range %s..%s", - arg, next); - } - - if (!seen_dashdash) { - *dotdot = '.'; - verify_non_filename(revs->prefix, arg); - } - - if (symmetric) { - exclude = get_merge_bases(a, b, 1); - add_pending_commit_list(revs, exclude, - flags_exclude); - free_commit_list(exclude); - a->object.flags |= flags; - } else - a->object.flags |= flags_exclude; - b->object.flags |= flags; - add_pending_object(revs, &a->object, this); - add_pending_object(revs, &b->object, next); - continue; - } - *dotdot = '.'; - } - dotdot = strstr(arg, "^@"); - if (dotdot && !dotdot[2]) { - *dotdot = 0; - if (add_parents_only(revs, arg, flags)) - continue; - *dotdot = '^'; - } - local_flags = 0; - if (*arg == '^') { - local_flags = UNINTERESTING; - arg++; - } - if (get_sha1(arg, sha1)) { - int j; - if (seen_dashdash || local_flags) + if (handle_revision_arg(arg, revs, flags, seen_dashdash)) { + int j; + if (seen_dashdash || *arg == '^') die("bad revision '%s'", arg); /* If we didn't have a "--": @@ -902,14 +998,12 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch for (j = i; j < argc; j++) verify_filename(revs->prefix, argv[j]); - revs->prune_data = get_pathspec(revs->prefix, argv + i); + revs->prune_data = get_pathspec(revs->prefix, + argv + i); break; } - if (!seen_dashdash) - verify_non_filename(revs->prefix, arg); - object = get_reference(revs, arg, sha1, flags ^ local_flags); - add_pending_object(revs, object, arg); } + if (show_merge) prepare_show_merge(revs); if (def && !revs->pending.nr) { @@ -939,6 +1033,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch if (diff_setup_done(&revs->diffopt) < 0) die("diff_setup_done failed"); + if (revs->grep_filter) { + revs->grep_filter->all_match = all_match; + compile_grep_patterns(revs->grep_filter); + } + return left; } @@ -1011,6 +1110,15 @@ static void mark_boundary_to_show(struct commit *commit) } } +static int commit_match(struct commit *commit, struct rev_info *opt) +{ + if (!opt->grep_filter) + return 1; + return grep_buffer(opt->grep_filter, + NULL, /* we say nothing, not even filename */ + commit->buffer, strlen(commit->buffer)); +} + struct commit *get_revision(struct rev_info *revs) { struct commit_list *list = revs->commits; @@ -1042,7 +1150,8 @@ struct commit *get_revision(struct rev_info *revs) */ if (!revs->limited) { if ((revs->unpacked && - has_sha1_pack(commit->object.sha1)) || + has_sha1_pack(commit->object.sha1, + revs->ignore_packed)) || (revs->max_age != -1 && (commit->date < revs->max_age))) continue; @@ -1070,6 +1179,8 @@ struct commit *get_revision(struct rev_info *revs) if (revs->no_merges && commit->parents && commit->parents->next) continue; + if (!commit_match(commit, revs)) + continue; if (revs->prune_fn && revs->dense) { /* Commit without changes? */ if (!(commit->object.flags & TREECHANGE)) {