mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 00:42:41 +01:00
Make "Land Revision" show merge conflicts more clearly
Summary: Ref T182. We just show "an error happened" right now. Improve this behavior. This error handling chain is a bit ad-hoc for now but we can formalize it as we hit other cases. Test Plan: {F910247} {F910248} Reviewers: chad Reviewed By: chad Maniphest Tasks: T182 Differential Revision: https://secure.phabricator.com/D14343
This commit is contained in:
parent
2326d5f8d0
commit
0b24a6e200
4 changed files with 153 additions and 10 deletions
|
@ -3,6 +3,8 @@
|
|||
final class DrydockWorkingCopyBlueprintImplementation
|
||||
extends DrydockBlueprintImplementation {
|
||||
|
||||
const PHASE_SQUASHMERGE = 'squashmerge';
|
||||
|
||||
public function isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
@ -288,7 +290,7 @@ final class DrydockWorkingCopyBlueprintImplementation
|
|||
$merges = idx($spec, 'merges');
|
||||
if ($merges) {
|
||||
foreach ($merges as $merge) {
|
||||
$this->applyMerge($interface, $merge);
|
||||
$this->applyMerge($lease, $interface, $merge);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -416,6 +418,7 @@ final class DrydockWorkingCopyBlueprintImplementation
|
|||
}
|
||||
|
||||
private function applyMerge(
|
||||
DrydockLease $lease,
|
||||
DrydockCommandInterface $interface,
|
||||
array $merge) {
|
||||
|
||||
|
@ -428,15 +431,48 @@ final class DrydockWorkingCopyBlueprintImplementation
|
|||
$src_ref,
|
||||
$src_ref);
|
||||
|
||||
$command = csprintf(
|
||||
'git merge --no-stat --squash --ff-only -- %R',
|
||||
$src_ref);
|
||||
|
||||
try {
|
||||
$interface->execx(
|
||||
'git merge --no-stat --squash --ff-only -- %s',
|
||||
$src_ref);
|
||||
$interface->execx('%C', $command);
|
||||
} catch (CommandException $ex) {
|
||||
// TODO: Specifically note this as a merge conflict.
|
||||
$this->setWorkingCopyVCSErrorFromCommandException(
|
||||
$lease,
|
||||
self::PHASE_SQUASHMERGE,
|
||||
$command,
|
||||
$ex);
|
||||
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
protected function setWorkingCopyVCSErrorFromCommandException(
|
||||
DrydockLease $lease,
|
||||
$phase,
|
||||
$command,
|
||||
CommandException $ex) {
|
||||
|
||||
$error = array(
|
||||
'phase' => $phase,
|
||||
'command' => (string)$command,
|
||||
'raw' => (string)$ex->getCommand(),
|
||||
'err' => $ex->getError(),
|
||||
'stdout' => $ex->getStdout(),
|
||||
'stderr' => $ex->getStderr(),
|
||||
);
|
||||
|
||||
$lease->setAttribute('workingcopy.vcs.error', $error);
|
||||
}
|
||||
|
||||
public function getWorkingCopyVCSError(DrydockLease $lease) {
|
||||
$error = $lease->getAttribute('workingcopy.vcs.error');
|
||||
if (!$error) {
|
||||
return null;
|
||||
} else {
|
||||
return $error;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -175,6 +175,14 @@ final class DrydockRepositoryOperation extends DrydockDAO
|
|||
return $this->getProperty('exec.leasePHID');
|
||||
}
|
||||
|
||||
public function setWorkingCopyVCSError(array $error) {
|
||||
return $this->setProperty('exec.workingcopy.error', $error);
|
||||
}
|
||||
|
||||
public function getWorkingCopyVCSError() {
|
||||
return $this->getProperty('exec.workingcopy.error');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
|
|
@ -73,12 +73,104 @@ final class DrydockRepositoryOperationStatusView
|
|||
if ($state != DrydockRepositoryOperation::STATE_FAIL) {
|
||||
$item->addAttribute($operation->getOperationCurrentStatus($viewer));
|
||||
} else {
|
||||
// TODO: Make this more useful.
|
||||
$item->addAttribute(pht('Operation encountered an error.'));
|
||||
$vcs_error = $operation->getWorkingCopyVCSError();
|
||||
if ($vcs_error) {
|
||||
switch ($vcs_error['phase']) {
|
||||
case DrydockWorkingCopyBlueprintImplementation::PHASE_SQUASHMERGE:
|
||||
$message = pht(
|
||||
'This change did not merge cleanly. This usually indicates '.
|
||||
'that the change is out of date and needs to be updated.');
|
||||
break;
|
||||
default:
|
||||
$message = pht(
|
||||
'Operation encountered an error while performing repository '.
|
||||
'operations.');
|
||||
break;
|
||||
}
|
||||
|
||||
$item->addAttribute($message);
|
||||
|
||||
$table = $this->renderVCSErrorTable($vcs_error);
|
||||
list($links, $info) = $this->renderDetailToggles($table);
|
||||
|
||||
$item->addAttribute($links);
|
||||
$item->appendChild($info);
|
||||
} else {
|
||||
$item->addAttribute(pht('Operation encountered an error.'));
|
||||
}
|
||||
}
|
||||
|
||||
return id(new PHUIObjectItemListView())
|
||||
->addItem($item);
|
||||
}
|
||||
|
||||
private function renderVCSErrorTable(array $vcs_error) {
|
||||
$rows = array();
|
||||
$rows[] = array(pht('Command'), $vcs_error['command']);
|
||||
$rows[] = array(pht('Error'), $vcs_error['err']);
|
||||
$rows[] = array(pht('Stdout'), $vcs_error['stdout']);
|
||||
$rows[] = array(pht('Stderr'), $vcs_error['stderr']);
|
||||
|
||||
$table = id(new AphrontTableView($rows))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
'header',
|
||||
'wide',
|
||||
));
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
private function renderDetailToggles(AphrontTableView $table) {
|
||||
$show_id = celerity_generate_unique_node_id();
|
||||
$hide_id = celerity_generate_unique_node_id();
|
||||
$info_id = celerity_generate_unique_node_id();
|
||||
|
||||
Javelin::initBehavior('phabricator-reveal-content');
|
||||
|
||||
$show_details = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'id' => $show_id,
|
||||
'href' => '#',
|
||||
'sigil' => 'reveal-content',
|
||||
'mustcapture' => true,
|
||||
'meta' => array(
|
||||
'hideIDs' => array($show_id),
|
||||
'showIDs' => array($hide_id, $info_id),
|
||||
),
|
||||
),
|
||||
pht('Show Details'));
|
||||
|
||||
$hide_details = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'id' => $hide_id,
|
||||
'href' => '#',
|
||||
'sigil' => 'reveal-content',
|
||||
'mustcapture' => true,
|
||||
'style' => 'display: none',
|
||||
'meta' => array(
|
||||
'hideIDs' => array($hide_id, $info_id),
|
||||
'showIDs' => array($show_id),
|
||||
),
|
||||
),
|
||||
pht('Hide Details'));
|
||||
|
||||
$info = javelin_tag(
|
||||
'div',
|
||||
array(
|
||||
'id' => $info_id,
|
||||
'style' => 'display: none',
|
||||
),
|
||||
$table);
|
||||
|
||||
$links = array(
|
||||
$show_details,
|
||||
$hide_details,
|
||||
);
|
||||
|
||||
return array($links, $info);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -90,6 +90,9 @@ final class DrydockRepositoryOperationUpdateWorker
|
|||
// TODO: This is very similar to leasing in Harbormaster, maybe we can
|
||||
// share some of the logic?
|
||||
|
||||
$working_copy = new DrydockWorkingCopyBlueprintImplementation();
|
||||
$working_copy_type = $working_copy->getType();
|
||||
|
||||
$lease_phid = $operation->getProperty('exec.leasePHID');
|
||||
if ($lease_phid) {
|
||||
$lease = id(new DrydockLeaseQuery())
|
||||
|
@ -103,9 +106,6 @@ final class DrydockRepositoryOperationUpdateWorker
|
|||
$lease_phid));
|
||||
}
|
||||
} else {
|
||||
$working_copy_type = id(new DrydockWorkingCopyBlueprintImplementation())
|
||||
->getType();
|
||||
|
||||
$repository = $operation->getRepository();
|
||||
|
||||
$allowed_phids = $repository->getAutomationBlueprintPHIDs();
|
||||
|
@ -138,6 +138,13 @@ final class DrydockRepositoryOperationUpdateWorker
|
|||
}
|
||||
|
||||
if (!$lease->isActive()) {
|
||||
$vcs_error = $working_copy->getWorkingCopyVCSError($lease);
|
||||
if ($vcs_error) {
|
||||
$operation
|
||||
->setWorkingCopyVCSError($vcs_error)
|
||||
->save();
|
||||
}
|
||||
|
||||
throw new PhabricatorWorkerPermanentFailureException(
|
||||
pht(
|
||||
'Lease "%s" never activated.',
|
||||
|
|
Loading…
Reference in a new issue