/** * {@inheritdoc} * * @throws \RuntimeException When invalid mode is specified. */ protected function execute(InputInterface $input, OutputInterface $output) { $mode = $this->io->getOption('mode'); if (!in_array($mode, $this->getModes())) { throw new \RuntimeException('The "' . $mode . '" mode is unknown.'); } $wc_path = $this->getWorkingCopyPath(); switch ($mode) { case self::MODE_SHOW: $recorded_conflicts = $this->_workingCopyConflictTracker->getRecordedConflicts($wc_path); if (!$recorded_conflicts) { $this->io->writeln('<info>The working copy doesn\'t have any recorded conflicts.</info>'); } else { $this->io->writeln('<error>Recorded Conflicts (' . count($recorded_conflicts) . ' paths):</error>'); foreach ($recorded_conflicts as $conflicted_path) { $this->io->writeln(' * ' . $conflicted_path); } } break; case self::MODE_ADD: $this->_workingCopyConflictTracker->add($wc_path); $this->io->writeln('<info>Conflicts updated.</info>'); break; case self::MODE_REPLACE: $this->_workingCopyConflictTracker->replace($wc_path); $this->io->writeln('<info>Conflicts updated.</info>'); break; case self::MODE_ERASE: $this->_workingCopyConflictTracker->erase($wc_path); $this->io->writeln('<info>Conflicts erased.</info>'); break; } }
/** * Returns commit message fragment for recent conflicts. * * @param string $wc_path Working copy path. * * @return string */ protected function getFragmentForRecentConflicts($wc_path) { $recorded_conflicts = $this->workingCopyConflictTracker->getRecordedConflicts($wc_path); if (!$recorded_conflicts) { return ''; } // Ensure empty line before. $ret = PHP_EOL . 'Conflicts:'; foreach ($recorded_conflicts as $conflict_path) { $ret .= PHP_EOL . ' * ' . $conflict_path; } return $ret; }
/** * Ensures, that there are no unresolved conflicts in working copy. * * @param string $source_url Source url. * @param string $wc_path Working copy path. * @param integer $largest_suggested_revision Largest revision, that is suggested in error message. * * @return void * @throws CommandException When merge conflicts detected. */ protected function ensureWorkingCopyWithoutConflicts($source_url, $wc_path, $largest_suggested_revision = null) { $this->io->write(' * Previous Merge Status ... '); $conflicts = $this->_workingCopyConflictTracker->getNewConflicts($wc_path); if (!$conflicts) { $this->io->writeln('<info>Successful</info>'); return; } $this->_workingCopyConflictTracker->add($wc_path); $this->io->writeln('<error>' . count($conflicts) . ' conflict(-s)</error>'); $table = new Table($this->io->getOutput()); if ($largest_suggested_revision) { $table->setHeaders(array('Path', 'Associated Revisions (before ' . $largest_suggested_revision . ')')); } else { $table->setHeaders(array('Path', 'Associated Revisions')); } $revision_log = $this->getRevisionLog($source_url); $source_path = $this->repositoryConnector->getRelativePath($source_url) . '/'; /** @var OutputHelper $output_helper */ $output_helper = $this->getHelper('output'); foreach ($conflicts as $conflict_path) { $path_revisions = $revision_log->find('paths', $source_path . $conflict_path); $path_revisions = array_intersect($this->_unmergedRevisions, $path_revisions); if ($path_revisions && isset($largest_suggested_revision)) { $path_revisions = $this->limitRevisions($path_revisions, $largest_suggested_revision); } $table->addRow(array($conflict_path, $path_revisions ? $output_helper->formatArray($path_revisions, 4) : '-')); } $table->render(); throw new CommandException('Working copy contains unresolved merge conflicts.'); }
/** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { $wc_path = $this->getWorkingCopyPath(); // Collect added path before "svn revert" because then they won't be shown as added by "svn status". $added_paths = $this->getAddedPaths(); $this->io->writeln('Reverting local changes in working copy ... '); $command = $this->repositoryConnector->getCommand('revert', '--depth infinity {' . $wc_path . '}'); $command->runLive(array($wc_path => '.')); $this->deletePaths($added_paths); $recorded_conflicts = $this->_workingCopyConflictTracker->getRecordedConflicts($wc_path); if ($recorded_conflicts) { $this->io->writeln(array('', 'Reverted Recorded Conflicts (' . count($recorded_conflicts) . ' paths):')); foreach ($recorded_conflicts as $conflicted_path) { $this->io->writeln(' * ' . $conflicted_path); } } $this->_workingCopyConflictTracker->erase($wc_path); $this->io->writeln('<info>Done</info>'); }
/** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { $wc_path = $this->getWorkingCopyPath(); $revision = $this->io->getOption('revision'); $ignore_externals = $this->io->getOption('ignore-externals'); $show_revision = $revision ? $revision : 'HEAD'; $show_externals = $ignore_externals ? '(excluding externals)' : '(including externals)'; $this->io->writeln('Updating working copy to <info>' . $show_revision . '</info> revision ' . $show_externals . ' ... '); $param_string = '{' . $wc_path . '}'; if ($revision) { $param_string .= ' --revision ' . $revision; } if ($ignore_externals) { $param_string .= ' --ignore-externals'; } $command = $this->repositoryConnector->getCommand('update', $param_string); $command->runLive(array($wc_path => '.')); if ($this->_workingCopyConflictTracker->getNewConflicts($wc_path)) { $this->_workingCopyConflictTracker->add($wc_path); } $this->io->writeln('<info>Done</info>'); }
/** * {@inheritdoc} * * @throws CommandException When conflicts are detected. * @throws CommandException Working copy has no changes. * @throws CommandException User decides not to perform a commit. */ protected function execute(InputInterface $input, OutputInterface $output) { $wc_path = $this->getWorkingCopyPath(); $conflicts = $this->_workingCopyConflictTracker->getNewConflicts($wc_path); if ($conflicts) { throw new CommandException('Conflicts detected. Please resolve them before committing.'); } $changelist = $this->getChangelist($wc_path); $compact_working_copy_status = $this->repositoryConnector->getCompactWorkingCopyStatus($wc_path, $changelist); if (!$compact_working_copy_status) { throw new CommandException('Nothing to commit.'); } $commit_message = $this->_commitMessageBuilder->build($wc_path, $this->getMergeTemplate(), $changelist); $commit_message .= PHP_EOL . PHP_EOL . self::STOP_LINE . PHP_EOL . PHP_EOL . $compact_working_copy_status; $edited_commit_message = $this->_editor->setDocumentName('commit_message')->setContent($commit_message)->launch(); $stop_line_pos = strpos($edited_commit_message, self::STOP_LINE); if ($stop_line_pos !== false) { $edited_commit_message = trim(substr($edited_commit_message, 0, $stop_line_pos)); } $this->io->writeln(array('<fg=white;options=bold>Commit message:</>', $edited_commit_message, '')); if (!$this->io->askConfirmation('Run "svn commit"', false)) { throw new CommandException('Commit aborted by user.'); } $tmp_file = tempnam(sys_get_temp_dir(), 'commit_message_'); file_put_contents($tmp_file, $edited_commit_message); $arguments = array('-F {' . $tmp_file . '}'); if (strlen($changelist)) { $arguments[] = '--depth empty'; // Relative path used to make command line shorter. foreach (array_keys($this->repositoryConnector->getWorkingCopyStatus($wc_path, $changelist)) as $path) { $arguments[] = '{' . $path . '}'; } } else { $arguments[] = '{' . $wc_path . '}'; } $this->repositoryConnector->getCommand('commit', implode(' ', $arguments))->runLive(); $this->_workingCopyConflictTracker->erase($wc_path); unlink($tmp_file); $this->io->writeln('<info>Done</info>'); }
public function testGetRecordedConflicts() { $wc_path = '/path/to/working-copy'; $this->expectRecordedConflicts($wc_path, array('old-file.txt')); $this->assertEquals(array('old-file.txt'), $this->workingCopyConflictTracker->getRecordedConflicts($wc_path)); }