Fix uncommitted change detection, refs #3633
parent
9f4f8a9578
commit
be4d385942
|
@ -81,7 +81,7 @@ EOT
|
|||
}
|
||||
|
||||
if ($downloader instanceof DvcsDownloaderInterface) {
|
||||
if ($unpushed = $downloader->getUnpushedChanges($targetDir)) {
|
||||
if ($unpushed = $downloader->getUnpushedChanges($package, $targetDir)) {
|
||||
$unpushedChanges[$targetDir] = $unpushed;
|
||||
}
|
||||
}
|
||||
|
@ -123,8 +123,8 @@ EOT
|
|||
}
|
||||
}
|
||||
|
||||
if ($errors && !$input->getOption('verbose')) {
|
||||
$io->writeError('Use --verbose (-v) to see modified files');
|
||||
if (($errors || $unpushedChanges) && !$input->getOption('verbose')) {
|
||||
$io->writeError('Use --verbose (-v) to see a list of files');
|
||||
}
|
||||
|
||||
// Dispatch post-status-command
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
namespace Composer\Downloader;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* DVCS Downloader interface.
|
||||
*
|
||||
|
@ -22,8 +24,9 @@ interface DvcsDownloaderInterface
|
|||
/**
|
||||
* Checks for unpushed changes to a current branch
|
||||
*
|
||||
* @param string $path package directory
|
||||
* @return string|null changes or null
|
||||
* @param PackageInterface $package package directory
|
||||
* @param string $path package directory
|
||||
* @return string|null changes or null
|
||||
*/
|
||||
public function getUnpushedChanges($path);
|
||||
public function getUnpushedChanges(PackageInterface $package, $path);
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
|
|||
return trim($output) ?: null;
|
||||
}
|
||||
|
||||
public function getUnpushedChanges($path)
|
||||
public function getUnpushedChanges(PackageInterface $package, $path)
|
||||
{
|
||||
GitUtil::cleanEnv();
|
||||
$path = $this->normalizePath($path);
|
||||
|
@ -127,11 +127,41 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
|
|||
|
||||
$branch = trim($output);
|
||||
|
||||
$command = sprintf('git diff --name-status %s..composer/%s', $branch, $branch);
|
||||
// we are on a detached HEAD tag so no need to check for changes
|
||||
if ($branch === 'HEAD') {
|
||||
return;
|
||||
}
|
||||
|
||||
// check that the branch exists in composer remote, if not then we should assume it is an unpushed branch
|
||||
$command = sprintf('git rev-parse --verify composer/%s', $branch);
|
||||
if (0 !== $this->process->execute($command, $output, $path)) {
|
||||
$composerBranch = preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $package->getPrettyVersion());
|
||||
$branches = '';
|
||||
if (0 === $this->process->execute('git branch -r', $output, $path)) {
|
||||
$branches = $output;
|
||||
}
|
||||
// add 'v' in front of the branch if it was stripped when generating the pretty name
|
||||
if (!preg_match('{^\s+composer/'.preg_quote($composerBranch).'$}m', $branches) && preg_match('{^\s+composer/v'.preg_quote($composerBranch).'$}m', $branches)) {
|
||||
$composerBranch = 'v' . $composerBranch;
|
||||
}
|
||||
} else {
|
||||
$composerBranch = $branch;
|
||||
}
|
||||
|
||||
$command = sprintf('git diff --name-status composer/%s...%s', $composerBranch, $branch);
|
||||
if (0 !== $this->process->execute($command, $output, $path)) {
|
||||
throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
|
||||
}
|
||||
|
||||
if (trim($output)) {
|
||||
// fetch from both to make sure we have up to date remotes
|
||||
$this->process->execute('git fetch composer && git fetch origin', $output, $path);
|
||||
|
||||
if (0 !== $this->process->execute($command, $output, $path)) {
|
||||
throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
|
||||
}
|
||||
}
|
||||
|
||||
return trim($output) ?: null;
|
||||
}
|
||||
|
||||
|
@ -143,8 +173,9 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
|
|||
GitUtil::cleanEnv();
|
||||
$path = $this->normalizePath($path);
|
||||
|
||||
if (null !== $this->getUnpushedChanges($path)) {
|
||||
throw new \RuntimeException('Source directory ' . $path . ' has unpushed changes on the current branch.');
|
||||
$unpushed = $this->getUnpushedChanges($package, $path);
|
||||
if ($unpushed && ($this->io->isInteractive() || $this->config->get('discard-changes') !== true)) {
|
||||
throw new \RuntimeException('Source directory ' . $path . ' has unpushed changes on the current branch: '."\n".$unpushed);
|
||||
}
|
||||
|
||||
if (!$changes = $this->getLocalChanges($package, $path)) {
|
||||
|
|
|
@ -271,25 +271,29 @@ class GitDownloaderTest extends TestCase
|
|||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(1))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git diff --name-status ..composer/")))
|
||||
->with($this->equalTo($this->winCompat("git rev-parse --verify composer/")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(2))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git status --porcelain --untracked-files=no")))
|
||||
->with($this->equalTo($this->winCompat("git diff --name-status composer/...")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(3))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git remote -v")))
|
||||
->with($this->equalTo($this->winCompat("git status --porcelain --untracked-files=no")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(4))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat($expectedGitUpdateCommand)), $this->equalTo(null), $this->equalTo($this->winCompat($this->workingDir)))
|
||||
->with($this->equalTo($this->winCompat("git remote -v")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(5))
|
||||
->method('execute')
|
||||
->with($this->equalTo('git branch -r'))
|
||||
->with($this->equalTo($this->winCompat($expectedGitUpdateCommand)), $this->equalTo(null), $this->equalTo($this->winCompat($this->workingDir)))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(6))
|
||||
->method('execute')
|
||||
->with($this->equalTo('git branch -r'))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(7))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git checkout 'ref' -- && git reset --hard 'ref' --")), $this->equalTo(null), $this->equalTo($this->winCompat($this->workingDir)))
|
||||
->will($this->returnValue(0));
|
||||
|
@ -321,17 +325,21 @@ class GitDownloaderTest extends TestCase
|
|||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(1))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git diff --name-status ..composer/")))
|
||||
->with($this->equalTo($this->winCompat("git rev-parse --verify composer/")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(2))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git status --porcelain --untracked-files=no")))
|
||||
->with($this->equalTo($this->winCompat("git diff --name-status composer/...")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(3))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git remote -v")))
|
||||
->with($this->equalTo($this->winCompat("git status --porcelain --untracked-files=no")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(4))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git remote -v")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(5))
|
||||
->method('execute')
|
||||
->with($this->equalTo($expectedGitUpdateCommand))
|
||||
->will($this->returnValue(1));
|
||||
|
@ -356,33 +364,45 @@ class GitDownloaderTest extends TestCase
|
|||
$processExecutor = $this->getMock('Composer\Util\ProcessExecutor');
|
||||
$processExecutor->expects($this->at(0))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git status --porcelain --untracked-files=no")))
|
||||
->with($this->equalTo($this->winCompat("git rev-parse --abbrev-ref HEAD")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(1))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git remote -v")))
|
||||
->with($this->equalTo($this->winCompat("git rev-parse --verify composer/")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(2))
|
||||
->method('execute')
|
||||
->with($this->equalTo($expectedFirstGitUpdateCommand))
|
||||
->will($this->returnValue(1));
|
||||
$processExecutor->expects($this->at(4))
|
||||
->with($this->equalTo($this->winCompat("git diff --name-status composer/...")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(3))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git --version")))
|
||||
->with($this->equalTo($this->winCompat("git status --porcelain --untracked-files=no")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(4))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git remote -v")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(5))
|
||||
->method('execute')
|
||||
->with($this->equalTo($expectedFirstGitUpdateCommand))
|
||||
->will($this->returnValue(1));
|
||||
$processExecutor->expects($this->at(7))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git --version")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(8))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git remote -v")))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(6))
|
||||
$processExecutor->expects($this->at(9))
|
||||
->method('execute')
|
||||
->with($this->equalTo($expectedSecondGitUpdateCommand))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(7))
|
||||
$processExecutor->expects($this->at(11))
|
||||
->method('execute')
|
||||
->with($this->equalTo('git branch -r'))
|
||||
->will($this->returnValue(0));
|
||||
$processExecutor->expects($this->at(8))
|
||||
$processExecutor->expects($this->at(13))
|
||||
->method('execute')
|
||||
->with($this->equalTo($this->winCompat("git checkout 'ref' -- && git reset --hard 'ref' --")), $this->equalTo(null), $this->equalTo($this->winCompat($this->workingDir)))
|
||||
->will($this->returnValue(0));
|
||||
|
|
Loading…
Reference in New Issue