1
0
Fork 0

Merge remote-tracking branch 'xrstf/mercurial-support'

pull/1520/head
Jordi Boggiano 2013-01-23 15:47:51 +01:00
commit 5bac9ffaaa
2 changed files with 117 additions and 32 deletions

View File

@ -160,9 +160,21 @@ class RootPackageLoader extends ArrayLoader
}
private function guessVersion(array $config)
{
if (function_exists('proc_open')) {
$version = $this->guessGitVersion($config);
if (null !== $version) {
return $version;
}
return $this->guessHgVersion($config);
}
}
private function guessGitVersion(array $config)
{
// try to fetch current version from git branch
if (function_exists('proc_open') && 0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output)) {
if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output)) {
$branches = array();
$isFeatureBranch = false;
$version = null;
@ -193,32 +205,71 @@ class RootPackageLoader extends ArrayLoader
return $version;
}
// ignore feature branches if they have no branch-alias or self.version is used
// and find the branch they came from to use as a version instead
if ((isset($config['extra']['branch-alias']) && !isset($config['extra']['branch-alias'][$version]))
|| strpos(json_encode($config), '"self.version"')
) {
$branch = preg_replace('{^dev-}', '', $version);
$length = PHP_INT_MAX;
foreach ($branches as $candidate) {
// do not compare against other feature branches
if ($candidate === $branch || !preg_match('{^(master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
continue;
}
if (0 !== $this->process->execute('git rev-list '.$candidate.'..'.$branch, $output)) {
continue;
}
if (strlen($output) < $length) {
$length = strlen($output);
$version = $this->versionParser->normalizeBranch($candidate);
if ('9999999-dev' === $version) {
$version = 'dev-'.$match[1];
}
}
}
}
// try to find the best (nearest) version branch to assume this feature's version
$version = $this->guessFeatureVersion($config, $version, $branches, 'git rev-list %candidate%..%branch%');
return $version;
}
}
private function guessHgVersion(array $config)
{
// try to fetch current version from hg branch
if (0 === $this->process->execute('hg branch', $output)) {
$branch = trim($output);
$version = $this->versionParser->normalizeBranch($branch);
$isFeatureBranch = 0 === strpos($version, 'dev-');
if ('9999999-dev' === $version) {
$version = 'dev-'.$branch;
}
if (!$isFeatureBranch) {
return $version;
}
// re-use the HgDriver to fetch branches (this properly includes bookmarks)
$config = array('url' => getcwd());
$driver = new HgDriver($config, new NullIO(), $this->config, $this->process);
$branches = array_keys($driver->getBranches());
// try to find the best (nearest) version branch to assume this feature's version
$version = $this->guessFeatureVersion($config, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"');
return $version;
}
}
private function guessFeatureVersion(array $config, $version, array $branches, $scmCmdline)
{
// ignore feature branches if they have no branch-alias or self.version is used
// and find the branch they came from to use as a version instead
if ((isset($config['extra']['branch-alias']) && !isset($config['extra']['branch-alias'][$version]))
|| strpos(json_encode($config), '"self.version"')
) {
$branch = preg_replace('{^dev-}', '', $version);
$length = PHP_INT_MAX;
foreach ($branches as $candidate) {
// do not compare against other feature branches
if ($candidate === $branch || !preg_match('{^(master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
continue;
}
$cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
if (0 !== $this->process->execute($cmdLine, $output)) {
continue;
}
if (strlen($output) < $length) {
$length = strlen($output);
$version = $this->versionParser->normalizeBranch($candidate);
if ('9999999-dev' === $version) {
$version = 'dev-'.$match[1];
}
}
}
}
return $version;
}
}

View File

@ -288,13 +288,9 @@ class Locker
unset($spec['version_normalized']);
if ($package->isDev()) {
if (function_exists('proc_open') && 'git' === $package->getSourceType() && ($path = $this->installationManager->getInstallPath($package))) {
$sourceRef = $package->getSourceReference() ?: $package->getDistReference();
$process = new ProcessExecutor();
if (0 === $process->execute('git log -n1 --pretty=%ct '.escapeshellarg($sourceRef), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) {
$datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
$spec['time'] = $datetime->format('Y-m-d H:i:s');
}
$time = $this->getPackageTime($package);
if (null !== $time) {
$spec['time'] = $time;
}
}
@ -316,4 +312,42 @@ class Locker
return $locked;
}
/**
* Returns the packages's datetime for its source reference.
*
* @param PackageInterface $package The package to scan.
* @return string|null The formatted datetime or null if none was found.
*/
private function getPackageTime(PackageInterface $package)
{
if (!function_exists('proc_open')) {
return null;
}
$path = $this->installationManager->getInstallPath($package);
$sourceType = $package->getSourceType();
$datetime = null;
if ($path && in_array($sourceType, array('git', 'hg'))) {
$sourceRef = $package->getSourceReference() ?: $package->getDistReference();
$process = new ProcessExecutor();
switch ($sourceType) {
case 'git':
if (0 === $process->execute('git log -n1 --pretty=%ct '.escapeshellarg($sourceRef), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) {
$datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
}
break;
case 'hg':
if (0 === $process->execute('hg log --template "{date|hgdate}" -r '.escapeshellarg($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) {
$datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC'));
}
break;
}
}
return $datetime ? $datetime->format('Y-m-d H:i:s') : null;
}
}