Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions Documentation/line-range-options.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
give zero or one positive revision arguments, and
_<start>_ and _<end>_ (or _<funcname>_) must exist in the starting revision.
You can specify this option more than once. Implies `--patch`.
Patch output can be suppressed using `--no-patch`, but other diff formats
(namely `--raw`, `--numstat`, `--shortstat`, `--dirstat`, `--summary`,
`--name-only`, `--name-status`, `--check`) are not currently implemented.
Patch output can be suppressed using `--no-patch`.
Non-patch diff formats `--raw`, `--name-only`, `--name-status`,
`--summary`, and `--check` are supported; diff stat formats
(`--stat`, `--numstat`, `--shortstat`, `--dirstat`) are not
currently implemented.
+
Patch formatting options such as `--word-diff`, `--color-moved`,
`--no-prefix`, and whitespace options (`-w`, `-b`) are supported,
as are pickaxe options (`-S`, `-G`).
as are pickaxe options (`-S`, `-G`) and `--diff-filter`.
+
include::line-range-format.adoc[]
30 changes: 9 additions & 21 deletions line-log.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#include "revision.h"
#include "xdiff-interface.h"
#include "strbuf.h"
#include "log-tree.h"
#include "line-log.h"
#include "setup.h"
#include "strvec.h"
Expand Down Expand Up @@ -1004,29 +1003,18 @@ static int process_all_files(struct line_log_data **range_out,
return changed;
}

