Page MenuHomePhabricator

D14270.id.diff
No OneTemporary

D14270.id.diff

diff --git a/src/applications/differential/controller/DifferentialRevisionOperationController.php b/src/applications/differential/controller/DifferentialRevisionOperationController.php
--- a/src/applications/differential/controller/DifferentialRevisionOperationController.php
+++ b/src/applications/differential/controller/DifferentialRevisionOperationController.php
@@ -10,6 +10,7 @@
$revision = id(new DifferentialRevisionQuery())
->withIDs(array($id))
->setViewer($viewer)
+ ->needActiveDiffs(true)
->executeOne();
if (!$revision) {
return new Aphront404Response();
@@ -58,13 +59,20 @@
}
if ($request->isFormPost()) {
+ // NOTE: The operation is locked to the current active diff, so if the
+ // revision is updated before the operation applies nothing sneaky
+ // occurs.
+
+ $diff = $revision->getActiveDiff();
+
$op = new DrydockLandRepositoryOperation();
$operation = DrydockRepositoryOperation::initializeNewOperation($op)
->setAuthorPHID($viewer->getPHID())
->setObjectPHID($revision->getPHID())
->setRepositoryPHID($repository->getPHID())
- ->setRepositoryTarget('branch:master');
+ ->setRepositoryTarget('branch:master')
+ ->setProperty('differential.diffPHID', $diff->getPHID());
$operation->save();
$operation->scheduleUpdate();
diff --git a/src/applications/differential/storage/DifferentialDiff.php b/src/applications/differential/storage/DifferentialDiff.php
--- a/src/applications/differential/storage/DifferentialDiff.php
+++ b/src/applications/differential/storage/DifferentialDiff.php
@@ -447,12 +447,8 @@
$results['repository.vcs'] = $repo->getVersionControlSystem();
$results['repository.uri'] = $repo->getPublicCloneURI();
- // TODO: We're just hoping to get lucky. Instead, `arc` should store
- // where it sent changes and we should only provide staging details
- // if we reasonably believe they are accurate.
- $staging_ref = 'refs/tags/phabricator/diff/'.$this->getID();
$results['repository.staging.uri'] = $repo->getStagingURI();
- $results['repository.staging.ref'] = $staging_ref;
+ $results['repository.staging.ref'] = $this->getStagingRef();
}
}
@@ -480,6 +476,13 @@
);
}
+ public function getStagingRef() {
+ // TODO: We're just hoping to get lucky. Instead, `arc` should store
+ // where it sent changes and we should only provide staging details
+ // if we reasonably believe they are accurate.
+ return 'refs/tags/phabricator/diff/'.$this->getID();
+ }
+
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
diff --git a/src/applications/drydock/operation/DrydockLandRepositoryOperation.php b/src/applications/drydock/operation/DrydockLandRepositoryOperation.php
--- a/src/applications/drydock/operation/DrydockLandRepositoryOperation.php
+++ b/src/applications/drydock/operation/DrydockLandRepositoryOperation.php
@@ -5,4 +5,94 @@
const OPCONST = 'land';
+ public function applyOperation(
+ DrydockRepositoryOperation $operation,
+ DrydockInterface $interface) {
+ $viewer = $this->getViewer();
+ $repository = $operation->getRepository();
+
+ $cmd = array();
+ $arg = array();
+
+ $object = $operation->getObject();
+ if ($object instanceof DifferentialRevision) {
+ $revision = $object;
+
+ $diff_phid = $operation->getProperty('differential.diffPHID');
+
+ $diff = id(new DifferentialDiffQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($diff_phid))
+ ->executeOne();
+ if (!$diff) {
+ throw new Exception(
+ pht(
+ 'Unable to load diff "%s".',
+ $diff_phid));
+ }
+
+ $diff_revid = $diff->getRevisionID();
+ $revision_id = $revision->getID();
+ if ($diff_revid != $revision_id) {
+ throw new Exception(
+ pht(
+ 'Diff ("%s") has wrong revision ID ("%s", expected "%s").',
+ $diff_phid,
+ $diff_revid,
+ $revision_id));
+ }
+
+ $cmd[] = 'git fetch --no-tags -- %s +%s:%s';
+ $arg[] = $repository->getStagingURI();
+ $arg[] = $diff->getStagingRef();
+ $arg[] = $diff->getStagingRef();
+
+ $merge_src = $diff->getStagingRef();
+ } else {
+ throw new Exception(
+ pht(
+ 'Invalid or unknown object ("%s") for land operation, expected '.
+ 'Differential Revision.',
+ $operation->getObjectPHID()));
+ }
+
+ $target = $operation->getRepositoryTarget();
+ list($type, $name) = explode(':', $target, 2);
+ switch ($type) {
+ case 'branch':
+ $push_dst = 'refs/heads/'.$name;
+ $merge_dst = 'refs/remotes/origin/'.$name;
+ break;
+ default:
+ throw new Exception(
+ pht(
+ 'Unknown repository operation target type "%s" (in target "%s").',
+ $type,
+ $target));
+ }
+
+ $cmd[] = 'git checkout %s';
+ $arg[] = $merge_dst;
+
+ $cmd[] = 'git merge --no-stat --squash --ff-only -- %s';
+ $arg[] = $merge_src;
+
+ $cmd[] = 'git -c user.name=%s -c user.email=%s commit --author %s -m %s';
+ $arg[] = 'autocommitter';
+ $arg[] = 'autocommitter@example.com';
+ $arg[] = 'autoauthor <autoauthor@example.com>';
+ $arg[] = pht('(Automerge!)');
+
+ $cmd[] = 'git push origin -- %s:%s';
+ $arg[] = 'HEAD';
+ $arg[] = $push_dst;
+
+ $cmd = implode(' && ', $cmd);
+ $argv = array_merge(array($cmd), $arg);
+
+ $result = call_user_func_array(
+ array($interface, 'execx'),
+ $argv);
+ }
+
}
diff --git a/src/applications/drydock/operation/DrydockRepositoryOperationType.php b/src/applications/drydock/operation/DrydockRepositoryOperationType.php
--- a/src/applications/drydock/operation/DrydockRepositoryOperationType.php
+++ b/src/applications/drydock/operation/DrydockRepositoryOperationType.php
@@ -2,6 +2,21 @@
abstract class DrydockRepositoryOperationType extends Phobject {
+ private $viewer;
+
+ abstract public function applyOperation(
+ DrydockRepositoryOperation $operation,
+ DrydockInterface $interface);
+
+ final public function setViewer(PhabricatorUser $viewer) {
+ $this->viewer = $viewer;
+ return $this;
+ }
+
+ final public function getViewer() {
+ return $this->viewer;
+ }
+
final public function getOperationConstant() {
return $this->getPhobjectClassConstant('OPCONST', 32);
}
diff --git a/src/applications/drydock/query/DrydockRepositoryOperationQuery.php b/src/applications/drydock/query/DrydockRepositoryOperationQuery.php
--- a/src/applications/drydock/query/DrydockRepositoryOperationQuery.php
+++ b/src/applications/drydock/query/DrydockRepositoryOperationQuery.php
@@ -42,6 +42,19 @@
}
protected function willFilterPage(array $operations) {
+ $implementations = DrydockRepositoryOperationType::getAllOperationTypes();
+
+ foreach ($operations as $key => $operation) {
+ $impl = idx($implementations, $operation->getOperationType());
+ if (!$impl) {
+ $this->didRejectResult($operation);
+ unset($operations[$key]);
+ continue;
+ }
+ $impl = clone $impl;
+ $operation->attachImplementation($impl);
+ }
+
$repository_phids = mpull($operations, 'getRepositoryPHID');
if ($repository_phids) {
$repositories = id(new PhabricatorRepositoryQuery())
@@ -75,7 +88,7 @@
->setParentQuery($this)
->withPHIDs($object_phids)
->execute();
- $objects = mpull($objects, 'getPHID');
+ $objects = mpull($objects, null, 'getPHID');
} else {
$objects = array();
}
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
@@ -23,6 +23,7 @@
private $repository = self::ATTACHABLE;
private $object = self::ATTACHABLE;
+ private $implementation = self::ATTACHABLE;
public static function initializeNewOperation(
DrydockRepositoryOperationType $op) {
@@ -77,6 +78,15 @@
return $this->assertAttached($this->object);
}
+ public function attachImplementation(DrydockRepositoryOperationType $impl) {
+ $this->implementation = $impl;
+ return $this;
+ }
+
+ public function getImplementation() {
+ return $this->implementation;
+ }
+
public function getProperty($key, $default = null) {
return idx($this->properties, $key, $default);
}
@@ -120,6 +130,12 @@
));
}
+ public function applyOperation(DrydockInterface $interface) {
+ return $this->getImplementation()->applyOperation(
+ $this,
+ $interface);
+ }
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
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
@@ -25,6 +25,8 @@
private function handleUpdate(DrydockRepositoryOperation $operation) {
+ $viewer = $this->getViewer();
+
$operation_state = $operation->getOperationState();
switch ($operation_state) {
@@ -59,9 +61,11 @@
// No matter what happens here, destroy the lease away once we're done.
$lease->releaseOnDestruction(true);
- // TODO: Some day, do useful things instead of running `git show`.
- list($stdout) = $interface->execx('git show');
- phlog($stdout);
+ $operation->getImplementation()
+ ->setViewer($viewer);
+
+ $operation->applyOperation($interface);
+
} catch (PhabricatorWorkerYieldException $ex) {
throw $ex;
} catch (Exception $ex) {

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 14, 4:50 AM (1 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7390678
Default Alt Text
D14270.id.diff (9 KB)

Event Timeline