Plugins/VcsPlugins/vcsMercurial/QueuesExtension/queues.py

changeset 1035
2cd7817ac659
parent 1034
8a7fa049e9d3
child 1046
5dd14be5d6a1
equal deleted inserted replaced
1034:8a7fa049e9d3 1035:2cd7817ac659
16 from ..HgDialog import HgDialog 16 from ..HgDialog import HgDialog
17 from ..HgDiffDialog import HgDiffDialog 17 from ..HgDiffDialog import HgDiffDialog
18 18
19 from .HgQueuesNewPatchDialog import HgQueuesNewPatchDialog 19 from .HgQueuesNewPatchDialog import HgQueuesNewPatchDialog
20 from .HgQueuesListDialog import HgQueuesListDialog 20 from .HgQueuesListDialog import HgQueuesListDialog
21 from .HgQueuesRenamePatchDialog import HgQueuesRenamePatchDialog
22 from .HgQueuesFoldDialog import HgQueuesFoldDialog
23 from .HgQueuesHeaderDialog import HgQueuesHeaderDialog
21 24
22 import Preferences 25 import Preferences
23 26
24 27
25 class Queues(QObject): 28 class Queues(QObject):
28 """ 31 """
29 APPLIED_LIST = 0 32 APPLIED_LIST = 0
30 UNAPPLIED_LIST = 1 33 UNAPPLIED_LIST = 1
31 SERIES_LIST = 2 34 SERIES_LIST = 2
32 35
36 POP = 0
37 PUSH = 1
38 GOTO = 2
39
33 def __init__(self, vcs): 40 def __init__(self, vcs):
34 """ 41 """
35 Constructor 42 Constructor
36 """ 43 """
37 QObject.__init__(self, vcs) 44 QObject.__init__(self, vcs)
38 45
39 self.vcs = vcs 46 self.vcs = vcs
40 47
41 self.qdiffDialog = None 48 self.qdiffDialog = None
49 self.qheaderDialog = None
42 50
43 def shutdown(self): 51 def shutdown(self):
44 """ 52 """
45 Public method used to shutdown the queues interface. 53 Public method used to shutdown the queues interface.
46 """ 54 """
47 if self.qdiffDialog is not None: 55 if self.qdiffDialog is not None:
48 self.qdiffDialog.close() 56 self.qdiffDialog.close()
57 if self.qheaderDialog is not None:
58 self.qheaderDialog.close()
59
60 def __getPatchesList(self, repodir, listType, withSummary=False):
61 """
62 Public method to get a list of patches of a given type.
63
64 @param repodir directory name of the repository (string)
65 @param listType type of patches list to get
66 (Queues.APPLIED_LIST, Queues.UNAPPLIED_LIST, Queues.SERIES_LIST)
67 @param withSummary flag indicating to get a summary as well (boolean)
68 @return list of patches (list of string)
69 """
70 patchesList = []
71
72 ioEncoding = Preferences.getSystem("IOEncoding")
73 process = QProcess()
74 args = []
75 if listType == Queues.APPLIED_LIST:
76 args.append("qapplied")
77 elif listType == Queues.UNAPPLIED_LIST:
78 args.append("qunapplied")
79 elif listType == Queues.SERIES_LIST:
80 args.append("qseries")
81 else:
82 raise ValueError("illegal value for listType")
83 if withSummary:
84 args.append("--summary")
85
86 process.setWorkingDirectory(repodir)
87 process.start('hg', args)
88 procStarted = process.waitForStarted()
89 if procStarted:
90 finished = process.waitForFinished(30000)
91 if finished and process.exitCode() == 0:
92 output = \
93 str(process.readAllStandardOutput(), ioEncoding, 'replace')
94 for line in output.splitlines():
95 if withSummary:
96 l = line.strip().split(": ")
97 if len(l) == 1:
98 patch, summary = l[0][:-1], ""
99 else:
100 patch, summary = l[0], l[1]
101 patchesList.append("{0}@@{1}".format(patch, summary))
102 else:
103 patchesList.append(line.strip())
104
105 return patchesList
106
107 def __getCurrentPatch(self, repodir):
108 """
109 Public method to get the name of the current patch.
110
111 @param repodir directory name of the repository (string)
112 @return name of the current patch (string)
113 """
114 currentPatch = ""
115
116 ioEncoding = Preferences.getSystem("IOEncoding")
117 process = QProcess()
118 args = []
119 args.append("qtop")
120
121 process.setWorkingDirectory(repodir)
122 process.start('hg', args)
123 procStarted = process.waitForStarted()
124 if procStarted:
125 finished = process.waitForFinished(30000)
126 if finished and process.exitCode() == 0:
127 currentPatch = str(
128 process.readAllStandardOutput(),
129 ioEncoding, 'replace').strip()
130
131 return currentPatch
132
133 def __getCommitMessage(self, repodir):
134 """
135 Public method to get the commit message of the current patch.
136
137 @param repodir directory name of the repository (string)
138 @return name of the current patch (string)
139 """
140 message = ""
141
142 ioEncoding = Preferences.getSystem("IOEncoding")
143 process = QProcess()
144 args = []
145 args.append("qheader")
146
147 process.setWorkingDirectory(repodir)
148 process.start('hg', args)
149 procStarted = process.waitForStarted()
150 if procStarted:
151 finished = process.waitForFinished(30000)
152 if finished and process.exitCode() == 0:
153 message = str(
154 process.readAllStandardOutput(),
155 ioEncoding, 'replace')
156
157 return message
49 158
50 def hgQueueNewPatch(self, name): 159 def hgQueueNewPatch(self, name):
51 """ 160 """
52 Public method to create a new named patch. 161 Public method to create a new named patch.
53 162
58 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)): 167 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)):
59 repodir = os.path.dirname(repodir) 168 repodir = os.path.dirname(repodir)
60 if repodir == os.sep: 169 if repodir == os.sep:
61 return 170 return
62 171
63 dlg = HgQueuesNewPatchDialog() 172 dlg = HgQueuesNewPatchDialog(HgQueuesNewPatchDialog.NEW_MODE)
64 if dlg.exec_() == QDialog.Accepted: 173 if dlg.exec_() == QDialog.Accepted:
65 name, message, (userData, currentUser, userName), \ 174 name, message, (userData, currentUser, userName), \
66 (dateData, currentDate, dateStr) = dlg.getData() 175 (dateData, currentDate, dateStr) = dlg.getData()
67 176
68 args = [] 177 args = []
88 res = dia.startProcess(args, repodir) 197 res = dia.startProcess(args, repodir)
89 if res: 198 if res:
90 dia.exec_() 199 dia.exec_()
91 self.vcs.checkVCSStatus() 200 self.vcs.checkVCSStatus()
92 201
93 def hgQueueRefreshPatch(self, name): 202 def hgQueueRefreshPatch(self, name, editMessage=False):
94 """ 203 """
95 Public method to create a new named patch. 204 Public method to refresh the current patch.
96 205
97 @param name file/directory name (string) 206 @param name file/directory name (string)
207 @param editMessage flag indicating to edit the current
208 commit message (boolean)
98 """ 209 """
99 # find the root of the repo 210 # find the root of the repo
100 repodir = self.vcs.splitPath(name)[0] 211 repodir = self.vcs.splitPath(name)[0]
101 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)): 212 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)):
102 repodir = os.path.dirname(repodir) 213 repodir = os.path.dirname(repodir)
103 if repodir == os.sep: 214 if repodir == os.sep:
104 return 215 return
105 216
106 args = [] 217 args = []
107 args.append("qrefresh") 218 args.append("qrefresh")
219
220 if editMessage:
221 currentMessage = self.__getCommitMessage(repodir)
222 dlg = HgQueuesNewPatchDialog(HgQueuesNewPatchDialog.REFRESH_MODE,
223 currentMessage)
224 if dlg.exec_() == QDialog.Accepted:
225 name, message, (userData, currentUser, userName), \
226 (dateData, currentDate, dateStr) = dlg.getData()
227 if message != "" and message != currentMessage:
228 args.append("--message")
229 args.append(message)
230 if userData:
231 if currentUser:
232 args.append("--currentuser")
233 else:
234 args.append("--user")
235 args.append(userName)
236 if dateData:
237 if currentDate:
238 args.append("--currentdate")
239 else:
240 args.append("--date")
241 args.append(dateStr)
242 else:
243 return
108 244
109 dia = HgDialog(self.trUtf8('Update Current Patch')) 245 dia = HgDialog(self.trUtf8('Update Current Patch'))
110 res = dia.startProcess(args, repodir) 246 res = dia.startProcess(args, repodir)
111 if res: 247 if res:
112 dia.exec_() 248 dia.exec_()
113 self.vcs.checkVCSStatus() 249 self.vcs.checkVCSStatus()
114 250
115 def hgQueueShowPatch(self, name): 251 def hgQueueShowPatch(self, name):
116 """ 252 """
117 Public method to create a new named patch. 253 Public method to show the contents of the current patch.
118 254
119 @param name file/directory name (string) 255 @param name file/directory name (string)
120 """ 256 """
121 self.qdiffDialog = HgDiffDialog(self.vcs) 257 self.qdiffDialog = HgDiffDialog(self.vcs)
122 self.qdiffDialog.show() 258 self.qdiffDialog.show()
123 QApplication.processEvents() 259 QApplication.processEvents()
124 self.qdiffDialog.start(name, qdiff=True) 260 self.qdiffDialog.start(name, qdiff=True)
125 261
126 def hgQueuePushPopPatches(self, name, pop=False, all=False, named=False, force=False): 262 def hgQueueShowHeader(self, name):
263 """
264 Public method to show the commit message of the current patch.
265
266 @param name file/directory name (string)
267 """
268 self.qheaderDialog = HgQueuesHeaderDialog(self.vcs)
269 self.qheaderDialog.show()
270 QApplication.processEvents()
271 self.qheaderDialog.start(name)
272
273 def hgQueuePushPopPatches(self, name, operation, all=False, named=False, force=False):
127 """ 274 """
128 Public method to push patches onto the stack or pop patches off the stack. 275 Public method to push patches onto the stack or pop patches off the stack.
129 276
130 @param name file/directory name (string) 277 @param name file/directory name (string)
131 @keyparam pop flag indicating a pop action (boolean) 278 @param operation operation type to be performed (Queues.POP,
279 Queues.PUSH, Queues.GOTO)
132 @keyparam all flag indicating to push/pop all (boolean) 280 @keyparam all flag indicating to push/pop all (boolean)
133 @keyparam named flag indicating to push/pop until a named patch 281 @keyparam named flag indicating to push/pop until a named patch
134 is at the top of the stack (boolean) 282 is at the top of the stack (boolean)
135 @keyparam force flag indicating a forceful pop (boolean) 283 @keyparam force flag indicating a forceful pop (boolean)
136 """ 284 """
140 repodir = os.path.dirname(repodir) 288 repodir = os.path.dirname(repodir)
141 if repodir == os.sep: 289 if repodir == os.sep:
142 return 290 return
143 291
144 args = [] 292 args = []
145 if pop: 293 if operation == Queues.POP:
146 args.append("qpop") 294 args.append("qpop")
147 title = self.trUtf8("Pop Patches") 295 title = self.trUtf8("Pop Patches")
148 listType = Queues.APPLIED_LIST 296 listType = Queues.APPLIED_LIST
149 else: 297 elif operation == Queues.PUSH:
150 args.append("qpush") 298 args.append("qpush")
151 title = self.trUtf8("Push Patches") 299 title = self.trUtf8("Push Patches")
152 listType = Queues.UNAPPLIED_LIST 300 listType = Queues.UNAPPLIED_LIST
301 elif operation == Queues.GOTO:
302 args.append("qgoto")
303 title = self.trUtf8("Go to Patch")
304 listType = Queues.SERIES_LIST
305 else:
306 raise ValueError("illegal value for operation")
153 if force: 307 if force:
154 args.append("--force") 308 args.append("--force")
155 if all: 309 if all and operation in (Queues.POP, Queues.PUSH):
156 args.append("--all") 310 args.append("--all")
157 elif named: 311 elif named or operation == Queues.GOTO:
158 patchnames = self.__getUnAppliedPatches(repodir, listType) 312 patchnames = self.__getPatchesList(repodir, listType)
159 if patchnames: 313 if patchnames:
160 patch, ok = QInputDialog.getItem( 314 patch, ok = QInputDialog.getItem(
161 None, 315 None,
162 self.trUtf8("Select Patch"), 316 self.trUtf8("Select Patch"),
163 self.trUtf8("Select the target patch name:"), 317 self.trUtf8("Select the target patch name:"),
177 res = dia.startProcess(args, repodir) 331 res = dia.startProcess(args, repodir)
178 if res: 332 if res:
179 dia.exec_() 333 dia.exec_()
180 self.vcs.checkVCSStatus() 334 self.vcs.checkVCSStatus()
181 335
182 def __getUnAppliedPatches(self, repodir, listType):
183 """
184 Public method to get the list of applied or unapplied patches.
185
186 @param repodir directory name of the repository (string)
187 @param listType type of patcheslist to get
188 (Queues.APPLIED_LIST, Queues.UNAPPLIED_LIST, Queues.SERIES_LIST)
189 @return list of patches (list of string)
190 """
191 patchesList = []
192
193 ioEncoding = Preferences.getSystem("IOEncoding")
194 process = QProcess()
195 args = []
196 if listType == Queues.APPLIED_LIST:
197 args.append("qapplied")
198 elif listType == Queues.UNAPPLIED_LIST:
199 args.append("qunapplied")
200 elif listType == Queues.SERIES_LIST:
201 args.append("qseries")
202 else:
203 raise ValueError("Illegal value for listType.")
204
205 process.setWorkingDirectory(repodir)
206 process.start('hg', args)
207 procStarted = process.waitForStarted()
208 if procStarted:
209 finished = process.waitForFinished(30000)
210 if finished and process.exitCode() == 0:
211 output = \
212 str(process.readAllStandardOutput(), ioEncoding, 'replace')
213 for line in output.splitlines():
214 patchesList.append(line.strip())
215
216 return patchesList
217
218 def hgQueueListPatches(self, name): 336 def hgQueueListPatches(self, name):
219 """ 337 """
220 Public method to create a new named patch. 338 Public method to show a list of all patches.
221 339
222 @param name file/directory name (string) 340 @param name file/directory name (string)
223 """ 341 """
224 self.queuesListDialog = HgQueuesListDialog(self.vcs) 342 self.queuesListDialog = HgQueuesListDialog(self.vcs)
225 self.queuesListDialog.show() 343 self.queuesListDialog.show()
226 self.queuesListDialog.start(name) 344 self.queuesListDialog.start(name)
227 345
228 def hgQueueFinishAppliedPatches(self, name): 346 def hgQueueFinishAppliedPatches(self, name):
229 """ 347 """
230 Public method to create a new named patch. 348 Public method to finish all applied patches.
231 349
232 @param name file/directory name (string) 350 @param name file/directory name (string)
233 """ 351 """
234 # find the root of the repo 352 # find the root of the repo
235 repodir = self.vcs.splitPath(name)[0] 353 repodir = self.vcs.splitPath(name)[0]
245 dia = HgDialog(self.trUtf8('Finish Applied Patches')) 363 dia = HgDialog(self.trUtf8('Finish Applied Patches'))
246 res = dia.startProcess(args, repodir) 364 res = dia.startProcess(args, repodir)
247 if res: 365 if res:
248 dia.exec_() 366 dia.exec_()
249 self.vcs.checkVCSStatus() 367 self.vcs.checkVCSStatus()
368
369 def hgQueueRenamePatch(self, name):
370 """
371 Public method to rename the current or a selected patch.
372
373 @param name file/directory name (string)
374 """
375 # find the root of the repo
376 repodir = self.vcs.splitPath(name)[0]
377 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)):
378 repodir = os.path.dirname(repodir)
379 if repodir == os.sep:
380 return
381
382 args = []
383 args.append("qrename")
384 patchnames = sorted(self.__getPatchesList(repodir, Queues.SERIES_LIST))
385 if patchnames:
386 currentPatch = self.__getCurrentPatch(repodir)
387 if currentPatch:
388 dlg = HgQueuesRenamePatchDialog(currentPatch, patchnames)
389 if dlg.exec_() == QDialog.Accepted:
390 newName, selectedPatch = dlg.getData()
391 if selectedPatch:
392 args.append(selectedPatch)
393 args.append(newName)
394
395 dia = HgDialog(self.trUtf8("Rename Patch"))
396 res = dia.startProcess(args, repodir)
397 if res:
398 dia.exec_()
399
400 def hgQueueDeletePatch(self, name):
401 """
402 Public method to delete a selected unapplied patch.
403
404 @param name file/directory name (string)
405 """
406 # find the root of the repo
407 repodir = self.vcs.splitPath(name)[0]
408 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)):
409 repodir = os.path.dirname(repodir)
410 if repodir == os.sep:
411 return
412
413 args = []
414 args.append("qdelete")
415 patchnames = sorted(self.__getPatchesList(repodir, Queues.UNAPPLIED_LIST))
416 if patchnames:
417 patch, ok = QInputDialog.getItem(
418 None,
419 self.trUtf8("Select Patch"),
420 self.trUtf8("Select the patch to be deleted:"),
421 patchnames,
422 0, False)
423 if ok and patch:
424 args.append(patch)
425
426 dia = HgDialog(self.trUtf8("Delete Patch"))
427 res = dia.startProcess(args, repodir)
428 if res:
429 dia.exec_()
430 else:
431 E5MessageBox.information(None,
432 self.trUtf8("Select Patch"),
433 self.trUtf8("""No patches to select from."""))
434
435 def hgQueueFoldUnappliedPatches(self, name):
436 """
437 Public method to fold patches into the current patch.
438
439 @param name file/directory name (string)
440 """
441 # find the root of the repo
442 repodir = self.vcs.splitPath(name)[0]
443 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)):
444 repodir = os.path.dirname(repodir)
445 if repodir == os.sep:
446 return
447
448 args = []
449 args.append("qfold")
450 patchnames = sorted(
451 self.__getPatchesList(repodir, Queues.UNAPPLIED_LIST, withSummary=True))
452 if patchnames:
453 dlg = HgQueuesFoldDialog(patchnames)
454 if dlg.exec_() == QDialog.Accepted:
455 message, patchesList = dlg.getData()
456 if message:
457 args.append("--message")
458 args.append(message)
459 if patchesList:
460 args.extend(patchesList)
461
462 dia = HgDialog(self.trUtf8("Fold Patches"))
463 res = dia.startProcess(args, repodir)
464 if res:
465 dia.exec_()
466 else:
467 E5MessageBox.information(None,
468 self.trUtf8("Fold Patches"),
469 self.trUtf8("""No patches selected."""))
470 else:
471 E5MessageBox.information(None,
472 self.trUtf8("Fold Patches"),
473 self.trUtf8("""No patches available to be folded."""))

eric ide

mercurial