|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2014 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the shelve extension interface. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 try: |
|
12 str = unicode |
|
13 except NameError: |
|
14 pass |
|
15 |
|
16 import os |
|
17 |
|
18 from PyQt4.QtCore import QProcess |
|
19 from PyQt4.QtGui import QDialog |
|
20 |
|
21 from E5Gui import E5MessageBox |
|
22 |
|
23 from ..HgExtension import HgExtension |
|
24 from ..HgDialog import HgDialog |
|
25 |
|
26 |
|
27 class Shelve(HgExtension): |
|
28 """ |
|
29 Class implementing the shelve extension interface. |
|
30 """ |
|
31 def __init__(self, vcs): |
|
32 """ |
|
33 Constructor |
|
34 |
|
35 @param vcs reference to the Mercurial vcs object |
|
36 """ |
|
37 super(Shelve, self).__init__(vcs) |
|
38 |
|
39 self.__unshelveKeep = False |
|
40 |
|
41 self.__shelveBrowserDialog = None |
|
42 |
|
43 def shutdown(self): |
|
44 """ |
|
45 Public method used to shutdown the shelve interface. |
|
46 """ |
|
47 if self.__shelveBrowserDialog is not None: |
|
48 self.__shelveBrowserDialog.close() |
|
49 |
|
50 def __hgGetShelveNamesList(self, repodir): |
|
51 """ |
|
52 Private method to get the list of shelved changes. |
|
53 |
|
54 @param repodir directory name of the repository (string) |
|
55 @return list of shelved changes (list of string) |
|
56 """ |
|
57 args = self.vcs.initCommand("shelve") |
|
58 args.append('--list') |
|
59 args.append('--quiet') |
|
60 |
|
61 client = self.vcs.getClient() |
|
62 output = "" |
|
63 if client: |
|
64 output = client.runcommand(args)[0] |
|
65 else: |
|
66 process = QProcess() |
|
67 process.setWorkingDirectory(repodir) |
|
68 process.start('hg', args) |
|
69 procStarted = process.waitForStarted(5000) |
|
70 if procStarted: |
|
71 finished = process.waitForFinished(30000) |
|
72 if finished and process.exitCode() == 0: |
|
73 output = str(process.readAllStandardOutput(), |
|
74 self.vcs.getEncoding(), 'replace') |
|
75 |
|
76 shelveNamesList = [] |
|
77 for line in output.splitlines(): |
|
78 shelveNamesList.append(line.strip()) |
|
79 |
|
80 return shelveNamesList[:] |
|
81 |
|
82 def hgShelve(self, name): |
|
83 """ |
|
84 Public method to shelve current changes of files or directories. |
|
85 |
|
86 @param name directory or file name (string) or list of directory |
|
87 or file names (list of string) |
|
88 @return flag indicating that the project should be reread (boolean) |
|
89 """ |
|
90 if isinstance(name, list): |
|
91 dname = self.vcs.splitPathList(name)[0] |
|
92 else: |
|
93 dname = self.vcs.splitPath(name)[0] |
|
94 |
|
95 # find the root of the repo |
|
96 repodir = dname |
|
97 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)): |
|
98 repodir = os.path.dirname(repodir) |
|
99 if os.path.splitdrive(repodir)[1] == os.sep: |
|
100 return False |
|
101 |
|
102 res = False |
|
103 from .HgShelveDataDialog import HgShelveDataDialog |
|
104 dlg = HgShelveDataDialog() |
|
105 if dlg.exec_() == QDialog.Accepted: |
|
106 shelveName, dateTime, message, addRemove = dlg.getData() |
|
107 |
|
108 args = self.vcs.initCommand("shelve") |
|
109 if shelveName: |
|
110 args.append("--name") |
|
111 args.append(shelveName) |
|
112 if message: |
|
113 args.append("--message") |
|
114 args.append(message) |
|
115 if addRemove: |
|
116 args.append("--addRemove") |
|
117 if dateTime.isValid(): |
|
118 args.append("--date") |
|
119 args.append(dateTime.toString("yyyy-MM-dd hh:mm:ss")) |
|
120 args.append("-v") |
|
121 |
|
122 if isinstance(name, list): |
|
123 self.vcs.addArguments(args, name) |
|
124 else: |
|
125 args.append(name) |
|
126 |
|
127 dia = HgDialog(self.tr('Shelve current changes'), self.vcs) |
|
128 res = dia.startProcess(args, repodir) |
|
129 if res: |
|
130 dia.exec_() |
|
131 res = dia.hasAddOrDelete() |
|
132 self.vcs.checkVCSStatus() |
|
133 return res |
|
134 |
|
135 def hgShelveBrowser(self, projectDir): |
|
136 """ |
|
137 Public method to show the shelve browser dialog. |
|
138 |
|
139 @param projectDir name of the project directory (string) |
|
140 """ |
|
141 if self.__shelveBrowserDialog is None: |
|
142 from .HgShelveBrowserDialog import HgShelveBrowserDialog |
|
143 self.__shelveBrowserDialog = HgShelveBrowserDialog( |
|
144 self.vcs) |
|
145 self.__shelveBrowserDialog.show() |
|
146 self.__shelveBrowserDialog.start(projectDir) |
|
147 |
|
148 def hgUnshelve(self, name, shelveName=""): |
|
149 """ |
|
150 Public method to restore shelved changes to the project directory. |
|
151 |
|
152 @param name name of the project directory (string) |
|
153 @keyparam shelveName name of the shelve to restore (string) |
|
154 @return flag indicating that the project should be reread (boolean) |
|
155 """ |
|
156 # find the root of the repo |
|
157 repodir = name |
|
158 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)): |
|
159 repodir = os.path.dirname(repodir) |
|
160 if os.path.splitdrive(repodir)[1] == os.sep: |
|
161 return False |
|
162 |
|
163 res = False |
|
164 from .HgUnshelveDataDialog import HgUnshelveDataDialog |
|
165 dlg = HgUnshelveDataDialog(self.__hgGetShelveNamesList(repodir), |
|
166 shelveName=shelveName) |
|
167 if dlg.exec_() == QDialog.Accepted: |
|
168 shelveName, keep = dlg.getData() |
|
169 self.__unshelveKeep = keep # store for potential continue |
|
170 |
|
171 args = self.vcs.initCommand("unshelve") |
|
172 if keep: |
|
173 args.append("--keep") |
|
174 if shelveName: |
|
175 args.append(shelveName) |
|
176 |
|
177 dia = HgDialog(self.tr('Restore shelved changes'), self.vcs) |
|
178 res = dia.startProcess(args, repodir) |
|
179 if res: |
|
180 dia.exec_() |
|
181 res = dia.hasAddOrDelete() |
|
182 self.vcs.checkVCSStatus() |
|
183 return res |
|
184 |
|
185 def hgUnshelveAbort(self, name): |
|
186 """ |
|
187 Public method to abort the ongoing restore operation. |
|
188 |
|
189 @param name name of the project directory (string) |
|
190 @return flag indicating that the project should be reread (boolean) |
|
191 """ |
|
192 # find the root of the repo |
|
193 repodir = name |
|
194 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)): |
|
195 repodir = os.path.dirname(repodir) |
|
196 if os.path.splitdrive(repodir)[1] == os.sep: |
|
197 return False |
|
198 |
|
199 args = self.vcs.initCommand("unshelve") |
|
200 args.append("--abort") |
|
201 |
|
202 dia = HgDialog(self.tr('Abort restore operation'), self.vcs) |
|
203 res = dia.startProcess(args, repodir) |
|
204 if res: |
|
205 dia.exec_() |
|
206 res = dia.hasAddOrDelete() |
|
207 self.vcs.checkVCSStatus() |
|
208 return res |
|
209 |
|
210 def hgUnshelveContinue(self, name): |
|
211 """ |
|
212 Public method to continue the ongoing restore operation. |
|
213 |
|
214 @param name name of the project directory (string) |
|
215 @return flag indicating that the project should be reread (boolean) |
|
216 """ |
|
217 # find the root of the repo |
|
218 repodir = name |
|
219 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)): |
|
220 repodir = os.path.dirname(repodir) |
|
221 if os.path.splitdrive(repodir)[1] == os.sep: |
|
222 return False |
|
223 |
|
224 args = self.vcs.initCommand("unshelve") |
|
225 if self.__unshelveKeep: |
|
226 args.append("--keep") |
|
227 args.append("--continue") |
|
228 |
|
229 dia = HgDialog(self.tr('Continue restore operation'), self.vcs) |
|
230 res = dia.startProcess(args, repodir) |
|
231 if res: |
|
232 dia.exec_() |
|
233 res = dia.hasAddOrDelete() |
|
234 self.vcs.checkVCSStatus() |
|
235 return res |
|
236 |
|
237 def hgDeleteShelves(self, name, shelveNames=None): |
|
238 """ |
|
239 Public method to delete named shelves. |
|
240 |
|
241 @param name name of the project directory (string) |
|
242 @param shelveNames name of shelves to delete (list of string) |
|
243 """ |
|
244 # find the root of the repo |
|
245 repodir = name |
|
246 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)): |
|
247 repodir = os.path.dirname(repodir) |
|
248 if os.path.splitdrive(repodir)[1] == os.sep: |
|
249 return |
|
250 |
|
251 if not shelveNames: |
|
252 from .HgShelvesSelectionDialog import HgShelvesSelectionDialog |
|
253 dlg = HgShelvesSelectionDialog( |
|
254 self.tr("Select the shelves to be deleted:"), |
|
255 self.__hgGetShelveNamesList(repodir)) |
|
256 if dlg.exec_() == QDialog.Accepted: |
|
257 shelveNames = dlg.getSelectedShelves() |
|
258 else: |
|
259 return |
|
260 |
|
261 from UI.DeleteFilesConfirmationDialog import \ |
|
262 DeleteFilesConfirmationDialog |
|
263 dlg = DeleteFilesConfirmationDialog( |
|
264 None, |
|
265 self.tr("Delete shelves"), |
|
266 self.tr("Do you really want to delete these shelves?"), |
|
267 shelveNames) |
|
268 if dlg.exec_() == QDialog.Accepted: |
|
269 args = self.vcs.initCommand("shelve") |
|
270 args.append("--delete") |
|
271 args.extend(shelveNames) |
|
272 |
|
273 dia = HgDialog(self.tr('Delete shelves'), self.vcs) |
|
274 res = dia.startProcess(args, repodir) |
|
275 if res: |
|
276 dia.exec_() |
|
277 |
|
278 def hgCleanupShelves(self, name): |
|
279 """ |
|
280 Public method to delete all shelves. |
|
281 |
|
282 @param name name of the project directory (string) |
|
283 """ |
|
284 # find the root of the repo |
|
285 repodir = name |
|
286 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)): |
|
287 repodir = os.path.dirname(repodir) |
|
288 if os.path.splitdrive(repodir)[1] == os.sep: |
|
289 return |
|
290 |
|
291 res = E5MessageBox.yesNo( |
|
292 None, |
|
293 self.tr("Delete all shelves"), |
|
294 self.tr("""Do you really want to delete all shelved changes?""")) |
|
295 if res: |
|
296 args = self.vcs.initCommand("shelve") |
|
297 args.append("--cleanup") |
|
298 |
|
299 dia = HgDialog(self.tr('Delete all shelves'), self.vcs) |
|
300 res = dia.startProcess(args, repodir) |
|
301 if res: |
|
302 dia.exec_() |