int line_log_print(struct rev_info *rev, struct commit *commit)
void line_log_queue_pairs(struct rev_info *rev, struct commit *commit)
{
show_log(rev);
if (!(rev->diffopt.output_format & DIFF_FORMAT_NO_OUTPUT)) {
struct line_log_data *range = lookup_line_range(rev, commit);
struct line_log_data *r;
const char *prefix = diff_line_prefix(&rev->diffopt);

fprintf(rev->diffopt.file, "%s\n", prefix);

for (r = range; r; r = r->next) {
if (r->pair) {
struct diff_filepair *p =
diff_filepair_dup(r->pair);
p->line_ranges = &r->ranges;
diff_q(&diff_queued_diff, p);
}
}
struct line_log_data *range = lookup_line_range(rev, commit);
struct line_log_data *r;

diffcore_std(&rev->diffopt);
diff_flush(&rev->diffopt);
for (r = range; r; r = r->next) {
if (r->pair) {
struct diff_filepair *p = diff_filepair_dup(r->pair);
p->line_ranges = &r->ranges;
diff_q(&diff_queued_diff, p);
}
}
return 1;
}

static int bloom_filter_check(struct rev_info *rev,
Expand Down
2 changes: 1 addition & 1 deletion line-log.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ int line_log_filter(struct rev_info *rev);
int line_log_process_ranges_arbitrary_commit(struct rev_info *rev,
struct commit *commit);

int line_log_print(struct rev_info *rev, struct commit *commit);
void line_log_queue_pairs(struct rev_info *rev, struct commit *commit);

void line_log_free(struct rev_info *rev);

Expand Down
9 changes: 5 additions & 4 deletions log-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,11 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log
if (!all_need_diff && !opt->merges_need_diff)
return 0;

if (opt->line_level_traverse) {
line_log_queue_pairs(opt, commit);
return log_tree_diff_flush(opt);
}

parse_commit_or_die(commit);
oid = get_commit_tree_oid(commit);

Expand Down Expand Up @@ -1179,10 +1184,6 @@ int log_tree_commit(struct rev_info *opt, struct commit *commit)
opt->loginfo = &log;
opt->diffopt.no_free = 1;

/* NEEDSWORK: no restoring of no_free? Why? */
if (opt->line_level_traverse)
return line_log_print(opt, commit);

if (opt->track_linear && !opt->linear && !opt->reverse_output_stage)
fprintf(opt->diffopt.file, "\n%s\n", opt->break_bar);
shown = log_tree_diff(opt, commit, &log);
Expand Down
27 changes: 17 additions & 10 deletions revision.c
Original file line number Diff line number Diff line change
Expand Up @@ -3112,6 +3112,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
object_context_release(&oc);
}

if (revs->line_level_traverse) {
if (want_ancestry(revs))
revs->limited = 1;
revs->topo_order = 1;
if (!revs->diffopt.output_format)
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
}

/* Did the user ask for any diff output? Run the diff! */
if (revs->diffopt.output_format & ~DIFF_FORMAT_NO_OUTPUT)
revs->diff = 1;
Expand All @@ -3125,14 +3133,6 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
if (revs->diffopt.objfind)
revs->simplify_history = 0;

if (revs->line_level_traverse) {
if (want_ancestry(revs))
revs->limited = 1;
revs->topo_order = 1;
if (!revs->diffopt.output_format)
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
}

if (revs->topo_order && !generation_numbers_enabled(the_repository))
revs->limited = 1;

Expand Down Expand Up @@ -3179,8 +3179,15 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
die(_("the option '%s' requires '%s'"), "--grep-reflog", "--walk-reflogs");

if (revs->line_level_traverse &&
(revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
die(_("-L does not yet support diff formats besides -p and -s"));
(revs->diffopt.output_format &
~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT |
DIFF_FORMAT_RAW | DIFF_FORMAT_NAME |
DIFF_FORMAT_NAME_STATUS | DIFF_FORMAT_SUMMARY |
DIFF_FORMAT_CHECKDIFF)))
die(_("-L does not yet support diff stat formats "
"(--stat, --numstat, --shortstat, --dirstat)"));
if (revs->line_level_traverse && revs->full_diff)
die(_("-L is not compatible with --full-diff"));

if (revs->expand_tabs_in_log < 0)
revs->expand_tabs_in_log = revs->expand_tabs_in_log_default;
Expand Down
108 changes: 93 additions & 15 deletions t/t4211-line-log.sh
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,27 @@ test_expect_success '-p shows the default patch output' '
test_cmp expect actual
'

test_expect_success '--raw is forbidden' '
test_must_fail git log -L1,24:b.c --raw
test_expect_success '--raw shows mode, oid, status and path' '
git log -L1,24:b.c --raw --format= >actual &&
grep "^:100644 100644 .* M b.c$" actual
'

test_expect_success '--name-only shows path' '
git log -L1,24:b.c --name-only --format= >actual &&
grep "^b.c$" actual
'

test_expect_success '--name-status shows status and path' '
git log -L1,24:b.c --name-status --format= >actual &&
grep "^M b.c$" actual
'

test_expect_success '--stat is not yet supported with -L' '
test_must_fail git log -L1,24:b.c --stat
'

test_expect_success '--full-diff is not supported with -L' '
test_must_fail git log -L1,24:b.c --full-diff
'

test_expect_success 'setup for checking fancy rename following' '
Expand Down Expand Up @@ -368,7 +387,6 @@ test_expect_success '-L diff output includes index and new file mode' '

test_expect_success '-L with --word-diff' '
cat >expect <<-\EOF &&

diff --git a/file.c b/file.c
--- a/file.c
+++ b/file.c
Expand All @@ -377,7 +395,6 @@ test_expect_success '-L with --word-diff' '
{
return [-F2;-]{+F2 + 2;+}
}

diff --git a/file.c b/file.c
new file mode 100644
--- /dev/null
Expand Down Expand Up @@ -433,7 +450,6 @@ test_expect_success 'show line-log with graph' '
null_blob=$(test_oid zero | cut -c1-7) &&
qz_to_tab_space >expect <<-EOF &&
* $head_oid Modify func2() in file.c
|Z
| diff --git a/file.c b/file.c
| index $head_blob_old..$head_blob_new 100644
| --- a/file.c
Expand All @@ -445,7 +461,6 @@ test_expect_success 'show line-log with graph' '
| + return F2 + 2;
| }
* $root_oid Add func1() and func2() in file.c
ZZ
diff --git a/file.c b/file.c
new file mode 100644
index $null_blob..$root_blob
Expand Down Expand Up @@ -494,23 +509,17 @@ test_expect_success '-L --find-object does not crash with merge and rename' '
--find-object=$(git rev-parse HEAD:file) >actual
'

