diff --git a/src/Composer/Repository/Vcs/FossilDriver.php b/src/Composer/Repository/Vcs/FossilDriver.php index e0abd10fc..3874e56c5 100644 --- a/src/Composer/Repository/Vcs/FossilDriver.php +++ b/src/Composer/Repository/Vcs/FossilDriver.php @@ -34,56 +34,76 @@ class FossilDriver extends VcsDriver */ public function initialize() { - if (Filesystem::isLocalPath($this->url)) { + // Make sure fossil is installed and reachable. + $this->checkFossil(); + + // Ensure we are allowed to use this URL by config. + $this->config->prohibitUrlByConfig($this->url, $this->io); + + // Only if url points to a locally accessible directory, assume it's the checkout directory. + // Otherwise, it should be something fossil can clone from. + if (Filesystem::isLocalPath($this->url) && is_dir($this->url)) { $this->checkoutDir = $this->url; } else { - $this->repoFile = $this->config->get('cache-repo-dir') . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '.fossil'; - $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/'; + $localName = preg_replace('{[^a-z0-9]}i', '-', $this->url); + $this->repoFile = $this->config->get('cache-repo-dir') . '/' . $localName . '.fossil'; + $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . $localName . '/'; - $fs = new Filesystem(); - $fs->ensureDirectoryExists($this->checkoutDir); - - if (!is_writable(dirname($this->checkoutDir))) { - throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$this->checkoutDir.'" directory is not writable by the current user.'); - } - - // Ensure we are allowed to use this URL by config - $this->config->prohibitUrlByConfig($this->url, $this->io); - - // update the repo if it is a valid fossil repository - if (is_file($this->repoFile) && is_dir($this->checkoutDir) && 0 === $this->process->execute('fossil info', $output, $this->checkoutDir)) { - if (0 !== $this->process->execute('fossil pull', $output, $this->checkoutDir)) { - $this->io->writeError('Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')'); - } - } else { - // clean up directory and do a fresh clone into it - $fs->removeDirectory($this->checkoutDir); - $fs->remove($this->repoFile); - - $fs->ensureDirectoryExists($this->checkoutDir); - - if (0 !== $this->process->execute(sprintf('fossil clone %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoFile)), $output)) { - $output = $this->process->getErrorOutput(); - - if (0 !== $this->process->execute('fossil version', $ignoredOutput)) { - throw new \RuntimeException('Failed to clone '.$this->url.', fossil was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput()); - } - - throw new \RuntimeException('Failed to clone '.$this->url.' to repository ' . $this->repoFile . "\n\n" .$output); - } - - if (0 !== $this->process->execute(sprintf('fossil open %s', ProcessExecutor::escape($this->repoFile)), $output, $this->checkoutDir)) { - $output = $this->process->getErrorOutput(); - - throw new \RuntimeException('Failed to open repository '.$this->repoFile.' in ' . $this->checkoutDir . "\n\n" .$output); - } - } + $this->updateLocalRepo(); } $this->getTags(); $this->getBranches(); } + /** + * Check that fossil can be invoked via command line. + */ + protected function checkFossil() + { + if (0 !== $this->process->execute('fossil version', $ignoredOutput)) { + throw new \RuntimeException("fossil was not found, check that it is installed and in your PATH env.\n\n" . $this->process->getErrorOutput()); + } + } + + /** + * Clone or update existing local fossil repository. + */ + protected function updateLocalRepo() + { + $fs = new Filesystem(); + $fs->ensureDirectoryExists($this->checkoutDir); + + if (!is_writable(dirname($this->checkoutDir))) { + throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$this->checkoutDir.'" directory is not writable by the current user.'); + } + + // update the repo if it is a valid fossil repository + if (is_file($this->repoFile) && is_dir($this->checkoutDir) && 0 === $this->process->execute('fossil info', $output, $this->checkoutDir)) { + if (0 !== $this->process->execute('fossil pull', $output, $this->checkoutDir)) { + $this->io->writeError('Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')'); + } + } else { + // clean up directory and do a fresh clone into it + $fs->removeDirectory($this->checkoutDir); + $fs->remove($this->repoFile); + + $fs->ensureDirectoryExists($this->checkoutDir); + + if (0 !== $this->process->execute(sprintf('fossil clone %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoFile)), $output)) { + $output = $this->process->getErrorOutput(); + + throw new \RuntimeException('Failed to clone '.$this->url.' to repository ' . $this->repoFile . "\n\n" .$output); + } + + if (0 !== $this->process->execute(sprintf('fossil open %s', ProcessExecutor::escape($this->repoFile)), $output, $this->checkoutDir)) { + $output = $this->process->getErrorOutput(); + + throw new \RuntimeException('Failed to open repository '.$this->repoFile.' in ' . $this->checkoutDir . "\n\n" .$output); + } + } + } + /** * {@inheritDoc} */ @@ -140,9 +160,10 @@ class FossilDriver extends VcsDriver */ public function getChangeDate($identifier) { - $this->process->execute(sprintf('fossil finfo composer.json | head -n 2 | tail -n 1 | awk \'{print $1}\''), $output, $this->checkoutDir); - - return new \DateTime(trim($output), new \DateTimeZone('UTC')); + $this->process->execute('fossil finfo -b -n 1 composer.json', $output, $this->checkoutDir); + list($ckout, $date, $message) = explode(' ', trim($output), 3); + + return new \DateTime($date, new \DateTimeZone('UTC')); } /**