mirror of
https://github.com/git/git.git
synced 2026-03-12 09:59:45 +01:00
Refactor parse_loc
Both 'git blame -L' and 'git log -L' parse the same style of line number arguments, so put the 'parse_loc' function to line.c and export it. The caller of parse_loc should provide a callback function which is used to calculate the start position of the nth line. Other parts such as regexp search, line number parsing are abstracted and re-used. Note that, we can use '$' to specify the last line of a file. Signed-off-by: Bo Yang <struggleyb.nku@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include "parse-options.h"
|
||||
#include "utf8.h"
|
||||
#include "userdiff.h"
|
||||
#include "line.h"
|
||||
|
||||
static char blame_usage[] = "git blame [options] [rev-opts] [rev] [--] file";
|
||||
|
||||
@@ -541,11 +542,16 @@ static void dup_entry(struct blame_entry *dst, struct blame_entry *src)
|
||||
dst->score = 0;
|
||||
}
|
||||
|
||||
static const char *nth_line(struct scoreboard *sb, int lno)
|
||||
static const char *nth_line(struct scoreboard *sb, long lno)
|
||||
{
|
||||
return sb->final_buf + sb->lineno[lno];
|
||||
}
|
||||
|
||||
static const char *nth_line_cb(void *data, long lno)
|
||||
{
|
||||
return nth_line((struct scoreboard *)data, lno);
|
||||
}
|
||||
|
||||
/*
|
||||
* It is known that lines between tlno to same came from parent, and e
|
||||
* has an overlap with that range. it also is known that parent's
|
||||
@@ -1906,83 +1912,6 @@ static const char *add_prefix(const char *prefix, const char *path)
|
||||
return prefix_path(prefix, prefix ? strlen(prefix) : 0, path);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parsing of (comma separated) one item in the -L option
|
||||
*/
|
||||
static const char *parse_loc(const char *spec,
|
||||
struct scoreboard *sb, long lno,
|
||||
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(sb, 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++ < lno) {
|
||||
nline = nth_line(sb, 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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parsing of -L option
|
||||
*/
|
||||
@@ -1993,9 +1922,9 @@ static void prepare_blame_range(struct scoreboard *sb,
|
||||
{
|
||||
const char *term;
|
||||
|
||||
term = parse_loc(bottomtop, sb, lno, 1, bottom);
|
||||
term = parse_loc(bottomtop, nth_line_cb, sb, lno, 1, bottom);
|
||||
if (*term == ',') {
|
||||
term = parse_loc(term + 1, sb, lno, *bottom + 1, top);
|
||||
term = parse_loc(term + 1, nth_line_cb, sb, lno, *bottom + 1, top);
|
||||
if (*term)
|
||||
usage(blame_usage);
|
||||
}
|
||||
|
||||
52
line.c
52
line.c
@@ -95,25 +95,29 @@ static void fill_line_ends(struct diff_filespec *spec, long *lines,
|
||||
*line_ends = ends;
|
||||
}
|
||||
|
||||
static const char *nth_line(struct diff_filespec *spec, long line,
|
||||
long lines, unsigned long *line_ends)
|
||||
struct nth_line_cb {
|
||||
struct diff_filespec *spec;
|
||||
long lines;
|
||||
unsigned long *line_ends;
|
||||
};
|
||||
|
||||
static const char *nth_line(void *data, long line)
|
||||
{
|
||||
assert(line < lines);
|
||||
assert(spec && spec->data);
|
||||
struct nth_line_cb *d = data;
|
||||
assert(d && line < d->lines);
|
||||
assert(d->spec && d->spec->data);
|
||||
|
||||
if (line == 0)
|
||||
return (char *)spec->data;
|
||||
return (char *)d->spec->data;
|
||||
else
|
||||
return (char *)spec->data + line_ends[line] + 1;
|
||||
return (char *)d->spec->data + d->line_ends[line] + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* copied from blame.c, indeed, we can even to use this to test
|
||||
* whether line log works. :)
|
||||
* Parsing of (comma separated) one item in the -L option
|
||||
*/
|
||||
static const char *parse_loc(const char *spec, struct diff_filespec *file,
|
||||
long lines, unsigned long *line_ends,
|
||||
long begin, long *ret)
|
||||
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;
|
||||
@@ -122,6 +126,13 @@ static const char *parse_loc(const char *spec, struct diff_filespec *file,
|
||||
regex_t regexp;
|
||||
regmatch_t match[1];
|
||||
|
||||
/* Catch the '$' matcher, now it is used to match the last
|
||||
* line of the file. */
|
||||
if (spec[0] == '$') {
|
||||
*ret = lines;
|
||||
return spec + 1;
|
||||
}
|
||||
|
||||
/* Allow "-L <something>,+20" to mean starting at <something>
|
||||
* for 20 lines, or "-L <something>,-5" for 5 lines ending at
|
||||
* <something>.
|
||||
@@ -160,7 +171,7 @@ static const char *parse_loc(const char *spec, struct diff_filespec *file,
|
||||
/* try [spec+1 .. term-1] as regexp */
|
||||
*term = 0;
|
||||
begin--; /* input is in human terms */
|
||||
line = nth_line(file, begin, lines, line_ends);
|
||||
line = nth_line(data, begin);
|
||||
|
||||
if (!(reg_error = regcomp(®exp, spec + 1, REG_NEWLINE)) &&
|
||||
!(reg_error = regexec(®exp, line, 1, match, 0))) {
|
||||
@@ -168,7 +179,7 @@ static const char *parse_loc(const char *spec, struct diff_filespec *file,
|
||||
const char *nline;
|
||||
|
||||
while (begin++ < lines) {
|
||||
nline = nth_line(file, begin, lines, line_ends);
|
||||
nline = nth_line(data, begin);
|
||||
if (line <= cp && cp < nline)
|
||||
break;
|
||||
line = nline;
|
||||
@@ -188,10 +199,11 @@ static void parse_range(long lines, unsigned long *line_ends,
|
||||
struct line_range *r, struct diff_filespec *spec)
|
||||
{
|
||||
const char *term;
|
||||
struct nth_line_cb data = {spec, lines, line_ends};
|
||||
|
||||
term = parse_loc(r->arg, spec, lines, line_ends, 1, &r->start);
|
||||
term = parse_loc(r->arg, nth_line, &data, lines - 1, 1, &r->start);
|
||||
if (*term == ',') {
|
||||
term = parse_loc(term + 1, spec, lines, line_ends,
|
||||
term = parse_loc(term + 1, nth_line, &data, lines - 1,
|
||||
r->start + 1, &r->end);
|
||||
if (*term)
|
||||
die("-L parameter's argument should be <start>,<end>");
|
||||
@@ -200,16 +212,16 @@ static void parse_range(long lines, unsigned long *line_ends,
|
||||
if (*term)
|
||||
die("-L parameter's argument should be <start>,<end>");
|
||||
|
||||
if (r->start < 1)
|
||||
r->start = 1;
|
||||
if (r->end >= lines)
|
||||
r->end = lines - 1;
|
||||
|
||||
if (r->start > r->end) {
|
||||
long tmp = r->start;
|
||||
r->start = r->end;
|
||||
r->end = tmp;
|
||||
}
|
||||
|
||||
if (r->start < 1)
|
||||
r->start = 1;
|
||||
if (r->end >= lines)
|
||||
r->end = lines - 1;
|
||||
}
|
||||
|
||||
static void parse_lines(struct commit *commit, struct diff_line_range *r)
|
||||
|
||||
5
line.h
5
line.h
@@ -8,6 +8,8 @@ struct commit;
|
||||
struct diff_line_range;
|
||||
struct diff_options;
|
||||
|
||||
typedef const char *(*nth_line_fn_t)(void *data, long lno);
|
||||
|
||||
struct print_range {
|
||||
int start, end; /* Line range of post-image */
|
||||
int pstart, pend; /* Line range of pre-image */
|
||||
@@ -125,4 +127,7 @@ extern void add_line_range(struct rev_info *revs, struct commit *commit,
|
||||
extern struct diff_line_range *lookup_line_range(struct rev_info *revs,
|
||||
struct commit *commit);
|
||||
|
||||
const char *parse_loc(const char *spec, nth_line_fn_t nth_line,
|
||||
void *data, long lines, long begin, long *ret);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user