Skip to content

Commit 8b1c389

Browse files
authored
Merge pull request #5 from SpacePossum/master_last_hunk_context_lines_bug
Number of context lines vs. common threshold
2 parents 4652003 + 798e8a1 commit 8b1c389

File tree

5 files changed

+434
-82
lines changed

5 files changed

+434
-82
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,13 @@ Diff:
7777
```
7878

7979
Options:
80-
- `contextLines`, default: `3`.
8180
- `collapseRanges`, default: `true`.
81+
- `commonLineThreshold`, default: `6`.
82+
- `contextLines`, default: `3`.
8283
- `fromFile`, default: `<null>`.
8384
- `fromFileDate`, default: `<null>`.
8485
- `toFile`, default: `<null>`.
8586
- `toFileDate`, default: `<null>`.
86-
- `commonLineThreshold`, default: `6`.
8787

8888

8989
### Links

src/DiffOutputBuilder/UnifiedDiffOutputBuilder.php

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ final class UnifiedDiffOutputBuilder implements DiffOutputBuilderInterface
5959
private $contextLines;
6060

6161
private static $default = [
62-
'contextLines' => 3, // like `diff: -u, -U NUM, --unified[=NUM]`, for patch/git apply compatibility best to keep at least @ 3
63-
'collapseRanges' => true, // ranges of length one are rendered with the trailing `,1`
62+
'collapseRanges' => true, // ranges of length one are rendered with the trailing `,1`
63+
'commonLineThreshold' => 6, // number of same lines before ending a new hunk and creating a new one (if needed)
64+
'contextLines' => 3, // like `diff: -u, -U NUM, --unified[=NUM]`, for patch/git apply compatibility best to keep at least @ 3
6465
'fromFile' => null,
6566
'fromFileDate' => null,
6667
'toFile' => null,
6768
'toFileDate' => null,
68-
'commonLineThreshold' => 6, // number of same lines before ending a new hunk and creating a new one (if needed)
6969
];
7070

7171
public function __construct(array $options = [])
@@ -122,15 +122,24 @@ public function getDiff(array $diff): string
122122

123123
$this->writeDiffHunks($buffer, $diff);
124124

125+
if (!$this->changed) {
126+
\fclose($buffer);
127+
128+
return '';
129+
}
130+
125131
$diff = \stream_get_contents($buffer, -1, 0);
126132

127133
\fclose($buffer);
128134

129-
if (!$this->changed) {
130-
return '';
131-
}
135+
// If the last char is not a linebreak: add it.
136+
// This might happen when both the `from` and `to` do not have a trailing linebreak
137+
$last = \substr($diff, -1);
132138

133-
return $diff;
139+
return "\n" !== $last && "\r" !== $last
140+
? $diff."\n"
141+
: $diff
142+
;
134143
}
135144

136145
private function writeDiffHunks($output, array $diff)
@@ -139,7 +148,6 @@ private function writeDiffHunks($output, array $diff)
139148

140149
$upperLimit = \count($diff);
141150

142-
// append "\ No newline at end of file" if needed
143151
if (0 === $diff[$upperLimit - 1][1]) {
144152
$lc = \substr($diff[$upperLimit - 1][0], -1);
145153
if ("\n" !== $lc) {
@@ -185,24 +193,30 @@ private function writeDiffHunks($output, array $diff)
185193
++$fromRange;
186194

187195
if ($sameCount === $cutOff) {
188-
$contextStartOffset = $hunkCapture - $this->contextLines < 0
196+
$contextStartOffset = ($hunkCapture - $this->contextLines) < 0
189197
? $hunkCapture
190198
: $this->contextLines
191199
;
192200

193-
$contextEndOffset = $i + $this->contextLines >= \count($diff)
194-
? \count($diff) - $i
195-
: $this->contextLines
196-
;
201+
// note: $contextEndOffset = $this->contextLines;
202+
//
203+
// because we never go beyond the end of the diff.
204+
// with the cutoff/contextlines here the follow is never true;
205+
//
206+
// if ($i - $cutOff + $this->contextLines + 1 > \count($diff)) {
207+
// $contextEndOffset = count($diff) - 1;
208+
// }
209+
//
210+
// ; that would be true for a trailing incomplete hunk case which is dealt with after this loop
197211

198212
$this->writeHunk(
199213
$diff,
200214
$hunkCapture - $contextStartOffset,
201-
$i - $cutOff + $contextEndOffset + 1,
215+
$i - $cutOff + $this->contextLines + 1,
202216
$fromStart - $contextStartOffset,
203-
$fromRange - $cutOff + $contextStartOffset + $contextEndOffset,
217+
$fromRange - $cutOff + $contextStartOffset + $this->contextLines,
204218
$toStart - $contextStartOffset,
205-
$toRange - $cutOff + $contextStartOffset + $contextEndOffset,
219+
$toRange - $cutOff + $contextStartOffset + $this->contextLines,
206220
$output
207221
);
208222

@@ -237,23 +251,35 @@ private function writeDiffHunks($output, array $diff)
237251
}
238252
}
239253

240-
if (false !== $hunkCapture) {
241-
$contextStartOffset = $hunkCapture - $this->contextLines < 0
242-
? $hunkCapture
243-
: $this->contextLines
244-
;
245-
246-
$this->writeHunk(
247-
$diff,
248-
$hunkCapture - $contextStartOffset,
249-
\count($diff),
250-
$fromStart - $contextStartOffset,
251-
$fromRange + $contextStartOffset,
252-
$toStart - $contextStartOffset,
253-
$toRange + $contextStartOffset,
254-
$output
255-
);
254+
if (false === $hunkCapture) {
255+
return;
256256
}
257+
258+
// we end here when cutoff (commonLineThreshold) was not reached, but we where capturing a hunk,
259+
// do not render hunk till end automatically because the number of context lines might be less than the commonLineThreshold
260+
261+
$contextStartOffset = $hunkCapture - $this->contextLines < 0
262+
? $hunkCapture
263+
: $this->contextLines
264+
;
265+
266+
// prevent trying to write out more common lines than there are in the diff _and_
267+
// do not write more than configured through the context lines
268+
$contextEndOffset = \min($sameCount, $this->contextLines);
269+
270+
$fromRange -= $sameCount;
271+
$toRange -= $sameCount;
272+
273+
$this->writeHunk(
274+
$diff,
275+
$hunkCapture - $contextStartOffset,
276+
$i - $sameCount + $contextEndOffset + 1,
277+
$fromStart - $contextStartOffset,
278+
$fromRange + $contextStartOffset + $contextEndOffset,
279+
$toStart - $contextStartOffset,
280+
$toRange + $contextStartOffset + $contextEndOffset,
281+
$output
282+
);
257283
}
258284

259285
private function writeHunk(
@@ -292,6 +318,11 @@ private function writeHunk(
292318
$this->changed = true;
293319
\fwrite($output, $diff[$i][0]);
294320
}
321+
//} elseif ($diff[$i][1] === 3) { // custom comment inserted by PHPUnit/diff package
322+
// skip
323+
//} else {
324+
// unknown/invalid
325+
//}
295326
}
296327
}
297328
}

0 commit comments

Comments
 (0)