Skip to content

Commit 05c8580

Browse files
author
Daniel Kroening
authored
Merge pull request #556 from smowton/better_linter_filtering
Better linter filtering
2 parents 0e2f389 + 628c66b commit 05c8580

File tree

4 files changed

+81
-64
lines changed

4 files changed

+81
-64
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ matrix:
4040
compiler: clang
4141
env: COMPILER=clang++
4242
- env: NAME="CPP-LINT"
43-
script: scripts/run_lint.sh master HEAD || true
43+
script: scripts/travis_lint.sh || true
4444

4545
script:
4646
- if [ -L bin/gcc ] ; then export PATH=$PWD/bin:$PATH ; fi ;

scripts/filter_lint_by_diff.py

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env python
2+
3+
import sys
4+
import unidiff
5+
import os.path
6+
7+
if len(sys.argv) != 3:
8+
print >>sys.stderr, "Usage: filter_lint_by_diff.py diff.patch repository_root_directory < cpplint_warnings.txt"
9+
sys.exit(1)
10+
11+
added_lines = set()
12+
repository_root = sys.argv[2]
13+
14+
with open(sys.argv[1], "r") as f:
15+
diff = unidiff.PatchSet(f)
16+
for diff_file in diff:
17+
filename = diff_file.target_file
18+
assert filename.startswith("b/")
19+
filename = os.path.join(repository_root, filename[2:])
20+
added_lines.add((filename, 0))
21+
for diff_hunk in diff_file:
22+
for diff_line in diff_hunk:
23+
if diff_line.line_type == "+":
24+
added_lines.add((filename, diff_line.target_line_no))
25+
26+
for l in sys.stdin:
27+
bits = l.split(":")
28+
if len(bits) < 3:
29+
continue
30+
filename = os.path.join(repository_root, bits[0])
31+
linenum = int(bits[1])
32+
if (filename, linenum) in added_lines:
33+
sys.stdout.write(l)

scripts/run_lint.sh

+34-63
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@
33
set -e
44

55
script_folder=`dirname $0`
6+
absolute_repository_root=`readlink -f $script_folder/..`
67

7-
if [[ "$#" -ne 2 ]]
8+
if [[ "$#" -gt 2 ]]
89
then
9-
echo "Script for running the CPP linter only on modified lines."
10-
echo "Requires two arguments the start and the end"
11-
echo "start - a git reference that marks the first commit whose changes to consider"
12-
echo "end - a git reference that marks the last commit whose changes to consider"
13-
10+
echo "Script for running the CPP linter only on modified lines. Arguments:"
11+
echo "target - a git reference to the branch we want to compare against (default: 'master')"
12+
echo "tip - a git reference to the commit with changes (default: current working tree)"
1413
exit 1
1514
fi
1615

@@ -21,75 +20,49 @@ then
2120
exit 1
2221
fi
2322

24-
git_start=$1
25-
git_end=$2
23+
if [[ "$#" -gt 0 ]]
24+
then
25+
git_start=$1
26+
else
27+
git_start="master"
28+
fi
2629

27-
# Get the list of files that have changed
28-
diff_files=`git diff --name-only $git_start $git_end`
30+
if [[ "$#" -gt 1 ]]
31+
then
32+
git_end=$2
33+
git_merge_base_end=$2
34+
else
35+
git_end=""
36+
git_merge_base_end="HEAD"
37+
fi
38+
39+
git_start=`git merge-base $git_start $git_merge_base_end`
2940

30-
# Build a filter that will filter the blame output
31-
# to only include lines that come from one of the relevant_commits
32-
# We do this by making the blame tool output the same hash for all
33-
# lines that are too old.
34-
blame_grep_filter=`git rev-parse "$git_start"`
41+
cleanup()
42+
{
43+
rm -f $diff_file
44+
}
3545

36-
# Build a regex for finding the line number of a given line inside blame
37-
# First matches the 40 digit hash of the commi
38-
# Then match an arbitary length number that represents the line in the original file
39-
# Finally matches (and groups) another arbitary length digit which is the
40-
# line in the final file
41-
regex="[0-9a-f]{40} [0-9]+ ([0-9]+)"
46+
trap cleanup EXIT
4247

43-
# We only split on lines or otherwise the git blame output is nonsense
44-
IFS=$'\n'
48+
diff_file=`mktemp`
4549

46-
are_errors=0
50+
git diff $git_start $git_end > $diff_file
51+
52+
# Get the list of files that have changed
53+
diff_files=`git diff --name-only $git_start $git_end`
4754

4855
for file in $diff_files; do
56+
file=$absolute_repository_root/$file
4957
# If the file has been deleted we don't want to run the linter on it
5058
if ! [[ -e $file ]]
5159
then
5260
continue
5361
fi
5462

55-
# We build another grep filter the output of the linting script
56-
lint_grep_filter="^("
57-
58-
# Include line 0 errors (e.g. copyright)
59-
lint_grep_filter+=$file
60-
lint_grep_filter+=":0:"
61-
62-
# We first filter only the lines that start with a commit hash
63-
# Then we filter out the ones that come from the start commit
64-
modified_lines=`git blame $git_start..$git_end --line-porcelain $file | grep -E "^[0-9a-f]{40}" | { grep -v "$blame_grep_filter" || true; }`
65-
66-
# For each modified line we find the line number
67-
for line in $modified_lines; do
68-
69-
# Use the above regex to match the line number
70-
if [[ $line =~ $regex ]]
71-
then
72-
# Some bash magic to get the first group from the regex (the line number)
73-
LINENUM="${BASH_REMATCH[1]}"
74-
75-
# The format from the linting script is filepath:linenum: [error type]
76-
# So we build the first bit to filter out relevant lines
77-
LINE_FILTER=$file:$LINENUM:
78-
79-
# Add the line filter on to the grep expression as we want
80-
# lines that match any of the line filters
81-
lint_grep_filter+="|"
82-
lint_grep_filter+=$LINE_FILTER
83-
fi
84-
done
85-
86-
# Add the closing bracket
87-
lint_grep_filter+=")"
88-
89-
# Run the linting script and filter by the filter we've build
90-
# of all the modified lines
63+
# Run the linting script and filter:
9164
# The errors from the linter go to STDERR so must be redirected to STDOUT
92-
result=`$script_folder/cpplint.py $file 2>&1 | { grep -E "$lint_grep_filter" || true; }`
65+
result=`$script_folder/cpplint.py $file 2>&1 | $script_folder/filter_lint_by_diff.py $diff_file $absolute_repository_root`
9366

9467
# Providing some errors were relevant we print them out
9568
if [ "$result" ]
@@ -99,7 +72,5 @@ for file in $diff_files; do
9972
fi
10073
done
10174

102-
unset IFS
103-
10475
# Return an error code if errors are found
10576
exit $are_errors

scripts/travis_lint.sh

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
script_folder=`dirname $0`
6+
pip install --user unidiff
7+
8+
if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
9+
$script_folder/run_lint.sh HEAD~1 # Check for errors introduced in last commit
10+
else
11+
$script_folder/run_lint.sh $TRAVIS_BRANCH # Check for errors compared to merge target
12+
fi
13+

0 commit comments

Comments
 (0)