Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15376546
D14270.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Referenced Files
None
Subscribers
None
D14270.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Fri, Mar 14, 4:29 AM (1 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7390678
Default Alt Text
D14270.diff (9 KB)
Attached To
Mode
D14270: If the stars align, make "Land Revision" kind of work
Attached
Detach File
Event Timeline
Log In to Comment