git-blame: migrate to incremental parse-option [1/2]
authorPierre Habouzit <madcoder@debian.org>
Tue, 8 Jul 2008 13:19:34 +0000 (15:19 +0200)
committerJunio C Hamano <gitster@pobox.com>
Tue, 8 Jul 2008 22:40:51 +0000 (15:40 -0700)
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>
builtin-blame.c

index cf41511c798330a7e0ec02db5785747ad2b662a5..5e82cd3d54c4013e29e3b502f01ce1e5af968507 100644 (file)
 #include "cache-tree.h"
 #include "path-list.h"
 #include "mailmap.h"
+#include "parse-options.h"
 
-static char blame_usage[] =
-"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"
-"  -b                  Show blank SHA-1 for boundary commits (Default: off)\n"
-"  -l                  Show long commit SHA1 (Default: off)\n"
-"  --root              Do not treat root commits as boundaries (Default: off)\n"
-"  -t                  Show raw timestamp (Default: off)\n"
-"  -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 char blame_usage[] = "git-blame [options] [rev-opts] [rev] [--] file";
+
+static const char *blame_opt_usage[] = {
+       blame_usage,
+       "",
+       "[rev-opts] are documented in git-rev-parse(1)",
+       NULL
+};
 
 static int longest_file;
 static int longest_author;
@@ -2219,6 +2211,50 @@ static const char *prepare_initial(struct scoreboard *sb)
        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)
 {
        struct rev_info revs;
@@ -2226,98 +2262,79 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
        struct scoreboard sb;
        struct origin *o;
        struct blame_entry *ent;
-       int i, seen_dashdash, unk, opt;
+       int i, seen_dashdash, unk;
        long bottom, top, lno;
-       int output_option = 0;
-       int show_stats = 0;
-       const char *revs_file = NULL;
        const char *final_commit_name = NULL;
        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");
 
        git_config(git_blame_config, NULL);
+       init_revisions(&revs, NULL);
        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;
        for (unk = i = 1; i < argc; i++) {
                const char *arg = argv[i];
                if (*arg != '-')
                        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)) {
                        seen_dashdash = 1;
                        i++;
@@ -2364,16 +2381,16 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
        if (seen_dashdash) {
                /* (1) */
                if (argc <= i)
-                       usage(blame_usage);
+                       usage_with_options(blame_opt_usage, options);
                path = add_prefix(prefix, argv[i]);
                if (i + 1 == argc - 1) {
                        if (unk != 1)
-                               usage(blame_usage);
+                               usage_with_options(blame_opt_usage, options);
                        argv[unk++] = argv[i + 1];
                }
                else if (i + 1 != argc)
                        /* garbage at end */
-                       usage(blame_usage);
+                       usage_with_options(blame_opt_usage, options);
        }
        else {
                int j;
@@ -2383,7 +2400,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
                if (seen_dashdash) {
                        /* (2) */
                        if (seen_dashdash + 1 != argc - 1)
-                               usage(blame_usage);
+                               usage_with_options(blame_opt_usage, options);
                        path = add_prefix(prefix, argv[seen_dashdash + 1]);
                        for (j = i; j < seen_dashdash; j++)
                                argv[unk++] = argv[j];
@@ -2391,7 +2408,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
                else {
                        /* (3) */
                        if (argc <= i)
-                               usage(blame_usage);
+                               usage_with_options(blame_opt_usage, options);
                        path = add_prefix(prefix, argv[i]);
                        if (i + 1 == argc - 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)
-                               usage(blame_usage); /* garbage at end */
+                               usage_with_options(blame_opt_usage, options);
 
                        setup_work_tree();
                        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] = NULL;
 
-       init_revisions(&revs, NULL);
        setup_revisions(unk, argv, &revs, NULL);
        memset(&sb, 0, sizeof(sb));