Page MenuHomePhabricator

D14343.diff
No OneTemporary

D14343.diff

diff --git a/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php
--- a/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php
+++ b/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php
@@ -3,6 +3,8 @@
final class DrydockWorkingCopyBlueprintImplementation
extends DrydockBlueprintImplementation {
+ const PHASE_SQUASHMERGE = 'squashmerge';
+
public function isEnabled() {
return true;
}
@@ -288,7 +290,7 @@
$merges = idx($spec, 'merges');
if ($merges) {
foreach ($merges as $merge) {
- $this->applyMerge($interface, $merge);
+ $this->applyMerge($lease, $interface, $merge);
}
}
@@ -416,6 +418,7 @@
}
private function applyMerge(
+ DrydockLease $lease,
DrydockCommandInterface $interface,
array $merge) {
@@ -428,15 +431,48 @@
$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;
+ }
+ }
}
diff --git a/src/applications/drydock/storage/DrydockRepositoryOperation.php b/src/applications/drydock/storage/DrydockRepositoryOperation.php
--- a/src/applications/drydock/storage/DrydockRepositoryOperation.php
+++ b/src/applications/drydock/storage/DrydockRepositoryOperation.php
@@ -175,6 +175,14 @@
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 )----------------------------------------- */
diff --git a/src/applications/drydock/view/DrydockRepositoryOperationStatusView.php b/src/applications/drydock/view/DrydockRepositoryOperationStatusView.php
--- a/src/applications/drydock/view/DrydockRepositoryOperationStatusView.php
+++ b/src/applications/drydock/view/DrydockRepositoryOperationStatusView.php
@@ -73,12 +73,104 @@
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);
+ }
+
}
diff --git a/src/applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php b/src/applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php
--- a/src/applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php
+++ b/src/applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php
@@ -90,6 +90,9 @@
// 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 @@
$lease_phid));
}
} else {
- $working_copy_type = id(new DrydockWorkingCopyBlueprintImplementation())
- ->getType();
-
$repository = $operation->getRepository();
$allowed_phids = $repository->getAutomationBlueprintPHIDs();
@@ -138,6 +138,13 @@
}
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.',

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 5, 1:27 PM (23 h, 30 m ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7225642
Default Alt Text
D14343.diff (7 KB)

Event Timeline