зеркало из https://github.com/microsoft/git.git
git-blame: migrate to incremental parse-option [1/2]
This step merely moves the parser to an incremental version, still using parse_revisions. Signed-off-by: Pierre Habouzit <madcoder@debian.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
02e542206f
Коммит
5817da0143
220
builtin-blame.c
220
builtin-blame.c
|
@ -18,24 +18,16 @@
|
||||||
#include "cache-tree.h"
|
#include "cache-tree.h"
|
||||||
#include "path-list.h"
|
#include "path-list.h"
|
||||||
#include "mailmap.h"
|
#include "mailmap.h"
|
||||||
|
#include "parse-options.h"
|
||||||
|
|
||||||
static char blame_usage[] =
|
static char blame_usage[] = "git-blame [options] [rev-opts] [rev] [--] file";
|
||||||
"git-blame [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-w] [-L n,m] [-S <revs-file>] [-M] [-C] [-C] [--contents <filename>] [--incremental] [commit] [--] file\n"
|
|
||||||
" -c Use the same output mode as git-annotate (Default: off)\n"
|
static const char *blame_opt_usage[] = {
|
||||||
" -b Show blank SHA-1 for boundary commits (Default: off)\n"
|
blame_usage,
|
||||||
" -l Show long commit SHA1 (Default: off)\n"
|
"",
|
||||||
" --root Do not treat root commits as boundaries (Default: off)\n"
|
"[rev-opts] are documented in git-rev-parse(1)",
|
||||||
" -t Show raw timestamp (Default: off)\n"
|
NULL
|
||||||
" -f, --show-name Show original filename (Default: auto)\n"
|
};
|
||||||
" -n, --show-number Show original linenumber (Default: off)\n"
|
|
||||||
" -s Suppress author name and timestamp (Default: off)\n"
|
|
||||||
" -p, --porcelain Show in a format designed for machine consumption\n"
|
|
||||||
" -w Ignore whitespace differences\n"
|
|
||||||
" -L n,m Process only line range n,m, counting from 1\n"
|
|
||||||
" -M, -C Find line movements within and across files\n"
|
|
||||||
" --incremental Show blame entries as we find them, incrementally\n"
|
|
||||||
" --contents file Use <file>'s contents as the final image\n"
|
|
||||||
" -S revs-file Use revisions from revs-file instead of calling git-rev-list\n";
|
|
||||||
|
|
||||||
static int longest_file;
|
static int longest_file;
|
||||||
static int longest_author;
|
static int longest_author;
|
||||||
|
@ -2219,6 +2211,50 @@ static const char *prepare_initial(struct scoreboard *sb)
|
||||||
return final_commit_name;
|
return final_commit_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int blame_copy_callback(const struct option *option, const char *arg, int unset)
|
||||||
|
{
|
||||||
|
int *opt = option->value;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* -C enables copy from removed files;
|
||||||
|
* -C -C enables copy from existing files, but only
|
||||||
|
* when blaming a new file;
|
||||||
|
* -C -C -C enables copy from existing files for
|
||||||
|
* everybody
|
||||||
|
*/
|
||||||
|
if (*opt & PICKAXE_BLAME_COPY_HARDER)
|
||||||
|
*opt |= PICKAXE_BLAME_COPY_HARDEST;
|
||||||
|
if (*opt & PICKAXE_BLAME_COPY)
|
||||||
|
*opt |= PICKAXE_BLAME_COPY_HARDER;
|
||||||
|
*opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE;
|
||||||
|
|
||||||
|
if (arg)
|
||||||
|
blame_copy_score = parse_score(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int blame_move_callback(const struct option *option, const char *arg, int unset)
|
||||||
|
{
|
||||||
|
int *opt = option->value;
|
||||||
|
|
||||||
|
*opt |= PICKAXE_BLAME_MOVE;
|
||||||
|
|
||||||
|
if (arg)
|
||||||
|
blame_move_score = parse_score(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int blame_bottomtop_callback(const struct option *option, const char *arg, int unset)
|
||||||
|
{
|
||||||
|
const char **bottomtop = option->value;
|
||||||
|
if (!arg)
|
||||||
|
return -1;
|
||||||
|
if (*bottomtop)
|
||||||
|
die("More than one '-L n,m' option given");
|
||||||
|
*bottomtop = arg;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int cmd_blame(int argc, const char **argv, const char *prefix)
|
int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
struct rev_info revs;
|
struct rev_info revs;
|
||||||
|
@ -2226,98 +2262,79 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||||
struct scoreboard sb;
|
struct scoreboard sb;
|
||||||
struct origin *o;
|
struct origin *o;
|
||||||
struct blame_entry *ent;
|
struct blame_entry *ent;
|
||||||
int i, seen_dashdash, unk, opt;
|
int i, seen_dashdash, unk;
|
||||||
long bottom, top, lno;
|
long bottom, top, lno;
|
||||||
int output_option = 0;
|
|
||||||
int show_stats = 0;
|
|
||||||
const char *revs_file = NULL;
|
|
||||||
const char *final_commit_name = NULL;
|
const char *final_commit_name = NULL;
|
||||||
enum object_type type;
|
enum object_type type;
|
||||||
const char *bottomtop = NULL;
|
|
||||||
const char *contents_from = NULL;
|
static const char *bottomtop = NULL;
|
||||||
|
static int output_option = 0, opt = 0;
|
||||||
|
static int show_stats = 0;
|
||||||
|
static const char *revs_file = NULL;
|
||||||
|
static const char *contents_from = NULL;
|
||||||
|
static const struct option options[] = {
|
||||||
|
OPT_BOOLEAN(0, "incremental", &incremental, "Show blame entries as we find them, incrementally"),
|
||||||
|
OPT_BOOLEAN('b', NULL, &blank_boundary, "Show blank SHA-1 for boundary commits (Default: off)"),
|
||||||
|
OPT_BOOLEAN(0, "root", &show_root, "Do not treat root commits as boundaries (Default: off)"),
|
||||||
|
OPT_BOOLEAN(0, "show-stats", &show_stats, "Show work cost statistics"),
|
||||||
|
OPT_BIT(0, "score-debug", &output_option, "Show output score for blame entries", OUTPUT_SHOW_SCORE),
|
||||||
|
OPT_BIT('f', "show-name", &output_option, "Show original filename (Default: auto)", OUTPUT_SHOW_NAME),
|
||||||
|
OPT_BIT('n', "show-number", &output_option, "Show original linenumber (Default: off)", OUTPUT_SHOW_NUMBER),
|
||||||
|
OPT_BIT('p', "porcelain", &output_option, "Show in a format designed for machine consumption", OUTPUT_PORCELAIN),
|
||||||
|
OPT_BIT('c', NULL, &output_option, "Use the same output mode as git-annotate (Default: off)", OUTPUT_ANNOTATE_COMPAT),
|
||||||
|
OPT_BIT('t', NULL, &output_option, "Show raw timestamp (Default: off)", OUTPUT_RAW_TIMESTAMP),
|
||||||
|
OPT_BIT('l', NULL, &output_option, "Show long commit SHA1 (Default: off)", OUTPUT_LONG_OBJECT_NAME),
|
||||||
|
OPT_BIT('s', NULL, &output_option, "Suppress author name and timestamp (Default: off)", OUTPUT_NO_AUTHOR),
|
||||||
|
OPT_BIT('w', NULL, &xdl_opts, "Ignore whitespace differences", XDF_IGNORE_WHITESPACE),
|
||||||
|
OPT_STRING('S', NULL, &revs_file, "file", "Use revisions from <file> instead of calling git-rev-list"),
|
||||||
|
OPT_STRING(0, "contents", &contents_from, "file", "Use <file>'s contents as the final image"),
|
||||||
|
{ OPTION_CALLBACK, 'C', NULL, &opt, "score", "Find line copies within and across files", PARSE_OPT_OPTARG, blame_copy_callback },
|
||||||
|
{ OPTION_CALLBACK, 'M', NULL, &opt, "score", "Find line movements within and across files", PARSE_OPT_OPTARG, blame_move_callback },
|
||||||
|
OPT_CALLBACK('L', NULL, &bottomtop, "n,m", "Process only line range n,m, counting from 1", blame_bottomtop_callback),
|
||||||
|
OPT_END()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct parse_opt_ctx_t ctx;
|
||||||
|
|
||||||
cmd_is_annotate = !strcmp(argv[0], "annotate");
|
cmd_is_annotate = !strcmp(argv[0], "annotate");
|
||||||
|
|
||||||
git_config(git_blame_config, NULL);
|
git_config(git_blame_config, NULL);
|
||||||
|
init_revisions(&revs, NULL);
|
||||||
save_commit_buffer = 0;
|
save_commit_buffer = 0;
|
||||||
|
|
||||||
opt = 0;
|
parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
|
||||||
|
PARSE_OPT_KEEP_ARGV0);
|
||||||
|
for (;;) {
|
||||||
|
int n;
|
||||||
|
|
||||||
|
switch (parse_options_step(&ctx, options, blame_opt_usage)) {
|
||||||
|
case PARSE_OPT_HELP:
|
||||||
|
exit(129);
|
||||||
|
case PARSE_OPT_DONE:
|
||||||
|
goto parse_done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(ctx.argv[0], "--reverse")) {
|
||||||
|
ctx.argv[0] = "--children";
|
||||||
|
reverse = 1;
|
||||||
|
}
|
||||||
|
n = handle_revision_opt(&revs, ctx.argc, ctx.argv,
|
||||||
|
&ctx.cpidx, ctx.out);
|
||||||
|
if (n <= 0) {
|
||||||
|
error("unknown option `%s'", ctx.argv[0]);
|
||||||
|
usage_with_options(blame_opt_usage, options);
|
||||||
|
}
|
||||||
|
ctx.argv += n;
|
||||||
|
ctx.argc -= n;
|
||||||
|
}
|
||||||
|
parse_done:
|
||||||
|
argc = parse_options_end(&ctx);
|
||||||
|
|
||||||
seen_dashdash = 0;
|
seen_dashdash = 0;
|
||||||
for (unk = i = 1; i < argc; i++) {
|
for (unk = i = 1; i < argc; i++) {
|
||||||
const char *arg = argv[i];
|
const char *arg = argv[i];
|
||||||
if (*arg != '-')
|
if (*arg != '-')
|
||||||
break;
|
break;
|
||||||
else if (!strcmp("-b", arg))
|
|
||||||
blank_boundary = 1;
|
|
||||||
else if (!strcmp("--root", arg))
|
|
||||||
show_root = 1;
|
|
||||||
else if (!strcmp("--reverse", arg)) {
|
|
||||||
argv[unk++] = "--children";
|
|
||||||
reverse = 1;
|
|
||||||
}
|
|
||||||
else if (!strcmp(arg, "--show-stats"))
|
|
||||||
show_stats = 1;
|
|
||||||
else if (!strcmp("-c", arg))
|
|
||||||
output_option |= OUTPUT_ANNOTATE_COMPAT;
|
|
||||||
else if (!strcmp("-t", arg))
|
|
||||||
output_option |= OUTPUT_RAW_TIMESTAMP;
|
|
||||||
else if (!strcmp("-l", arg))
|
|
||||||
output_option |= OUTPUT_LONG_OBJECT_NAME;
|
|
||||||
else if (!strcmp("-s", arg))
|
|
||||||
output_option |= OUTPUT_NO_AUTHOR;
|
|
||||||
else if (!strcmp("-w", arg))
|
|
||||||
xdl_opts |= XDF_IGNORE_WHITESPACE;
|
|
||||||
else if (!strcmp("-S", arg) && ++i < argc)
|
|
||||||
revs_file = argv[i];
|
|
||||||
else if (!prefixcmp(arg, "-M")) {
|
|
||||||
opt |= PICKAXE_BLAME_MOVE;
|
|
||||||
blame_move_score = parse_score(arg+2);
|
|
||||||
}
|
|
||||||
else if (!prefixcmp(arg, "-C")) {
|
|
||||||
/*
|
|
||||||
* -C enables copy from removed files;
|
|
||||||
* -C -C enables copy from existing files, but only
|
|
||||||
* when blaming a new file;
|
|
||||||
* -C -C -C enables copy from existing files for
|
|
||||||
* everybody
|
|
||||||
*/
|
|
||||||
if (opt & PICKAXE_BLAME_COPY_HARDER)
|
|
||||||
opt |= PICKAXE_BLAME_COPY_HARDEST;
|
|
||||||
if (opt & PICKAXE_BLAME_COPY)
|
|
||||||
opt |= PICKAXE_BLAME_COPY_HARDER;
|
|
||||||
opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE;
|
|
||||||
blame_copy_score = parse_score(arg+2);
|
|
||||||
}
|
|
||||||
else if (!prefixcmp(arg, "-L")) {
|
|
||||||
if (!arg[2]) {
|
|
||||||
if (++i >= argc)
|
|
||||||
usage(blame_usage);
|
|
||||||
arg = argv[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
arg += 2;
|
|
||||||
if (bottomtop)
|
|
||||||
die("More than one '-L n,m' option given");
|
|
||||||
bottomtop = arg;
|
|
||||||
}
|
|
||||||
else if (!strcmp("--contents", arg)) {
|
|
||||||
if (++i >= argc)
|
|
||||||
usage(blame_usage);
|
|
||||||
contents_from = argv[i];
|
|
||||||
}
|
|
||||||
else if (!strcmp("--incremental", arg))
|
|
||||||
incremental = 1;
|
|
||||||
else if (!strcmp("--score-debug", arg))
|
|
||||||
output_option |= OUTPUT_SHOW_SCORE;
|
|
||||||
else if (!strcmp("-f", arg) ||
|
|
||||||
!strcmp("--show-name", arg))
|
|
||||||
output_option |= OUTPUT_SHOW_NAME;
|
|
||||||
else if (!strcmp("-n", arg) ||
|
|
||||||
!strcmp("--show-number", arg))
|
|
||||||
output_option |= OUTPUT_SHOW_NUMBER;
|
|
||||||
else if (!strcmp("-p", arg) ||
|
|
||||||
!strcmp("--porcelain", arg))
|
|
||||||
output_option |= OUTPUT_PORCELAIN;
|
|
||||||
else if (!strcmp("--", arg)) {
|
else if (!strcmp("--", arg)) {
|
||||||
seen_dashdash = 1;
|
seen_dashdash = 1;
|
||||||
i++;
|
i++;
|
||||||
|
@ -2364,16 +2381,16 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||||
if (seen_dashdash) {
|
if (seen_dashdash) {
|
||||||
/* (1) */
|
/* (1) */
|
||||||
if (argc <= i)
|
if (argc <= i)
|
||||||
usage(blame_usage);
|
usage_with_options(blame_opt_usage, options);
|
||||||
path = add_prefix(prefix, argv[i]);
|
path = add_prefix(prefix, argv[i]);
|
||||||
if (i + 1 == argc - 1) {
|
if (i + 1 == argc - 1) {
|
||||||
if (unk != 1)
|
if (unk != 1)
|
||||||
usage(blame_usage);
|
usage_with_options(blame_opt_usage, options);
|
||||||
argv[unk++] = argv[i + 1];
|
argv[unk++] = argv[i + 1];
|
||||||
}
|
}
|
||||||
else if (i + 1 != argc)
|
else if (i + 1 != argc)
|
||||||
/* garbage at end */
|
/* garbage at end */
|
||||||
usage(blame_usage);
|
usage_with_options(blame_opt_usage, options);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int j;
|
int j;
|
||||||
|
@ -2383,7 +2400,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||||
if (seen_dashdash) {
|
if (seen_dashdash) {
|
||||||
/* (2) */
|
/* (2) */
|
||||||
if (seen_dashdash + 1 != argc - 1)
|
if (seen_dashdash + 1 != argc - 1)
|
||||||
usage(blame_usage);
|
usage_with_options(blame_opt_usage, options);
|
||||||
path = add_prefix(prefix, argv[seen_dashdash + 1]);
|
path = add_prefix(prefix, argv[seen_dashdash + 1]);
|
||||||
for (j = i; j < seen_dashdash; j++)
|
for (j = i; j < seen_dashdash; j++)
|
||||||
argv[unk++] = argv[j];
|
argv[unk++] = argv[j];
|
||||||
|
@ -2391,7 +2408,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||||
else {
|
else {
|
||||||
/* (3) */
|
/* (3) */
|
||||||
if (argc <= i)
|
if (argc <= i)
|
||||||
usage(blame_usage);
|
usage_with_options(blame_opt_usage, options);
|
||||||
path = add_prefix(prefix, argv[i]);
|
path = add_prefix(prefix, argv[i]);
|
||||||
if (i + 1 == argc - 1) {
|
if (i + 1 == argc - 1) {
|
||||||
final_commit_name = argv[i + 1];
|
final_commit_name = argv[i + 1];
|
||||||
|
@ -2405,7 +2422,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (i != argc - 1)
|
else if (i != argc - 1)
|
||||||
usage(blame_usage); /* garbage at end */
|
usage_with_options(blame_opt_usage, options);
|
||||||
|
|
||||||
setup_work_tree();
|
setup_work_tree();
|
||||||
if (!has_path_in_work_tree(path))
|
if (!has_path_in_work_tree(path))
|
||||||
|
@ -2424,7 +2441,6 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||||
argv[unk++] = "--"; /* terminate the rev name */
|
argv[unk++] = "--"; /* terminate the rev name */
|
||||||
argv[unk] = NULL;
|
argv[unk] = NULL;
|
||||||
|
|
||||||
init_revisions(&revs, NULL);
|
|
||||||
setup_revisions(unk, argv, &revs, NULL);
|
setup_revisions(unk, argv, &revs, NULL);
|
||||||
memset(&sb, 0, sizeof(sb));
|
memset(&sb, 0, sizeof(sb));
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче