{"thread":{"id":"43068","subject":"[PATCH] git-pickaxe: -L /regexp/,/regexp/","startedAt":"2006-11-07T01:57:33Z","lastAt":"2006-11-07T01:57:33Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"293805","messageId":"7vmz749fxu.fsf@assigned-by-dhcp.cox.net","threadId":"43068","inReplyTo":null,"subject":"[PATCH] git-pickaxe: -L /regexp/,/regexp/","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-07T01:57:33Z","receivedAt":"2006-11-07T01:57:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"With this change, you can specify the beginning and the ending\nline of the range you wish to inspect with pattern matching.\n\nFor example, these are equivalent with the git.git sources:\n\n    git pickaxe -L 7,21                       v1.4.0 -- commit.c\n    git pickaxe -L '/^struct sort_node/,/^}/' v1.4.0 -- commit.c\n    git pickaxe -L '7,/^}/'                   v1.4.0 -- commit.c\n    git pickaxe -L '/^struct sort_node/,21'   v1.4.0 -- commit.c\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n * Pasky, the other day I overheard that you were moaning about\n   git-annotate using -S to mean something other than pickaxe,\n   and git-pickaxe needed to stay compatible with it.  I think\n   this is a better way to do what you wanted.\n\n builtin-pickaxe.c |  103 ++++++++++++++++++++++++++++++++++++++++++++++-------\n 1 files changed, 90 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin-pickaxe.c b/builtin-pickaxe.c\nindex f45edbd..007b1b8 100644\n--- a/builtin-pickaxe.c\n+++ b/builtin-pickaxe.c\n@@ -17,6 +17,7 @@\n \n #include <time.h>\n #include <sys/time.h>\n+#include <regex.h>\n \n static char pickaxe_usage[] =\n \"git-pickaxe [-c] [-l] [-t] [-f] [-n] [-p] [-L n,m] [-S <revs-file>] [-M] [-C] [-C] [commit] [--] file\\n\"\n@@ -1533,6 +1534,85 @@ static const char *add_prefix(const char\n \treturn prefix_path(prefix, strlen(prefix), path);\n }\n \n+static const char *parse_loc(const char *spec,\n+\t\t\t     struct scoreboard *sb, long lno,\n+\t\t\t     long begin, long *ret)\n+{\n+\tchar *term;\n+\tconst char *line;\n+\tlong num;\n+\tregex_t regexp;\n+\n+\tnum = strtol(spec, &term, 10);\n+\tif (term != spec) {\n+\t\t*ret = num;\n+\t\treturn term;\n+\t}\n+\n+\tif (spec[0] != '/')\n+\t\treturn spec;\n+\n+\t/* it could be a regexp of form /.../ */\n+\tfor (term = (char*) spec + 1; *term && *term != '/'; term++) {\n+\t\tif (*term == '\\\\')\n+\t\t\tterm++;\n+\t}\n+\tif (*term != '/')\n+\t\treturn spec;\n+\t/* try [spec+1 .. term-1] as regexp */\n+\t*term = 0;\n+\tif (regcomp(&regexp, spec + 1, REG_NEWLINE)) {\n+\t\t/* not a regexp */\n+\terror_return:\n+\t\tregfree(&regexp);\n+\t\t*term = '/';\n+\t\treturn spec;\n+\t}\n+\n+\t/* Now find the first line that matches the regexp, after\n+\t * line \"begin\" in sb->final_buf.\n+\t */\n+\twhile (begin < lno) {\n+\t\tchar *nline;\n+\t\tint hit;\n+\n+\t\tbegin++;\n+\t\tline = nth_line(sb, begin);\n+\t\tif (begin < lno) {\n+\t\t\tnline = (char*) nth_line(sb, begin+1);\n+\t\t\tnline[-1] = 0;\n+\t\t}\n+\t\thit = regexec(&regexp, line, 0, NULL, 0);\n+\t\tif (begin < lno)\n+\t\t\tnline[-1] = '\\n';\n+\t\tif (!hit) {\n+\t\t\t/* lines count from 1 in UI terms */\n+\t\t\t*ret = begin + 1;\n+\t\t\tregfree(&regexp);\n+\t\t\t*term++ = '/';\n+\t\t\treturn term;\n+\t\t}\n+\t}\n+\tgoto error_return;\n+}\n+\n+static void prepare_blame_range(struct scoreboard *sb,\n+\t\t\t\tconst char *bottomtop,\n+\t\t\t\tlong lno,\n+\t\t\t\tlong *bottom, long *top)\n+{\n+\tconst char *term;\n+\n+\tterm = parse_loc(bottomtop, sb, lno, 0, bottom);\n+\tif (*term == ',') {\n+\t\tterm = parse_loc(term + 1, sb, lno, *bottom + 1, top);\n+\t\tif (*term)\n+\t\t\tusage(pickaxe_usage);\n+\t}\n+\tif (*term)\n+\t\tusage(pickaxe_usage);\n+}\n+\n int cmd_pickaxe(int argc, const char **argv, const char *prefix)\n {\n \tstruct rev_info revs;\n@@ -1547,11 +1627,11 @@ int cmd_pickaxe(int argc, const char **a\n \tconst char *revs_file = NULL;\n \tconst char *final_commit_name = NULL;\n \tchar type[10];\n+\tconst char *bottomtop = NULL;\n \n \tsave_commit_buffer = 0;\n \n \topt = 0;\n-\tbottom = top = 0;\n \tseen_dashdash = 0;\n \tfor (unk = i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n@@ -1578,7 +1658,6 @@ int cmd_pickaxe(int argc, const char **a\n \t\t\tblame_copy_score = parse_score(arg+2);\n \t\t}\n \t\telse if (!strncmp(\"-L\", arg, 2)) {\n-\t\t\tchar *term;\n \t\t\tif (!arg[2]) {\n \t\t\t\tif (++i >= argc)\n \t\t\t\t\tusage(pickaxe_usage);\n@@ -1586,18 +1665,9 @@ int cmd_pickaxe(int argc, const char **a\n \t\t\t}\n \t\t\telse\n \t\t\t\targ += 2;\n-\t\t\tif (bottom || top)\n+\t\t\tif (bottomtop)\n \t\t\t\tdie(\"More than one '-L n,m' option given\");\n-\t\t\tbottom = strtol(arg, &term, 10);\n-\t\t\tif (*term == ',') {\n-\t\t\t\ttop = strtol(term + 1, &term, 10);\n-\t\t\t\tif (*term)\n-\t\t\t\t\tusage(pickaxe_usage);\n-\t\t\t}\n-\t\t\tif (bottom && top && top < bottom) {\n-\t\t\t\tunsigned long tmp;\n-\t\t\t\ttmp = top; top = bottom; bottom = tmp;\n-\t\t\t}\n+\t\t\tbottomtop = arg;\n \t\t}\n \t\telse if (!strcmp(\"--score-debug\", arg))\n \t\t\toutput_option |= OUTPUT_SHOW_SCORE;\n@@ -1758,6 +1828,13 @@ int cmd_pickaxe(int argc, const char **a\n \tnum_read_blob++;\n \tlno = prepare_lines(&sb);\n \n+\tbottom = top = 0;\n+\tif (bottomtop)\n+\t\tprepare_blame_range(&sb, bottomtop, lno, &bottom, &top);\n+\tif (bottom && top && top < bottom) {\n+\t\tlong tmp;\n+\t\ttmp = top; top = bottom; bottom = tmp;\n+\t}\n \tif (bottom < 1)\n \t\tbottom = 1;\n \tif (top < 1)\n-- \n1.4.3.4.g9f05\n\n"}]}