Skip to content
Merged
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
18 changes: 15 additions & 3 deletions src/Gitonomy/Git/Diff/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public function __construct(
private readonly ?string $oldIndex,
private readonly ?string $newIndex,
private readonly bool $isBinary,
private readonly bool $isCopy = false,
) {
}

Expand Down Expand Up @@ -65,11 +66,21 @@ public function isModification(): bool
/**
* Indicates if it's a rename.
*
* A rename can only occurs if it's a modification (not a creation or a deletion).
* A rename can only occurs if it's a modification (not a creation or a deletion), and is not a copy.
*/
public function isRename(): bool
{
return $this->isModification() && $this->oldName !== $this->newName;
return $this->isModification() && $this->oldName !== $this->newName && !$this->isCopy;
}

/**
* Indicates if it's a copy.
*
* Unlike a rename, the source file of a copy still exists after the change.
*/
public function isCopy(): bool
{
return $this->isCopy;
}

/**
Expand Down Expand Up @@ -184,6 +195,7 @@ public function toArray(): array
'old_index' => $this->oldIndex,
'new_index' => $this->newIndex,
'is_binary' => $this->isBinary,
'is_copy' => $this->isCopy,
'changes' => array_map(static function (FileChange $change) {
return $change->toArray();
}, $this->changes),
Expand All @@ -192,7 +204,7 @@ public function toArray(): array

public static function fromArray(array $array): self
{
$file = new self($array['old_name'], $array['new_name'], $array['old_mode'], $array['new_mode'], $array['old_index'], $array['new_index'], $array['is_binary']);
$file = new self($array['old_name'], $array['new_name'], $array['old_mode'], $array['new_mode'], $array['old_index'], $array['new_index'], $array['is_binary'], $array['is_copy'] ?? false);

foreach ($array['changes'] as $change) {
$file->addChange(FileChange::fromArray($change));
Expand Down
10 changes: 7 additions & 3 deletions src/Gitonomy/Git/Parser/DiffParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,16 @@ protected function doParse(): void
$this->consumeNewLine();
}

$isCopy = false;
if ($this->expects('similarity index ')) {
$this->consumeRegexp('/\d{1,3}%\n/');
$this->consume('rename from ');
$isCopy = $this->expects('copy from ');
if (!$isCopy) {
$this->consume('rename from ');
}
$this->consumeTo("\n");
$this->consumeNewLine();
$this->consume('rename to ');
$this->consume($isCopy ? 'copy to ' : 'rename to ');
$this->consumeTo("\n");
$this->consumeNewLine();
}
Expand Down Expand Up @@ -120,7 +124,7 @@ protected function doParse(): void
$newIndex = null === $newIndex ? '' : $newIndex;
$oldIndex = preg_match('/^0+$/', $oldIndex) ? null : $oldIndex;
$newIndex = preg_match('/^0+$/', $newIndex) ? null : $newIndex;
$file = new File($oldName, $newName, $oldMode, $newMode, $oldIndex, $newIndex, $isBinary);
$file = new File($oldName, $newName, $oldMode, $newMode, $oldIndex, $newIndex, $isBinary, $isCopy);

// 5. Diff
while ($this->expects('@@ ')) {
Expand Down
49 changes: 49 additions & 0 deletions tests/Gitonomy/Git/Tests/DiffTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,55 @@ public function testModeChangeFileWithRaw(): void
$this->assertSame('d1af4b23d0cc9313e5b2d3ef2fb9696c94afaa82', $secondFile->getNewIndex());
}

public function testCopyFileWithoutRaw(): void
{
$this->expectUserDeprecationMessage('Using Diff::parse without raw information is deprecated. See https://github.com/gitonomy/gitlib/issues/227.');

$diff = Diff::parse(<<<'DIFF'
diff --git a/style.css b/common.css
similarity index 97%
copy from style.css
copy to common.css
index 1234567..89abcde 100644
--- a/style.css
+++ b/common.css
@@ -1,3 +1,4 @@
body {
+ color: red;
}

DIFF);
$firstFile = $diff->getFiles()[0];

$this->assertTrue($firstFile->isModification());
$this->assertTrue($firstFile->isCopy());
$this->assertFalse($firstFile->isRename());
$this->assertFalse($firstFile->isDeletion());
$this->assertFalse($firstFile->isCreation());
$this->assertSame('style.css', $firstFile->getOldName());
$this->assertSame('common.css', $firstFile->getNewName());
$this->assertSame(1, $firstFile->getAdditions());
}

public function testPureCopyFileWithoutRaw(): void
{
$this->expectUserDeprecationMessage('Using Diff::parse without raw information is deprecated. See https://github.com/gitonomy/gitlib/issues/227.');

$diff = Diff::parse(<<<'DIFF'
diff --git a/style.css b/common.css
similarity index 100%
copy from style.css
copy to common.css

DIFF);
$firstFile = $diff->getFiles()[0];

$this->assertTrue($firstFile->isCopy());
$this->assertFalse($firstFile->isRename());
$this->assertSame('style.css', $firstFile->getOldName());
$this->assertSame('common.css', $firstFile->getNewName());
}

public function testThrowErrorOnBlobGetWithoutIndex(): void
{
$repository = self::createEmptyRepository();
Expand Down