Skip to content

Commit 40052f4

Browse files
Ignore lines by git commit ref
1 parent 9962022 commit 40052f4

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed

PHP/CodeCoverage.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,16 @@ protected function getLinesToBeIgnored($filename)
878878
}
879879
}
880880

881+
if (count($this->filter->getExcludeCommits())) {
882+
$excludeCommits = $this->filter->getExcludeCommits();
883+
$blameLines = PHP_CodeCoverage_Git_Blame::getBlameInfo($filename);
884+
foreach ($blameLines as $blameLine) {
885+
if (in_array($blameLine->rev, $excludeCommits)) {
886+
$this->ignoredLines[$filename][] = $blameLine->lineNo;
887+
}
888+
}
889+
}
890+
881891
if ($this->cacheTokens) {
882892
$tokens = PHP_Token_Stream_CachingFactory::get($filename);
883893
} else {

PHP/CodeCoverage/Filter.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ class PHP_CodeCoverage_Filter
7575
*/
7676
protected $blacklistPrefilled = FALSE;
7777

78+
/**
79+
* List of SCM commits which are to be excluded.
80+
*
81+
* @var array
82+
*/
83+
protected $excludeCommits = array();
84+
7885
/**
7986
* Adds a directory to the blacklist (recursively).
8087
*
@@ -341,4 +348,14 @@ protected function addDirectoryContainingClassToBlacklist($className, $parent =
341348

342349
$this->addDirectoryToBlacklist($directory);
343350
}
351+
352+
public function setExcludeCommits($excludeCommits)
353+
{
354+
$this->excludeCommits = $excludeCommits;
355+
}
356+
357+
public function getExcludeCommits()
358+
{
359+
return $this->excludeCommits;
360+
}
344361
}

PHP/CodeCoverage/Git/Blame.php

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
class PHP_CodeCoverage_Git_Blame
4+
{
5+
public $rev;
6+
public $author;
7+
public $lineNo;
8+
public $linesLeftInBlameGroup;
9+
public $isStartGroupLine;
10+
11+
/**
12+
* Returns an array of line number to blame info
13+
*
14+
* @param $file
15+
* @param $lines
16+
* @throws PHP_CodeCoverage_Exception
17+
* @return array of PHP_CodeCoverage_Git_Blame
18+
*/
19+
public static function getBlameInfo($file)
20+
{
21+
$blameOutput = self::getBlameOutput($file);
22+
$ret = array();
23+
$i = 0;
24+
$linesLeftInBlameGroup = 1;
25+
$blameLine = current($blameOutput);
26+
while (false !== $blameLine) {
27+
$i++;
28+
$linesLeftInBlameGroup--;
29+
$isStartGroupLine = !$linesLeftInBlameGroup;
30+
if ($isStartGroupLine) {
31+
if (!preg_match('/^(.{40}) (\d+) (\d+) (\d+)$/', $blameLine, $matches)) {
32+
throw new PHP_CodeCoverage_Exception(
33+
"Unexpected output from git blame for file line $i: " . $blameLine);
34+
}
35+
$linesLeftInBlameGroup = $matches[4];
36+
} else {
37+
if (!preg_match('/^(.{40}) (\d+) (\d+)$/', $blameLine, $matches)) {
38+
throw new PHP_CodeCoverage_Exception(
39+
"Unexpected output from git blame for file line $i: " . $blameLine);
40+
}
41+
}
42+
$sha = $matches[1];
43+
if ($i != $matches[3]) {
44+
throw new PHP_CodeCoverage_Exception(
45+
"Unexpected output from git blame (expected line $i): " . $blameLine);
46+
}
47+
48+
$author = '';
49+
do
50+
{
51+
$blameData = next($blameOutput);
52+
if (0 === strpos($blameData, 'author ')) {
53+
$author = substr($blameData, strlen('author '));
54+
}
55+
} while (
56+
false !== $blameData && // EOF
57+
0 !== strpos($blameData, "\t") && // End of line info
58+
'' !== $blameData); // End of line info which has been trim()ed by exec
59+
60+
$info = new PHP_CodeCoverage_Git_Blame();
61+
$info->rev = $sha;
62+
$info->author = $author;
63+
$info->lineNo = $i;
64+
$info->linesLeftInBlameGroup = $linesLeftInBlameGroup;
65+
$info->isStartGroupLine = $isStartGroupLine;
66+
$ret[$i] = $info;
67+
68+
$blameLine = next($blameOutput);
69+
}
70+
return $ret;
71+
}
72+
73+
/**
74+
* Runs "git blame" on the given file and returns the output.
75+
*
76+
* @param $file
77+
* @return array of strings - the "porcelain" output from "git blame"
78+
* @throws PHP_CodeCoverage_Exception
79+
*/
80+
protected static function getBlameOutput($file)
81+
{
82+
if (strpos(`uname`, 'CYGWIN') !== false) {
83+
// Cygwin git does not like absolute Windows filenames
84+
$file = `cygpath "$file"`;
85+
}
86+
$file = escapeshellarg($file);
87+
$cmd = "git blame -p $file";
88+
exec($cmd, $blameOutput, $retval);
89+
if ($retval != 0) {
90+
throw new PHP_CodeCoverage_Exception(
91+
"Error running git blame. Perhaps you do not have git installed, or perhaps the " .
92+
"project is not in git source control. Please either fix this error or don't use " .
93+
"the 'excludeCommits' option.\nCommand: $cmd\nOutput: $blameOutput");
94+
}
95+
return $blameOutput;
96+
}
97+
98+
}

0 commit comments

Comments
 (0)