function GitDownloader::updateToCommit
Updates the given path to the given commit ref
Return value
null|string if a string is returned, it is the commit reference that was checked out if the original could not be found
Throws
\RuntimeException
2 calls to GitDownloader::updateToCommit()
- GitDownloader::doInstall in vendor/
composer/ composer/ src/ Composer/ Downloader/ GitDownloader.php - @inheritDoc
- GitDownloader::doUpdate in vendor/
composer/ composer/ src/ Composer/ Downloader/ GitDownloader.php - @inheritDoc
File
-
vendor/
composer/ composer/ src/ Composer/ Downloader/ GitDownloader.php, line 435
Class
- GitDownloader
- @author Jordi Boggiano <j.boggiano@seld.be>
Namespace
Composer\DownloaderCode
protected function updateToCommit(PackageInterface $package, string $path, string $reference, string $prettyVersion) : ?string {
$force = !empty($this->hasDiscardedChanges[$path]) || !empty($this->hasStashedChanges[$path]) ? [
'-f',
] : [];
// This uses the "--" sequence to separate branch from file parameters.
//
// Otherwise git tries the branch name as well as file name.
// If the non-existent branch is actually the name of a file, the file
// is checked out.
$branch = Preg::replace('{(?:^dev-|(?:\\.x)?-dev$)}i', '', $prettyVersion);
/**
* @var \Closure(non-empty-list<string>): bool $execute
* @phpstan-ignore varTag.nativeType
*/
$execute = function (array $command) use (&$output, $path) {
/** @var non-empty-list<string> $command */
$output = '';
return 0 === $this->process
->execute($command, $output, $path);
};
$branches = null;
if ($execute([
'git',
'branch',
'-r',
])) {
$branches = $output;
}
// check whether non-commitish are branches or tags, and fetch branches with the remote name
$gitRef = $reference;
if (!Preg::isMatch('{^[a-f0-9]{40}$}', $reference) && null !== $branches && Preg::isMatch('{^\\s+composer/' . preg_quote($reference) . '$}m', $branches)) {
$command1 = array_merge([
'git',
'checkout',
], $force, [
'-B',
$branch,
'composer/' . $reference,
'--',
]);
$command2 = [
'git',
'reset',
'--hard',
'composer/' . $reference,
'--',
];
if ($execute($command1) && $execute($command2)) {
return null;
}
}
// try to checkout branch by name and then reset it so it's on the proper branch name
if (Preg::isMatch('{^[a-f0-9]{40}$}', $reference)) {
// add 'v' in front of the branch if it was stripped when generating the pretty name
if (null !== $branches && !Preg::isMatch('{^\\s+composer/' . preg_quote($branch) . '$}m', $branches) && Preg::isMatch('{^\\s+composer/v' . preg_quote($branch) . '$}m', $branches)) {
$branch = 'v' . $branch;
}
$command = [
'git',
'checkout',
$branch,
'--',
];
$fallbackCommand = array_merge([
'git',
'checkout',
], $force, [
'-B',
$branch,
'composer/' . $branch,
'--',
]);
$resetCommand = [
'git',
'reset',
'--hard',
$reference,
'--',
];
if (($execute($command) || $execute($fallbackCommand)) && $execute($resetCommand)) {
return null;
}
}
$command1 = array_merge([
'git',
'checkout',
], $force, [
$gitRef,
'--',
]);
$command2 = [
'git',
'reset',
'--hard',
$gitRef,
'--',
];
if ($execute($command1) && $execute($command2)) {
return null;
}
$exceptionExtra = '';
// reference was not found (prints "fatal: reference is not a tree: $ref")
if (false !== strpos($this->process
->getErrorOutput(), $reference)) {
$this->io
->writeError(' <warning>' . $reference . ' is gone (history was rewritten?)</warning>');
$exceptionExtra = "\nIt looks like the commit hash is not available in the repository, maybe " . ($package->isDev() ? 'the commit was removed from the branch' : 'the tag was recreated') . '? Run "composer update ' . $package->getPrettyName() . '" to resolve this.';
}
$command = implode(' ', $command1) . ' && ' . implode(' ', $command2);
throw new \RuntimeException(Url::sanitize('Failed to execute ' . $command . "\n\n" . $this->process
->getErrorOutput() . $exceptionExtra));
}