Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4444be6

Browse files
committedJan 7, 2025·
fix error with empty index by including raw information in diff
1 parent ac17834 commit 4444be6

File tree

6 files changed

+140
-6
lines changed

6 files changed

+140
-6
lines changed
 

Diff for: ‎src/Gitonomy/Git/Commit.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public function setData(array $data)
6262
*/
6363
public function getDiff()
6464
{
65-
$args = ['-r', '-p', '-m', '-M', '--no-commit-id', '--full-index', $this->revision];
65+
$args = ['-r', '-p', '--raw', '-m', '-M', '--no-commit-id', '--full-index', $this->revision];
6666

6767
$diff = Diff::parse($this->repository->run('diff-tree', $args));
6868
$diff->setRepository($this->repository);

Diff for: ‎src/Gitonomy/Git/Diff/File.php

+8
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,10 @@ public function getOldBlob()
278278
throw new \LogicException('Can\'t return old Blob on a creation');
279279
}
280280

281+
if($this->oldIndex === '') {
282+
throw new \RuntimeException('Index is missing to return Blob object.');
283+
}
284+
281285
return $this->repository->getBlob($this->oldIndex);
282286
}
283287

@@ -291,6 +295,10 @@ public function getNewBlob()
291295
throw new \LogicException('Can\'t return new Blob on a deletion');
292296
}
293297

298+
if($this->newIndex === '') {
299+
throw new \RuntimeException('Index is missing to return Blob object.');
300+
}
301+
294302
return $this->repository->getBlob($this->newIndex);
295303
}
296304
}

Diff for: ‎src/Gitonomy/Git/Parser/DiffParser.php

