1<?php
2
3final class ArcanistMercurialLocalState
4  extends ArcanistRepositoryLocalState {
5
6  private $localCommit;
7  private $localBranch;
8  private $localBookmark;
9
10  protected function executeSaveLocalState() {
11    $api = $this->getRepositoryAPI();
12    $log = $this->getWorkflow()->getLogEngine();
13
14    $markers = $api->newMarkerRefQuery()
15      ->execute();
16
17    $local_commit = null;
18    foreach ($markers as $marker) {
19      if ($marker->isCommitState()) {
20        $local_commit = $marker->getCommitHash();
21      }
22    }
23
24    if ($local_commit === null) {
25      throw new Exception(
26        pht(
27          'Unable to identify the current commit in the working copy.'));
28    }
29
30    $this->localCommit = $local_commit;
31
32    $local_branch = null;
33    foreach ($markers as $marker) {
34      if ($marker->isBranchState()) {
35        $local_branch = $marker->getName();
36        break;
37      }
38    }
39
40    if ($local_branch === null) {
41      throw new Exception(
42        pht(
43          'Unable to identify the current branch in the working copy.'));
44    }
45
46    if ($local_branch !== null) {
47      $this->localBranch = $local_branch;
48    }
49
50    $local_bookmark = null;
51    foreach ($markers as $marker) {
52      if ($marker->isBookmark()) {
53        if ($marker->getIsActive()) {
54          $local_bookmark = $marker->getName();
55          break;
56        }
57      }
58    }
59
60    if ($local_bookmark !== null) {
61      $this->localBookmark = $local_bookmark;
62    }
63
64    $has_bookmark = ($this->localBookmark !== null);
65
66    if ($has_bookmark) {
67      $location = pht(
68        'Saving local state (at "%s" on branch "%s", bookmarked as "%s").',
69        $api->getDisplayHash($this->localCommit),
70        $this->localBranch,
71        $this->localBookmark);
72    } else {
73      $location = pht(
74        'Saving local state (at "%s" on branch "%s").',
75        $api->getDisplayHash($this->localCommit),
76        $this->localBranch);
77    }
78
79    $log->writeTrace(pht('SAVE STATE'), $location);
80  }
81
82  protected function executeRestoreLocalState() {
83    $api = $this->getRepositoryAPI();
84    $log = $this->getWorkflow()->getLogEngine();
85
86    if ($this->localBookmark !== null) {
87      $location = pht(
88        'Restoring local state (at "%s" on branch "%s", bookmarked as "%s").',
89        $api->getDisplayHash($this->localCommit),
90        $this->localBranch,
91        $this->localBookmark);
92    } else {
93      $location = pht(
94        'Restoring local state (at "%s" on branch "%s").',
95        $api->getDisplayHash($this->localCommit),
96        $this->localBranch);
97    }
98
99    $log->writeStatus(pht('LOAD STATE'), $location);
100
101    $api->execxLocal('update -- %s', $this->localCommit);
102    $api->execxLocal('branch --force -- %s', $this->localBranch);
103
104    if ($this->localBookmark !== null) {
105      $api->execxLocal('bookmark --force -- %s', $this->localBookmark);
106    }
107  }
108
109  protected function executeDiscardLocalState() {
110    return;
111  }
112
113  protected function canStashChanges() {
114    $api = $this->getRepositoryAPI();
115    return $api->getMercurialFeature('shelve');
116  }
117
118  protected function getIgnoreHints() {
119    return array(
120      pht(
121        'To configure Mercurial to ignore certain files in the working '.
122        'copy, add them to ".hgignore".'),
123    );
124  }
125
126  protected function newRestoreCommandsForDisplay() {
127    $api = $this->getRepositoryAPI();
128    $commands = array();
129
130    $commands[] = csprintf(
131      'hg update -- %s',
132      $api->getDisplayHash($this->localCommit));
133
134    $commands[] = csprintf(
135      'hg branch --force -- %s',
136      $this->localBranch);
137
138    if ($this->localBookmark !== null) {
139      $commands[] = csprintf(
140        'hg bookmark --force -- %s',
141        $this->localBookmark);
142    }
143
144    return $commands;
145  }
146
147  protected function saveStash() {
148    $api = $this->getRepositoryAPI();
149    $log = $this->getWorkflow()->getLogEngine();
150
151    $stash_ref = sprintf(
152      'arc-%s',
153      Filesystem::readRandomCharacters(12));
154
155    $api->execxLocal(
156      '--config extensions.shelve= shelve --unknown --name %s --',
157      $stash_ref);
158
159    $log->writeStatus(
160      pht('SHELVE'),
161      pht('Shelving uncommitted changes from working copy.'));
162
163    return $stash_ref;
164  }
165
166  protected function restoreStash($stash_ref) {
167    $api = $this->getRepositoryAPI();
168    $log = $this->getWorkflow()->getLogEngine();
169
170    $log->writeStatus(
171      pht('UNSHELVE'),
172      pht('Restoring uncommitted changes to working copy.'));
173
174    $api->execxLocal(
175      '--config extensions.shelve= unshelve --keep --name %s --',
176      $stash_ref);
177  }
178
179  protected function discardStash($stash_ref) {
180    $api = $this->getRepositoryAPI();
181
182    $api->execxLocal(
183      '--config extensions.shelve= shelve --delete %s --',
184      $stash_ref);
185  }
186
187}
188