Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added status command to display local changes to packages #842

Merged
merged 1 commit into from
Aug 18, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions src/Composer/Command/StatusCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Composer\Command;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Composer\Downloader\VcsDownloader;

/**
* @author Tiago Ribeiro <tiago.ribeiro@seegno.com>
* @author Rui Marinho <rui.marinho@seegno.com>
*/
class StatusCommand extends Command
{
protected function configure()
{
$this
->setName('status')
->setDescription('Show a list of locally modified packages')
->setHelp(<<<EOT
The status command displays a list of packages that have
been modified locally.

EOT
)
;
}

protected function execute(InputInterface $input, OutputInterface $output)
{
// init repos
$composer = $this->getComposer();
$installedRepo = $composer->getRepositoryManager()->getLocalRepository();

$dm = $composer->getDownloadManager();
$im = $composer->getInstallationManager();

$errors = array();

// list packages
foreach ($installedRepo->getPackages() as $package) {
$downloader = $dm->getDownloaderForInstalledPackage($package);

if ($downloader instanceof VcsDownloader) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is InstallerInterface descendants knows 'correct' disposition of package files. Downloaders just bring files here from somewhere... and their result can be altered by installers.

$targetDir = $im->getInstallPath($package);

if ($downloader->hasLocalChanges($targetDir)) {
$errors[] = $targetDir;
}
}
}

// output errors/warnings
if (!$errors) {
$output->writeln('<info>No local changes</info>');
} else {
$output->writeln('<error>You have changes in the following packages:</error>');
}

foreach ($errors as $error) {
$output->writeln($error);
}

return $errors ? 1 : 0;
}
}
1 change: 1 addition & 0 deletions src/Composer/Console/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ protected function getDefaultCommands()
$commands[] = new Command\ValidateCommand();
$commands[] = new Command\ShowCommand();
$commands[] = new Command\RequireCommand();
$commands[] = new Command\StatusCommand();

if ('phar:' === substr(__FILE__, 0, 5)) {
$commands[] = new Command\SelfUpdateCommand();
Expand Down
28 changes: 13 additions & 15 deletions src/Composer/Downloader/GitDownloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,19 @@ public function doUpdate(PackageInterface $initial, PackageInterface $target, $p
$this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate());
}

/**
* {@inheritDoc}
*/
public function hasLocalChanges($path)
{
$command = sprintf('cd %s && git status --porcelain --untracked-files=no', escapeshellarg($path));
if (0 !== $this->process->execute($command, $output)) {
throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
}

return (bool) trim($output);
}

protected function updateToCommit($path, $reference, $branch, $date)
{
$template = 'git checkout %s && git reset --hard %1$s';
Expand Down Expand Up @@ -113,21 +126,6 @@ protected function updateToCommit($path, $reference, $branch, $date)
throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
}

/**
* {@inheritDoc}
*/
protected function enforceCleanDirectory($path)
{
$command = sprintf('cd %s && git status --porcelain --untracked-files=no', escapeshellarg($path));
if (0 !== $this->process->execute($command, $output)) {
throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
}

if (trim($output)) {
throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes');
}
}

/**
* Runs a command doing attempts for each protocol supported by github.
*
Expand Down
7 changes: 3 additions & 4 deletions src/Composer/Downloader/HgDownloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,10 @@ public function doUpdate(PackageInterface $initial, PackageInterface $target, $p
/**
* {@inheritDoc}
*/
protected function enforceCleanDirectory($path)
public function hasLocalChanges($path)
{
$this->process->execute(sprintf('cd %s && hg st', escapeshellarg($path)), $output);
if (trim($output)) {
throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes');
}

return (bool) trim($output);
}
}
7 changes: 3 additions & 4 deletions src/Composer/Downloader/SvnDownloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,11 @@ public function doUpdate(PackageInterface $initial, PackageInterface $target, $p
/**
* {@inheritDoc}
*/
protected function enforceCleanDirectory($path)
public function hasLocalChanges($path)
{
$this->process->execute('svn status --ignore-externals', $output, $path);
if (preg_match('{^ *[^X ] +}m', $output)) {
throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes:'."\n\n".rtrim($output));
}

return preg_match('{^ *[^X ] +}m', $output);
}

/**
Expand Down
19 changes: 16 additions & 3 deletions src/Composer/Downloader/VcsDownloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ public function remove(PackageInterface $package, $path)
}
}

/**
* Guarantee that no changes have been made to the local copy
*
* @throws \RuntimeException if the directory is not clean
*/
protected function enforceCleanDirectory($path)
{
if ($this->hasLocalChanges($path)) {
throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.');
}
}

/**
* Downloads specific package into specific folder.
*
Expand All @@ -101,9 +113,10 @@ abstract protected function doDownload(PackageInterface $package, $path);
abstract protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path);

/**
* Checks that no changes have been made to the local copy
* Checks for changes to the local copy
*
* @throws \RuntimeException if the directory is not clean
* @param string $path package directory
* @return boolean whether package has local changes
*/
abstract protected function enforceCleanDirectory($path);
abstract public function hasLocalChanges($path);
}