Page MenuHomePhabricator

D21329.id50759.diff
No OneTemporary

D21329.id50759.diff

diff --git a/src/land/engine/ArcanistGitLandEngine.php b/src/land/engine/ArcanistGitLandEngine.php
--- a/src/land/engine/ArcanistGitLandEngine.php
+++ b/src/land/engine/ArcanistGitLandEngine.php
@@ -1349,7 +1349,7 @@
}
$commits = phutil_split_lines($commits, false);
- $is_first = false;
+ $is_first = true;
foreach ($commits as $line) {
if (!strlen($line)) {
continue;
diff --git a/src/land/engine/ArcanistMercurialLandEngine.php b/src/land/engine/ArcanistMercurialLandEngine.php
--- a/src/land/engine/ArcanistMercurialLandEngine.php
+++ b/src/land/engine/ArcanistMercurialLandEngine.php
@@ -406,6 +406,7 @@
}
$commits = phutil_split_lines($commits, false);
+ $is_first = true;
foreach ($commits as $line) {
if (!strlen($line)) {
continue;
@@ -438,7 +439,12 @@
}
$commit = $commit_map[$hash];
- $commit->addSymbol($symbol);
+ if ($is_first) {
+ $commit->addDirectSymbol($symbol);
+ $is_first = false;
+ }
+
+ $commit->addIndirectSymbol($symbol);
}
}
@@ -607,14 +613,12 @@
$message = pht(
'Holding changes locally, they have not been pushed.');
- $push_command = csprintf(
- '$ hg push -- %s %Ls',
-
- // TODO: When a parameter contains only "safe" characters, we could
- // relax the behavior of hgsprintf().
+ // TODO: This is only vaguely correct.
+ $push_command = csprintf(
+ '$ hg push --rev %s -- %s',
hgsprintf('%s', $this->getDisplayHash($into_commit)),
- $this->newOntoRefArguments($into_commit));
+ $this->getOntoRemote());
echo tsprintf(
"\n%!\n%s\n\n",
@@ -643,7 +647,7 @@
}
echo tsprintf(
- "%s\n".
+ "%s\n",
pht(
'Local branches and bookmarks have not been changed, and are still '.
'in the same state as before.'));
diff --git a/src/repository/api/ArcanistMercurialAPI.php b/src/repository/api/ArcanistMercurialAPI.php
--- a/src/repository/api/ArcanistMercurialAPI.php
+++ b/src/repository/api/ArcanistMercurialAPI.php
@@ -12,6 +12,9 @@
private $supportsRebase;
private $supportsPhases;
+ private $featureResults = array();
+ private $featureFutures = array();
+
protected function buildLocalFuture(array $argv) {
$env = $this->getMercurialEnvironmentVariables();
@@ -1167,5 +1170,57 @@
->setRepositoryAPI($this);
}
+ public function willTestMercurialFeature($feature) {
+ $this->executeMercurialFeatureTest($feature, false);
+ return $this;
+ }
+
+ public function getMercurialFeature($feature) {
+ return $this->executeMercurialFeatureTest($feature, true);
+ }
+
+ private function executeMercurialFeatureTest($feature, $resolve) {
+ if (array_key_exists($feature, $this->featureResults)) {
+ return $this->featureResults[$feature];
+ }
+
+ if (!array_key_exists($feature, $this->featureFutures)) {
+ $future = $this->newMercurialFeatureFuture($feature);
+ $future->start();
+ $this->featureFutures[$feature] = $future;
+ }
+
+ if (!$resolve) {
+ return;
+ }
+
+ $future = $this->featureFutures[$feature];
+ $result = $this->resolveMercurialFeatureFuture($feature, $future);
+ $this->featureResults[$feature] = $result;
+
+ return $result;
+ }
+
+ private function newMercurialFeatureFuture($feature) {
+ switch ($feature) {
+ case 'shelve':
+ return $this->execFutureLocal(
+ '--config extensions.shelve= shelve --help');
+ default:
+ throw new Exception(
+ pht(
+ 'Unknown Mercurial feature "%s".',
+ $feature));
+ }
+ }
+
+ private function resolveMercurialFeatureFuture($feature, $future) {
+ // By default, assume the feature is a simple capability test and the
+ // capability is present if the feature resolves without an error.
+
+ list($err) = $future->resolve();
+ return !$err;
+ }
+
}
diff --git a/src/repository/state/ArcanistMercurialLocalState.php b/src/repository/state/ArcanistMercurialLocalState.php
--- a/src/repository/state/ArcanistMercurialLocalState.php
+++ b/src/repository/state/ArcanistMercurialLocalState.php
@@ -5,7 +5,6 @@
private $localCommit;
private $localRef;
- private $localPath;
public function getLocalRef() {
return $this->localRef;
@@ -17,6 +16,7 @@
protected function executeSaveLocalState() {
$api = $this->getRepositoryAPI();
+
// TODO: Fix this.
}
@@ -36,13 +36,16 @@
}
protected function canStashChanges() {
- // Depends on stash extension.
- return false;
+ $api = $this->getRepositoryAPI();
+ return $api->getMercurialFeature('shelve');
}
protected function getIgnoreHints() {
- // TODO: Provide this.
- return array();
+ return array(
+ pht(
+ 'To configure Mercurial to ignore certain files in the working '.
+ 'copy, add them to ".hgignore".'),
+ );
}
protected function newRestoreCommandsForDisplay() {
@@ -51,15 +54,43 @@
}
protected function saveStash() {
- return null;
+ $api = $this->getRepositoryAPI();
+ $log = $this->getWorkflow()->getLogEngine();
+
+ $stash_ref = sprintf(
+ 'arc-%s',
+ Filesystem::readRandomCharacters(12));
+
+ $api->execxLocal(
+ '--config extensions.shelve= shelve --unknown --name %s --',
+ $stash_ref);
+
+ $log->writeStatus(
+ pht('SHELVE'),
+ pht('Shelving uncommitted changes from working copy.'));
+
+ return $stash_ref;
}
protected function restoreStash($stash_ref) {
- return null;
+ $api = $this->getRepositoryAPI();
+ $log = $this->getWorkflow()->getLogEngine();
+
+ $log->writeStatus(
+ pht('UNSHELVE'),
+ pht('Restoring uncommitted changes to working copy.'));
+
+ $api->execxLocal(
+ '--config extensions.shelve= unshelve --keep --name %s --',
+ $stash_ref);
}
protected function discardStash($stash_ref) {
- return null;
+ $api = $this->getRepositoryAPI();
+
+ $api->execxLocal(
+ '--config extensions.shelve= shelve --delete %s --',
+ $stash_ref);
}
}
diff --git a/src/repository/state/ArcanistRepositoryLocalState.php b/src/repository/state/ArcanistRepositoryLocalState.php
--- a/src/repository/state/ArcanistRepositoryLocalState.php
+++ b/src/repository/state/ArcanistRepositoryLocalState.php
@@ -161,9 +161,8 @@
$this->shouldRestore = false;
$this->executeRestoreLocalState();
- if ($this->stashRef !== null) {
- $this->restoreStash($this->stashRef);
- }
+ $this->applyStash();
+ $this->executeDiscardLocalState();
return $this;
}
@@ -171,12 +170,8 @@
final public function discardLocalState() {
$this->shouldRestore = false;
+ $this->applyStash();
$this->executeDiscardLocalState();
- if ($this->stashRef !== null) {
- $this->restoreStash($this->stashRef);
- $this->discardStash($this->stashRef);
- $this->stashRef = null;
- }
return $this;
}
@@ -184,9 +179,9 @@
final public function __destruct() {
if ($this->shouldRestore) {
$this->restoreLocalState();
+ } else {
+ $this->discardLocalState();
}
-
- $this->discardLocalState();
}
final public function getRestoreCommandsForDisplay() {
@@ -209,6 +204,17 @@
throw new PhutilMethodNotImplementedException();
}
+ private function applyStash() {
+ if ($this->stashRef === null) {
+ return;
+ }
+ $stash_ref = $this->stashRef;
+ $this->stashRef = null;
+
+ $this->restoreStash($stash_ref);
+ $this->discardStash($stash_ref);
+ }
+
abstract protected function executeSaveLocalState();
abstract protected function executeRestoreLocalState();
abstract protected function executeDiscardLocalState();
diff --git a/src/xsprintf/hgsprintf.php b/src/xsprintf/hgsprintf.php
--- a/src/xsprintf/hgsprintf.php
+++ b/src/xsprintf/hgsprintf.php
@@ -22,7 +22,14 @@
switch ($type) {
case 's':
- $value = "'".addcslashes($value, "'\\")."'";
+ // If this is symbol only has "safe" alphanumeric latin characters,
+ // and is at least one character long, we can let it through without
+ // escaping it. This tends to produce more readable commands.
+ if (preg_match('(^[a-zA-Z0-9]+\z)', $value)) {
+ $value = $value;
+ } else {
+ $value = "'".addcslashes($value, "'\\")."'";
+ }
break;
case 'R':
$type = 's';

File Metadata

Mime Type
text/plain
Expires
Mon, Mar 17, 4:51 AM (6 d, 8 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7388994
Default Alt Text
D21329.id50759.diff (8 KB)

Event Timeline