Merge branch 'jc/maint-log-grep'
* jc/maint-log-grep: log --author/--committer: really match only with name part diff --cumulative is a sub-option of --dirstat bash completion: Hide more plumbing commands
This commit is contained in:
commit
80d12c23de
@ -386,7 +386,9 @@ __git_porcelain_commands ()
|
|||||||
cat-file) : plumbing;;
|
cat-file) : plumbing;;
|
||||||
check-attr) : plumbing;;
|
check-attr) : plumbing;;
|
||||||
check-ref-format) : plumbing;;
|
check-ref-format) : plumbing;;
|
||||||
|
checkout-index) : plumbing;;
|
||||||
commit-tree) : plumbing;;
|
commit-tree) : plumbing;;
|
||||||
|
count-objects) : infrequent;;
|
||||||
cvsexportcommit) : export;;
|
cvsexportcommit) : export;;
|
||||||
cvsimport) : import;;
|
cvsimport) : import;;
|
||||||
cvsserver) : daemon;;
|
cvsserver) : daemon;;
|
||||||
@ -395,6 +397,7 @@ __git_porcelain_commands ()
|
|||||||
diff-index) : plumbing;;
|
diff-index) : plumbing;;
|
||||||
diff-tree) : plumbing;;
|
diff-tree) : plumbing;;
|
||||||
fast-import) : import;;
|
fast-import) : import;;
|
||||||
|
fast-export) : export;;
|
||||||
fsck-objects) : plumbing;;
|
fsck-objects) : plumbing;;
|
||||||
fetch-pack) : plumbing;;
|
fetch-pack) : plumbing;;
|
||||||
fmt-merge-msg) : plumbing;;
|
fmt-merge-msg) : plumbing;;
|
||||||
@ -404,6 +407,10 @@ __git_porcelain_commands ()
|
|||||||
index-pack) : plumbing;;
|
index-pack) : plumbing;;
|
||||||
init-db) : deprecated;;
|
init-db) : deprecated;;
|
||||||
local-fetch) : plumbing;;
|
local-fetch) : plumbing;;
|
||||||
|
lost-found) : infrequent;;
|
||||||
|
ls-files) : plumbing;;
|
||||||
|
ls-remote) : plumbing;;
|
||||||
|
ls-tree) : plumbing;;
|
||||||
mailinfo) : plumbing;;
|
mailinfo) : plumbing;;
|
||||||
mailsplit) : plumbing;;
|
mailsplit) : plumbing;;
|
||||||
merge-*) : plumbing;;
|
merge-*) : plumbing;;
|
||||||
@ -428,6 +435,7 @@ __git_porcelain_commands ()
|
|||||||
runstatus) : plumbing;;
|
runstatus) : plumbing;;
|
||||||
sh-setup) : internal;;
|
sh-setup) : internal;;
|
||||||
shell) : daemon;;
|
shell) : daemon;;
|
||||||
|
show-ref) : plumbing;;
|
||||||
send-pack) : plumbing;;
|
send-pack) : plumbing;;
|
||||||
show-index) : plumbing;;
|
show-index) : plumbing;;
|
||||||
ssh-*) : transport;;
|
ssh-*) : transport;;
|
||||||
@ -442,6 +450,8 @@ __git_porcelain_commands ()
|
|||||||
upload-archive) : plumbing;;
|
upload-archive) : plumbing;;
|
||||||
upload-pack) : plumbing;;
|
upload-pack) : plumbing;;
|
||||||
write-tree) : plumbing;;
|
write-tree) : plumbing;;
|
||||||
|
var) : infrequent;;
|
||||||
|
verify-pack) : infrequent;;
|
||||||
verify-tag) : plumbing;;
|
verify-tag) : plumbing;;
|
||||||
*) echo $i;;
|
*) echo $i;;
|
||||||
esac
|
esac
|
||||||
|
9
diff.c
9
diff.c
@ -1078,7 +1078,7 @@ static void show_dirstat(struct diff_options *options)
|
|||||||
dir.alloc = 0;
|
dir.alloc = 0;
|
||||||
dir.nr = 0;
|
dir.nr = 0;
|
||||||
dir.percent = options->dirstat_percent;
|
dir.percent = options->dirstat_percent;
|
||||||
dir.cumulative = options->output_format & DIFF_FORMAT_CUMULATIVE;
|
dir.cumulative = DIFF_OPT_TST(options, DIRSTAT_CUMULATIVE);
|
||||||
|
|
||||||
changed = 0;
|
changed = 0;
|
||||||
for (i = 0; i < q->nr; i++) {
|
for (i = 0; i < q->nr; i++) {
|
||||||
@ -2300,6 +2300,7 @@ void diff_setup(struct diff_options *options)
|
|||||||
options->break_opt = -1;
|
options->break_opt = -1;
|
||||||
options->rename_limit = -1;
|
options->rename_limit = -1;
|
||||||
options->dirstat_percent = 3;
|
options->dirstat_percent = 3;
|
||||||
|
DIFF_OPT_CLR(options, DIRSTAT_CUMULATIVE);
|
||||||
options->context = 3;
|
options->context = 3;
|
||||||
|
|
||||||
options->change = diff_change;
|
options->change = diff_change;
|
||||||
@ -2472,8 +2473,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
|||||||
options->output_format |= DIFF_FORMAT_SHORTSTAT;
|
options->output_format |= DIFF_FORMAT_SHORTSTAT;
|
||||||
else if (opt_arg(arg, 'X', "dirstat", &options->dirstat_percent))
|
else if (opt_arg(arg, 'X', "dirstat", &options->dirstat_percent))
|
||||||
options->output_format |= DIFF_FORMAT_DIRSTAT;
|
options->output_format |= DIFF_FORMAT_DIRSTAT;
|
||||||
else if (!strcmp(arg, "--cumulative"))
|
else if (!strcmp(arg, "--cumulative")) {
|
||||||
options->output_format |= DIFF_FORMAT_CUMULATIVE;
|
options->output_format |= DIFF_FORMAT_DIRSTAT;
|
||||||
|
DIFF_OPT_SET(options, DIRSTAT_CUMULATIVE);
|
||||||
|
}
|
||||||
else if (!strcmp(arg, "--check"))
|
else if (!strcmp(arg, "--check"))
|
||||||
options->output_format |= DIFF_FORMAT_CHECKDIFF;
|
options->output_format |= DIFF_FORMAT_CHECKDIFF;
|
||||||
else if (!strcmp(arg, "--summary"))
|
else if (!strcmp(arg, "--summary"))
|
||||||
|
2
diff.h
2
diff.h
@ -31,7 +31,6 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
|
|||||||
#define DIFF_FORMAT_PATCH 0x0010
|
#define DIFF_FORMAT_PATCH 0x0010
|
||||||
#define DIFF_FORMAT_SHORTSTAT 0x0020
|
#define DIFF_FORMAT_SHORTSTAT 0x0020
|
||||||
#define DIFF_FORMAT_DIRSTAT 0x0040
|
#define DIFF_FORMAT_DIRSTAT 0x0040
|
||||||
#define DIFF_FORMAT_CUMULATIVE 0x0080
|
|
||||||
|
|
||||||
/* These override all above */
|
/* These override all above */
|
||||||
#define DIFF_FORMAT_NAME 0x0100
|
#define DIFF_FORMAT_NAME 0x0100
|
||||||
@ -64,6 +63,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
|
|||||||
#define DIFF_OPT_CHECK_FAILED (1 << 16)
|
#define DIFF_OPT_CHECK_FAILED (1 << 16)
|
||||||
#define DIFF_OPT_RELATIVE_NAME (1 << 17)
|
#define DIFF_OPT_RELATIVE_NAME (1 << 17)
|
||||||
#define DIFF_OPT_IGNORE_SUBMODULES (1 << 18)
|
#define DIFF_OPT_IGNORE_SUBMODULES (1 << 18)
|
||||||
|
#define DIFF_OPT_DIRSTAT_CUMULATIVE (1 << 19)
|
||||||
#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
|
#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
|
||||||
#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)
|
#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)
|
||||||
#define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag)
|
#define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag)
|
||||||
|
52
grep.c
52
grep.c
@ -2,6 +2,19 @@
|
|||||||
#include "grep.h"
|
#include "grep.h"
|
||||||
#include "xdiff-interface.h"
|
#include "xdiff-interface.h"
|
||||||
|
|
||||||
|
void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field field, const char *pat)
|
||||||
|
{
|
||||||
|
struct grep_pat *p = xcalloc(1, sizeof(*p));
|
||||||
|
p->pattern = pat;
|
||||||
|
p->origin = "header";
|
||||||
|
p->no = 0;
|
||||||
|
p->token = GREP_PATTERN_HEAD;
|
||||||
|
p->field = field;
|
||||||
|
*opt->pattern_tail = p;
|
||||||
|
opt->pattern_tail = &p->next;
|
||||||
|
p->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void append_grep_pattern(struct grep_opt *opt, const char *pat,
|
void append_grep_pattern(struct grep_opt *opt, const char *pat,
|
||||||
const char *origin, int no, enum grep_pat_token t)
|
const char *origin, int no, enum grep_pat_token t)
|
||||||
{
|
{
|
||||||
@ -247,16 +260,53 @@ static int fixmatch(const char *pattern, char *line, regmatch_t *match)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int strip_timestamp(char *bol, char **eol_p)
|
||||||
|
{
|
||||||
|
char *eol = *eol_p;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
while (bol < --eol) {
|
||||||
|
if (*eol != '>')
|
||||||
|
continue;
|
||||||
|
*eol_p = ++eol;
|
||||||
|
ch = *eol;
|
||||||
|
*eol = '\0';
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
const char *field;
|
||||||
|
size_t len;
|
||||||
|
} header_field[] = {
|
||||||
|
{ "author ", 7 },
|
||||||
|
{ "committer ", 10 },
|
||||||
|
};
|
||||||
|
|
||||||
static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol, char *eol, enum grep_context ctx)
|
static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol, char *eol, enum grep_context ctx)
|
||||||
{
|
{
|
||||||
int hit = 0;
|
int hit = 0;
|
||||||
int at_true_bol = 1;
|
int at_true_bol = 1;
|
||||||
|
int saved_ch = 0;
|
||||||
regmatch_t pmatch[10];
|
regmatch_t pmatch[10];
|
||||||
|
|
||||||
if ((p->token != GREP_PATTERN) &&
|
if ((p->token != GREP_PATTERN) &&
|
||||||
((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD)))
|
((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (p->token == GREP_PATTERN_HEAD) {
|
||||||
|
const char *field;
|
||||||
|
size_t len;
|
||||||
|
assert(p->field < ARRAY_SIZE(header_field));
|
||||||
|
field = header_field[p->field].field;
|
||||||
|
len = header_field[p->field].len;
|
||||||
|
if (strncmp(bol, field, len))
|
||||||
|
return 0;
|
||||||
|
bol += len;
|
||||||
|
saved_ch = strip_timestamp(bol, &eol);
|
||||||
|
}
|
||||||
|
|
||||||
again:
|
again:
|
||||||
if (!opt->fixed) {
|
if (!opt->fixed) {
|
||||||
regex_t *exp = &p->regexp;
|
regex_t *exp = &p->regexp;
|
||||||
@ -298,6 +348,8 @@ static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol
|
|||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (p->token == GREP_PATTERN_HEAD && saved_ch)
|
||||||
|
*eol = saved_ch;
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
grep.h
7
grep.h
@ -17,12 +17,18 @@ enum grep_context {
|
|||||||
GREP_CONTEXT_BODY,
|
GREP_CONTEXT_BODY,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum grep_header_field {
|
||||||
|
GREP_HEADER_AUTHOR = 0,
|
||||||
|
GREP_HEADER_COMMITTER,
|
||||||
|
};
|
||||||
|
|
||||||
struct grep_pat {
|
struct grep_pat {
|
||||||
struct grep_pat *next;
|
struct grep_pat *next;
|
||||||
const char *origin;
|
const char *origin;
|
||||||
int no;
|
int no;
|
||||||
enum grep_pat_token token;
|
enum grep_pat_token token;
|
||||||
const char *pattern;
|
const char *pattern;
|
||||||
|
enum grep_header_field field;
|
||||||
regex_t regexp;
|
regex_t regexp;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -74,6 +80,7 @@ struct grep_opt {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
|
extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
|
||||||
|
extern void append_header_grep_pattern(struct grep_opt *, enum grep_header_field, const char *);
|
||||||
extern void compile_grep_patterns(struct grep_opt *opt);
|
extern void compile_grep_patterns(struct grep_opt *opt);
|
||||||
extern void free_grep_patterns(struct grep_opt *opt);
|
extern void free_grep_patterns(struct grep_opt *opt);
|
||||||
extern int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size);
|
extern int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size);
|
||||||
|
21
revision.c
21
revision.c
@ -953,22 +953,9 @@ static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token
|
|||||||
append_grep_pattern(&revs->grep_filter, ptn, "command line", 0, what);
|
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)
|
static void add_header_grep(struct rev_info *revs, enum grep_header_field field, const char *pattern)
|
||||||
{
|
{
|
||||||
char *pat;
|
append_header_grep_pattern(&revs->grep_filter, field, pattern);
|
||||||
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)
|
static void add_message_grep(struct rev_info *revs, const char *pattern)
|
||||||
@ -1159,9 +1146,9 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
|
|||||||
* Grepping the commit log
|
* Grepping the commit log
|
||||||
*/
|
*/
|
||||||
else if (!prefixcmp(arg, "--author=")) {
|
else if (!prefixcmp(arg, "--author=")) {
|
||||||
add_header_grep(revs, "author", arg+9);
|
add_header_grep(revs, GREP_HEADER_AUTHOR, arg+9);
|
||||||
} else if (!prefixcmp(arg, "--committer=")) {
|
} else if (!prefixcmp(arg, "--committer=")) {
|
||||||
add_header_grep(revs, "committer", arg+12);
|
add_header_grep(revs, GREP_HEADER_COMMITTER, arg+12);
|
||||||
} else if (!prefixcmp(arg, "--grep=")) {
|
} else if (!prefixcmp(arg, "--grep=")) {
|
||||||
add_message_grep(revs, arg+7);
|
add_message_grep(revs, arg+7);
|
||||||
} else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
|
} else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
|
||||||
|
@ -22,6 +22,7 @@ test_expect_success setup '
|
|||||||
mkdir t &&
|
mkdir t &&
|
||||||
echo test >t/t &&
|
echo test >t/t &&
|
||||||
git add file x y z t/t &&
|
git add file x y z t/t &&
|
||||||
|
test_tick &&
|
||||||
git commit -m initial
|
git commit -m initial
|
||||||
'
|
'
|
||||||
|
|
||||||
@ -113,4 +114,54 @@ do
|
|||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
|
test_expect_success 'log grep setup' '
|
||||||
|
echo a >>file &&
|
||||||
|
test_tick &&
|
||||||
|
GIT_AUTHOR_NAME="With * Asterisk" \
|
||||||
|
GIT_AUTHOR_EMAIL="xyzzy@frotz.com" \
|
||||||
|
git commit -a -m "second" &&
|
||||||
|
|
||||||
|
echo a >>file &&
|
||||||
|
test_tick &&
|
||||||
|
git commit -a -m "third"
|
||||||
|
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'log grep (1)' '
|
||||||
|
git log --author=author --pretty=tformat:%s >actual &&
|
||||||
|
( echo third ; echo initial ) >expect &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'log grep (2)' '
|
||||||
|
git log --author=" * " -F --pretty=tformat:%s >actual &&
|
||||||
|
( echo second ) >expect &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'log grep (3)' '
|
||||||
|
git log --author="^A U" --pretty=tformat:%s >actual &&
|
||||||
|
( echo third ; echo initial ) >expect &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'log grep (4)' '
|
||||||
|
git log --author="frotz\.com>$" --pretty=tformat:%s >actual &&
|
||||||
|
( echo second ) >expect &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'log grep (5)' '
|
||||||
|
git log --author=Thor -F --grep=Thu --pretty=tformat:%s >actual &&
|
||||||
|
( echo third ; echo initial ) >expect &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'log grep (6)' '
|
||||||
|
git log --author=-0700 --pretty=tformat:%s >actual &&
|
||||||
|
>expect &&
|
||||||
|
test_cmp expect actual
|
||||||
|
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user