Page MenuHomePhabricator

D14337.diff
No OneTemporary

D14337.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
@@ -237,8 +237,7 @@
$cmd = array();
$arg = array();
- $cmd[] = 'cd %s';
- $arg[] = "{$root}/repo/{$directory}/";
+ $interface->pushWorkingDirectory("{$root}/repo/{$directory}/");
$cmd[] = 'git clean -d --force';
$cmd[] = 'git fetch';
@@ -285,6 +284,15 @@
if (idx($spec, 'default')) {
$default = $directory;
}
+
+ $merges = idx($spec, 'merges');
+ if ($merges) {
+ foreach ($merges as $merge) {
+ $this->applyMerge($interface, $merge);
+ }
+ }
+
+ $interface->popWorkingDirectory();
}
if ($default === null) {
@@ -333,7 +341,7 @@
$command_interface = $host_lease->getInterface($type);
$path = $lease->getAttribute('workingcopy.default');
- $command_interface->setWorkingDirectory($path);
+ $command_interface->pushWorkingDirectory($path);
return $command_interface;
}
@@ -407,5 +415,28 @@
return true;
}
+ private function applyMerge(
+ DrydockCommandInterface $interface,
+ array $merge) {
+
+ $src_uri = $merge['src.uri'];
+ $src_ref = $merge['src.ref'];
+
+ $interface->execx(
+ 'git fetch --no-tags -- %s +%s:%s',
+ $src_uri,
+ $src_ref,
+ $src_ref);
+
+ try {
+ $interface->execx(
+ 'git merge --no-stat --squash --ff-only -- %s',
+ $src_ref);
+ } catch (CommandException $ex) {
+ // TODO: Specifically note this as a merge conflict.
+ throw $ex;
+ }
+ }
+
}
diff --git a/src/applications/drydock/interface/command/DrydockCommandInterface.php b/src/applications/drydock/interface/command/DrydockCommandInterface.php
--- a/src/applications/drydock/interface/command/DrydockCommandInterface.php
+++ b/src/applications/drydock/interface/command/DrydockCommandInterface.php
@@ -4,15 +4,27 @@
const INTERFACE_TYPE = 'command';
- private $workingDirectory;
+ private $workingDirectoryStack = array();
- public function setWorkingDirectory($working_directory) {
- $this->workingDirectory = $working_directory;
+ public function pushWorkingDirectory($working_directory) {
+ $this->workingDirectoryStack[] = $working_directory;
return $this;
}
- public function getWorkingDirectory() {
- return $this->workingDirectory;
+ public function popWorkingDirectory() {
+ if (!$this->workingDirectoryStack) {
+ throw new Exception(
+ pht(
+ 'Unable to pop working directory, directory stack is empty.'));
+ }
+ return array_pop($this->workingDirectoryStack);
+ }
+
+ public function peekWorkingDirectory() {
+ if ($this->workingDirectoryStack) {
+ return last($this->workingDirectoryStack);
+ }
+ return null;
}
final public function getInterfaceType() {
@@ -38,12 +50,14 @@
abstract public function getExecFuture($command);
protected function applyWorkingDirectoryToArgv(array $argv) {
- if ($this->getWorkingDirectory() !== null) {
+ $directory = $this->peekWorkingDirectory();
+
+ if ($directory !== null) {
$cmd = $argv[0];
$cmd = "(cd %s && {$cmd})";
$argv = array_merge(
array($cmd),
- array($this->getWorkingDirectory()),
+ array($directory),
array_slice($argv, 1));
}
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
@@ -35,6 +35,28 @@
}
}
+ public function getWorkingCopyMerges(DrydockRepositoryOperation $operation) {
+ $repository = $operation->getRepository();
+ $merges = array();
+
+ $object = $operation->getObject();
+ if ($object instanceof DifferentialRevision) {
+ $diff = $this->loadDiff($operation);
+ $merges[] = array(
+ 'src.uri' => $repository->getStagingURI(),
+ 'src.ref' => $diff->getStagingRef(),
+ );
+ } else {
+ throw new Exception(
+ pht(
+ 'Invalid or unknown object ("%s") for land operation, expected '.
+ 'Differential Revision.',
+ $operation->getObjectPHID()));
+ }
+
+ return $merges;
+ }
+
public function applyOperation(
DrydockRepositoryOperation $operation,
DrydockInterface $interface) {
@@ -48,36 +70,7 @@
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();
+ $diff = $this->loadDiff($operation);
$dict = $diff->getDiffAuthorshipDict();
$author_name = idx($dict, 'authorName');
@@ -104,7 +97,6 @@
switch ($type) {
case 'branch':
$push_dst = 'refs/heads/'.$name;
- $merge_dst = 'refs/remotes/origin/'.$name;
break;
default:
throw new Exception(
@@ -116,30 +108,24 @@
$committer_info = $this->getCommitterInfo($operation);
- $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[] = $committer_info['name'];
- $arg[] = $committer_info['email'];
+ // NOTE: We're doing this commit with "-F -" so we don't run into trouble
+ // with enormous commit messages which might otherwise exceed the maximum
+ // size of a command.
- $arg[] = "{$author_name} <{$author_email}>";
- $arg[] = $commit_message;
+ $future = $interface->getExecFuture(
+ 'git -c user.name=%s -c user.email=%s commit --author %s -F - --',
+ $committer_info['name'],
+ $committer_info['email'],
+ "{$author_name} <{$author_email}>");
- $cmd[] = 'git push origin -- %s:%s';
- $arg[] = 'HEAD';
- $arg[] = $push_dst;
+ $future
+ ->write($commit_message)
+ ->resolvex();
- $cmd = implode(' && ', $cmd);
- $argv = array_merge(array($cmd), $arg);
-
- $result = call_user_func_array(
- array($interface, 'execx'),
- $argv);
+ $interface->execx(
+ 'git push origin -- %s:%s',
+ 'HEAD',
+ $push_dst);
}
private function getCommitterInfo(DrydockRepositoryOperation $operation) {
@@ -172,4 +158,35 @@
);
}
+ private function loadDiff(DrydockRepositoryOperation $operation) {
+ $viewer = $this->getViewer();
+ $revision = $operation->getObject();
+
+ $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));
+ }
+
+ return $diff;
+ }
+
}
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
@@ -16,6 +16,10 @@
DrydockRepositoryOperation $operation,
PhabricatorUser $viewer);
+ public function getWorkingCopyMerges(DrydockRepositoryOperation $operation) {
+ return array();
+ }
+
final public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
return $this;
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
@@ -158,6 +158,11 @@
return false;
}
+ public function getWorkingCopyMerges() {
+ return $this->getImplementation()->getWorkingCopyMerges(
+ $this);
+ }
+
/* -( 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
@@ -53,6 +53,9 @@
// waiting for a lease we're holding.
try {
+ $operation->getImplementation()
+ ->setViewer($viewer);
+
$lease = $this->loadWorkingCopyLease($operation);
$interface = $lease->getInterface(
@@ -61,9 +64,6 @@
// No matter what happens here, destroy the lease away once we're done.
$lease->releaseOnDestruction(true);
- $operation->getImplementation()
- ->setViewer($viewer);
-
$operation->applyOperation($interface);
} catch (PhabricatorWorkerYieldException $ex) {
@@ -166,6 +166,8 @@
$target));
}
+ $spec['merges'] = $operation->getWorkingCopyMerges();
+
$map = array();
$map[$repository->getCloneName()] = array(
'phid' => $repository->getPHID(),

File Metadata

Mime Type
text/plain
Expires
Mon, Dec 23, 12:37 PM (18 h, 24 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6921264
Default Alt Text
D14337.diff (10 KB)

Event Timeline