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" |
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: |
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[:] |
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), |
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 |
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 = [] |
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") |
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), |
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") |
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) |