#include <time.h>
#include <sys/time.h>
+#include <regex.h>
static char pickaxe_usage[] =
"git-pickaxe [-c] [-l] [-t] [-f] [-n] [-p] [-L n,m] [-S <revs-file>] [-M] [-C] [-C] [commit] [--] file\n"
return prefix_path(prefix, strlen(prefix), path);
}
+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];
+
+ 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);
+ }
+}
+
+static void prepare_blame_range(struct scoreboard *sb,
+ const char *bottomtop,
+ long lno,
+ long *bottom, long *top)
+{
+ const char *term;
+
+ term = parse_loc(bottomtop, sb, lno, 1, bottom);
+ if (*term == ',') {
+ term = parse_loc(term + 1, sb, lno, *bottom + 1, top);
+ if (*term)
+ usage(pickaxe_usage);
+ }
+ if (*term)
+ usage(pickaxe_usage);
+}
+
int cmd_pickaxe(int argc, const char **argv, const char *prefix)
{
struct rev_info revs;
const char *revs_file = NULL;
const char *final_commit_name = NULL;
char type[10];
+ const char *bottomtop = NULL;
save_commit_buffer = 0;
opt = 0;
- bottom = top = 0;
seen_dashdash = 0;
for (unk = i = 1; i < argc; i++) {
const char *arg = argv[i];
blame_copy_score = parse_score(arg+2);
}
else if (!strncmp("-L", arg, 2)) {
- char *term;
if (!arg[2]) {
if (++i >= argc)
usage(pickaxe_usage);
}
else
arg += 2;
- if (bottom || top)
+ if (bottomtop)
die("More than one '-L n,m' option given");
- bottom = strtol(arg, &term, 10);
- if (*term == ',') {
- top = strtol(term + 1, &term, 10);
- if (*term)
- usage(pickaxe_usage);
- }
- if (bottom && top && top < bottom) {
- unsigned long tmp;
- tmp = top; top = bottom; bottom = tmp;
- }
+ bottomtop = arg;
}
else if (!strcmp("--score-debug", arg))
output_option |= OUTPUT_SHOW_SCORE;
num_read_blob++;
lno = prepare_lines(&sb);
+ bottom = top = 0;
+ if (bottomtop)
+ prepare_blame_range(&sb, bottomtop, lno, &bottom, &top);
+ if (bottom && top && top < bottom) {
+ long tmp;
+ tmp = top; top = bottom; bottom = tmp;
+ }
if (bottom < 1)
bottom = 1;
if (top < 1)