From bcec83a9b954d858b502514cd5902f58f3e21a6c Mon Sep 17 00:00:00 2001 From: Eirik Stanghelle Morland Date: Mon, 6 Feb 2023 13:10:15 +0100 Subject: [PATCH] Add method for retrieving tags between shas (#10) --- src/ChangelogRetriever.php | 46 +++++++++++++++++++++++++++ tests/Unit/ChangelogRetrieverTest.php | 19 +++++++++++ tests/assets/psrlog-example.txt | 21 ++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 tests/assets/psrlog-example.txt diff --git a/src/ChangelogRetriever.php b/src/ChangelogRetriever.php index ee38813..2e65aee 100644 --- a/src/ChangelogRetriever.php +++ b/src/ChangelogRetriever.php @@ -2,6 +2,7 @@ namespace Violinist\ChangelogFetcher; +use Symfony\Component\Process\Process; use Violinist\ComposerLockData\ComposerLockData; use Violinist\GitLogFormat\ChangeLogData; use Violinist\ProcessFactory\ProcessFactoryInterface; @@ -31,6 +32,51 @@ public function __construct(DependencyRepoRetriever $retriever, ProcessFactoryIn $this->processFactory = $processFactory; } + public function retrieveTagsBetweenShas($lockdata, $package_name, $sha1, $sha2) : array + { + $clone_path = $this->getClonePathAndRetrieveRepo($lockdata, $package_name); + $command = [ + 'git', + '-C', + $clone_path, + 'log', + sprintf('%s...%s', $sha1, $sha2), + '--decorate', '--simplify-by-decoration', + ]; + $process = $this->processFactory->getProcess($command); + $process->run(); + if ($process->getExitCode()) { + throw new \Exception('No tags found for the range'); + } + + $output = $process->getOutput(); + // OK, so filter all lines that contain something like "tag: v1.2.3". Or + // mimick what would be a pipe to grep like this: + // | grep -o 'tag: [^,)]\+' + $useful_array = array_values(array_filter(explode("\n", $output), function ($line) { + return preg_match('/tag: [^,)]/', $line); + })); + // Now we have the lines, now we just need to filter out the tag parts + // of it. This mimics doing some pipe to sed thing we used to have. + $actual_tags = array_map(function ($line) { + // At this point, the string will either look something like this: + // commit 5f0f17732e88efcd15d2554d4d4c2df4e380e65f (tag: v3.3.1, origin/3.3) + // or like this: + // commit e26ee41a73d1ae3adbd3c06eaf039ac3c1dfcc57 (tag: 3.3.0) + // or variations of that. + $tag_line_matches = []; + preg_match('/tag: .*[,)]/', $line, $tag_line_matches); + // Now, remove the string "tag: " + if (empty($tag_line_matches[0])) { + return null; + } + $without_tag = str_replace('tag: ', '', $tag_line_matches[0]); + $only_actual_tag = preg_replace('/\)?|,.*/', '', $without_tag); + return $only_actual_tag; + }, $useful_array); + return array_filter($actual_tags); + } + public function retrieveChangelogAndChangedFiles($package_name, $lockdata, $version_from, $version_to) : ChangesData { $changelog = $this->retrieveChangelog($package_name, $lockdata, $version_from, $version_to); diff --git a/tests/Unit/ChangelogRetrieverTest.php b/tests/Unit/ChangelogRetrieverTest.php index 0b0c568..4cafad9 100644 --- a/tests/Unit/ChangelogRetrieverTest.php +++ b/tests/Unit/ChangelogRetrieverTest.php @@ -133,6 +133,25 @@ public function testRetrieveChangelogAndChangedFiles() ', $markdown); } + public function testRetrieveTags() + { + $fake_package_data = $this->getTestData(); + $mock_retriever = $this->getMockRetriever($fake_package_data); + $mock_process = $this->createMock(Process::class); + $mock_process->method('getOutput') + ->willReturn(file_get_contents(__DIR__ . '/../assets/psrlog-example.txt')); + $mock_process_factory = $this->createMock(ProcessFactoryInterface::class); + $mock_process_factory->method('getProcess') + ->willReturn($mock_process); + $retriever = new ChangelogRetriever($mock_retriever, $mock_process_factory); + $fake_lock = (object) [ + 'packages' => [ + $fake_package_data, + ], + ]; + $tags = $retriever->retrieveTagsBetweenShas($fake_lock, 'psr/log', 'd49695b909c3b7628b6289db5479a1c204601f11', 'bf73deb2b3b896a9d9c75f3f0d88185d2faa27e2'); + self::assertEquals(['1.1.4', '1.1.3', '1.1.2'], $tags); + } protected function getMockRetriever($fake_package_data) { diff --git a/tests/assets/psrlog-example.txt b/tests/assets/psrlog-example.txt new file mode 100644 index 0000000..88aa798 --- /dev/null +++ b/tests/assets/psrlog-example.txt @@ -0,0 +1,21 @@ +commit d49695b909c3b7628b6289db5479a1c204601f11 (tag: 1.1.4) +Author: Jordi Boggiano +Date: Mon May 3 13:20:27 2021 +0200 + + Merge pull request #74 from Jeckerson/master + + Clarify type of 2nd argument `context` + +commit 0f73288fd15629204f9d42b7055f72dacbe811fc (tag: 1.1.3) +Author: Jordi Boggiano +Date: Mon Mar 23 10:12:05 2020 +0100 + + Merge pull request #70 from greg0ire/better-typehints + + Be explicit about mixed context elements + +commit 446d54b4cb6bf489fc9d75f55843658e6f25d801 (tag: 1.1.2) +Author: sebastianstucke87 <47354551+sebastianstucke87@users.noreply.github.com> +Date: Fri Nov 1 12:05:21 2019 +0100 + + Add "exception"-context array key to docs