# Commit-level filtering with pickaxe does not yet work for -L.
# show_log() prints the commit header before diffcore_std() runs
# pickaxe, so commits cannot be suppressed even when no diff pairs
# survive filtering. Fixing this would require deferring show_log()
# until after diffcore_std(), which is a larger restructuring of the
# log-tree output pipeline.
test_expect_failure '-L -G should filter commits by pattern' '
test_expect_success '-L -G should filter commits by pattern' '
git log --format="%s" --no-patch -L 1,1:file -G "nomatch" >actual &&
test_must_be_empty actual
'

test_expect_failure '-L -S should filter commits by pattern' '
test_expect_success '-L -S should filter commits by pattern' '
git log --format="%s" --no-patch -L 1,1:file -S "nomatch" >actual &&
test_must_be_empty actual
'

test_expect_failure '-L --find-object should filter commits by object' '
test_expect_success '-L --find-object should filter commits by object' '
git log --format="%s" --no-patch -L 1,1:file \
--find-object=$ZERO_OID >actual &&
test_must_be_empty actual
Expand Down Expand Up @@ -711,4 +720,73 @@ test_expect_success '-L with -G filters to diff-text matches' '
grep "F2 + 2" actual
'

test_expect_success '-L with --diff-filter=M excludes root commit' '
git checkout parent-oids &&
git log -L:func2:file.c --diff-filter=M --format=%s --no-patch >actual &&
# Root commit is an Add (A), not a Modify (M), so it should
# be excluded; only the modification commit remains.
echo "Modify func2() in file.c" >expect &&
test_cmp expect actual
'

test_expect_success '-L with --diff-filter=A shows only root commit' '
git checkout parent-oids &&
git log -L:func2:file.c --diff-filter=A --format=%s --no-patch >actual &&
echo "Add func1() and func2() in file.c" >expect &&
test_cmp expect actual
'

test_expect_success '-L with -S suppresses non-matching commits' '
git checkout parent-oids &&
git log -L:func2:file.c -S "F2 + 2" --format=%s --no-patch >actual &&
# Only the commit that changes the count of "F2 + 2" should appear.
echo "Modify func2() in file.c" >expect &&
test_cmp expect actual
'

test_expect_success '--summary shows new file on root commit' '
git checkout parent-oids &&
git log -L:func2:file.c --summary --format= >actual &&
grep "create mode 100644 file.c" actual
'

test_expect_success 'setup for --check test' '
git checkout --orphan check-test &&
git reset --hard &&
cat >check.c <<-\EOF &&
void tracked()
{
return;
}

void other()
{
return;
}
EOF
git add check.c &&
test_tick &&
git commit -m "add check.c" &&
# Introduce trailing whitespace errors in both functions
sed "s/return;/return; /" check.c >check.c.tmp &&
mv check.c.tmp check.c &&
git commit -a -m "introduce trailing whitespace"
'

test_expect_success '--check reports whitespace errors in tracked range' '
test_must_fail git log -L:tracked:check.c --check --format= >actual &&
grep "trailing whitespace" actual
'

# --check currently examines the entire file diff, not just the tracked
# range. Scoping --check to line_ranges would require threading range
# filtering into run_checkdiff(), similar to how builtin_diff() filters
# patch output.
test_expect_failure '--check should not report errors outside tracked range' '
test_must_fail git log -L:tracked:check.c --check --format= >actual &&
# line 3 is inside tracked(), line 8 is inside other()
grep "check.c:3" actual &&
! grep "check.c:8" actual
'

test_done
1 change: 0 additions & 1 deletion t/t4211/sha1/expect.parallel-change-f-to-main
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ Date: Fri Apr 12 16:16:24 2013 +0200

Merge across the rename


commit 6ce3c4ff690136099bb17e1a8766b75764726ea7
Author: Thomas Rast <trast@student.ethz.ch>
Date: Thu Feb 28 10:49:50 2013 +0100
Expand Down
1 change: 0 additions & 1 deletion t/t4211/sha256/expect.parallel-change-f-to-main
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ Date: Fri Apr 12 16:16:24 2013 +0200

Merge across the rename


commit 4f7a58195a92c400e28a2354328587f1ff14fb77f5cf894536f17ccbc72931b9
Author: Thomas Rast <trast@student.ethz.ch>
Date: Thu Feb 28 10:49:50 2013 +0100
Expand Down
Loading