Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Corrected refs removal upon project removal #160

Merged
merged 1 commit into from
Oct 19, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- When there was a cache miss, then explain why (absent, invalidated, expired) during verbose output.
- Queue SVN-Buddy new repository commit discovery, after a new commit in SVN-Buddy was made.
- The `log` and `merge` commands no longer fails with large (>999) revision lists on SQLite <= 3.32.0.
- The deletion of project wasn't deleting its refs (branches/tags) resulting them to reported as existing.

## [0.7.0] - 2024-04-12
### Added
Expand Down
22 changes: 22 additions & 0 deletions migrations/20241019_1708_propagate_path_revision_deleted.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php
use ConsoleHelpers\DatabaseMigration\MigrationContext;

return function (MigrationContext $context) {
$db = $context->getDatabase();

$sql = 'SELECT Path, RevisionDeleted
FROM Paths
WHERE Path LIKE "%/" AND RevisionDeleted IS NOT NULL';
$deleted_paths = $db->fetchPairs($sql);

if ( !$deleted_paths ) {
return;
}

foreach ( $deleted_paths as $path => $revision ) {
$sql = 'UPDATE Paths
SET RevisionDeleted = :revision
WHERE Path LIKE :path AND RevisionDeleted IS NULL';
$db->perform($sql, array('revision' => $revision, 'path' => $path . '%'));
}
};
26 changes: 25 additions & 1 deletion src/SVNBuddy/Repository/RevisionLog/RepositoryFiller.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,14 @@ public function touchPath($path, $revision, array $fields_hash)
throw new \InvalidArgumentException('The "$fields_hash" variable can\'t be empty.');
}

// This is $revision, where $path was deleted.
if ( array_key_exists('RevisionDeleted', $fields_hash)
&& $fields_hash['RevisionDeleted'] !== null
&& substr($path, -1) === '/'
) {
$this->propagateRevisionDeleted($path, $fields_hash['RevisionDeleted']);
}

$path_hash = $this->getPathChecksum($path);
$to_update = $this->propagateRevisionLastSeen($path, $revision);
$to_update[$path_hash] = $fields_hash;
Expand All @@ -255,7 +263,7 @@ public function touchPath($path, $revision, array $fields_hash)
}

/**
* Propagates revision last seen.
* Propagates revision last seen upwards in path hierarchy.
*
* @param string $path Path.
* @param string $revision Revision.
Expand Down Expand Up @@ -306,6 +314,22 @@ protected function propagateRevisionLastSeen($path, $revision)
return $to_update;
}

/**
* Propagates revision deleted downwards in path hierarchy.
*
* @param string $path Path.
* @param string $revision Revision.
*
* @return void
*/
protected function propagateRevisionDeleted($path, $revision)
{
$sql = 'UPDATE Paths
SET RevisionDeleted = :revision
WHERE Path LIKE :path AND RevisionDeleted IS NULL';
$this->database->perform($sql, array('revision' => $revision, 'path' => $path . '%'));
}

/**
* Returns fields, that needs to be changed for given path.
*
Expand Down
79 changes: 79 additions & 0 deletions tests/SVNBuddy/Repository/RevisionLog/Plugin/PathsPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,85 @@ public function testParsePathSorting()
);
}

public function testParsePathRemovalPropagated()
{
$this->repositoryConnector->getRefByPath(Argument::any())->willReturn(false)->shouldBeCalled();

$this->plugin->parse($this->getFixture('svn_log_path_deleted_propagate.xml'));

$this->assertTableContent(
'Paths',
array(
array(
'Id' => '1',
'Path' => '/path/',
'PathNestingLevel' => '1',
'PathHash' => '1753053843',
'RefName' => '',
'ProjectPath' => '',
'RevisionAdded' => '50',
'RevisionDeleted' => null,
'RevisionLastSeen' => '200',
),
array(
'Id' => '2',
'Path' => '/path/folder_a/',
'PathNestingLevel' => '2',
'PathHash' => '2557174829',
'RefName' => '',
'ProjectPath' => '',
'RevisionAdded' => '60',
'RevisionDeleted' => '200',
'RevisionLastSeen' => '100',
),
array(
'Id' => '3',
'Path' => '/path/folder_a/file_a.txt',
'PathNestingLevel' => '2',
'PathHash' => '2179111923',
'RefName' => '',
'ProjectPath' => '',
'RevisionAdded' => '60',
'RevisionDeleted' => '100',
'RevisionLastSeen' => '60',
),
array(
'Id' => '4',
'Path' => '/path/folder_a/sub_folder_a/',
'PathNestingLevel' => '3',
'PathHash' => '1400457329',
'RefName' => '',
'ProjectPath' => '',
'RevisionAdded' => '60',
'RevisionDeleted' => '200',
'RevisionLastSeen' => '70',
),
array(
'Id' => '5',
'Path' => '/path/folder_b/',
'PathNestingLevel' => '2',
'PathHash' => '3007723502',
'RefName' => '',
'ProjectPath' => '',
'RevisionAdded' => '60',
'RevisionDeleted' => null,
'RevisionLastSeen' => '60',
),
array(
'Id' => '6',
'Path' => '/path/folder_a/sub_folder_a/sub_file_a.txt',
'PathNestingLevel' => '3',
'PathHash' => '2415052021',
'RefName' => '',
'ProjectPath' => '',
'RevisionAdded' => '70',
'RevisionDeleted' => '200',
'RevisionLastSeen' => '70',
),
)
);
}

public function testFindNoMatch()
{
$this->commitBuilder
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0"?>
<log>
<logentry revision="50">
<author>user</author>
<date>2015-10-13T13:30:16.473960Z</date>
<paths>
<path action="A" kind="dir">/path</path>
</paths>
<msg>message</msg>
</logentry>
<logentry revision="60">
<author>user</author>
<date>2015-10-13T13:30:16.473960Z</date>
<paths>
<path action="A" kind="dir">/path/folder_a</path>
<path action="A" kind="file">/path/folder_a/file_a.txt</path>
<path action="A" kind="dir">/path/folder_a/sub_folder_a</path>
<path action="A" kind="dir">/path/folder_b</path>
</paths>
<msg>message</msg>
</logentry>
<logentry revision="70">
<author>user</author>
<date>2015-10-13T13:30:16.473960Z</date>
<paths>
<path action="A" kind="file">/path/folder_a/sub_folder_a/sub_file_a.txt</path>
</paths>
<msg>message</msg>
</logentry>
<logentry revision="100">
<author>user</author>
<date>2015-10-13T13:30:16.473960Z</date>
<paths>
<path action="D" kind="file">/path/folder_a/file_a.txt</path>
</paths>
<msg>message</msg>
</logentry>
<logentry revision="200">
<author>user</author>
<date>2015-10-13T13:30:16.473960Z</date>
<paths>
<path action="D" kind="dir">/path/folder_a</path>
</paths>
<msg>message</msg>
</logentry>
</log>
Loading