/** * Determine historic release plan from a past composer constraint * * @param LibraryRelease $newRelease * @param Version $historicVersion * @return ChangelogLibrary Changelog information for a library */ protected function getChangelogLibrary(LibraryRelease $newRelease, Version $historicVersion) { // Build root release node $historicRelease = new ChangelogLibrary($newRelease, $historicVersion); // Check all dependencies from this past commit $pastComposer = null; foreach ($newRelease->getItems() as $childNewRelease) { // Lazy-load historic composer content as needed if (!isset($pastComposer)) { $pastComposer = $newRelease->getLibrary()->getHistoryComposerData($historicVersion); } // Check if this release has a historic tag. $childReleaseName = $childNewRelease->getLibrary()->getName(); if (empty($pastComposer['require'][$childReleaseName])) { continue; } $historicConstraintName = $pastComposer['require'][$childReleaseName]; // Get oldest existing tag that matches the given constraint as the "from" for changelog purposes. $historicConstraint = new ComposerConstraint($historicConstraintName, $historicVersion, $childReleaseName); $childVersions = $historicConstraint->filterVersions($childNewRelease->getLibrary()->getTags()); // If "to" is stable, then filter out unstable "from" // E.g. prefer "3.4.0..3.4.1" over "3.4.0-rc1..3.4.1" if ($childNewRelease->getVersion()->isStable()) { $childVersions = Version::filter($childVersions, function (Version $nextTag) { return $nextTag->isStable(); }); } // Get smallest matching version $childVersions = Version::sort($childVersions, Version::ASC); if (empty($childVersions)) { throw new \LogicException("No historic version for library {$childReleaseName} matches constraint {$historicConstraintName}"); } // Check if to == from version $childHistoricVersion = reset($childVersions); if ($childHistoricVersion->getValue() === $childNewRelease->getVersion()->getValue()) { continue; } // Recursively generate historic tree $childChangelog = $this->getChangelogLibrary($childNewRelease, $childHistoricVersion); $historicRelease->addItem($childChangelog); } return $historicRelease; }
/** * Propose a new version to tag for a given dependency * * @param LibraryRelease $parentRelease * @param Library $childModule * @return mixed|Version * @throws Exception */ protected function proposeNewReleaseVersion(LibraryRelease $parentRelease, Library $childModule) { // Get tags and composer constraint to filter by $tags = $childModule->getTags(); $constraint = $parentRelease->getLibrary()->getChildConstraint($childModule->getName(), $parentRelease->getVersion()); // Upgrade to self.version if ($constraint->isSelfVersion()) { $candidateVersion = $parentRelease->getVersion(); // If this is already tagged, just upgrade without a new release if (array_key_exists($candidateVersion->getValue(), $tags)) { return new LibraryRelease($childModule, $candidateVersion); } // Build release return new LibraryRelease($childModule, $candidateVersion); } // Get stability to use for the new tag $useSameStability = $parentRelease->getLibrary()->isStabilityInherited($childModule); if ($useSameStability) { $stability = $parentRelease->getVersion()->getStability(); $stabilityVersion = $parentRelease->getVersion()->getStabilityVersion(); } else { $stability = ''; $stabilityVersion = null; } // Filter versions $candidates = $constraint->filterVersions($tags); $tags = Version::sort($candidates, 'descending'); // Determine which best tag to create (with the correct stability) $existingTag = reset($tags); if ($existingTag) { // Increment from to guess next version $version = $existingTag->getNextVersion($stability, $stabilityVersion); } else { // In this case, the lower bounds of the constraint isn't a valid tag, // so this is our new candidate $version = clone $constraint->getMinVersion(); $version->setStability($stability); $version->setStabilityVersion($stabilityVersion); } // Report new tag return new LibraryRelease($childModule, $version); }