src/eric7/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/queues.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2011 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the queues extension interface.
8 """
9
10 from PyQt6.QtWidgets import QDialog, QApplication, QInputDialog
11
12 from EricWidgets import EricMessageBox
13
14 from ..HgExtension import HgExtension
15 from ..HgDialog import HgDialog
16
17
18 class Queues(HgExtension):
19 """
20 Class implementing the queues extension interface.
21 """
22 APPLIED_LIST = 0
23 UNAPPLIED_LIST = 1
24 SERIES_LIST = 2
25
26 POP = 0
27 PUSH = 1
28 GOTO = 2
29
30 QUEUE_DELETE = 0
31 QUEUE_PURGE = 1
32 QUEUE_ACTIVATE = 2
33
34 def __init__(self, vcs):
35 """
36 Constructor
37
38 @param vcs reference to the Mercurial vcs object
39 """
40 super().__init__(vcs)
41
42 self.qdiffDialog = None
43 self.qheaderDialog = None
44 self.queuesListDialog = None
45 self.queuesListGuardsDialog = None
46 self.queuesListAllGuardsDialog = None
47 self.queuesDefineGuardsDialog = None
48 self.queuesListQueuesDialog = None
49 self.queueStatusDialog = None
50
51 def shutdown(self):
52 """
53 Public method used to shutdown the queues interface.
54 """
55 if self.qdiffDialog is not None:
56 self.qdiffDialog.close()
57 if self.qheaderDialog is not None:
58 self.qheaderDialog.close()
59 if self.queuesListDialog is not None:
60 self.queuesListDialog.close()
61 if self.queuesListGuardsDialog is not None:
62 self.queuesListGuardsDialog.close()
63 if self.queuesListAllGuardsDialog is not None:
64 self.queuesListAllGuardsDialog.close()
65 if self.queuesDefineGuardsDialog is not None:
66 self.queuesDefineGuardsDialog.close()
67 if self.queuesListQueuesDialog is not None:
68 self.queuesListQueuesDialog.close()
69 if self.queueStatusDialog is not None:
70 self.queueStatusDialog.close()
71
72 def __getPatchesList(self, listType, withSummary=False):
73 """
74 Private method to get a list of patches of a given type.
75
76 @param listType type of patches list to get
77 (Queues.APPLIED_LIST, Queues.UNAPPLIED_LIST, Queues.SERIES_LIST)
78 @param withSummary flag indicating to get a summary as well (boolean)
79 @return list of patches (list of string)
80 @exception ValueError raised to indicate an invalid patch list type
81 """
82 patchesList = []
83
84 if listType not in (Queues.APPLIED_LIST, Queues.UNAPPLIED_LIST,
85 Queues.SERIES_LIST):
86 raise ValueError("illegal value for listType")
87
88 if listType == Queues.APPLIED_LIST:
89 args = self.vcs.initCommand("qapplied")
90 elif listType == Queues.UNAPPLIED_LIST:
91 args = self.vcs.initCommand("qunapplied")
92 else:
93 args = self.vcs.initCommand("qseries")
94
95 if withSummary:
96 args.append("--summary")
97
98 client = self.vcs.getClient()
99 output = client.runcommand(args)[0]
100
101 for line in output.splitlines():
102 if withSummary:
103 li = line.strip().split(": ")
104 if len(li) == 1:
105 patch, summary = li[0][:-1], ""
106 else:
107 patch, summary = li[0], li[1]
108 patchesList.append("{0}@@{1}".format(patch, summary))
109 else:
110 patchesList.append(line.strip())
111
112 return patchesList
113
114 def __getCurrentPatch(self):
115 """
116 Private method to get the name of the current patch.
117
118 @return name of the current patch (string)
119 """
120 currentPatch = ""
121
122 args = self.vcs.initCommand("qtop")
123
124 client = self.vcs.getClient()
125 currentPatch = client.runcommand(args)[0].strip()
126
127 return currentPatch
128
129 def __getCommitMessage(self):
130 """
131 Private method to get the commit message of the current patch.
132
133 @return name of the current patch (string)
134 """
135 message = ""
136
137 args = self.vcs.initCommand("qheader")
138
139 client = self.vcs.getClient()
140 message = client.runcommand(args)[0]
141
142 return message
143
144 def getGuardsList(self, allGuards=True):
145 """
146 Public method to get a list of all guards defined.
147
148 @param allGuards flag indicating to get all guards (boolean)
149 @return sorted list of guards (list of strings)
150 """
151 guardsList = []
152
153 args = self.vcs.initCommand("qselect")
154 if allGuards:
155 args.append("--series")
156
157 client = self.vcs.getClient()
158 output = client.runcommand(args)[0]
159
160 for guard in output.splitlines():
161 guard = guard.strip()
162 if allGuards:
163 guard = guard[1:]
164 if guard not in guardsList:
165 guardsList.append(guard)
166
167 return sorted(guardsList)
168
169 def hgQueueNewPatch(self):
170 """
171 Public method to create a new named patch.
172 """
173 from .HgQueuesNewPatchDialog import HgQueuesNewPatchDialog
174 dlg = HgQueuesNewPatchDialog(HgQueuesNewPatchDialog.NEW_MODE)
175 if dlg.exec() == QDialog.DialogCode.Accepted:
176 (name, message,
177 (userData, currentUser, userName),
178 (dateData, currentDate, dateStr)) = dlg.getData()
179
180 args = self.vcs.initCommand("qnew")
181 if message != "":
182 args.append("--message")
183 args.append(message)
184 if userData:
185 if currentUser:
186 args.append("--currentuser")
187 else:
188 args.append("--user")
189 args.append(userName)
190 if dateData:
191 if currentDate:
192 args.append("--currentdate")
193 else:
194 args.append("--date")
195 args.append(dateStr)
196 args.append(name)
197
198 dia = HgDialog(self.tr('New Patch'), self.vcs)
199 res = dia.startProcess(args)
200 if res:
201 dia.exec()
202 self.vcs.checkVCSStatus()
203
204 def hgQueueRefreshPatch(self, editMessage=False):
205 """
206 Public method to refresh the current patch.
207
208 @param editMessage flag indicating to edit the current
209 commit message (boolean)
210 """
211 args = self.vcs.initCommand("qrefresh")
212
213 if editMessage:
214 currentMessage = self.__getCommitMessage()
215 from .HgQueuesNewPatchDialog import HgQueuesNewPatchDialog
216 dlg = HgQueuesNewPatchDialog(HgQueuesNewPatchDialog.REFRESH_MODE,
217 currentMessage)
218 if dlg.exec() == QDialog.DialogCode.Accepted:
219 (name, message,
220 (userData, currentUser, userName),
221 (dateData, currentDate, dateStr)) = dlg.getData()
222 if message != "" and message != currentMessage:
223 args.append("--message")
224 args.append(message)
225 if userData:
226 if currentUser:
227 args.append("--currentuser")
228 else:
229 args.append("--user")
230 args.append(userName)
231 if dateData:
232 if currentDate:
233 args.append("--currentdate")
234 else:
235 args.append("--date")
236 args.append(dateStr)
237 else:
238 return
239
240 dia = HgDialog(self.tr('Update Current Patch'), self.vcs)
241 res = dia.startProcess(args)
242 if res:
243 dia.exec()
244 self.vcs.checkVCSStatus()
245
246 def hgQueueShowPatch(self, name):
247 """
248 Public method to show the contents of the current patch.
249
250 @param name file/directory name (string)
251 """
252 from ..HgDiffDialog import HgDiffDialog
253 self.qdiffDialog = HgDiffDialog(self.vcs)
254 self.qdiffDialog.show()
255 QApplication.processEvents()
256 self.qdiffDialog.start(name, qdiff=True)
257
258 def hgQueueShowHeader(self):
259 """
260 Public method to show the commit message of the current patch.
261 """
262 from .HgQueuesHeaderDialog import HgQueuesHeaderDialog
263 self.qheaderDialog = HgQueuesHeaderDialog(self.vcs)
264 self.qheaderDialog.show()
265 QApplication.processEvents()
266 self.qheaderDialog.start()
267
268 def hgQueuePushPopPatches(self, operation, doAll=False, named=False,
269 force=False):
270 """
271 Public method to push patches onto the stack or pop patches off the
272 stack.
273
274 @param operation operation type to be performed (Queues.POP,
275 Queues.PUSH, Queues.GOTO)
276 @param doAll flag indicating to push/pop all (boolean)
277 @param named flag indicating to push/pop until a named patch
278 is at the top of the stack (boolean)
279 @param force flag indicating a forceful pop (boolean)
280 @return flag indicating that the project should be reread (boolean)
281 @exception ValueError raised to indicate an invalid operation
282 """
283 if operation not in (Queues.POP, Queues.PUSH, Queues.GOTO):
284 raise ValueError("illegal value for operation")
285
286 if operation == Queues.POP:
287 args = self.vcs.initCommand("qpop")
288 title = self.tr("Pop Patches")
289 listType = Queues.APPLIED_LIST
290 elif operation == Queues.PUSH:
291 args = self.vcs.initCommand("qpush")
292 title = self.tr("Push Patches")
293 listType = Queues.UNAPPLIED_LIST
294 else:
295 args = self.vcs.initCommand("qgoto")
296 title = self.tr("Go to Patch")
297 listType = Queues.SERIES_LIST
298
299 args.append("-v")
300 if force:
301 args.append("--force")
302 if doAll and operation in (Queues.POP, Queues.PUSH):
303 args.append("--all")
304 elif named or operation == Queues.GOTO:
305 patchnames = self.__getPatchesList(listType)
306 if patchnames:
307 patch, ok = QInputDialog.getItem(
308 None,
309 self.tr("Select Patch"),
310 self.tr("Select the target patch name:"),
311 patchnames,
312 0, False)
313 if ok and patch:
314 args.append(patch)
315 else:
316 return False
317 else:
318 EricMessageBox.information(
319 None,
320 self.tr("Select Patch"),
321 self.tr("""No patches to select from."""))
322 return False
323
324 dia = HgDialog(title, self.vcs)
325 res = dia.startProcess(args)
326 if res:
327 dia.exec()
328 res = dia.hasAddOrDelete()
329 self.vcs.checkVCSStatus()
330 return res
331
332 def hgQueueListPatches(self):
333 """
334 Public method to show a list of all patches.
335 """
336 from .HgQueuesListDialog import HgQueuesListDialog
337 self.queuesListDialog = HgQueuesListDialog(self.vcs)
338 self.queuesListDialog.show()
339 self.queuesListDialog.start()
340
341 def hgQueueFinishAppliedPatches(self):
342 """
343 Public method to finish all applied patches.
344 """
345 args = self.vcs.initCommand("qfinish")
346 args.append("--applied")
347
348 dia = HgDialog(self.tr('Finish Applied Patches'), self.vcs)
349 res = dia.startProcess(args)
350 if res:
351 dia.exec()
352 self.vcs.checkVCSStatus()
353
354 def hgQueueRenamePatch(self):
355 """
356 Public method to rename the current or a selected patch.
357 """
358 args = self.vcs.initCommand("qrename")
359 patchnames = sorted(self.__getPatchesList(Queues.SERIES_LIST))
360 if patchnames:
361 currentPatch = self.__getCurrentPatch()
362 if currentPatch:
363 from .HgQueuesRenamePatchDialog import (
364 HgQueuesRenamePatchDialog
365 )
366 dlg = HgQueuesRenamePatchDialog(currentPatch, patchnames)
367 if dlg.exec() == QDialog.DialogCode.Accepted:
368 newName, selectedPatch = dlg.getData()
369 if selectedPatch:
370 args.append(selectedPatch)
371 args.append(newName)
372
373 dia = HgDialog(self.tr("Rename Patch"), self.vcs)
374 res = dia.startProcess(args)
375 if res:
376 dia.exec()
377
378 def hgQueueDeletePatch(self):
379 """
380 Public method to delete a selected unapplied patch.
381 """
382 args = self.vcs.initCommand("qdelete")
383 patchnames = sorted(self.__getPatchesList(Queues.UNAPPLIED_LIST))
384 if patchnames:
385 patch, ok = QInputDialog.getItem(
386 None,
387 self.tr("Select Patch"),
388 self.tr("Select the patch to be deleted:"),
389 patchnames,
390 0, False)
391 if ok and patch:
392 args.append(patch)
393
394 dia = HgDialog(self.tr("Delete Patch"), self.vcs)
395 res = dia.startProcess(args)
396 if res:
397 dia.exec()
398 else:
399 EricMessageBox.information(
400 None,
401 self.tr("Select Patch"),
402 self.tr("""No patches to select from."""))
403
404 def hgQueueFoldUnappliedPatches(self):
405 """
406 Public method to fold patches into the current patch.
407 """
408 args = self.vcs.initCommand("qfold")
409 patchnames = sorted(
410 self.__getPatchesList(Queues.UNAPPLIED_LIST, withSummary=True))
411 if patchnames:
412 from .HgQueuesFoldDialog import HgQueuesFoldDialog
413 dlg = HgQueuesFoldDialog(patchnames)
414 if dlg.exec() == QDialog.DialogCode.Accepted:
415 message, patchesList = dlg.getData()
416 if message:
417 args.append("--message")
418 args.append(message)
419 if patchesList:
420 args.extend(patchesList)
421
422 dia = HgDialog(self.tr("Fold Patches"), self.vcs)
423 res = dia.startProcess(args)
424 if res:
425 dia.exec()
426 else:
427 EricMessageBox.information(
428 None,
429 self.tr("Fold Patches"),
430 self.tr("""No patches selected."""))
431 else:
432 EricMessageBox.information(
433 None,
434 self.tr("Fold Patches"),
435 self.tr("""No patches available to be folded."""))
436
437 def hgQueueGuardsList(self):
438 """
439 Public method to list the guards for the current or a named patch.
440 """
441 patchnames = sorted(self.__getPatchesList(Queues.SERIES_LIST))
442 if patchnames:
443 from .HgQueuesListGuardsDialog import HgQueuesListGuardsDialog
444 self.queuesListGuardsDialog = HgQueuesListGuardsDialog(
445 self.vcs, patchnames)
446 self.queuesListGuardsDialog.show()
447 self.queuesListGuardsDialog.start()
448 else:
449 EricMessageBox.information(
450 None,
451 self.tr("List Guards"),
452 self.tr("""No patches available to list guards for."""))
453
454 def hgQueueGuardsListAll(self):
455 """
456 Public method to list all guards of all patches.
457 """
458 from .HgQueuesListAllGuardsDialog import HgQueuesListAllGuardsDialog
459 self.queuesListAllGuardsDialog = HgQueuesListAllGuardsDialog(self.vcs)
460 self.queuesListAllGuardsDialog.show()
461 self.queuesListAllGuardsDialog.start()
462
463 def hgQueueGuardsDefine(self):
464 """
465 Public method to define guards for the current or a named patch.
466 """
467 patchnames = sorted(self.__getPatchesList(Queues.SERIES_LIST))
468 if patchnames:
469 from .HgQueuesDefineGuardsDialog import HgQueuesDefineGuardsDialog
470 self.queuesDefineGuardsDialog = HgQueuesDefineGuardsDialog(
471 self.vcs, self, patchnames)
472 self.queuesDefineGuardsDialog.show()
473 self.queuesDefineGuardsDialog.start()
474 else:
475 EricMessageBox.information(
476 None,
477 self.tr("Define Guards"),
478 self.tr("""No patches available to define guards for."""))
479
480 def hgQueueGuardsDropAll(self):
481 """
482 Public method to drop all guards of the current or a named patch.
483 """
484 patchnames = sorted(
485 self.__getPatchesList(Queues.SERIES_LIST))
486 if patchnames:
487 patch, ok = QInputDialog.getItem(
488 None,
489 self.tr("Drop All Guards"),
490 self.tr("Select the patch to drop guards for"
491 " (leave empty for the current patch):"),
492 [""] + patchnames,
493 0, False)
494 if ok:
495 args = self.vcs.initCommand("qguard")
496 if patch:
497 args.append(patch)
498 args.append("--none")
499
500 client = self.vcs.getClient()
501 client.runcommand(args)
502 else:
503 EricMessageBox.information(
504 None,
505 self.tr("Drop All Guards"),
506 self.tr("""No patches available to define guards for."""))
507
508 def hgQueueGuardsSetActive(self):
509 """
510 Public method to set the active guards.
511 """
512 guardsList = self.getGuardsList()
513 if guardsList:
514 activeGuardsList = self.getGuardsList(allGuards=False)
515 from .HgQueuesGuardsSelectionDialog import (
516 HgQueuesGuardsSelectionDialog
517 )
518 dlg = HgQueuesGuardsSelectionDialog(
519 guardsList, activeGuards=activeGuardsList, listOnly=False)
520 if dlg.exec() == QDialog.DialogCode.Accepted:
521 guards = dlg.getData()
522 if guards:
523 args = self.vcs.initCommand("qselect")
524 args.extend(guards)
525
526 dia = HgDialog(self.tr('Set Active Guards'), self.vcs)
527 res = dia.startProcess(args)
528 if res:
529 dia.exec()
530 else:
531 EricMessageBox.information(
532 None,
533 self.tr("Set Active Guards"),
534 self.tr("""No guards available to select from."""))
535 return
536
537 def hgQueueGuardsDeactivate(self):
538 """
539 Public method to deactivate all active guards.
540 """
541 args = self.vcs.initCommand("qselect")
542 args.append("--none")
543
544 dia = HgDialog(self.tr('Deactivate Guards'), self.vcs)
545 res = dia.startProcess(args)
546 if res:
547 dia.exec()
548
549 def hgQueueGuardsIdentifyActive(self):
550 """
551 Public method to list all active guards.
552 """
553 guardsList = self.getGuardsList(allGuards=False)
554 if guardsList:
555 from .HgQueuesGuardsSelectionDialog import (
556 HgQueuesGuardsSelectionDialog
557 )
558 dlg = HgQueuesGuardsSelectionDialog(guardsList, listOnly=True)
559 dlg.exec()
560
561 def hgQueueCreateRenameQueue(self, isCreate):
562 """
563 Public method to create a new queue or rename the active queue.
564
565 @param isCreate flag indicating to create a new queue (boolean)
566 """
567 from .HgQueuesQueueManagementDialog import (
568 HgQueuesQueueManagementDialog
569 )
570
571 title = (
572 self.tr("Create New Queue")
573 if isCreate else
574 self.tr("Rename Active Queue")
575 )
576 dlg = HgQueuesQueueManagementDialog(
577 HgQueuesQueueManagementDialog.NAME_INPUT,
578 title, False, self.vcs)
579 if dlg.exec() == QDialog.DialogCode.Accepted:
580 queueName = dlg.getData()
581 if queueName:
582 args = self.vcs.initCommand("qqueue")
583 if isCreate:
584 args.append("--create")
585 else:
586 args.append("--rename")
587 args.append(queueName)
588
589 client = self.vcs.getClient()
590 error = client.runcommand(args)[1]
591
592 if error:
593 if isCreate:
594 errMsg = self.tr(
595 "Error while creating a new queue.")
596 else:
597 errMsg = self.tr(
598 "Error while renaming the active queue.")
599 EricMessageBox.warning(
600 None,
601 title,
602 """<p>{0}</p><p>{1}</p>""".format(errMsg, error))
603 else:
604 if (
605 self.queuesListQueuesDialog is not None and
606 self.queuesListQueuesDialog.isVisible()
607 ):
608 self.queuesListQueuesDialog.refresh()
609
610 def hgQueueDeletePurgeActivateQueue(self, operation):
611 """
612 Public method to delete the reference to a queue and optionally
613 remove the patch directory or set the active queue.
614
615 @param operation operation to be performed (Queues.QUEUE_DELETE,
616 Queues.QUEUE_PURGE, Queues.QUEUE_ACTIVATE)
617 @exception ValueError raised to indicate an invalid operation
618 """
619 if operation not in (Queues.QUEUE_PURGE, Queues.QUEUE_DELETE,
620 Queues.QUEUE_ACTIVATE):
621 raise ValueError("illegal value for operation")
622
623 if operation == Queues.QUEUE_PURGE:
624 title = self.tr("Purge Queue")
625 elif operation == Queues.QUEUE_DELETE:
626 title = self.tr("Delete Queue")
627 else:
628 title = self.tr("Activate Queue")
629
630 from .HgQueuesQueueManagementDialog import (
631 HgQueuesQueueManagementDialog
632 )
633 dlg = HgQueuesQueueManagementDialog(
634 HgQueuesQueueManagementDialog.QUEUE_INPUT,
635 title, True, self.vcs)
636 if dlg.exec() == QDialog.DialogCode.Accepted:
637 queueName = dlg.getData()
638 if queueName:
639 args = self.vcs.initCommand("qqueue")
640 if operation == Queues.QUEUE_PURGE:
641 args.append("--purge")
642 elif operation == Queues.QUEUE_DELETE:
643 args.append("--delete")
644 args.append(queueName)
645
646 client = self.vcs.getClient()
647 error = client.runcommand(args)[1]
648
649 if error:
650 if operation == Queues.QUEUE_PURGE:
651 errMsg = self.tr("Error while purging the queue.")
652 elif operation == Queues.QUEUE_DELETE:
653 errMsg = self.tr("Error while deleting the queue.")
654 elif operation == Queues.QUEUE_ACTIVATE:
655 errMsg = self.tr(
656 "Error while setting the active queue.")
657 EricMessageBox.warning(
658 None,
659 title,
660 """<p>{0}</p><p>{1}</p>""".format(errMsg, error))
661 else:
662 if (
663 self.queuesListQueuesDialog is not None and
664 self.queuesListQueuesDialog.isVisible()
665 ):
666 self.queuesListQueuesDialog.refresh()
667
668 def hgQueueListQueues(self):
669 """
670 Public method to list available queues.
671 """
672 from .HgQueuesQueueManagementDialog import (
673 HgQueuesQueueManagementDialog
674 )
675 self.queuesListQueuesDialog = HgQueuesQueueManagementDialog(
676 HgQueuesQueueManagementDialog.NO_INPUT,
677 self.tr("Available Queues"),
678 False, self.vcs)
679 self.queuesListQueuesDialog.show()
680
681 def hgQueueInit(self, name):
682 """
683 Public method to initialize a new queue repository.
684
685 @param name directory name (string)
686 """
687 args = self.vcs.initCommand("init")
688 args.append('--mq')
689 args.append(self.vcs.getClient().getRepository())
690 # init is not possible with the command server
691 dia = HgDialog(
692 self.tr('Initializing new queue repository'), self.vcs)
693 res = dia.startProcess(args)
694 if res:
695 dia.exec()
696
697 def hgQueueStatus(self, name):
698 """
699 Public method used to view the status of a queue repository.
700
701 @param name directory name (string)
702 """
703 from ..HgStatusDialog import HgStatusDialog
704 self.queueStatusDialog = HgStatusDialog(self.vcs, mq=True)
705 self.queueStatusDialog.show()
706 self.queueStatusDialog.start(name)

eric ide

mercurial