-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
We want to use the same style of -L n,m argument for 'git log -L' as for git-blame. Refactor the argument parsing of the range arguments from builtin/blame.c to the (new) file that will hold the 'git log -L' logic. To accommodate different data structures in blame and log -L, the file contents are abstracted away; parse_range_arg takes a callback that it uses to get the contents of a line of the (notional) file. The new test is for a case that made me pause during debugging: the 'blame -L with invalid end' test was the only one that noticed an outright failure to parse the end *at all*. So make a more explicit test for that. Signed-off-by: Bo Yang <struggleyb.nku@gmail.com> Signed-off-by: Thomas Rast <trast@student.ethz.ch> Signed-off-by: Junio C Hamano <gitster@pobox.com>
- Loading branch information
Bo Yang
authored and
Junio C Hamano
committed
Mar 28, 2013
1 parent
443d803
commit 25ed341
Showing
7 changed files
with
151 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
- number | ||
+ | ||
If <start> or <end> is a number, it specifies an | ||
absolute line number (lines count from 1). | ||
+ | ||
|
||
- /regex/ | ||
+ | ||
This form will use the first line matching the given | ||
POSIX regex. If <end> is a regex, it will search | ||
starting at the line given by <start>. | ||
+ | ||
|
||
- +offset or -offset | ||
+ | ||
This is only valid for <end> and will specify a number | ||
of lines before or after the line given by <start>. | ||
+ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
#include "git-compat-util.h" | ||
#include "line-range.h" | ||
|
||
/* | ||
* Parse one item in the -L option | ||
*/ | ||
static const char *parse_loc(const char *spec, nth_line_fn_t nth_line, | ||
void *data, long lines, long begin, long *ret) | ||
{ | ||
char *term; | ||
const char *line; | ||
long num; | ||
int reg_error; | ||
regex_t regexp; | ||
regmatch_t match[1]; | ||
|
||
/* Allow "-L <something>,+20" to mean starting at <something> | ||
* for 20 lines, or "-L <something>,-5" for 5 lines ending at | ||
* <something>. | ||
*/ | ||
if (1 < begin && (spec[0] == '+' || spec[0] == '-')) { | ||
num = strtol(spec + 1, &term, 10); | ||
if (term != spec + 1) { | ||
if (spec[0] == '-') | ||
num = 0 - num; | ||
if (0 < num) | ||
*ret = begin + num - 2; | ||
else if (!num) | ||
*ret = begin; | ||
else | ||
*ret = begin + num; | ||
return term; | ||
} | ||
return spec; | ||
} | ||
num = strtol(spec, &term, 10); | ||
if (term != spec) { | ||
*ret = num; | ||
return term; | ||
} | ||
if (spec[0] != '/') | ||
return spec; | ||
|
||
/* it could be a regexp of form /.../ */ | ||
for (term = (char *) spec + 1; *term && *term != '/'; term++) { | ||
if (*term == '\\') | ||
term++; | ||
} | ||
if (*term != '/') | ||
return spec; | ||
|
||
/* try [spec+1 .. term-1] as regexp */ | ||
*term = 0; | ||
begin--; /* input is in human terms */ | ||
line = nth_line(data, begin); | ||
|
||
if (!(reg_error = regcomp(®exp, spec + 1, REG_NEWLINE)) && | ||
!(reg_error = regexec(®exp, line, 1, match, 0))) { | ||
const char *cp = line + match[0].rm_so; | ||
const char *nline; | ||
|
||
while (begin++ < lines) { | ||
nline = nth_line(data, begin); | ||
if (line <= cp && cp < nline) | ||
break; | ||
line = nline; | ||
} | ||
*ret = begin; | ||
regfree(®exp); | ||
*term++ = '/'; | ||
return term; | ||
} | ||
else { | ||
char errbuf[1024]; | ||
regerror(reg_error, ®exp, errbuf, 1024); | ||
die("-L parameter '%s': %s", spec + 1, errbuf); | ||
} | ||
} | ||
|
||
int parse_range_arg(const char *arg, nth_line_fn_t nth_line_cb, | ||
void *cb_data, long lines, long *begin, long *end) | ||
{ | ||
arg = parse_loc(arg, nth_line_cb, cb_data, lines, 1, begin); | ||
|
||
if (*arg == ',') | ||
arg = parse_loc(arg + 1, nth_line_cb, cb_data, lines, *begin + 1, end); | ||
|
||
if (*arg) | ||
return -1; | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#ifndef LINE_RANGE_H | ||
#define LINE_RANGE_H | ||
|
||
/* | ||
* Parse one item in an -L begin,end option w.r.t. the notional file | ||
* object 'cb_data' consisting of 'lines' lines. | ||
* | ||
* The 'nth_line_cb' callback is used to determine the start of the | ||
* line 'lno' inside the 'cb_data'. The caller is expected to already | ||
* have a suitable map at hand to make this a constant-time lookup. | ||
* | ||
* Returns 0 in case of success and -1 if there was an error. The | ||
* actual range is stored in *begin and *end. The counting starts | ||
* at 1! In case of error, the caller should show usage message. | ||
*/ | ||
|
||
typedef const char *(*nth_line_fn_t)(void *data, long lno); | ||
|
||
extern int parse_range_arg(const char *arg, | ||
nth_line_fn_t nth_line_cb, | ||
void *cb_data, long lines, | ||
long *begin, long *end); | ||
|
||
#endif /* LINE_RANGE_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters