Plugins/VcsPlugins/vcsMercurial/hg.py

changeset 3008
7848489bcb92
parent 2974
4312c5a2bcd3
child 3020
542e97d4ecb3
child 3057
10516539f238
equal deleted inserted replaced
3007:bad2e89047e7 3008:7848489bcb92
32 class Hg(VersionControl): 32 class Hg(VersionControl):
33 """ 33 """
34 Class implementing the version control systems interface to Mercurial. 34 Class implementing the version control systems interface to Mercurial.
35 35
36 @signal committed() emitted after the commit action has completed 36 @signal committed() emitted after the commit action has completed
37 @signal activeExtensionsChanged() emitted when the list of active extensions 37 @signal activeExtensionsChanged() emitted when the list of active
38 has changed 38 extensions has changed
39 """ 39 """
40 committed = pyqtSignal() 40 committed = pyqtSignal()
41 activeExtensionsChanged = pyqtSignal() 41 activeExtensionsChanged = pyqtSignal()
42 42
43 IgnoreFileName = ".hgignore" 43 IgnoreFileName = ".hgignore"
193 193
194 def vcsExists(self): 194 def vcsExists(self):
195 """ 195 """
196 Public method used to test for the presence of the hg executable. 196 Public method used to test for the presence of the hg executable.
197 197
198 @return flag indicating the existance (boolean) and an error message (string) 198 @return flag indicating the existance (boolean) and an error message
199 (string)
199 """ 200 """
200 self.versionStr = '' 201 self.versionStr = ''
201 errMsg = "" 202 errMsg = ""
202 ioEncoding = Preferences.getSystem("IOEncoding") 203 ioEncoding = Preferences.getSystem("IOEncoding")
203 204
222 self.version = tuple(v) 223 self.version = tuple(v)
223 self.__getExtensionsInfo() 224 self.__getExtensionsInfo()
224 return True, errMsg 225 return True, errMsg
225 else: 226 else:
226 if finished: 227 if finished:
227 errMsg = \ 228 errMsg = self.trUtf8(
228 self.trUtf8("The hg process finished with the exit code {0}")\ 229 "The hg process finished with the exit code {0}")\
229 .format(process.exitCode()) 230 .format(process.exitCode())
230 else: 231 else:
231 errMsg = self.trUtf8("The hg process did not finish within 30s.") 232 errMsg = self.trUtf8(
233 "The hg process did not finish within 30s.")
232 else: 234 else:
233 errMsg = self.trUtf8("Could not start the hg executable.") 235 errMsg = self.trUtf8("Could not start the hg executable.")
234 236
235 return False, errMsg 237 return False, errMsg
236 238
237 def vcsInit(self, vcsDir, noDialog=False): 239 def vcsInit(self, vcsDir, noDialog=False):
238 """ 240 """
239 Public method used to initialize the mercurial repository. 241 Public method used to initialize the mercurial repository.
240 242
241 The initialization is done, when a project is converted into a Mercurial 243 The initialization is done, when a project is converted into a
242 controlled project. Therefore we always return TRUE without doing anything. 244 Mercurial controlled project. Therefore we always return TRUE without
245 doing anything.
243 246
244 @param vcsDir name of the VCS directory (string) 247 @param vcsDir name of the VCS directory (string)
245 @param noDialog flag indicating quiet operations (boolean) 248 @param noDialog flag indicating quiet operations (boolean)
246 @return always TRUE 249 @return always TRUE
247 """ 250 """
248 return True 251 return True
249 252
250 def vcsConvertProject(self, vcsDataDict, project): 253 def vcsConvertProject(self, vcsDataDict, project):
251 """ 254 """
252 Public method to convert an uncontrolled project to a version controlled project. 255 Public method to convert an uncontrolled project to a version
256 controlled project.
253 257
254 @param vcsDataDict dictionary of data required for the conversion 258 @param vcsDataDict dictionary of data required for the conversion
255 @param project reference to the project object 259 @param project reference to the project object
256 """ 260 """
257 success = self.vcsImport(vcsDataDict, project.ppath)[0] 261 success = self.vcsImport(vcsDataDict, project.ppath)[0]
258 if not success: 262 if not success:
259 E5MessageBox.critical(self.__ui, 263 E5MessageBox.critical(self.__ui,
260 self.trUtf8("Create project repository"), 264 self.trUtf8("Create project repository"),
261 self.trUtf8("""The project repository could not be created.""")) 265 self.trUtf8(
266 """The project repository could not be created."""))
262 else: 267 else:
263 pfn = project.pfile 268 pfn = project.pfile
264 if not os.path.isfile(pfn): 269 if not os.path.isfile(pfn):
265 pfn += "z" 270 pfn += "z"
266 project.closeProject() 271 project.closeProject()
267 project.openProject(pfn) 272 project.openProject(pfn)
268 273
269 def vcsImport(self, vcsDataDict, projectDir, noDialog=False): 274 def vcsImport(self, vcsDataDict, projectDir, noDialog=False):
270 """ 275 """
271 Public method used to import the project into the Subversion repository. 276 Public method used to import the project into the Mercurial repository.
272 277
273 @param vcsDataDict dictionary of data required for the import 278 @param vcsDataDict dictionary of data required for the import
274 @param projectDir project directory (string) 279 @param projectDir project directory (string)
275 @param noDialog flag indicating quiet operations 280 @param noDialog flag indicating quiet operations
276 @return flag indicating an execution without errors (boolean) 281 @return flag indicating an execution without errors (boolean)
299 args = [] 304 args = []
300 args.append('commit') 305 args.append('commit')
301 args.append('--addremove') 306 args.append('--addremove')
302 args.append('--message') 307 args.append('--message')
303 args.append(msg) 308 args.append(msg)
304 dia = HgDialog(self.trUtf8('Initial commit to Mercurial repository'), 309 dia = HgDialog(
305 self) 310 self.trUtf8('Initial commit to Mercurial repository'),
311 self)
306 res = dia.startProcess(args, projectDir) 312 res = dia.startProcess(args, projectDir)
307 if res: 313 if res:
308 dia.exec_() 314 dia.exec_()
309 status = dia.normalExit() 315 status = dia.normalExit()
310 316
311 return status, False 317 return status, False
312 318
313 def vcsCheckout(self, vcsDataDict, projectDir, noDialog=False): 319 def vcsCheckout(self, vcsDataDict, projectDir, noDialog=False):
314 """ 320 """
315 Public method used to check the project out of a Mercurial repository (clone). 321 Public method used to check the project out of a Mercurial repository
322 (clone).
316 323
317 @param vcsDataDict dictionary of data required for the checkout 324 @param vcsDataDict dictionary of data required for the checkout
318 @param projectDir project directory to create (string) 325 @param projectDir project directory to create (string)
319 @param noDialog flag indicating quiet operations 326 @param noDialog flag indicating quiet operations
320 @return flag indicating an execution without errors (boolean) 327 @return flag indicating an execution without errors (boolean)
345 return self.startSynchronizedProcess(QProcess(), 'hg', args) 352 return self.startSynchronizedProcess(QProcess(), 'hg', args)
346 else: 353 else:
347 out, err = self.__client.runcommand(args) 354 out, err = self.__client.runcommand(args)
348 return err == "" 355 return err == ""
349 else: 356 else:
350 dia = HgDialog(self.trUtf8('Cloning project from a Mercurial repository'), 357 dia = HgDialog(
351 self) 358 self.trUtf8('Cloning project from a Mercurial repository'),
359 self)
352 res = dia.startProcess(args) 360 res = dia.startProcess(args)
353 if res: 361 if res:
354 dia.exec_() 362 dia.exec_()
355 return dia.normalExit() 363 return dia.normalExit()
356 364
357 def vcsExport(self, vcsDataDict, projectDir): 365 def vcsExport(self, vcsDataDict, projectDir):
358 """ 366 """
359 Public method used to export a directory from the Subversion repository. 367 Public method used to export a directory from the Mercurial repository.
360 368
361 @param vcsDataDict dictionary of data required for the checkout 369 @param vcsDataDict dictionary of data required for the checkout
362 @param projectDir project directory to create (string) 370 @param projectDir project directory to create (string)
363 @return flag indicating an execution without errors (boolean) 371 @return flag indicating an execution without errors (boolean)
364 """ 372 """
366 shutil.rmtree(os.path.join(projectDir, self.adminDir), True) 374 shutil.rmtree(os.path.join(projectDir, self.adminDir), True)
367 if os.path.exists(os.path.join(projectDir, '.hgignore')): 375 if os.path.exists(os.path.join(projectDir, '.hgignore')):
368 os.remove(os.path.join(projectDir, '.hgignore')) 376 os.remove(os.path.join(projectDir, '.hgignore'))
369 return status 377 return status
370 378
371 def vcsCommit(self, name, message, noDialog=False, closeBranch=False, mq=False): 379 def vcsCommit(self, name, message, noDialog=False, closeBranch=False,
372 """ 380 mq=False):
373 Public method used to make the change of a file/directory permanent in the 381 """
374 Mercurial repository. 382 Public method used to make the change of a file/directory permanent
375 383 in the Mercurial repository.
376 @param name file/directory name to be committed (string or list of strings) 384
385 @param name file/directory name to be committed (string or list of
386 strings)
377 @param message message for this operation (string) 387 @param message message for this operation (string)
378 @param noDialog flag indicating quiet operations 388 @param noDialog flag indicating quiet operations
379 @keyparam closeBranch flag indicating a close branch commit (boolean) 389 @keyparam closeBranch flag indicating a close branch commit (boolean)
380 @keyparam mq flag indicating a queue commit (boolean) 390 @keyparam mq flag indicating a queue commit (boolean)
381 """ 391 """
424 for nam in nameList: 434 for nam in nameList:
425 # check for commit of the project 435 # check for commit of the project
426 if os.path.isdir(nam): 436 if os.path.isdir(nam):
427 project = e5App().getObject("Project") 437 project = e5App().getObject("Project")
428 if nam == project.getProjectPath(): 438 if nam == project.getProjectPath():
429 ok &= project.checkAllScriptsDirty(reportSyntaxErrors=True) and \ 439 ok &= \
430 project.checkDirty() 440 project.checkAllScriptsDirty(
441 reportSyntaxErrors=True) and \
442 project.checkDirty()
431 continue 443 continue
432 elif os.path.isfile(nam): 444 elif os.path.isfile(nam):
433 editor = e5App().getObject("ViewManager").getOpenEditor(nam) 445 editor = \
446 e5App().getObject("ViewManager").getOpenEditor(nam)
434 if editor: 447 if editor:
435 ok &= editor.checkDirty() 448 ok &= editor.checkDirty()
436 if not ok: 449 if not ok:
437 break 450 break
438 451
439 if not ok: 452 if not ok:
440 res = E5MessageBox.yesNo(self.__ui, 453 res = E5MessageBox.yesNo(self.__ui,
441 self.trUtf8("Commit Changes"), 454 self.trUtf8("Commit Changes"),
442 self.trUtf8("""The commit affects files, that have unsaved""" 455 self.trUtf8(
443 """ changes. Shall the commit be continued?"""), 456 """The commit affects files, that have unsaved"""
457 """ changes. Shall the commit be continued?"""),
444 icon=E5MessageBox.Warning) 458 icon=E5MessageBox.Warning)
445 if not res: 459 if not res:
446 return 460 return
447 461
448 if self.__commitDialog is not None: 462 if self.__commitDialog is not None:
501 args.append(fname) 515 args.append(fname)
502 516
503 if noDialog: 517 if noDialog:
504 self.startSynchronizedProcess(QProcess(), "hg", args, dname) 518 self.startSynchronizedProcess(QProcess(), "hg", args, dname)
505 else: 519 else:
506 dia = HgDialog(self.trUtf8('Committing changes to Mercurial repository'), 520 dia = HgDialog(
507 self) 521 self.trUtf8('Committing changes to Mercurial repository'),
522 self)
508 res = dia.startProcess(args, dname) 523 res = dia.startProcess(args, dname)
509 if res: 524 if res:
510 dia.exec_() 525 dia.exec_()
511 self.committed.emit() 526 self.committed.emit()
512 if self.__forgotNames: 527 if self.__forgotNames:
516 self.__forgotNames = [] 531 self.__forgotNames = []
517 self.checkVCSStatus() 532 self.checkVCSStatus()
518 533
519 def vcsUpdate(self, name, noDialog=False, revision=None): 534 def vcsUpdate(self, name, noDialog=False, revision=None):
520 """ 535 """
521 Public method used to update a file/directory with the Mercurial repository. 536 Public method used to update a file/directory with the Mercurial
522 537 repository.
523 @param name file/directory name to be updated (string or list of strings) 538
539 @param name file/directory name to be updated (string or list of
540 strings)
524 @param noDialog flag indicating quiet operations (boolean) 541 @param noDialog flag indicating quiet operations (boolean)
525 @keyparam revision revision to update to (string) 542 @keyparam revision revision to update to (string)
526 @return flag indicating, that the update contained an add 543 @return flag indicating, that the update contained an add
527 or delete (boolean) 544 or delete (boolean)
528 """ 545 """
553 self.startSynchronizedProcess(QProcess(), 'hg', args, repodir) 570 self.startSynchronizedProcess(QProcess(), 'hg', args, repodir)
554 else: 571 else:
555 out, err = self.__client.runcommand(args) 572 out, err = self.__client.runcommand(args)
556 res = False 573 res = False
557 else: 574 else:
558 dia = HgDialog(self.trUtf8('Synchronizing with the Mercurial repository'), 575 dia = HgDialog(self.trUtf8(
559 self) 576 'Synchronizing with the Mercurial repository'),
577 self)
560 res = dia.startProcess(args, repodir) 578 res = dia.startProcess(args, repodir)
561 if res: 579 if res:
562 dia.exec_() 580 dia.exec_()
563 res = dia.hasAddOrDelete() 581 res = dia.hasAddOrDelete()
564 self.checkVCSStatus() 582 self.checkVCSStatus()
606 self.startSynchronizedProcess(QProcess(), 'hg', args, repodir) 624 self.startSynchronizedProcess(QProcess(), 'hg', args, repodir)
607 else: 625 else:
608 out, err = self.__client.runcommand(args) 626 out, err = self.__client.runcommand(args)
609 else: 627 else:
610 dia = HgDialog( 628 dia = HgDialog(
611 self.trUtf8('Adding files/directories to the Mercurial repository'), self) 629 self.trUtf8(
630 'Adding files/directories to the Mercurial repository'),
631 self)
612 res = dia.startProcess(args, repodir) 632 res = dia.startProcess(args, repodir)
613 if res: 633 if res:
614 dia.exec_() 634 dia.exec_()
615 635
616 def vcsAddBinary(self, name, isDir=False): 636 def vcsAddBinary(self, name, isDir=False):
623 """ 643 """
624 self.vcsAdd(name, isDir) 644 self.vcsAdd(name, isDir)
625 645
626 def vcsAddTree(self, path): 646 def vcsAddTree(self, path):
627 """ 647 """
628 Public method to add a directory tree rooted at path to the Mercurial repository. 648 Public method to add a directory tree rooted at path to the Mercurial
629 649 repository.
630 @param path root directory of the tree to be added (string or list of strings)) 650
651 @param path root directory of the tree to be added (string or list of
652 strings))
631 """ 653 """
632 self.vcsAdd(path, isDir=False) 654 self.vcsAdd(path, isDir=False)
633 655
634 def vcsRemove(self, name, project=False, noDialog=False): 656 def vcsRemove(self, name, project=False, noDialog=False):
635 """ 657 """
636 Public method used to remove a file/directory from the Mercurial repository. 658 Public method used to remove a file/directory from the Mercurial
659 repository.
637 660
638 The default operation is to remove the local copy as well. 661 The default operation is to remove the local copy as well.
639 662
640 @param name file/directory name to be removed (string or list of strings)) 663 @param name file/directory name to be removed (string or list of
641 @param project flag indicating deletion of a project tree (boolean) (not needed) 664 strings))
665 @param project flag indicating deletion of a project tree (boolean)
666 (not needed)
642 @param noDialog flag indicating quiet operations 667 @param noDialog flag indicating quiet operations
643 @return flag indicating successfull operation (boolean) 668 @return flag indicating successfull operation (boolean)
644 """ 669 """
645 args = [] 670 args = []
646 args.append('remove') 671 args.append('remove')
664 if os.path.splitdrive(repodir)[1] == os.sep: 689 if os.path.splitdrive(repodir)[1] == os.sep:
665 return False 690 return False
666 691
667 if noDialog: 692 if noDialog:
668 if self.__client is None: 693 if self.__client is None:
669 res = self.startSynchronizedProcess(QProcess(), 'hg', args, repodir) 694 res = self.startSynchronizedProcess(
695 QProcess(), 'hg', args, repodir)
670 else: 696 else:
671 out, err = self.__client.runcommand(args) 697 out, err = self.__client.runcommand(args)
672 res = err == "" 698 res = err == ""
673 else: 699 else:
674 dia = HgDialog( 700 dia = HgDialog(
675 self.trUtf8('Removing files/directories from the Mercurial repository'), 701 self.trUtf8(
702 'Removing files/directories from the Mercurial'
703 ' repository'),
676 self) 704 self)
677 res = dia.startProcess(args, repodir) 705 res = dia.startProcess(args, repodir)
678 if res: 706 if res:
679 dia.exec_() 707 dia.exec_()
680 res = dia.normalExitWithoutErrors() 708 res = dia.normalExitWithoutErrors()
728 if os.path.splitdrive(repodir)[1] == os.sep: 756 if os.path.splitdrive(repodir)[1] == os.sep:
729 return False 757 return False
730 758
731 if noDialog: 759 if noDialog:
732 if self.__client is None: 760 if self.__client is None:
733 res = self.startSynchronizedProcess(QProcess(), 'hg', args, repodir) 761 res = self.startSynchronizedProcess(
762 QProcess(), 'hg', args, repodir)
734 else: 763 else:
735 out, err = self.__client.runcommand(args) 764 out, err = self.__client.runcommand(args)
736 res = err == "" 765 res = err == ""
737 else: 766 else:
738 dia = HgDialog(self.trUtf8('Renaming {0}').format(name), self) 767 dia = HgDialog(self.trUtf8('Renaming {0}').format(name), self)
770 if os.path.splitdrive(repodir)[1] == os.sep: 799 if os.path.splitdrive(repodir)[1] == os.sep:
771 return 800 return
772 801
773 if self.isExtensionActive("bookmarks"): 802 if self.isExtensionActive("bookmarks"):
774 bookmarksList = \ 803 bookmarksList = \
775 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) 804 self.getExtensionObject("bookmarks")\
805 .hgGetBookmarksList(repodir)
776 else: 806 else:
777 bookmarksList = None 807 bookmarksList = None
778 808
779 from .HgMultiRevisionSelectionDialog import HgMultiRevisionSelectionDialog 809 from .HgMultiRevisionSelectionDialog import \
810 HgMultiRevisionSelectionDialog
780 dlg = HgMultiRevisionSelectionDialog( 811 dlg = HgMultiRevisionSelectionDialog(
781 self.hgGetTagsList(repodir), 812 self.hgGetTagsList(repodir),
782 self.hgGetBranchesList(repodir), 813 self.hgGetBranchesList(repodir),
783 bookmarksList, 814 bookmarksList,
784 emptyRevsOk=True, 815 emptyRevsOk=True,
795 """ 826 """
796 Public method used to view the difference of a file/directory to the 827 Public method used to view the difference of a file/directory to the
797 Mercurial repository. 828 Mercurial repository.
798 829
799 If name is a directory and is the project directory, all project files 830 If name is a directory and is the project directory, all project files
800 are saved first. If name is a file (or list of files), which is/are being edited 831 are saved first. If name is a file (or list of files), which is/are
801 and has unsaved modification, they can be saved or the operation may be aborted. 832 being edited and has unsaved modification, they can be saved or the
833 operation may be aborted.
802 834
803 @param name file/directory name to be diffed (string) 835 @param name file/directory name to be diffed (string)
804 """ 836 """
805 if isinstance(name, list): 837 if isinstance(name, list):
806 names = name[:] 838 names = name[:]
842 @param mq flag indicating to show the queue status as well (boolean) 874 @param mq flag indicating to show the queue status as well (boolean)
843 """ 875 """
844 from .HgSummaryDialog import HgSummaryDialog 876 from .HgSummaryDialog import HgSummaryDialog
845 self.summary = HgSummaryDialog(self) 877 self.summary = HgSummaryDialog(self)
846 self.summary.show() 878 self.summary.show()
847 self.summary.start(self.__projectHelper.getProject().getProjectPath(), mq=mq) 879 self.summary.start(self.__projectHelper.getProject().getProjectPath(),
880 mq=mq)
848 881
849 def vcsTag(self, name): 882 def vcsTag(self, name):
850 """ 883 """
851 Public method used to set the tag in the Mercurial repository. 884 Public method used to set the tag in the Mercurial repository.
852 885
918 return False 951 return False
919 952
920 project = e5App().getObject("Project") 953 project = e5App().getObject("Project")
921 names = [project.getRelativePath(nam) for nam in names] 954 names = [project.getRelativePath(nam) for nam in names]
922 if names[0]: 955 if names[0]:
923 from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog 956 from UI.DeleteFilesConfirmationDialog import \
957 DeleteFilesConfirmationDialog
924 dlg = DeleteFilesConfirmationDialog(self.parent(), 958 dlg = DeleteFilesConfirmationDialog(self.parent(),
925 self.trUtf8("Revert changes"), 959 self.trUtf8("Revert changes"),
926 self.trUtf8("Do you really want to revert all changes to these files" 960 self.trUtf8(
927 " or directories?"), 961 "Do you really want to revert all changes to these files"
962 " or directories?"),
928 names) 963 names)
929 yes = dlg.exec_() == QDialog.Accepted 964 yes = dlg.exec_() == QDialog.Accepted
930 else: 965 else:
931 yes = E5MessageBox.yesNo(None, 966 yes = E5MessageBox.yesNo(None,
932 self.trUtf8("Revert changes"), 967 self.trUtf8("Revert changes"),
964 if force: 999 if force:
965 del opts[opts.index('--force')] 1000 del opts[opts.index('--force')]
966 1001
967 if self.isExtensionActive("bookmarks"): 1002 if self.isExtensionActive("bookmarks"):
968 bookmarksList = \ 1003 bookmarksList = \
969 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) 1004 self.getExtensionObject("bookmarks")\
1005 .hgGetBookmarksList(repodir)
970 else: 1006 else:
971 bookmarksList = None 1007 bookmarksList = None
972 from .HgMergeDialog import HgMergeDialog 1008 from .HgMergeDialog import HgMergeDialog
973 dlg = HgMergeDialog(force, self.hgGetTagsList(repodir), 1009 dlg = HgMergeDialog(force, self.hgGetTagsList(repodir),
974 self.hgGetBranchesList(repodir), 1010 self.hgGetBranchesList(repodir),
993 dia.exec_() 1029 dia.exec_()
994 self.checkVCSStatus() 1030 self.checkVCSStatus()
995 1031
996 def vcsSwitch(self, name): 1032 def vcsSwitch(self, name):
997 """ 1033 """
998 Public method used to switch a working directory to a different revision. 1034 Public method used to switch a working directory to a different
1035 revision.
999 1036
1000 @param name directory name to be switched (string) 1037 @param name directory name to be switched (string)
1001 @return flag indicating, that the switch contained an add 1038 @return flag indicating, that the switch contained an add
1002 or delete (boolean) 1039 or delete (boolean)
1003 """ 1040 """
1010 if os.path.splitdrive(repodir)[1] == os.sep: 1047 if os.path.splitdrive(repodir)[1] == os.sep:
1011 return False 1048 return False
1012 1049
1013 if self.isExtensionActive("bookmarks"): 1050 if self.isExtensionActive("bookmarks"):
1014 bookmarksList = \ 1051 bookmarksList = \
1015 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) 1052 self.getExtensionObject("bookmarks")\
1053 .hgGetBookmarksList(repodir)
1016 else: 1054 else:
1017 bookmarksList = None 1055 bookmarksList = None
1018 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog 1056 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog
1019 dlg = HgRevisionSelectionDialog(self.hgGetTagsList(repodir), 1057 dlg = HgRevisionSelectionDialog(self.hgGetTagsList(repodir),
1020 self.hgGetBranchesList(repodir), 1058 self.hgGetBranchesList(repodir),
1087 1125
1088 return self.canBeAdded 1126 return self.canBeAdded
1089 1127
1090 def vcsAllRegisteredStates(self, names, dname, shortcut=True): 1128 def vcsAllRegisteredStates(self, names, dname, shortcut=True):
1091 """ 1129 """
1092 Public method used to get the registered states of a number of files in the vcs. 1130 Public method used to get the registered states of a number of files
1093 1131 in the vcs.
1094 <b>Note:</b> If a shortcut is to be taken, the code will only check, if the named 1132
1095 directory has been scanned already. If so, it is assumed, that the states for 1133 <b>Note:</b> If a shortcut is to be taken, the code will only check,
1096 all files have been populated by the previous run. 1134 if the named directory has been scanned already. If so, it is assumed,
1135 that the states for all files have been populated by the previous run.
1097 1136
1098 @param names dictionary with all filenames to be checked as keys 1137 @param names dictionary with all filenames to be checked as keys
1099 @param dname directory to check in (string) 1138 @param dname directory to check in (string)
1100 @param shortcut flag indicating a shortcut should be taken (boolean) 1139 @param shortcut flag indicating a shortcut should be taken (boolean)
1101 @return the received dictionary completed with a combination of 1140 @return the received dictionary completed with a combination of
1303 infoBlock = [] 1342 infoBlock = []
1304 if output: 1343 if output:
1305 index = 0 1344 index = 0
1306 for line in output.splitlines(): 1345 for line in output.splitlines():
1307 index += 1 1346 index += 1
1308 changeset, tags, author, date, branches, bookmarks = line.split("@@@") 1347 changeset, tags, author, date, branches, bookmarks = \
1348 line.split("@@@")
1309 cdate, ctime = date.split()[:2] 1349 cdate, ctime = date.split()[:2]
1310 info = [] 1350 info = []
1311 info.append(QApplication.translate("mercurial", 1351 info.append(QApplication.translate("mercurial",
1312 """<tr><td><b>Parent #{0}</b></td><td></td></tr>\n""" 1352 """<tr><td><b>Parent #{0}</b></td><td></td></tr>\n"""
1313 """<tr><td><b>Changeset</b></td><td>{1}</td></tr>""")\ 1353 """<tr><td><b>Changeset</b></td><td>{1}</td></tr>""")\
1366 """<tr><td><b>URL</b></td><td>{1}</td></tr>\n""" 1406 """<tr><td><b>URL</b></td><td>{1}</td></tr>\n"""
1367 """{2}""" 1407 """{2}"""
1368 """</table></p>\n""" 1408 """</table></p>\n"""
1369 ).format(self.versionStr, url, infoStr) 1409 ).format(self.versionStr, url, infoStr)
1370 1410
1371 ############################################################################ 1411 ###########################################################################
1372 ## Private Mercurial specific methods are below. 1412 ## Private Mercurial specific methods are below.
1373 ############################################################################ 1413 ###########################################################################
1374 1414
1375 def __hgURL(self, url): 1415 def __hgURL(self, url):
1376 """ 1416 """
1377 Private method to format a url for Mercurial. 1417 Private method to format a url for Mercurial.
1378 1418
1390 scheme, user, host, port, urllib.parse.quote(path)) 1430 scheme, user, host, port, urllib.parse.quote(path))
1391 elif len(url) == 3: 1431 elif len(url) == 3:
1392 scheme = url[0] 1432 scheme = url[0]
1393 host = url[1] 1433 host = url[1]
1394 port, path = url[2].split("/", 1) 1434 port, path = url[2].split("/", 1)
1395 return "{0}:{1}:{2}/{3}".format(scheme, host, port, urllib.parse.quote(path)) 1435 return "{0}:{1}:{2}/{3}".format(
1436 scheme, host, port, urllib.parse.quote(path))
1396 else: 1437 else:
1397 scheme = url[0] 1438 scheme = url[0]
1398 if scheme == "file": 1439 if scheme == "file":
1399 return "{0}:{1}".format(scheme, urllib.parse.quote(url[1])) 1440 return "{0}:{1}".format(scheme, urllib.parse.quote(url[1]))
1400 else: 1441 else:
1401 host, path = url[1][2:].split("/", 1) 1442 host, path = url[1][2:].split("/", 1)
1402 return "{0}://{1}/{2}".format(scheme, host, urllib.parse.quote(path)) 1443 return "{0}://{1}/{2}".format(
1444 scheme, host, urllib.parse.quote(path))
1403 1445
1404 def hgNormalizeURL(self, url): 1446 def hgNormalizeURL(self, url):
1405 """ 1447 """
1406 Public method to normalize a url for Mercurial. 1448 Public method to normalize a url for Mercurial.
1407 1449
1567 allTagsBranchesList = self.allTagsBranchesList 1609 allTagsBranchesList = self.allTagsBranchesList
1568 else: 1610 else:
1569 self.branchesList = [] 1611 self.branchesList = []
1570 allTagsBranchesList = None 1612 allTagsBranchesList = None
1571 self.tagbranchList.start(path, tags, 1613 self.tagbranchList.start(path, tags,
1572 self.branchesList, self.allTagsBranchesList) 1614 self.branchesList,
1615 self.allTagsBranchesList)
1573 1616
1574 def hgAnnotate(self, name): 1617 def hgAnnotate(self, name):
1575 """ 1618 """
1576 Public method to show the output of the hg annotate command. 1619 Public method to show the output of the hg annotate command.
1577 1620
1586 """ 1629 """
1587 Public method used to view the difference of a file/directory to the 1630 Public method used to view the difference of a file/directory to the
1588 Mercurial repository. 1631 Mercurial repository.
1589 1632
1590 If name is a directory and is the project directory, all project files 1633 If name is a directory and is the project directory, all project files
1591 are saved first. If name is a file (or list of files), which is/are being edited 1634 are saved first. If name is a file (or list of files), which is/are
1592 and has unsaved modification, they can be saved or the operation may be aborted. 1635 being edited and has unsaved modification, they can be saved or the
1636 operation may be aborted.
1593 1637
1594 This method gives the chance to enter the revisions to be compared. 1638 This method gives the chance to enter the revisions to be compared.
1595 1639
1596 @param name file/directory name to be diffed (string) 1640 @param name file/directory name to be diffed (string)
1597 """ 1641 """
1618 if os.path.splitdrive(repodir)[1] == os.sep: 1662 if os.path.splitdrive(repodir)[1] == os.sep:
1619 return 1663 return
1620 1664
1621 if self.isExtensionActive("bookmarks"): 1665 if self.isExtensionActive("bookmarks"):
1622 bookmarksList = \ 1666 bookmarksList = \
1623 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) 1667 self.getExtensionObject("bookmarks")\
1668 .hgGetBookmarksList(repodir)
1624 else: 1669 else:
1625 bookmarksList = None 1670 bookmarksList = None
1626 from .HgRevisionsSelectionDialog import HgRevisionsSelectionDialog 1671 from .HgRevisionsSelectionDialog import HgRevisionsSelectionDialog
1627 dlg = HgRevisionsSelectionDialog(self.hgGetTagsList(repodir), 1672 dlg = HgRevisionsSelectionDialog(self.hgGetTagsList(repodir),
1628 self.hgGetBranchesList(repodir), 1673 self.hgGetBranchesList(repodir),
1634 self.diff.show() 1679 self.diff.show()
1635 self.diff.start(name, revisions) 1680 self.diff.start(name, revisions)
1636 1681
1637 def __hgGetFileForRevision(self, name, rev=""): 1682 def __hgGetFileForRevision(self, name, rev=""):
1638 """ 1683 """
1639 Private method to get a file for a specific revision from the repository. 1684 Private method to get a file for a specific revision from the
1685 repository.
1640 1686
1641 @param name file name to get from the repository (string) 1687 @param name file name to get from the repository (string)
1642 @keyparam rev revision to retrieve (string) 1688 @keyparam rev revision to retrieve (string)
1643 @return contents of the file (string) and an error message (string) 1689 @return contents of the file (string) and an error message (string)
1644 """ 1690 """
1672 Preferences.getSystem("IOEncoding"), 'replace') 1718 Preferences.getSystem("IOEncoding"), 'replace')
1673 else: 1719 else:
1674 error = str(process.readAllStandardError(), 1720 error = str(process.readAllStandardError(),
1675 Preferences.getSystem("IOEncoding"), 'replace') 1721 Preferences.getSystem("IOEncoding"), 'replace')
1676 else: 1722 else:
1677 error = self.trUtf8("The hg process did not finish within 30s.") 1723 error = self.trUtf8(
1724 "The hg process did not finish within 30s.")
1678 else: 1725 else:
1679 error = self.trUtf8('The process {0} could not be started. ' 1726 error = self.trUtf8('The process {0} could not be started. '
1680 'Ensure, that it is in the search path.').format('hg') 1727 'Ensure, that it is in the search path.').format('hg')
1681 else: 1728 else:
1682 output, error = self.__client.runcommand(args) 1729 output, error = self.__client.runcommand(args)
1683 1730
1684 return output, error 1731 return output, error
1685 1732
1686 def hgSbsDiff(self, name, extended=False, revisions=None): 1733 def hgSbsDiff(self, name, extended=False, revisions=None):
1687 """ 1734 """
1688 Public method used to view the difference of a file to the Mercurial repository 1735 Public method used to view the difference of a file to the Mercurial
1689 side-by-side. 1736 repository side-by-side.
1690 1737
1691 @param name file name to be diffed (string) 1738 @param name file name to be diffed (string)
1692 @keyparam extended flag indicating the extended variant (boolean) 1739 @keyparam extended flag indicating the extended variant (boolean)
1693 @keyparam revisions tuple of two revisions (tuple of strings) 1740 @keyparam revisions tuple of two revisions (tuple of strings)
1694 @exception ValueError raised to indicate an invalid name parameter 1741 @exception ValueError raised to indicate an invalid name parameter
1704 if os.path.splitdrive(repodir)[1] == os.sep: 1751 if os.path.splitdrive(repodir)[1] == os.sep:
1705 return 1752 return
1706 1753
1707 if self.isExtensionActive("bookmarks"): 1754 if self.isExtensionActive("bookmarks"):
1708 bookmarksList = \ 1755 bookmarksList = \
1709 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) 1756 self.getExtensionObject("bookmarks")\
1757 .hgGetBookmarksList(repodir)
1710 else: 1758 else:
1711 bookmarksList = None 1759 bookmarksList = None
1712 1760
1713 from .HgRevisionsSelectionDialog import HgRevisionsSelectionDialog 1761 from .HgRevisionsSelectionDialog import HgRevisionsSelectionDialog
1714 dlg = HgRevisionsSelectionDialog(self.hgGetTagsList(repodir), 1762 dlg = HgRevisionsSelectionDialog(self.hgGetTagsList(repodir),
1744 f1.close() 1792 f1.close()
1745 name2 = name 1793 name2 = name
1746 except IOError: 1794 except IOError:
1747 E5MessageBox.critical(self.__ui, 1795 E5MessageBox.critical(self.__ui,
1748 self.trUtf8("Mercurial Side-by-Side Difference"), 1796 self.trUtf8("Mercurial Side-by-Side Difference"),
1749 self.trUtf8("""<p>The file <b>{0}</b> could not be read.</p>""") 1797 self.trUtf8(
1798 """<p>The file <b>{0}</b> could not be read.</p>""")
1750 .format(name)) 1799 .format(name))
1751 return 1800 return
1752 1801
1753 if self.sbsDiff is None: 1802 if self.sbsDiff is None:
1754 from UI.CompareDialog import CompareDialog 1803 from UI.CompareDialog import CompareDialog
1760 """ 1809 """
1761 Public method used to browse the log of a file/directory from the 1810 Public method used to browse the log of a file/directory from the
1762 Mercurial repository. 1811 Mercurial repository.
1763 1812
1764 @param path file/directory name to show the log of (string) 1813 @param path file/directory name to show the log of (string)
1765 @keyparam isFile flag indicating log for a file is to be shown (boolean) 1814 @keyparam isFile flag indicating log for a file is to be shown
1815 (boolean)
1766 """ 1816 """
1767 from .HgLogBrowserDialog import HgLogBrowserDialog 1817 from .HgLogBrowserDialog import HgLogBrowserDialog
1768 self.logBrowser = HgLogBrowserDialog(self, isFile=isFile) 1818 self.logBrowser = HgLogBrowserDialog(self, isFile=isFile)
1769 self.logBrowser.show() 1819 self.logBrowser.show()
1770 self.logBrowser.start(path) 1820 self.logBrowser.start(path)
1871 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 1921 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
1872 repodir = os.path.dirname(repodir) 1922 repodir = os.path.dirname(repodir)
1873 if os.path.splitdrive(repodir)[1] == os.sep: 1923 if os.path.splitdrive(repodir)[1] == os.sep:
1874 return 1924 return
1875 1925
1876 dia = HgDialog(self.trUtf8('Pushing to a remote Mercurial repository'), self) 1926 dia = HgDialog(
1927 self.trUtf8('Pushing to a remote Mercurial repository'), self)
1877 res = dia.startProcess(args, repodir) 1928 res = dia.startProcess(args, repodir)
1878 if res: 1929 if res:
1879 dia.exec_() 1930 dia.exec_()
1880 res = dia.hasAddOrDelete() 1931 res = dia.hasAddOrDelete()
1881 self.checkVCSStatus() 1932 self.checkVCSStatus()
1883 def hgInfo(self, ppath, mode="heads"): 1934 def hgInfo(self, ppath, mode="heads"):
1884 """ 1935 """
1885 Public method to show information about the heads of the repository. 1936 Public method to show information about the heads of the repository.
1886 1937
1887 @param ppath local path to get the repository infos (string) 1938 @param ppath local path to get the repository infos (string)
1888 @keyparam mode mode of the operation (string, one of heads, parents, tip) 1939 @keyparam mode mode of the operation (string, one of heads, parents,
1940 tip)
1889 """ 1941 """
1890 if mode not in ("heads", "parents", "tip"): 1942 if mode not in ("heads", "parents", "tip"):
1891 mode = "heads" 1943 mode = "heads"
1892 1944
1893 info = [] 1945 info = []
2022 if ok and name: 2074 if ok and name:
2023 args = [] 2075 args = []
2024 args.append('branch') 2076 args.append('branch')
2025 args.append(name.strip().replace(" ", "_")) 2077 args.append(name.strip().replace(" ", "_"))
2026 2078
2027 dia = HgDialog(self.trUtf8('Creating branch in the Mercurial repository'), 2079 dia = HgDialog(
2028 self) 2080 self.trUtf8('Creating branch in the Mercurial repository'),
2081 self)
2029 res = dia.startProcess(args, repodir) 2082 res = dia.startProcess(args, repodir)
2030 if res: 2083 if res:
2031 dia.exec_() 2084 dia.exec_()
2032 2085
2033 def hgShowBranch(self, name): 2086 def hgShowBranch(self, name):
2060 from .HgUtilities import getConfigPath 2113 from .HgUtilities import getConfigPath
2061 cfgFile = getConfigPath() 2114 cfgFile = getConfigPath()
2062 if not os.path.exists(cfgFile): 2115 if not os.path.exists(cfgFile):
2063 try: 2116 try:
2064 f = open(cfgFile, "w") 2117 f = open(cfgFile, "w")
2065 f.write("[ui]\nusername = Firstname Lastname <email_address>\n") 2118 f.write("[ui]\nusername = Firstname Lastname"
2119 " <email_address>\n")
2066 f.close() 2120 f.close()
2067 except (IOError, OSError): 2121 except (IOError, OSError):
2068 # ignore these 2122 # ignore these
2069 pass 2123 pass
2070 self.userEditor = MiniEditor(cfgFile, "Properties") 2124 self.userEditor = MiniEditor(cfgFile, "Properties")
2112 return 2166 return
2113 2167
2114 args = [] 2168 args = []
2115 args.append('verify') 2169 args.append('verify')
2116 2170
2117 dia = HgDialog(self.trUtf8('Verifying the integrity of the Mercurial repository'), 2171 dia = HgDialog(
2118 self) 2172 self.trUtf8('Verifying the integrity of the Mercurial repository'),
2173 self)
2119 res = dia.startProcess(args, repodir) 2174 res = dia.startProcess(args, repodir)
2120 if res: 2175 if res:
2121 dia.exec_() 2176 dia.exec_()
2122 2177
2123 def hgShowConfig(self, name): 2178 def hgShowConfig(self, name):
2137 2192
2138 args = [] 2193 args = []
2139 args.append('showconfig') 2194 args.append('showconfig')
2140 args.append("--untrusted") 2195 args.append("--untrusted")
2141 2196
2142 dia = HgDialog(self.trUtf8('Showing the combined configuration settings'), self) 2197 dia = HgDialog(
2198 self.trUtf8('Showing the combined configuration settings'),
2199 self)
2143 res = dia.startProcess(args, repodir, False) 2200 res = dia.startProcess(args, repodir, False)
2144 if res: 2201 if res:
2145 dia.exec_() 2202 dia.exec_()
2146 2203
2147 def hgShowPaths(self, name): 2204 def hgShowPaths(self, name):
2160 return 2217 return
2161 2218
2162 args = [] 2219 args = []
2163 args.append('paths') 2220 args.append('paths')
2164 2221
2165 dia = HgDialog(self.trUtf8('Showing aliases for remote repositories'), self) 2222 dia = HgDialog(
2223 self.trUtf8('Showing aliases for remote repositories'),
2224 self)
2166 res = dia.startProcess(args, repodir, False) 2225 res = dia.startProcess(args, repodir, False)
2167 if res: 2226 if res:
2168 dia.exec_() 2227 dia.exec_()
2169 2228
2170 def hgRecover(self, name): 2229 def hgRecover(self, name):
2183 return 2242 return
2184 2243
2185 args = [] 2244 args = []
2186 args.append('recover') 2245 args.append('recover')
2187 2246
2188 dia = HgDialog(self.trUtf8('Recovering from interrupted transaction'), self) 2247 dia = HgDialog(
2248 self.trUtf8('Recovering from interrupted transaction'),
2249 self)
2189 res = dia.startProcess(args, repodir, False) 2250 res = dia.startProcess(args, repodir, False)
2190 if res: 2251 if res:
2191 dia.exec_() 2252 dia.exec_()
2192 2253
2193 def hgIdentify(self, name): 2254 def hgIdentify(self, name):
2284 if os.path.splitdrive(repodir)[1] == os.sep: 2345 if os.path.splitdrive(repodir)[1] == os.sep:
2285 return 2346 return
2286 2347
2287 if self.isExtensionActive("bookmarks"): 2348 if self.isExtensionActive("bookmarks"):
2288 bookmarksList = \ 2349 bookmarksList = \
2289 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) 2350 self.getExtensionObject("bookmarks")\
2351 .hgGetBookmarksList(repodir)
2290 else: 2352 else:
2291 bookmarksList = None 2353 bookmarksList = None
2292 from .HgBundleDialog import HgBundleDialog 2354 from .HgBundleDialog import HgBundleDialog
2293 dlg = HgBundleDialog(self.hgGetTagsList(repodir), 2355 dlg = HgBundleDialog(self.hgGetTagsList(repodir),
2294 self.hgGetBranchesList(repodir), 2356 self.hgGetBranchesList(repodir),
2467 'skip' or 'reset') 2529 'skip' or 'reset')
2468 @exception ValueError raised to indicate an invalid bisect subcommand 2530 @exception ValueError raised to indicate an invalid bisect subcommand
2469 """ 2531 """
2470 if subcommand not in ("good", "bad", "skip", "reset"): 2532 if subcommand not in ("good", "bad", "skip", "reset"):
2471 raise ValueError( 2533 raise ValueError(
2472 self.trUtf8("Bisect subcommand ({0}) invalid.").format(subcommand)) 2534 self.trUtf8("Bisect subcommand ({0}) invalid.")
2535 .format(subcommand))
2473 2536
2474 dname, fname = self.splitPath(name) 2537 dname, fname = self.splitPath(name)
2475 2538
2476 # find the root of the repo 2539 # find the root of the repo
2477 repodir = dname 2540 repodir = dname
2482 2545
2483 rev = "" 2546 rev = ""
2484 if subcommand in ("good", "bad", "skip"): 2547 if subcommand in ("good", "bad", "skip"):
2485 if self.isExtensionActive("bookmarks"): 2548 if self.isExtensionActive("bookmarks"):
2486 bookmarksList = \ 2549 bookmarksList = \
2487 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) 2550 self.getExtensionObject("bookmarks")\
2551 .hgGetBookmarksList(repodir)
2488 else: 2552 else:
2489 bookmarksList = None 2553 bookmarksList = None
2490 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog 2554 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog
2491 dlg = HgRevisionSelectionDialog(self.hgGetTagsList(repodir), 2555 dlg = HgRevisionSelectionDialog(self.hgGetTagsList(repodir),
2492 self.hgGetBranchesList(repodir), 2556 self.hgGetBranchesList(repodir),
2501 args.append("bisect") 2565 args.append("bisect")
2502 args.append("--{0}".format(subcommand)) 2566 args.append("--{0}".format(subcommand))
2503 if rev: 2567 if rev:
2504 args.append(rev) 2568 args.append(rev)
2505 2569
2506 dia = HgDialog(self.trUtf8('Mercurial Bisect ({0})').format(subcommand), self) 2570 dia = HgDialog(
2571 self.trUtf8('Mercurial Bisect ({0})').format(subcommand), self)
2507 res = dia.startProcess(args, repodir) 2572 res = dia.startProcess(args, repodir)
2508 if res: 2573 if res:
2509 dia.exec_() 2574 dia.exec_()
2510 2575
2511 def hgForget(self, name): 2576 def hgForget(self, name):
2512 """ 2577 """
2513 Public method used to remove a file from the Mercurial repository. 2578 Public method used to remove a file from the Mercurial repository.
2514 2579
2515 This will not remove the file from the project directory. 2580 This will not remove the file from the project directory.
2516 2581
2517 @param name file/directory name to be removed (string or list of strings)) 2582 @param name file/directory name to be removed (string or list of
2583 strings))
2518 """ 2584 """
2519 args = [] 2585 args = []
2520 args.append('forget') 2586 args.append('forget')
2521 self.addArguments(args, self.options['global']) 2587 self.addArguments(args, self.options['global'])
2522 args.append('-v') 2588 args.append('-v')
2534 repodir = os.path.dirname(repodir) 2600 repodir = os.path.dirname(repodir)
2535 if os.path.splitdrive(repodir)[1] == os.sep: 2601 if os.path.splitdrive(repodir)[1] == os.sep:
2536 return 2602 return
2537 2603
2538 dia = HgDialog( 2604 dia = HgDialog(
2539 self.trUtf8('Removing files from the Mercurial repository only'), self) 2605 self.trUtf8('Removing files from the Mercurial repository only'),
2606 self)
2540 res = dia.startProcess(args, repodir) 2607 res = dia.startProcess(args, repodir)
2541 if res: 2608 if res:
2542 dia.exec_() 2609 dia.exec_()
2543 if isinstance(name, list): 2610 if isinstance(name, list):
2544 self.__forgotNames.extend(name) 2611 self.__forgotNames.extend(name)
2545 else: 2612 else:
2546 self.__forgotNames.append(name) 2613 self.__forgotNames.append(name)
2547 2614
2548 def hgBackout(self, name): 2615 def hgBackout(self, name):
2549 """ 2616 """
2550 Public method used to backout an earlier changeset from the Mercurial repository. 2617 Public method used to backout an earlier changeset from the Mercurial
2618 repository.
2551 2619
2552 @param name directory name (string or list of strings) 2620 @param name directory name (string or list of strings)
2553 """ 2621 """
2554 dname, fname = self.splitPath(name) 2622 dname, fname = self.splitPath(name)
2555 2623
2560 if os.path.splitdrive(repodir)[1] == os.sep: 2628 if os.path.splitdrive(repodir)[1] == os.sep:
2561 return 2629 return
2562 2630
2563 if self.isExtensionActive("bookmarks"): 2631 if self.isExtensionActive("bookmarks"):
2564 bookmarksList = \ 2632 bookmarksList = \
2565 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) 2633 self.getExtensionObject("bookmarks")\
2634 .hgGetBookmarksList(repodir)
2566 else: 2635 else:
2567 bookmarksList = None 2636 bookmarksList = None
2568 from .HgBackoutDialog import HgBackoutDialog 2637 from .HgBackoutDialog import HgBackoutDialog
2569 dlg = HgBackoutDialog(self.hgGetTagsList(repodir), 2638 dlg = HgBackoutDialog(self.hgGetTagsList(repodir),
2570 self.hgGetBranchesList(repodir), 2639 self.hgGetBranchesList(repodir),
2610 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 2679 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
2611 repodir = os.path.dirname(repodir) 2680 repodir = os.path.dirname(repodir)
2612 if os.path.splitdrive(repodir)[1] == os.sep: 2681 if os.path.splitdrive(repodir)[1] == os.sep:
2613 return 2682 return
2614 2683
2615 res = E5MessageBox.yesNo(None, 2684 res = E5MessageBox.yesNo(
2685 None,
2616 self.trUtf8("Rollback last transaction"), 2686 self.trUtf8("Rollback last transaction"),
2617 self.trUtf8("""Are you sure you want to rollback the last transaction?"""), 2687 self.trUtf8("""Are you sure you want to rollback the last"""
2688 """ transaction?"""),
2618 icon=E5MessageBox.Warning) 2689 icon=E5MessageBox.Warning)
2619 if res: 2690 if res:
2620 dia = HgDialog(self.trUtf8('Rollback last transaction'), self) 2691 dia = HgDialog(self.trUtf8('Rollback last transaction'), self)
2621 res = dia.startProcess(["rollback"], repodir) 2692 res = dia.startProcess(["rollback"], repodir)
2622 if res: 2693 if res:
2795 def hgGraft(self, path, revs=None): 2866 def hgGraft(self, path, revs=None):
2796 """ 2867 """
2797 Public method to copy changesets from another branch. 2868 Public method to copy changesets from another branch.
2798 2869
2799 @param path directory name of the project (string) 2870 @param path directory name of the project (string)
2800 @param revs list of revisions to show in the revisions pane (list of strings) 2871 @param revs list of revisions to show in the revisions pane (list of
2872 strings)
2801 @return flag indicating that the project should be reread (boolean) 2873 @return flag indicating that the project should be reread (boolean)
2802 """ 2874 """
2803 # find the root of the repo 2875 # find the root of the repo
2804 repodir = self.splitPath(path)[0] 2876 repodir = self.splitPath(path)[0]
2805 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 2877 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
2901 dia = HgDialog(self.trUtf8("Create Unversioned Archive"), self) 2973 dia = HgDialog(self.trUtf8("Create Unversioned Archive"), self)
2902 res = dia.startProcess(args, repodir) 2974 res = dia.startProcess(args, repodir)
2903 if res: 2975 if res:
2904 dia.exec_() 2976 dia.exec_()
2905 2977
2906 ############################################################################ 2978 ###########################################################################
2907 ## Methods to deal with subrepositories are below. 2979 ## Methods to deal with subrepositories are below.
2908 ############################################################################ 2980 ###########################################################################
2909 2981
2910 def getHgSubPath(self): 2982 def getHgSubPath(self):
2911 """ 2983 """
2912 Public method to get the path to the .hgsub file containing the definitions 2984 Public method to get the path to the .hgsub file containing the
2913 of sub-repositories. 2985 definitions of sub-repositories.
2914 2986
2915 @return full path of the .hgsub file (string) 2987 @return full path of the .hgsub file (string)
2916 """ 2988 """
2917 ppath = self.__projectHelper.getProject().getProjectPath() 2989 ppath = self.__projectHelper.getProject().getProjectPath()
2918 return os.path.join(ppath, ".hgsub") 2990 return os.path.join(ppath, ".hgsub")
2951 contents = f.readlines() 3023 contents = f.readlines()
2952 f.close() 3024 f.close()
2953 except IOError as err: 3025 except IOError as err:
2954 E5MessageBox.critical(self.__ui, 3026 E5MessageBox.critical(self.__ui,
2955 self.trUtf8("Add Sub-repository"), 3027 self.trUtf8("Add Sub-repository"),
2956 self.trUtf8("""<p>The sub-repositories file .hgsub could not""" 3028 self.trUtf8(
2957 """ be read.</p><p>Reason: {0}</p>""") 3029 """<p>The sub-repositories file .hgsub could not"""
2958 .format(str(err))) 3030 """ be read.</p><p>Reason: {0}</p>""")
3031 .format(str(err)))
2959 return 3032 return
2960 3033
2961 if entry in contents: 3034 if entry in contents:
2962 E5MessageBox.critical(self.__ui, 3035 E5MessageBox.critical(self.__ui,
2963 self.trUtf8("Add Sub-repository"), 3036 self.trUtf8("Add Sub-repository"),
2964 self.trUtf8("""<p>The sub-repositories file .hgsub already""" 3037 self.trUtf8(
2965 """ contains an entry <b>{0}</b>. Aborting...</p>""") 3038 """<p>The sub-repositories file .hgsub already"""
2966 .format(entry)) 3039 """ contains an entry <b>{0}</b>."""
3040 """ Aborting...</p>""").format(entry))
2967 return 3041 return
2968 else: 3042 else:
2969 needsAdd = True 3043 needsAdd = True
2970 3044
2971 if contents and not contents[-1].endswith("\n"): 3045 if contents and not contents[-1].endswith("\n"):
2976 f.writelines(contents) 3050 f.writelines(contents)
2977 f.close() 3051 f.close()
2978 except IOError as err: 3052 except IOError as err:
2979 E5MessageBox.critical(self.__ui, 3053 E5MessageBox.critical(self.__ui,
2980 self.trUtf8("Add Sub-repository"), 3054 self.trUtf8("Add Sub-repository"),
2981 self.trUtf8("""<p>The sub-repositories file .hgsub could not""" 3055 self.trUtf8(
2982 """ be written to.</p><p>Reason: {0}</p>""") 3056 """<p>The sub-repositories file .hgsub could not"""
2983 .format(str(err))) 3057 """ be written to.</p><p>Reason: {0}</p>""")
3058 .format(str(err)))
2984 return 3059 return
2985 3060
2986 if needsAdd: 3061 if needsAdd:
2987 self.vcsAdd(hgsub) 3062 self.vcsAdd(hgsub)
2988 self.__projectHelper.getProject().appendFile(hgsub) 3063 self.__projectHelper.getProject().appendFile(hgsub)
3011 self.trUtf8("""<p>The sub-repositories file .hgsub could not""" 3086 self.trUtf8("""<p>The sub-repositories file .hgsub could not"""
3012 """ be read.</p><p>Reason: {0}</p>""") 3087 """ be read.</p><p>Reason: {0}</p>""")
3013 .format(str(err))) 3088 .format(str(err)))
3014 return 3089 return
3015 3090
3016 from .HgRemoveSubrepositoriesDialog import HgRemoveSubrepositoriesDialog 3091 from .HgRemoveSubrepositoriesDialog import \
3092 HgRemoveSubrepositoriesDialog
3017 dlg = HgRemoveSubrepositoriesDialog(subrepositories) 3093 dlg = HgRemoveSubrepositoriesDialog(subrepositories)
3018 if dlg.exec_() == QDialog.Accepted: 3094 if dlg.exec_() == QDialog.Accepted:
3019 subrepositories, removedSubrepos, deleteSubrepos = dlg.getData() 3095 subrepositories, removedSubrepos, deleteSubrepos = dlg.getData()
3020 contents = "\n".join(subrepositories) + "\n" 3096 contents = "\n".join(subrepositories) + "\n"
3021 try: 3097 try:
3023 f.write(contents) 3099 f.write(contents)
3024 f.close() 3100 f.close()
3025 except IOError as err: 3101 except IOError as err:
3026 E5MessageBox.critical(self.__ui, 3102 E5MessageBox.critical(self.__ui,
3027 self.trUtf8("Remove Sub-repositories"), 3103 self.trUtf8("Remove Sub-repositories"),
3028 self.trUtf8("""<p>The sub-repositories file .hgsub could not""" 3104 self.trUtf8(
3029 """ be written to.</p><p>Reason: {0}</p>""") 3105 """<p>The sub-repositories file .hgsub could not"""
3030 .format(str(err))) 3106 """ be written to.</p><p>Reason: {0}</p>""")
3107 .format(str(err)))
3031 return 3108 return
3032 3109
3033 if deleteSubrepos: 3110 if deleteSubrepos:
3034 ppath = self.__projectHelper.getProject().getProjectPath() 3111 ppath = self.__projectHelper.getProject().getProjectPath()
3035 for removedSubrepo in removedSubrepos: 3112 for removedSubrepo in removedSubrepos:
3036 subrepoPath = removedSubrepo.split("=", 1)[0].strip() 3113 subrepoPath = removedSubrepo.split("=", 1)[0].strip()
3037 subrepoAbsPath = os.path.join(ppath, subrepoPath) 3114 subrepoAbsPath = os.path.join(ppath, subrepoPath)
3038 shutil.rmtree(subrepoAbsPath, True) 3115 shutil.rmtree(subrepoAbsPath, True)
3039 3116
3040 ############################################################################ 3117 ###########################################################################
3041 ## Methods to handle extensions are below. 3118 ## Methods to handle extensions are below.
3042 ############################################################################ 3119 ###########################################################################
3043 3120
3044 def __iniFileChanged(self, path): 3121 def __iniFileChanged(self, path):
3045 """ 3122 """
3046 Private slot to handle a change of the Mercurial configuration file. 3123 Private slot to handle a change of the Mercurial configuration file.
3047 3124
3052 if self.__client: 3129 if self.__client:
3053 ok, err = self.__client.restartServer() 3130 ok, err = self.__client.restartServer()
3054 if not ok: 3131 if not ok:
3055 E5MessageBox.warning(None, 3132 E5MessageBox.warning(None,
3056 self.trUtf8("Mercurial Command Server"), 3133 self.trUtf8("Mercurial Command Server"),
3057 self.trUtf8("""<p>The Mercurial Command Server could not be""" 3134 self.trUtf8(
3058 """ restarted.</p><p>Reason: {0}</p>""").format(err)) 3135 """<p>The Mercurial Command Server could not be"""
3136 """ restarted.</p><p>Reason: {0}</p>""").format(err))
3059 self.__client = None 3137 self.__client = None
3060 3138
3061 def __monitorRepoIniFile(self, name): 3139 def __monitorRepoIniFile(self, name):
3062 """ 3140 """
3063 Private slot to add a repository configuration file to the list of monitored 3141 Private slot to add a repository configuration file to the list of
3064 files. 3142 monitored files.
3065 3143
3066 @param name directory name pointing into the repository (string) 3144 @param name directory name pointing into the repository (string)
3067 """ 3145 """
3068 dname, fname = self.splitPath(name) 3146 dname, fname = self.splitPath(name)
3069 3147
3102 else: 3180 else:
3103 output, error = self.__client.runcommand(args) 3181 output, error = self.__client.runcommand(args)
3104 3182
3105 if output: 3183 if output:
3106 for line in output.splitlines(): 3184 for line in output.splitlines():
3107 extensionName = line.split("=", 1)[0].strip().split(".")[-1].strip() 3185 extensionName = \
3186 line.split("=", 1)[0].strip().split(".")[-1].strip()
3108 self.__activeExtensions.append(extensionName) 3187 self.__activeExtensions.append(extensionName)
3109 3188
3110 if self.version >= (1, 8): 3189 if self.version >= (1, 8):
3111 if "bookmarks" not in self.__activeExtensions: 3190 if "bookmarks" not in self.__activeExtensions:
3112 self.__activeExtensions.append("bookmarks") 3191 self.__activeExtensions.append("bookmarks")
3121 @param extensionName name of the extension to check for (string) 3200 @param extensionName name of the extension to check for (string)
3122 @return flag indicating an active extension (boolean) 3201 @return flag indicating an active extension (boolean)
3123 """ 3202 """
3124 extensionName = extensionName.strip() 3203 extensionName = extensionName.strip()
3125 isActive = extensionName in self.__activeExtensions 3204 isActive = extensionName in self.__activeExtensions
3126 if isActive and extensionName == "transplant" and self.version >= (2, 3): 3205 if isActive and \
3206 extensionName == "transplant" and \
3207 self.version >= (2, 3):
3127 # transplant extension is deprecated as of Mercurial 2.3.0 3208 # transplant extension is deprecated as of Mercurial 2.3.0
3128 isActive = False 3209 isActive = False
3129 3210
3130 return isActive 3211 return isActive
3131 3212
3136 @param extensionName name of the extension (string) 3217 @param extensionName name of the extension (string)
3137 @return reference to the extension object (boolean) 3218 @return reference to the extension object (boolean)
3138 """ 3219 """
3139 return self.__extensions[extensionName] 3220 return self.__extensions[extensionName]
3140 3221
3141 ############################################################################ 3222 ###########################################################################
3142 ## Methods to get the helper objects are below. 3223 ## Methods to get the helper objects are below.
3143 ############################################################################ 3224 ###########################################################################
3144 3225
3145 def vcsGetProjectBrowserHelper(self, browser, project, isTranslationsBrowser=False): 3226 def vcsGetProjectBrowserHelper(self, browser, project,
3146 """ 3227 isTranslationsBrowser=False):
3147 Public method to instantiate a helper object for the different project browsers. 3228 """
3229 Public method to instantiate a helper object for the different
3230 project browsers.
3148 3231
3149 @param browser reference to the project browser object 3232 @param browser reference to the project browser object
3150 @param project reference to the project object 3233 @param project reference to the project object
3151 @param isTranslationsBrowser flag indicating, the helper is requested for the 3234 @param isTranslationsBrowser flag indicating, the helper is requested
3152 translations browser (this needs some special treatment) 3235 for the translations browser (this needs some special treatment)
3153 @return the project browser helper object 3236 @return the project browser helper object
3154 """ 3237 """
3155 from .ProjectBrowserHelper import HgProjectBrowserHelper 3238 from .ProjectBrowserHelper import HgProjectBrowserHelper
3156 return HgProjectBrowserHelper(self, browser, project, isTranslationsBrowser) 3239 return HgProjectBrowserHelper(self, browser, project,
3240 isTranslationsBrowser)
3157 3241
3158 def vcsGetProjectHelper(self, project): 3242 def vcsGetProjectHelper(self, project):
3159 """ 3243 """
3160 Public method to instantiate a helper object for the project. 3244 Public method to instantiate a helper object for the project.
3161 3245
3181 if ok: 3265 if ok:
3182 self.__client = client 3266 self.__client = client
3183 else: 3267 else:
3184 E5MessageBox.warning(None, 3268 E5MessageBox.warning(None,
3185 self.trUtf8("Mercurial Command Server"), 3269 self.trUtf8("Mercurial Command Server"),
3186 self.trUtf8("""<p>The Mercurial Command Server could not be""" 3270 self.trUtf8(
3187 """ started.</p><p>Reason: {0}</p>""").format(err)) 3271 """<p>The Mercurial Command Server could not be"""
3272 """ started.</p><p>Reason: {0}</p>""").format(err))
3188 3273
3189 return self.__projectHelper 3274 return self.__projectHelper
3190 3275
3191 ############################################################################ 3276 ###########################################################################
3192 ## Status Monitor Thread methods 3277 ## Status Monitor Thread methods
3193 ############################################################################ 3278 ###########################################################################
3194 3279
3195 def _createStatusMonitorThread(self, interval, project): 3280 def _createStatusMonitorThread(self, interval, project):
3196 """ 3281 """
3197 Protected method to create an instance of the VCS status monitor thread. 3282 Protected method to create an instance of the VCS status monitor
3198 3283 thread.
3199 @param interval check interval for the monitor thread in seconds (integer) 3284
3285 @param interval check interval for the monitor thread in seconds
3286 (integer)
3200 @param project reference to the project object (Project) 3287 @param project reference to the project object (Project)
3201 @return reference to the monitor thread (QThread) 3288 @return reference to the monitor thread (QThread)
3202 """ 3289 """
3203 from .HgStatusMonitorThread import HgStatusMonitorThread 3290 from .HgStatusMonitorThread import HgStatusMonitorThread
3204 return HgStatusMonitorThread(interval, project, self) 3291 return HgStatusMonitorThread(interval, project, self)

eric ide

mercurial