+19-2
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,31 @@ class DiffParser extends ParserBase
2222
protected function doParse()
2323
{
2424
$this->files = [];
25+
$indexes = [];
26+
// Diff contains raw information
27+
if (str_starts_with($this->content, ':')) {
28+
while($this->expects(':')) {
29+
$this->consumeRegexp('/\d{6} \d{6} /');
30+
$oldIndex = $this->consumeShortHash();
31+
$this->consume(' ');
32+
$newIndex = $this->consumeShortHash();
33+
$this->consumeTo("\n");
34+
$this->consumeNewLine();
35+
$indexes[] = [$oldIndex, $newIndex];
36+
}
37+
$this->consumeNewLine();
38+
} elseif (!$this->isFinished()) {
39+
trigger_error('Using Diff::parse without raw information is deprecated. See https://github.com/gitonomy/gitlib/issues/227.', E_USER_DEPRECATED);
40+
}
2541

42+
$fileIndex = 0;
2643
while (!$this->isFinished()) {
2744
// 1. title
2845
$vars = $this->consumeRegexp("/diff --git \"?(a\/.*?)\"? \"?(b\/.*?)\"?\n/");
2946
$oldName = $vars[1];
3047
$newName = $vars[2];
31-
$oldIndex = null;
32-
$newIndex = null;
48+
$oldIndex = isset($indexes[$fileIndex]) ? $indexes[$fileIndex][0] : null;
49+
$newIndex = isset($indexes[$fileIndex]) ? $indexes[$fileIndex][1] : null;
3350
$oldMode = null;
3451
$newMode = null;
3552

Diff for: ‎src/Gitonomy/Git/Repository.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ public function getDiff($revisions)
416416
$revisions = new RevisionList($this, $revisions);
417417
}
418418

419-
$args = array_merge(['-r', '-p', '-m', '-M', '--no-commit-id', '--full-index'], $revisions->getAsTextArray());
419+
$args = array_merge(['-r', '-p', '--raw', '-m', '-M', '--no-commit-id', '--full-index'], $revisions->getAsTextArray());
420420

421421
$diff = Diff::parse($this->run('diff', $args));
422422
$diff->setRepository($this);

Diff for: ‎src/Gitonomy/Git/WorkingCopy.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ public function getUntrackedFiles()
5050

5151
public function getDiffPending()
5252
{
53-
$diff = Diff::parse($this->run('diff', ['-r', '-p', '-m', '-M', '--full-index']));
53+
$diff = Diff::parse($this->run('diff', ['-r', '-p', '--raw', '-m', '-M', '--full-index']));
5454
$diff->setRepository($this->repository);
5555

5656
return $diff;
5757
}
5858

5959
public function getDiffStaged()
6060
{
61-
$diff = Diff::parse($this->run('diff', ['-r', '-p', '-m', '-M', '--full-index', '--staged']));
61+
$diff = Diff::parse($this->run('diff', ['-r', '-p', '--raw', '-m', '-M', '--full-index', '--staged']));
6262
$diff->setRepository($this->repository);
6363

6464
return $diff;

Diff for: ‎tests/Gitonomy/Git/Tests/DiffTest.php

+109
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
namespace Gitonomy\Git\Tests;
1414

1515
use Gitonomy\Git\Diff\Diff;
16+
use Gitonomy\Git\Diff\File;
17+
use Gitonomy\Git\Repository;
18+
use RuntimeException;
1619

1720
class DiffTest extends AbstractTest
1821
{
@@ -150,4 +153,110 @@ public function testWorksWithUmlauts($repository)
150153
$files = $repository->getCommit(self::FILE_WITH_UMLAUTS_COMMIT)->getDiff()->getFiles();
151154
$this->assertSame('file_with_umlauts_\303\244\303\266\303\274', $files[0]->getNewName());
152155
}
156+
157+
public function testDeleteFileWithoutRaw()
158+
{
159+
$deprecationCalled = false;
160+
$self = $this;
161+
set_error_handler(function (int $errno, string $errstr) use ($self, &$deprecationCalled): void {
162+
$deprecationCalled = true;
163+
$self->assertSame('Using Diff::parse without raw information is deprecated. See https://github.com/gitonomy/gitlib/issues/227.', $errstr);
164+
}, E_USER_DEPRECATED);
165+
166+
$diff = Diff::parse(<<<DIFF
167+
diff --git a/test b/test
168+
deleted file mode 100644
169+
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
170+
171+
DIFF);
172+
$firstFile = $diff->getFiles()[0];
173+
174+
restore_exception_handler();
175+
176+
$this->assertTrue($deprecationCalled);
177+
$this->assertFalse($firstFile->isCreation());
178+
$this->assertTrue($firstFile->isDeletion());
179+
$this->assertFalse($firstFile->isChangeMode());
180+
$this->assertSame('e69de29bb2d1d6434b8b29ae775ad8c2e48c5391', $firstFile->getOldIndex());
181+
$this->assertNull($firstFile->getNewIndex());
182+
}
183+
184+
public function testModeChangeFileWithoutRaw()
185+
{
186+
$deprecationCalled = false;
187+
$self = $this;
188+
set_error_handler(function (int $errno, string $errstr) use ($self, &$deprecationCalled): void {
189+
$deprecationCalled = true;
190+
$self->assertSame('Using Diff::parse without raw information is deprecated. See https://github.com/gitonomy/gitlib/issues/227.', $errstr);
191+
}, E_USER_DEPRECATED);
192+
193+
$diff = Diff::parse(<<<DIFF
194+
diff --git a/a.out b/a.out
195+
old mode 100755
196+
new mode 100644
197+
198+
DIFF);
199+
$firstFile = $diff->getFiles()[0];
200+
201+
restore_exception_handler();
202+
203+
$this->assertTrue($deprecationCalled);
204+
$this->assertFalse($firstFile->isCreation());
205+
$this->assertFalse($firstFile->isDeletion());
206+
$this->assertTrue($firstFile->isChangeMode());
207+
$this->assertSame('', $firstFile->getOldIndex());
208+
$this->assertSame('', $firstFile->getNewIndex());
209+
}
210+
211+
public function testModeChangeFileWithRaw()
212+
{
213+
$deprecationCalled = false;
214+
$self = $this;
215+
set_error_handler(function (int $errno, string $errstr) use ($self, &$deprecationCalled): void {
216+
$deprecationCalled = true;
217+
}, E_USER_DEPRECATED);
218+
219+
$diff = Diff::parse(<<<DIFF
220+
:100755 100644 d1af4b23d0cc9313e5b2d3ef2fb9696c94afaa81 d1af4b23d0cc9313e5b2d3ef2fb9696c94afaa81 M a.out
221+
222+
diff --git a/a.out b/a.out
223+
old mode 100755
224+
new mode 100644
225+
226+
DIFF);
227+
$firstFile = $diff->getFiles()[0];
228+
229+
restore_exception_handler();
230+
231+
$this->assertFalse($deprecationCalled);
232+
$this->assertFalse($firstFile->isCreation());
233+
$this->assertFalse($firstFile->isDeletion());
234+
$this->assertTrue($firstFile->isChangeMode());
235+
$this->assertSame('d1af4b23d0cc9313e5b2d3ef2fb9696c94afaa81', $firstFile->getOldIndex());
236+
$this->assertSame('d1af4b23d0cc9313e5b2d3ef2fb9696c94afaa81', $firstFile->getNewIndex());
237+
}
238+
239+
public function testThrowErrorOnBlobGetWithoutIndex()
240+
{
241+
$repository = $this->getMockBuilder(Repository::class)->disableOriginalConstructor()->getMock();
242+
$file = new File("oldName", "newName", "100755", "100644", "", '', false);
243+
$file->setRepository($repository);
244+
245+
try {
246+
$file->getOldBlob();
247+
} catch(\RuntimeException $exception) {
248+
$this->assertSame('Index is missing to return Blob object.', $exception->getMessage());
249+
}
250+
try {
251+
$file->getNewBlob();
252+
} catch(\RuntimeException $exception) {
253+
$this->assertSame('Index is missing to return Blob object.', $exception->getMessage());
254+
}
255+
256+
$this->assertFalse($file->isCreation());
257+
$this->assertFalse($file->isDeletion());
258+
$this->assertTrue($file->isChangeMode());
259+
$this->assertSame('', $file->getOldIndex());
260+
$this->assertSame('', $file->getNewIndex());
261+
}
153262
}

0 commit comments

Comments
 (0)
Please sign in to comment.