Skip to content

Commit

Permalink
Merge branch 'tr/line-log'
Browse files Browse the repository at this point in the history
* tr/line-log:
  git-log(1): remove --full-line-diff description
  line-log: fix documentation formatting
  log -L: improve comments in process_all_files()
  log -L: store the path instead of a diff_filespec
  log -L: test merge of parallel modify/rename
  t4211: pass -M to 'git log -M -L...' test
  log -L: fix overlapping input ranges
  log -L: check range set invariants when we look it up
  Speed up log -L... -M
  log -L: :pattern:file syntax to find by funcname
  Implement line-history search (git log -L)
  Export rewrite_parents() for 'log -L'
  Refactor parse_loc
  • Loading branch information
Junio C Hamano committed Jun 2, 2013
2 parents 4de1179 + 4999266 commit ed73fe5
Show file tree
Hide file tree
Showing 31 changed files with 3,374 additions and 123 deletions.
21 changes: 2 additions & 19 deletions Documentation/blame-options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,11 @@
--show-stats::
Include additional statistics at the end of blame output.

-L <start>,<end>::
-L <start>,<end>, -L :<regex>::
Annotate only the given line range. <start> and <end> can take
one of these forms:

- 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>.
+
include::line-range-format.txt[]

-l::
Show long rev (Default: off).
Expand Down
6 changes: 3 additions & 3 deletions Documentation/git-blame.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ git-blame - Show what revision and author last modified each line of a file
SYNOPSIS
--------
[verse]
'git blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-e] [-p] [-w] [--incremental] [-L n,m]
[-S <revs-file>] [-M] [-C] [-C] [-C] [--since=<date>] [--abbrev=<n>]
[<rev> | --contents <file> | --reverse <rev>] [--] <file>
'git blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-e] [-p] [-w] [--incremental]
[-L n,m | -L :fn] [-S <revs-file>] [-M] [-C] [-C] [-C] [--since=<date>]
[--abbrev=<n>] [<rev> | --contents <file> | --reverse <rev>] [--] <file>

DESCRIPTION
-----------
Expand Down
18 changes: 18 additions & 0 deletions Documentation/git-log.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ produced by --stat etc.
Note that only message is considered, if also a diff is shown
its size is not included.

-L <start>,<end>:<file>, -L :<regex>:<file>::

Trace the evolution of the line range given by "<start>,<end>"
(or the funcname regex <regex>) within the <file>. You may
not give any pathspec limiters. This is currently limited to
a walk starting from a single revision, i.e., you may only
give zero or one positive revision arguments.
You can specify this option more than once.
+
<start> and <end> can take one of these forms:

include::line-range-format.txt[]

<revision range>::
Show only commits in the specified revision range. When no
<revision range> is specified, it defaults to `HEAD` (i.e. the
Expand Down Expand Up @@ -140,6 +153,11 @@ Examples
This makes sense only when following a strict policy of merging all
topic branches when staying on a single integration branch.

git log -L '/int main/',/^}/:main.c::

Shows how the function `main()` in the file 'main.c' evolved
over time.

`git log -3`::
Limits the number of commits to show to 3.

Expand Down
25 changes: 25 additions & 0 deletions Documentation/line-range-format.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
- 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>.
+

- :regex
+
If the option's argument is of the form :regex, it denotes the range
from the first funcname line that matches <regex>, up to the next
funcname line.
+
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,8 @@ LIB_H += help.h
LIB_H += http.h
LIB_H += kwset.h
LIB_H += levenshtein.h
LIB_H += line-log.h
LIB_H += line-range.h
LIB_H += list-objects.h
LIB_H += ll-merge.h
LIB_H += log-tree.h
Expand Down Expand Up @@ -808,6 +810,8 @@ LIB_OBJS += hex.o
LIB_OBJS += ident.o
LIB_OBJS += kwset.o
LIB_OBJS += levenshtein.o
LIB_OBJS += line-log.o
LIB_OBJS += line-range.o
LIB_OBJS += list-objects.o
LIB_OBJS += ll-merge.o
LIB_OBJS += lockfile.o
Expand Down
99 changes: 8 additions & 91 deletions builtin/blame.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "parse-options.h"
#include "utf8.h"
#include "userdiff.h"
#include "line-range.h"

static char blame_usage[] = N_("git blame [options] [rev-opts] [rev] [--] file");

Expand Down Expand Up @@ -566,11 +567,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
Expand Down Expand Up @@ -1931,83 +1937,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(&regexp, spec + 1, REG_NEWLINE)) &&
!(reg_error = regexec(&regexp, 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(&regexp);
*term++ = '/';
return term;
}
else {
char errbuf[1024];
regerror(reg_error, &regexp, errbuf, 1024);
die("-L parameter '%s': %s", spec + 1, errbuf);
}
}

/*
* Parsing of -L option
*/
Expand All @@ -2016,15 +1945,7 @@ static void prepare_blame_range(struct scoreboard *sb,
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(blame_usage);
}
if (*term)
if (parse_range_arg(bottomtop, nth_line_cb, sb, lno, bottom, top, sb->path))
usage(blame_usage);
}

Expand Down Expand Up @@ -2574,10 +2495,6 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
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)
Expand Down
31 changes: 31 additions & 0 deletions builtin/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "remote.h"
#include "string-list.h"
#include "parse-options.h"
#include "line-log.h"
#include "branch.h"
#include "streaming.h"
#include "version.h"
Expand All @@ -42,6 +43,12 @@ static const char * const builtin_log_usage[] = {
NULL
};

struct line_opt_callback_data {
struct rev_info *rev;
const char *prefix;
struct string_list args;
};

static int parse_decoration_style(const char *var, const char *value)
{
switch (git_config_maybe_bool(var, value)) {
Expand Down Expand Up @@ -76,6 +83,19 @@ static int decorate_callback(const struct option *opt, const char *arg, int unse
return 0;
}

static int log_line_range_callback(const struct option *option, const char *arg, int unset)
{
struct line_opt_callback_data *data = option->value;

if (!arg)
return -1;

data->rev->line_level_traverse = 1;
string_list_append(&data->args, arg);

return 0;
}

static void cmd_log_init_defaults(struct rev_info *rev)
{
if (fmt_pretty)
Expand All @@ -98,16 +118,23 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
{
struct userformat_want w;
int quiet = 0, source = 0, mailmap = 0;
static struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};

const struct option builtin_log_options[] = {
OPT_BOOL(0, "quiet", &quiet, N_("suppress diff output")),
OPT_BOOL(0, "source", &source, N_("show source")),
OPT_BOOL(0, "use-mailmap", &mailmap, N_("Use mail map file")),
{ OPTION_CALLBACK, 0, "decorate", NULL, NULL, N_("decorate options"),
PARSE_OPT_OPTARG, decorate_callback},
OPT_CALLBACK('L', NULL, &line_cb, "n,m:file",
"Process line range n,m in file, counting from 1",
log_line_range_callback),
OPT_END()
};

line_cb.rev = rev;
line_cb.prefix = prefix;

mailmap = use_mailmap_config;
argc = parse_options(argc, argv, prefix,
builtin_log_options, builtin_log_usage,
Expand Down Expand Up @@ -161,6 +188,10 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
rev->show_decorations = 1;
load_ref_decorations(decoration_style);
}

if (rev->line_level_traverse)
line_log_init(rev, line_cb.prefix, &line_cb.args);

setup_pager();
}

Expand Down
Loading

0 comments on commit ed73fe5

Please sign in to comment.