Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14397978
D14337.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
D14337.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D14337: Make WorkingCopyBlueprint responsible for performing merges
Attached
Detach File
Event Timeline
Log In to Comment