38 class Hg(VersionControl): |
38 class Hg(VersionControl): |
39 """ |
39 """ |
40 Class implementing the version control systems interface to Mercurial. |
40 Class implementing the version control systems interface to Mercurial. |
41 |
41 |
42 @signal committed() emitted after the commit action has completed |
42 @signal committed() emitted after the commit action has completed |
43 @signal activeExtensionsChanged() emitted when the list of active extensions |
43 @signal activeExtensionsChanged() emitted when the list of active |
44 has changed |
44 extensions has changed |
45 """ |
45 """ |
46 committed = pyqtSignal() |
46 committed = pyqtSignal() |
47 activeExtensionsChanged = pyqtSignal() |
47 activeExtensionsChanged = pyqtSignal() |
48 |
48 |
49 IgnoreFileName = ".hgignore" |
49 IgnoreFileName = ".hgignore" |
228 self.version = tuple(v) |
229 self.version = tuple(v) |
229 self.__getExtensionsInfo() |
230 self.__getExtensionsInfo() |
230 return True, errMsg |
231 return True, errMsg |
231 else: |
232 else: |
232 if finished: |
233 if finished: |
233 errMsg = \ |
234 errMsg = self.trUtf8( |
234 self.trUtf8("The hg process finished with the exit code {0}")\ |
235 "The hg process finished with the exit code {0}")\ |
235 .format(process.exitCode()) |
236 .format(process.exitCode()) |
236 else: |
237 else: |
237 errMsg = self.trUtf8("The hg process did not finish within 30s.") |
238 errMsg = self.trUtf8( |
|
239 "The hg process did not finish within 30s.") |
238 else: |
240 else: |
239 errMsg = self.trUtf8("Could not start the hg executable.") |
241 errMsg = self.trUtf8("Could not start the hg executable.") |
240 |
242 |
241 return False, errMsg |
243 return False, errMsg |
242 |
244 |
243 def vcsInit(self, vcsDir, noDialog=False): |
245 def vcsInit(self, vcsDir, noDialog=False): |
244 """ |
246 """ |
245 Public method used to initialize the mercurial repository. |
247 Public method used to initialize the mercurial repository. |
246 |
248 |
247 The initialization is done, when a project is converted into a Mercurial |
249 The initialization is done, when a project is converted into a |
248 controlled project. Therefore we always return TRUE without doing anything. |
250 Mercurial controlled project. Therefore we always return TRUE without |
|
251 doing anything. |
249 |
252 |
250 @param vcsDir name of the VCS directory (string) |
253 @param vcsDir name of the VCS directory (string) |
251 @param noDialog flag indicating quiet operations (boolean) |
254 @param noDialog flag indicating quiet operations (boolean) |
252 @return always TRUE |
255 @return always TRUE |
253 """ |
256 """ |
254 return True |
257 return True |
255 |
258 |
256 def vcsConvertProject(self, vcsDataDict, project): |
259 def vcsConvertProject(self, vcsDataDict, project): |
257 """ |
260 """ |
258 Public method to convert an uncontrolled project to a version controlled project. |
261 Public method to convert an uncontrolled project to a version |
|
262 controlled project. |
259 |
263 |
260 @param vcsDataDict dictionary of data required for the conversion |
264 @param vcsDataDict dictionary of data required for the conversion |
261 @param project reference to the project object |
265 @param project reference to the project object |
262 """ |
266 """ |
263 success = self.vcsImport(vcsDataDict, project.ppath)[0] |
267 success = self.vcsImport(vcsDataDict, project.ppath)[0] |
264 if not success: |
268 if not success: |
265 E5MessageBox.critical(self.__ui, |
269 E5MessageBox.critical(self.__ui, |
266 self.trUtf8("Create project repository"), |
270 self.trUtf8("Create project repository"), |
267 self.trUtf8("""The project repository could not be created.""")) |
271 self.trUtf8( |
|
272 """The project repository could not be created.""")) |
268 else: |
273 else: |
269 pfn = project.pfile |
274 pfn = project.pfile |
270 if not os.path.isfile(pfn): |
275 if not os.path.isfile(pfn): |
271 pfn += "z" |
276 pfn += "z" |
272 project.closeProject() |
277 project.closeProject() |
273 project.openProject(pfn) |
278 project.openProject(pfn) |
274 |
279 |
275 def vcsImport(self, vcsDataDict, projectDir, noDialog=False): |
280 def vcsImport(self, vcsDataDict, projectDir, noDialog=False): |
276 """ |
281 """ |
277 Public method used to import the project into the Subversion repository. |
282 Public method used to import the project into the Mercurial repository. |
278 |
283 |
279 @param vcsDataDict dictionary of data required for the import |
284 @param vcsDataDict dictionary of data required for the import |
280 @param projectDir project directory (string) |
285 @param projectDir project directory (string) |
281 @param noDialog flag indicating quiet operations |
286 @param noDialog flag indicating quiet operations |
282 @return flag indicating an execution without errors (boolean) |
287 @return flag indicating an execution without errors (boolean) |
305 args = [] |
310 args = [] |
306 args.append('commit') |
311 args.append('commit') |
307 args.append('--addremove') |
312 args.append('--addremove') |
308 args.append('--message') |
313 args.append('--message') |
309 args.append(msg) |
314 args.append(msg) |
310 dia = HgDialog(self.trUtf8('Initial commit to Mercurial repository'), |
315 dia = HgDialog( |
311 self) |
316 self.trUtf8('Initial commit to Mercurial repository'), |
|
317 self) |
312 res = dia.startProcess(args, projectDir) |
318 res = dia.startProcess(args, projectDir) |
313 if res: |
319 if res: |
314 dia.exec_() |
320 dia.exec_() |
315 status = dia.normalExit() |
321 status = dia.normalExit() |
316 |
322 |
317 return status, False |
323 return status, False |
318 |
324 |
319 def vcsCheckout(self, vcsDataDict, projectDir, noDialog=False): |
325 def vcsCheckout(self, vcsDataDict, projectDir, noDialog=False): |
320 """ |
326 """ |
321 Public method used to check the project out of a Mercurial repository (clone). |
327 Public method used to check the project out of a Mercurial repository |
|
328 (clone). |
322 |
329 |
323 @param vcsDataDict dictionary of data required for the checkout |
330 @param vcsDataDict dictionary of data required for the checkout |
324 @param projectDir project directory to create (string) |
331 @param projectDir project directory to create (string) |
325 @param noDialog flag indicating quiet operations |
332 @param noDialog flag indicating quiet operations |
326 @return flag indicating an execution without errors (boolean) |
333 @return flag indicating an execution without errors (boolean) |
351 return self.startSynchronizedProcess(QProcess(), 'hg', args) |
358 return self.startSynchronizedProcess(QProcess(), 'hg', args) |
352 else: |
359 else: |
353 out, err = self.__client.runcommand(args) |
360 out, err = self.__client.runcommand(args) |
354 return err == "" |
361 return err == "" |
355 else: |
362 else: |
356 dia = HgDialog(self.trUtf8('Cloning project from a Mercurial repository'), |
363 dia = HgDialog( |
357 self) |
364 self.trUtf8('Cloning project from a Mercurial repository'), |
|
365 self) |
358 res = dia.startProcess(args) |
366 res = dia.startProcess(args) |
359 if res: |
367 if res: |
360 dia.exec_() |
368 dia.exec_() |
361 return dia.normalExit() |
369 return dia.normalExit() |
362 |
370 |
363 def vcsExport(self, vcsDataDict, projectDir): |
371 def vcsExport(self, vcsDataDict, projectDir): |
364 """ |
372 """ |
365 Public method used to export a directory from the Subversion repository. |
373 Public method used to export a directory from the Mercurial repository. |
366 |
374 |
367 @param vcsDataDict dictionary of data required for the checkout |
375 @param vcsDataDict dictionary of data required for the checkout |
368 @param projectDir project directory to create (string) |
376 @param projectDir project directory to create (string) |
369 @return flag indicating an execution without errors (boolean) |
377 @return flag indicating an execution without errors (boolean) |
370 """ |
378 """ |
372 shutil.rmtree(os.path.join(projectDir, self.adminDir), True) |
380 shutil.rmtree(os.path.join(projectDir, self.adminDir), True) |
373 if os.path.exists(os.path.join(projectDir, '.hgignore')): |
381 if os.path.exists(os.path.join(projectDir, '.hgignore')): |
374 os.remove(os.path.join(projectDir, '.hgignore')) |
382 os.remove(os.path.join(projectDir, '.hgignore')) |
375 return status |
383 return status |
376 |
384 |
377 def vcsCommit(self, name, message, noDialog=False, closeBranch=False, mq=False): |
385 def vcsCommit(self, name, message, noDialog=False, closeBranch=False, |
378 """ |
386 mq=False): |
379 Public method used to make the change of a file/directory permanent in the |
387 """ |
380 Mercurial repository. |
388 Public method used to make the change of a file/directory permanent |
381 |
389 in the Mercurial repository. |
382 @param name file/directory name to be committed (string or list of strings) |
390 |
|
391 @param name file/directory name to be committed (string or list of |
|
392 strings) |
383 @param message message for this operation (string) |
393 @param message message for this operation (string) |
384 @param noDialog flag indicating quiet operations |
394 @param noDialog flag indicating quiet operations |
385 @keyparam closeBranch flag indicating a close branch commit (boolean) |
395 @keyparam closeBranch flag indicating a close branch commit (boolean) |
386 @keyparam mq flag indicating a queue commit (boolean) |
396 @keyparam mq flag indicating a queue commit (boolean) |
387 """ |
397 """ |
430 for nam in nameList: |
440 for nam in nameList: |
431 # check for commit of the project |
441 # check for commit of the project |
432 if os.path.isdir(nam): |
442 if os.path.isdir(nam): |
433 project = e5App().getObject("Project") |
443 project = e5App().getObject("Project") |
434 if nam == project.getProjectPath(): |
444 if nam == project.getProjectPath(): |
435 ok &= project.checkAllScriptsDirty(reportSyntaxErrors=True) and \ |
445 ok &= \ |
436 project.checkDirty() |
446 project.checkAllScriptsDirty( |
|
447 reportSyntaxErrors=True) and \ |
|
448 project.checkDirty() |
437 continue |
449 continue |
438 elif os.path.isfile(nam): |
450 elif os.path.isfile(nam): |
439 editor = e5App().getObject("ViewManager").getOpenEditor(nam) |
451 editor = \ |
|
452 e5App().getObject("ViewManager").getOpenEditor(nam) |
440 if editor: |
453 if editor: |
441 ok &= editor.checkDirty() |
454 ok &= editor.checkDirty() |
442 if not ok: |
455 if not ok: |
443 break |
456 break |
444 |
457 |
445 if not ok: |
458 if not ok: |
446 res = E5MessageBox.yesNo(self.__ui, |
459 res = E5MessageBox.yesNo(self.__ui, |
447 self.trUtf8("Commit Changes"), |
460 self.trUtf8("Commit Changes"), |
448 self.trUtf8("""The commit affects files, that have unsaved""" |
461 self.trUtf8( |
449 """ changes. Shall the commit be continued?"""), |
462 """The commit affects files, that have unsaved""" |
|
463 """ changes. Shall the commit be continued?"""), |
450 icon=E5MessageBox.Warning) |
464 icon=E5MessageBox.Warning) |
451 if not res: |
465 if not res: |
452 return |
466 return |
453 |
467 |
454 if self.__commitDialog is not None: |
468 if self.__commitDialog is not None: |
522 self.__forgotNames = [] |
537 self.__forgotNames = [] |
523 self.checkVCSStatus() |
538 self.checkVCSStatus() |
524 |
539 |
525 def vcsUpdate(self, name, noDialog=False, revision=None): |
540 def vcsUpdate(self, name, noDialog=False, revision=None): |
526 """ |
541 """ |
527 Public method used to update a file/directory with the Mercurial repository. |
542 Public method used to update a file/directory with the Mercurial |
528 |
543 repository. |
529 @param name file/directory name to be updated (string or list of strings) |
544 |
|
545 @param name file/directory name to be updated (string or list of |
|
546 strings) |
530 @param noDialog flag indicating quiet operations (boolean) |
547 @param noDialog flag indicating quiet operations (boolean) |
531 @keyparam revision revision to update to (string) |
548 @keyparam revision revision to update to (string) |
532 @return flag indicating, that the update contained an add |
549 @return flag indicating, that the update contained an add |
533 or delete (boolean) |
550 or delete (boolean) |
534 """ |
551 """ |
559 self.startSynchronizedProcess(QProcess(), 'hg', args, repodir) |
576 self.startSynchronizedProcess(QProcess(), 'hg', args, repodir) |
560 else: |
577 else: |
561 out, err = self.__client.runcommand(args) |
578 out, err = self.__client.runcommand(args) |
562 res = False |
579 res = False |
563 else: |
580 else: |
564 dia = HgDialog(self.trUtf8('Synchronizing with the Mercurial repository'), |
581 dia = HgDialog(self.trUtf8( |
565 self) |
582 'Synchronizing with the Mercurial repository'), |
|
583 self) |
566 res = dia.startProcess(args, repodir) |
584 res = dia.startProcess(args, repodir) |
567 if res: |
585 if res: |
568 dia.exec_() |
586 dia.exec_() |
569 res = dia.hasAddOrDelete() |
587 res = dia.hasAddOrDelete() |
570 self.checkVCSStatus() |
588 self.checkVCSStatus() |
612 self.startSynchronizedProcess(QProcess(), 'hg', args, repodir) |
630 self.startSynchronizedProcess(QProcess(), 'hg', args, repodir) |
613 else: |
631 else: |
614 out, err = self.__client.runcommand(args) |
632 out, err = self.__client.runcommand(args) |
615 else: |
633 else: |
616 dia = HgDialog( |
634 dia = HgDialog( |
617 self.trUtf8('Adding files/directories to the Mercurial repository'), self) |
635 self.trUtf8( |
|
636 'Adding files/directories to the Mercurial repository'), |
|
637 self) |
618 res = dia.startProcess(args, repodir) |
638 res = dia.startProcess(args, repodir) |
619 if res: |
639 if res: |
620 dia.exec_() |
640 dia.exec_() |
621 |
641 |
622 def vcsAddBinary(self, name, isDir=False): |
642 def vcsAddBinary(self, name, isDir=False): |
629 """ |
649 """ |
630 self.vcsAdd(name, isDir) |
650 self.vcsAdd(name, isDir) |
631 |
651 |
632 def vcsAddTree(self, path): |
652 def vcsAddTree(self, path): |
633 """ |
653 """ |
634 Public method to add a directory tree rooted at path to the Mercurial repository. |
654 Public method to add a directory tree rooted at path to the Mercurial |
635 |
655 repository. |
636 @param path root directory of the tree to be added (string or list of strings)) |
656 |
|
657 @param path root directory of the tree to be added (string or list of |
|
658 strings)) |
637 """ |
659 """ |
638 self.vcsAdd(path, isDir=False) |
660 self.vcsAdd(path, isDir=False) |
639 |
661 |
640 def vcsRemove(self, name, project=False, noDialog=False): |
662 def vcsRemove(self, name, project=False, noDialog=False): |
641 """ |
663 """ |
642 Public method used to remove a file/directory from the Mercurial repository. |
664 Public method used to remove a file/directory from the Mercurial |
|
665 repository. |
643 |
666 |
644 The default operation is to remove the local copy as well. |
667 The default operation is to remove the local copy as well. |
645 |
668 |
646 @param name file/directory name to be removed (string or list of strings)) |
669 @param name file/directory name to be removed (string or list of |
647 @param project flag indicating deletion of a project tree (boolean) (not needed) |
670 strings)) |
|
671 @param project flag indicating deletion of a project tree (boolean) |
|
672 (not needed) |
648 @param noDialog flag indicating quiet operations |
673 @param noDialog flag indicating quiet operations |
649 @return flag indicating successfull operation (boolean) |
674 @return flag indicating successfull operation (boolean) |
650 """ |
675 """ |
651 args = [] |
676 args = [] |
652 args.append('remove') |
677 args.append('remove') |
670 if os.path.splitdrive(repodir)[1] == os.sep: |
695 if os.path.splitdrive(repodir)[1] == os.sep: |
671 return False |
696 return False |
672 |
697 |
673 if noDialog: |
698 if noDialog: |
674 if self.__client is None: |
699 if self.__client is None: |
675 res = self.startSynchronizedProcess(QProcess(), 'hg', args, repodir) |
700 res = self.startSynchronizedProcess( |
|
701 QProcess(), 'hg', args, repodir) |
676 else: |
702 else: |
677 out, err = self.__client.runcommand(args) |
703 out, err = self.__client.runcommand(args) |
678 res = err == "" |
704 res = err == "" |
679 else: |
705 else: |
680 dia = HgDialog( |
706 dia = HgDialog( |
681 self.trUtf8('Removing files/directories from the Mercurial repository'), |
707 self.trUtf8( |
|
708 'Removing files/directories from the Mercurial' |
|
709 ' repository'), |
682 self) |
710 self) |
683 res = dia.startProcess(args, repodir) |
711 res = dia.startProcess(args, repodir) |
684 if res: |
712 if res: |
685 dia.exec_() |
713 dia.exec_() |
686 res = dia.normalExitWithoutErrors() |
714 res = dia.normalExitWithoutErrors() |
733 repodir = os.path.dirname(repodir) |
761 repodir = os.path.dirname(repodir) |
734 if os.path.splitdrive(repodir)[1] == os.sep: |
762 if os.path.splitdrive(repodir)[1] == os.sep: |
735 return False |
763 return False |
736 |
764 |
737 if noDialog: |
765 if noDialog: |
738 res = self.startSynchronizedProcess(QProcess(), "hg", args, repodir) |
|
739 if self.__client is None: |
766 if self.__client is None: |
740 res = self.startSynchronizedProcess(QProcess(), 'hg', args, repodir) |
767 res = self.startSynchronizedProcess( |
|
768 QProcess(), 'hg', args, repodir) |
741 else: |
769 else: |
742 out, err = self.__client.runcommand(args) |
770 out, err = self.__client.runcommand(args) |
743 res = err == "" |
771 res = err == "" |
744 else: |
772 else: |
745 dia = HgDialog(self.trUtf8('Renaming {0}').format(name), self) |
773 dia = HgDialog(self.trUtf8('Renaming {0}').format(name), self) |
777 if os.path.splitdrive(repodir)[1] == os.sep: |
805 if os.path.splitdrive(repodir)[1] == os.sep: |
778 return |
806 return |
779 |
807 |
780 if self.isExtensionActive("bookmarks"): |
808 if self.isExtensionActive("bookmarks"): |
781 bookmarksList = \ |
809 bookmarksList = \ |
782 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) |
810 self.getExtensionObject("bookmarks")\ |
|
811 .hgGetBookmarksList(repodir) |
783 else: |
812 else: |
784 bookmarksList = None |
813 bookmarksList = None |
785 |
814 |
786 from .HgMultiRevisionSelectionDialog import HgMultiRevisionSelectionDialog |
815 from .HgMultiRevisionSelectionDialog import \ |
|
816 HgMultiRevisionSelectionDialog |
787 dlg = HgMultiRevisionSelectionDialog( |
817 dlg = HgMultiRevisionSelectionDialog( |
788 self.hgGetTagsList(repodir), |
818 self.hgGetTagsList(repodir), |
789 self.hgGetBranchesList(repodir), |
819 self.hgGetBranchesList(repodir), |
790 bookmarksList, |
820 bookmarksList, |
791 emptyRevsOk=True, |
821 emptyRevsOk=True, |
802 """ |
832 """ |
803 Public method used to view the difference of a file/directory to the |
833 Public method used to view the difference of a file/directory to the |
804 Mercurial repository. |
834 Mercurial repository. |
805 |
835 |
806 If name is a directory and is the project directory, all project files |
836 If name is a directory and is the project directory, all project files |
807 are saved first. If name is a file (or list of files), which is/are being edited |
837 are saved first. If name is a file (or list of files), which is/are |
808 and has unsaved modification, they can be saved or the operation may be aborted. |
838 being edited and has unsaved modification, they can be saved or the |
|
839 operation may be aborted. |
809 |
840 |
810 @param name file/directory name to be diffed (string) |
841 @param name file/directory name to be diffed (string) |
811 """ |
842 """ |
812 if isinstance(name, list): |
843 if isinstance(name, list): |
813 names = name[:] |
844 names = name[:] |
925 return False |
957 return False |
926 |
958 |
927 project = e5App().getObject("Project") |
959 project = e5App().getObject("Project") |
928 names = [project.getRelativePath(nam) for nam in names] |
960 names = [project.getRelativePath(nam) for nam in names] |
929 if names[0]: |
961 if names[0]: |
930 from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog |
962 from UI.DeleteFilesConfirmationDialog import \ |
|
963 DeleteFilesConfirmationDialog |
931 dlg = DeleteFilesConfirmationDialog(self.parent(), |
964 dlg = DeleteFilesConfirmationDialog(self.parent(), |
932 self.trUtf8("Revert changes"), |
965 self.trUtf8("Revert changes"), |
933 self.trUtf8("Do you really want to revert all changes to these files" |
966 self.trUtf8( |
934 " or directories?"), |
967 "Do you really want to revert all changes to these files" |
|
968 " or directories?"), |
935 names) |
969 names) |
936 yes = dlg.exec_() == QDialog.Accepted |
970 yes = dlg.exec_() == QDialog.Accepted |
937 else: |
971 else: |
938 yes = E5MessageBox.yesNo(None, |
972 yes = E5MessageBox.yesNo(None, |
939 self.trUtf8("Revert changes"), |
973 self.trUtf8("Revert changes"), |
971 if force: |
1005 if force: |
972 del opts[opts.index('--force')] |
1006 del opts[opts.index('--force')] |
973 |
1007 |
974 if self.isExtensionActive("bookmarks"): |
1008 if self.isExtensionActive("bookmarks"): |
975 bookmarksList = \ |
1009 bookmarksList = \ |
976 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) |
1010 self.getExtensionObject("bookmarks")\ |
|
1011 .hgGetBookmarksList(repodir) |
977 else: |
1012 else: |
978 bookmarksList = None |
1013 bookmarksList = None |
979 from .HgMergeDialog import HgMergeDialog |
1014 from .HgMergeDialog import HgMergeDialog |
980 dlg = HgMergeDialog(force, self.hgGetTagsList(repodir), |
1015 dlg = HgMergeDialog(force, self.hgGetTagsList(repodir), |
981 self.hgGetBranchesList(repodir), |
1016 self.hgGetBranchesList(repodir), |
1017 if os.path.splitdrive(repodir)[1] == os.sep: |
1053 if os.path.splitdrive(repodir)[1] == os.sep: |
1018 return False |
1054 return False |
1019 |
1055 |
1020 if self.isExtensionActive("bookmarks"): |
1056 if self.isExtensionActive("bookmarks"): |
1021 bookmarksList = \ |
1057 bookmarksList = \ |
1022 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) |
1058 self.getExtensionObject("bookmarks")\ |
|
1059 .hgGetBookmarksList(repodir) |
1023 else: |
1060 else: |
1024 bookmarksList = None |
1061 bookmarksList = None |
1025 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog |
1062 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog |
1026 dlg = HgRevisionSelectionDialog(self.hgGetTagsList(repodir), |
1063 dlg = HgRevisionSelectionDialog(self.hgGetTagsList(repodir), |
1027 self.hgGetBranchesList(repodir), |
1064 self.hgGetBranchesList(repodir), |
1094 |
1131 |
1095 return self.canBeAdded |
1132 return self.canBeAdded |
1096 |
1133 |
1097 def vcsAllRegisteredStates(self, names, dname, shortcut=True): |
1134 def vcsAllRegisteredStates(self, names, dname, shortcut=True): |
1098 """ |
1135 """ |
1099 Public method used to get the registered states of a number of files in the vcs. |
1136 Public method used to get the registered states of a number of files |
1100 |
1137 in the vcs. |
1101 <b>Note:</b> If a shortcut is to be taken, the code will only check, if the named |
1138 |
1102 directory has been scanned already. If so, it is assumed, that the states for |
1139 <b>Note:</b> If a shortcut is to be taken, the code will only check, |
1103 all files have been populated by the previous run. |
1140 if the named directory has been scanned already. If so, it is assumed, |
|
1141 that the states for all files have been populated by the previous run. |
1104 |
1142 |
1105 @param names dictionary with all filenames to be checked as keys |
1143 @param names dictionary with all filenames to be checked as keys |
1106 @param dname directory to check in (string) |
1144 @param dname directory to check in (string) |
1107 @param shortcut flag indicating a shortcut should be taken (boolean) |
1145 @param shortcut flag indicating a shortcut should be taken (boolean) |
1108 @return the received dictionary completed with a combination of |
1146 @return the received dictionary completed with a combination of |
1258 """ |
1296 """ |
1259 Public method to get a dialog to enter repository info. |
1297 Public method to get a dialog to enter repository info. |
1260 |
1298 |
1261 @param project reference to the project object |
1299 @param project reference to the project object |
1262 @param archive name of the project in the repository (string) |
1300 @param archive name of the project in the repository (string) |
1263 @param editable flag indicating that the project name is editable (boolean) |
1301 @param editable flag indicating that the project name is editable |
|
1302 (boolean) |
1264 @param parent parent widget (QWidget) |
1303 @param parent parent widget (QWidget) |
|
1304 @return reference to the instantiated options dialog (HgOptionsDialog) |
1265 """ |
1305 """ |
1266 from .HgOptionsDialog import HgOptionsDialog |
1306 from .HgOptionsDialog import HgOptionsDialog |
1267 return HgOptionsDialog(self, project, parent) |
1307 return HgOptionsDialog(self, project, parent) |
1268 |
1308 |
1269 def vcsNewProjectOptionsDialog(self, parent=None): |
1309 def vcsNewProjectOptionsDialog(self, parent=None): |
1270 """ |
1310 """ |
1271 Public method to get a dialog to enter repository info for getting a new project. |
1311 Public method to get a dialog to enter repository info for getting a |
|
1312 new project. |
1272 |
1313 |
1273 @param parent parent widget (QWidget) |
1314 @param parent parent widget (QWidget) |
|
1315 @return reference to the instantiated options dialog |
|
1316 (HgNewProjectOptionsDialog) |
1274 """ |
1317 """ |
1275 from .HgNewProjectOptionsDialog import HgNewProjectOptionsDialog |
1318 from .HgNewProjectOptionsDialog import HgNewProjectOptionsDialog |
1276 return HgNewProjectOptionsDialog(self, parent) |
1319 return HgNewProjectOptionsDialog(self, parent) |
1277 |
1320 |
1278 def vcsRepositoryInfos(self, ppath): |
1321 def vcsRepositoryInfos(self, ppath): |
1305 infoBlock = [] |
1348 infoBlock = [] |
1306 if output: |
1349 if output: |
1307 index = 0 |
1350 index = 0 |
1308 for line in output.splitlines(): |
1351 for line in output.splitlines(): |
1309 index += 1 |
1352 index += 1 |
1310 changeset, tags, author, date, branches, bookmarks = line.split("@@@") |
1353 changeset, tags, author, date, branches, bookmarks = \ |
|
1354 line.split("@@@") |
1311 cdate, ctime = date.split()[:2] |
1355 cdate, ctime = date.split()[:2] |
1312 info = [] |
1356 info = [] |
1313 info.append(QApplication.translate("mercurial", |
1357 info.append(QApplication.translate("mercurial", |
1314 """<tr><td><b>Parent #{0}</b></td><td></td></tr>\n""" |
1358 """<tr><td><b>Parent #{0}</b></td><td></td></tr>\n""" |
1315 """<tr><td><b>Changeset</b></td><td>{1}</td></tr>""")\ |
1359 """<tr><td><b>Changeset</b></td><td>{1}</td></tr>""")\ |
1368 """<tr><td><b>URL</b></td><td>{1}</td></tr>\n""" |
1412 """<tr><td><b>URL</b></td><td>{1}</td></tr>\n""" |
1369 """{2}""" |
1413 """{2}""" |
1370 """</table></p>\n""" |
1414 """</table></p>\n""" |
1371 ).format(self.versionStr, url, infoStr) |
1415 ).format(self.versionStr, url, infoStr) |
1372 |
1416 |
1373 ############################################################################ |
1417 ########################################################################### |
1374 ## Private Mercurial specific methods are below. |
1418 ## Private Mercurial specific methods are below. |
1375 ############################################################################ |
1419 ########################################################################### |
1376 |
1420 |
1377 def __hgURL(self, url): |
1421 def __hgURL(self, url): |
1378 """ |
1422 """ |
1379 Private method to format a url for Mercurial. |
1423 Private method to format a url for Mercurial. |
1380 |
1424 |
1392 scheme, user, host, port, parse.quote(path)) |
1436 scheme, user, host, port, parse.quote(path)) |
1393 elif len(url) == 3: |
1437 elif len(url) == 3: |
1394 scheme = url[0] |
1438 scheme = url[0] |
1395 host = url[1] |
1439 host = url[1] |
1396 port, path = url[2].split("/", 1) |
1440 port, path = url[2].split("/", 1) |
1397 return "{0}:{1}:{2}/{3}".format(scheme, host, port, parse.quote(path)) |
1441 return "{0}:{1}:{2}/{3}".format( |
|
1442 scheme, host, port, parse.quote(path)) |
1398 else: |
1443 else: |
1399 scheme = url[0] |
1444 scheme = url[0] |
1400 if scheme == "file": |
1445 if scheme == "file": |
1401 return "{0}:{1}".format(scheme, parse.quote(url[1])) |
1446 return "{0}:{1}".format(scheme, parse.quote(url[1])) |
1402 else: |
1447 else: |
1403 host, path = url[1][2:].split("/", 1) |
1448 host, path = url[1][2:].split("/", 1) |
1404 return "{0}://{1}/{2}".format(scheme, host, parse.quote(path)) |
1449 return "{0}://{1}/{2}".format( |
|
1450 scheme, host, parse.quote(path)) |
1405 |
1451 |
1406 def hgNormalizeURL(self, url): |
1452 def hgNormalizeURL(self, url): |
1407 """ |
1453 """ |
1408 Public method to normalize a url for Mercurial. |
1454 Public method to normalize a url for Mercurial. |
1409 |
1455 |
1569 allTagsBranchesList = self.allTagsBranchesList |
1615 allTagsBranchesList = self.allTagsBranchesList |
1570 else: |
1616 else: |
1571 self.branchesList = [] |
1617 self.branchesList = [] |
1572 allTagsBranchesList = None |
1618 allTagsBranchesList = None |
1573 self.tagbranchList.start(path, tags, |
1619 self.tagbranchList.start(path, tags, |
1574 self.branchesList, self.allTagsBranchesList) |
1620 self.branchesList, |
|
1621 self.allTagsBranchesList) |
1575 |
1622 |
1576 def hgAnnotate(self, name): |
1623 def hgAnnotate(self, name): |
1577 """ |
1624 """ |
1578 Public method to show the output of the hg annotate command. |
1625 Public method to show the output of the hg annotate command. |
1579 |
1626 |
1588 """ |
1635 """ |
1589 Public method used to view the difference of a file/directory to the |
1636 Public method used to view the difference of a file/directory to the |
1590 Mercurial repository. |
1637 Mercurial repository. |
1591 |
1638 |
1592 If name is a directory and is the project directory, all project files |
1639 If name is a directory and is the project directory, all project files |
1593 are saved first. If name is a file (or list of files), which is/are being edited |
1640 are saved first. If name is a file (or list of files), which is/are |
1594 and has unsaved modification, they can be saved or the operation may be aborted. |
1641 being edited and has unsaved modification, they can be saved or the |
|
1642 operation may be aborted. |
1595 |
1643 |
1596 This method gives the chance to enter the revisions to be compared. |
1644 This method gives the chance to enter the revisions to be compared. |
1597 |
1645 |
1598 @param name file/directory name to be diffed (string) |
1646 @param name file/directory name to be diffed (string) |
1599 """ |
1647 """ |
1620 if os.path.splitdrive(repodir)[1] == os.sep: |
1668 if os.path.splitdrive(repodir)[1] == os.sep: |
1621 return |
1669 return |
1622 |
1670 |
1623 if self.isExtensionActive("bookmarks"): |
1671 if self.isExtensionActive("bookmarks"): |
1624 bookmarksList = \ |
1672 bookmarksList = \ |
1625 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) |
1673 self.getExtensionObject("bookmarks")\ |
|
1674 .hgGetBookmarksList(repodir) |
1626 else: |
1675 else: |
1627 bookmarksList = None |
1676 bookmarksList = None |
1628 from .HgRevisionsSelectionDialog import HgRevisionsSelectionDialog |
1677 from .HgRevisionsSelectionDialog import HgRevisionsSelectionDialog |
1629 dlg = HgRevisionsSelectionDialog(self.hgGetTagsList(repodir), |
1678 dlg = HgRevisionsSelectionDialog(self.hgGetTagsList(repodir), |
1630 self.hgGetBranchesList(repodir), |
1679 self.hgGetBranchesList(repodir), |
1636 self.diff.show() |
1685 self.diff.show() |
1637 self.diff.start(name, revisions) |
1686 self.diff.start(name, revisions) |
1638 |
1687 |
1639 def __hgGetFileForRevision(self, name, rev=""): |
1688 def __hgGetFileForRevision(self, name, rev=""): |
1640 """ |
1689 """ |
1641 Private method to get a file for a specific revision from the repository. |
1690 Private method to get a file for a specific revision from the |
|
1691 repository. |
1642 |
1692 |
1643 @param name file name to get from the repository (string) |
1693 @param name file name to get from the repository (string) |
1644 @keyparam rev revision to retrieve (string) |
1694 @keyparam rev revision to retrieve (string) |
1645 @return contents of the file (string) and an error message (string) |
1695 @return contents of the file (string) and an error message (string) |
1646 """ |
1696 """ |
1674 Preferences.getSystem("IOEncoding"), 'replace') |
1724 Preferences.getSystem("IOEncoding"), 'replace') |
1675 else: |
1725 else: |
1676 error = str(process.readAllStandardError(), |
1726 error = str(process.readAllStandardError(), |
1677 Preferences.getSystem("IOEncoding"), 'replace') |
1727 Preferences.getSystem("IOEncoding"), 'replace') |
1678 else: |
1728 else: |
1679 error = self.trUtf8("The hg process did not finish within 30s.") |
1729 error = self.trUtf8( |
|
1730 "The hg process did not finish within 30s.") |
1680 else: |
1731 else: |
1681 error = self.trUtf8('The process {0} could not be started. ' |
1732 error = self.trUtf8('The process {0} could not be started. ' |
1682 'Ensure, that it is in the search path.').format('hg') |
1733 'Ensure, that it is in the search path.').format('hg') |
1683 else: |
1734 else: |
1684 output, error = self.__client.runcommand(args) |
1735 output, error = self.__client.runcommand(args) |
1685 |
1736 |
1686 return output, error |
1737 return output, error |
1687 |
1738 |
1688 def hgSbsDiff(self, name, extended=False, revisions=None): |
1739 def hgSbsDiff(self, name, extended=False, revisions=None): |
1689 """ |
1740 """ |
1690 Public method used to view the difference of a file to the Mercurial repository |
1741 Public method used to view the difference of a file to the Mercurial |
1691 side-by-side. |
1742 repository side-by-side. |
1692 |
1743 |
1693 @param name file name to be diffed (string) |
1744 @param name file name to be diffed (string) |
1694 @keyparam extended flag indicating the extended variant (boolean) |
1745 @keyparam extended flag indicating the extended variant (boolean) |
1695 @keyparam revisions tuple of two revisions (tuple of strings) |
1746 @keyparam revisions tuple of two revisions (tuple of strings) |
|
1747 @exception ValueError raised to indicate an invalid name parameter |
1696 """ |
1748 """ |
1697 if isinstance(name, list): |
1749 if isinstance(name, list): |
1698 raise ValueError("Wrong parameter type") |
1750 raise ValueError("Wrong parameter type") |
1699 |
1751 |
1700 if extended: |
1752 if extended: |
1761 """ |
1815 """ |
1762 Public method used to browse the log of a file/directory from the |
1816 Public method used to browse the log of a file/directory from the |
1763 Mercurial repository. |
1817 Mercurial repository. |
1764 |
1818 |
1765 @param path file/directory name to show the log of (string) |
1819 @param path file/directory name to show the log of (string) |
1766 @keyparam isFile flag indicating log for a file is to be shown (boolean) |
1820 @keyparam isFile flag indicating log for a file is to be shown |
|
1821 (boolean) |
1767 """ |
1822 """ |
1768 from .HgLogBrowserDialog import HgLogBrowserDialog |
1823 from .HgLogBrowserDialog import HgLogBrowserDialog |
1769 self.logBrowser = HgLogBrowserDialog(self, isFile=isFile) |
1824 self.logBrowser = HgLogBrowserDialog(self, isFile=isFile) |
1770 self.logBrowser.show() |
1825 self.logBrowser.show() |
1771 self.logBrowser.start(path) |
1826 self.logBrowser.start(path) |
1872 while not os.path.isdir(os.path.join(repodir, self.adminDir)): |
1927 while not os.path.isdir(os.path.join(repodir, self.adminDir)): |
1873 repodir = os.path.dirname(repodir) |
1928 repodir = os.path.dirname(repodir) |
1874 if os.path.splitdrive(repodir)[1] == os.sep: |
1929 if os.path.splitdrive(repodir)[1] == os.sep: |
1875 return |
1930 return |
1876 |
1931 |
1877 dia = HgDialog(self.trUtf8('Pushing to a remote Mercurial repository'), self) |
1932 dia = HgDialog( |
|
1933 self.trUtf8('Pushing to a remote Mercurial repository'), self) |
1878 res = dia.startProcess(args, repodir) |
1934 res = dia.startProcess(args, repodir) |
1879 if res: |
1935 if res: |
1880 dia.exec_() |
1936 dia.exec_() |
1881 res = dia.hasAddOrDelete() |
1937 res = dia.hasAddOrDelete() |
1882 self.checkVCSStatus() |
1938 self.checkVCSStatus() |
1884 def hgInfo(self, ppath, mode="heads"): |
1940 def hgInfo(self, ppath, mode="heads"): |
1885 """ |
1941 """ |
1886 Public method to show information about the heads of the repository. |
1942 Public method to show information about the heads of the repository. |
1887 |
1943 |
1888 @param ppath local path to get the repository infos (string) |
1944 @param ppath local path to get the repository infos (string) |
1889 @keyparam mode mode of the operation (string, one of heads, parents, tip) |
1945 @keyparam mode mode of the operation (string, one of heads, parents, |
|
1946 tip) |
1890 """ |
1947 """ |
1891 if mode not in ("heads", "parents", "tip"): |
1948 if mode not in ("heads", "parents", "tip"): |
1892 mode = "heads" |
1949 mode = "heads" |
1893 |
1950 |
1894 info = [] |
1951 info = [] |
1989 # find the root of the repo |
2046 # find the root of the repo |
1990 repodir = dname |
2047 repodir = dname |
1991 while not os.path.isdir(os.path.join(repodir, self.adminDir)): |
2048 while not os.path.isdir(os.path.join(repodir, self.adminDir)): |
1992 repodir = os.path.dirname(repodir) |
2049 repodir = os.path.dirname(repodir) |
1993 if os.path.splitdrive(repodir)[1] == os.sep: |
2050 if os.path.splitdrive(repodir)[1] == os.sep: |
1994 return False |
2051 return |
1995 |
2052 |
1996 dia = HgDialog(self.trUtf8('Resolving files/directories'), self) |
2053 dia = HgDialog(self.trUtf8('Resolving files/directories'), self) |
1997 res = dia.startProcess(args, repodir) |
2054 res = dia.startProcess(args, repodir) |
1998 if res: |
2055 if res: |
1999 dia.exec_() |
2056 dia.exec_() |
2061 from .HgUtilities import getConfigPath |
2119 from .HgUtilities import getConfigPath |
2062 cfgFile = getConfigPath() |
2120 cfgFile = getConfigPath() |
2063 if not os.path.exists(cfgFile): |
2121 if not os.path.exists(cfgFile): |
2064 try: |
2122 try: |
2065 f = open(cfgFile, "w") |
2123 f = open(cfgFile, "w") |
2066 f.write("[ui]\nusername = Firstname Lastname <email_address>\n") |
2124 f.write("[ui]\nusername = Firstname Lastname" |
|
2125 " <email_address>\n") |
2067 f.close() |
2126 f.close() |
2068 except (IOError, OSError): |
2127 except (IOError, OSError): |
2069 # ignore these |
2128 # ignore these |
2070 pass |
2129 pass |
2071 self.userEditor = MiniEditor(cfgFile, "Properties") |
2130 self.userEditor = MiniEditor(cfgFile, "Properties") |
2285 if os.path.splitdrive(repodir)[1] == os.sep: |
2351 if os.path.splitdrive(repodir)[1] == os.sep: |
2286 return |
2352 return |
2287 |
2353 |
2288 if self.isExtensionActive("bookmarks"): |
2354 if self.isExtensionActive("bookmarks"): |
2289 bookmarksList = \ |
2355 bookmarksList = \ |
2290 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) |
2356 self.getExtensionObject("bookmarks")\ |
|
2357 .hgGetBookmarksList(repodir) |
2291 else: |
2358 else: |
2292 bookmarksList = None |
2359 bookmarksList = None |
2293 from .HgBundleDialog import HgBundleDialog |
2360 from .HgBundleDialog import HgBundleDialog |
2294 dlg = HgBundleDialog(self.hgGetTagsList(repodir), |
2361 dlg = HgBundleDialog(self.hgGetTagsList(repodir), |
2295 self.hgGetBranchesList(repodir), |
2362 self.hgGetBranchesList(repodir), |
2464 Public method to perform bisect commands. |
2531 Public method to perform bisect commands. |
2465 |
2532 |
2466 @param name file/directory name (string) |
2533 @param name file/directory name (string) |
2467 @param subcommand name of the subcommand (string, one of 'good', 'bad', |
2534 @param subcommand name of the subcommand (string, one of 'good', 'bad', |
2468 'skip' or 'reset') |
2535 'skip' or 'reset') |
|
2536 @exception ValueError raised to indicate an invalid bisect subcommand |
2469 """ |
2537 """ |
2470 if subcommand not in ("good", "bad", "skip", "reset"): |
2538 if subcommand not in ("good", "bad", "skip", "reset"): |
2471 raise ValueError( |
2539 raise ValueError( |
2472 self.trUtf8("Bisect subcommand ({0}) invalid.").format(subcommand)) |
2540 self.trUtf8("Bisect subcommand ({0}) invalid.") |
|
2541 .format(subcommand)) |
2473 |
2542 |
2474 dname, fname = self.splitPath(name) |
2543 dname, fname = self.splitPath(name) |
2475 |
2544 |
2476 # find the root of the repo |
2545 # find the root of the repo |
2477 repodir = dname |
2546 repodir = dname |
2482 |
2551 |
2483 rev = "" |
2552 rev = "" |
2484 if subcommand in ("good", "bad", "skip"): |
2553 if subcommand in ("good", "bad", "skip"): |
2485 if self.isExtensionActive("bookmarks"): |
2554 if self.isExtensionActive("bookmarks"): |
2486 bookmarksList = \ |
2555 bookmarksList = \ |
2487 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) |
2556 self.getExtensionObject("bookmarks")\ |
|
2557 .hgGetBookmarksList(repodir) |
2488 else: |
2558 else: |
2489 bookmarksList = None |
2559 bookmarksList = None |
2490 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog |
2560 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog |
2491 dlg = HgRevisionSelectionDialog(self.hgGetTagsList(repodir), |
2561 dlg = HgRevisionSelectionDialog(self.hgGetTagsList(repodir), |
2492 self.hgGetBranchesList(repodir), |
2562 self.hgGetBranchesList(repodir), |
2501 args.append("bisect") |
2571 args.append("bisect") |
2502 args.append("--{0}".format(subcommand)) |
2572 args.append("--{0}".format(subcommand)) |
2503 if rev: |
2573 if rev: |
2504 args.append(rev) |
2574 args.append(rev) |
2505 |
2575 |
2506 dia = HgDialog(self.trUtf8('Mercurial Bisect ({0})').format(subcommand), self) |
2576 dia = HgDialog( |
|
2577 self.trUtf8('Mercurial Bisect ({0})').format(subcommand), self) |
2507 res = dia.startProcess(args, repodir) |
2578 res = dia.startProcess(args, repodir) |
2508 if res: |
2579 if res: |
2509 dia.exec_() |
2580 dia.exec_() |
2510 |
2581 |
2511 def hgForget(self, name): |
2582 def hgForget(self, name): |
2512 """ |
2583 """ |
2513 Public method used to remove a file from the Mercurial repository. |
2584 Public method used to remove a file from the Mercurial repository. |
2514 |
2585 |
2515 This will not remove the file from the project directory. |
2586 This will not remove the file from the project directory. |
2516 |
2587 |
2517 @param name file/directory name to be removed (string or list of strings)) |
2588 @param name file/directory name to be removed (string or list of |
|
2589 strings)) |
2518 """ |
2590 """ |
2519 args = [] |
2591 args = [] |
2520 args.append('forget') |
2592 args.append('forget') |
2521 self.addArguments(args, self.options['global']) |
2593 self.addArguments(args, self.options['global']) |
2522 args.append('-v') |
2594 args.append('-v') |
2534 repodir = os.path.dirname(repodir) |
2606 repodir = os.path.dirname(repodir) |
2535 if os.path.splitdrive(repodir)[1] == os.sep: |
2607 if os.path.splitdrive(repodir)[1] == os.sep: |
2536 return |
2608 return |
2537 |
2609 |
2538 dia = HgDialog( |
2610 dia = HgDialog( |
2539 self.trUtf8('Removing files from the Mercurial repository only'), self) |
2611 self.trUtf8('Removing files from the Mercurial repository only'), |
|
2612 self) |
2540 res = dia.startProcess(args, repodir) |
2613 res = dia.startProcess(args, repodir) |
2541 if res: |
2614 if res: |
2542 dia.exec_() |
2615 dia.exec_() |
2543 if isinstance(name, list): |
2616 if isinstance(name, list): |
2544 self.__forgotNames.extend(name) |
2617 self.__forgotNames.extend(name) |
2545 else: |
2618 else: |
2546 self.__forgotNames.append(name) |
2619 self.__forgotNames.append(name) |
2547 |
2620 |
2548 def hgBackout(self, name): |
2621 def hgBackout(self, name): |
2549 """ |
2622 """ |
2550 Public method used to backout an earlier changeset from the Mercurial repository. |
2623 Public method used to backout an earlier changeset from the Mercurial |
|
2624 repository. |
2551 |
2625 |
2552 @param name directory name (string or list of strings) |
2626 @param name directory name (string or list of strings) |
2553 """ |
2627 """ |
2554 dname, fname = self.splitPath(name) |
2628 dname, fname = self.splitPath(name) |
2555 |
2629 |
2560 if os.path.splitdrive(repodir)[1] == os.sep: |
2634 if os.path.splitdrive(repodir)[1] == os.sep: |
2561 return |
2635 return |
2562 |
2636 |
2563 if self.isExtensionActive("bookmarks"): |
2637 if self.isExtensionActive("bookmarks"): |
2564 bookmarksList = \ |
2638 bookmarksList = \ |
2565 self.getExtensionObject("bookmarks").hgGetBookmarksList(repodir) |
2639 self.getExtensionObject("bookmarks")\ |
|
2640 .hgGetBookmarksList(repodir) |
2566 else: |
2641 else: |
2567 bookmarksList = None |
2642 bookmarksList = None |
2568 from .HgBackoutDialog import HgBackoutDialog |
2643 from .HgBackoutDialog import HgBackoutDialog |
2569 dlg = HgBackoutDialog(self.hgGetTagsList(repodir), |
2644 dlg = HgBackoutDialog(self.hgGetTagsList(repodir), |
2570 self.hgGetBranchesList(repodir), |
2645 self.hgGetBranchesList(repodir), |
2610 while not os.path.isdir(os.path.join(repodir, self.adminDir)): |
2685 while not os.path.isdir(os.path.join(repodir, self.adminDir)): |
2611 repodir = os.path.dirname(repodir) |
2686 repodir = os.path.dirname(repodir) |
2612 if os.path.splitdrive(repodir)[1] == os.sep: |
2687 if os.path.splitdrive(repodir)[1] == os.sep: |
2613 return |
2688 return |
2614 |
2689 |
2615 res = E5MessageBox.yesNo(None, |
2690 res = E5MessageBox.yesNo( |
|
2691 None, |
2616 self.trUtf8("Rollback last transaction"), |
2692 self.trUtf8("Rollback last transaction"), |
2617 self.trUtf8("""Are you sure you want to rollback the last transaction?"""), |
2693 self.trUtf8("""Are you sure you want to rollback the last""" |
|
2694 """ transaction?"""), |
2618 icon=E5MessageBox.Warning) |
2695 icon=E5MessageBox.Warning) |
2619 if res: |
2696 if res: |
2620 dia = HgDialog(self.trUtf8('Rollback last transaction'), self) |
2697 dia = HgDialog(self.trUtf8('Rollback last transaction'), self) |
2621 res = dia.startProcess(["rollback"], repodir) |
2698 res = dia.startProcess(["rollback"], repodir) |
2622 if res: |
2699 if res: |
2745 |
2822 |
2746 @param name directory name of the project to export from (string) |
2823 @param name directory name of the project to export from (string) |
2747 @param data tuple giving phase data (list of revisions, phase, flag |
2824 @param data tuple giving phase data (list of revisions, phase, flag |
2748 indicating a forced operation) (list of strings, string, boolean) |
2825 indicating a forced operation) (list of strings, string, boolean) |
2749 @return flag indicating success (boolean) |
2826 @return flag indicating success (boolean) |
|
2827 @exception ValueError raised to indicate an invalid phase |
2750 """ |
2828 """ |
2751 dname, fname = self.splitPath(name) |
2829 dname, fname = self.splitPath(name) |
2752 |
2830 |
2753 # find the root of the repo |
2831 # find the root of the repo |
2754 repodir = dname |
2832 repodir = dname |
2794 def hgGraft(self, path, revs=None): |
2872 def hgGraft(self, path, revs=None): |
2795 """ |
2873 """ |
2796 Public method to copy changesets from another branch. |
2874 Public method to copy changesets from another branch. |
2797 |
2875 |
2798 @param path directory name of the project (string) |
2876 @param path directory name of the project (string) |
2799 @param revs list of revisions to show in the revisions pane (list of strings) |
2877 @param revs list of revisions to show in the revisions pane (list of |
|
2878 strings) |
2800 @return flag indicating that the project should be reread (boolean) |
2879 @return flag indicating that the project should be reread (boolean) |
2801 """ |
2880 """ |
2802 # find the root of the repo |
2881 # find the root of the repo |
2803 repodir = self.splitPath(path)[0] |
2882 repodir = self.splitPath(path)[0] |
2804 while not os.path.isdir(os.path.join(repodir, self.adminDir)): |
2883 while not os.path.isdir(os.path.join(repodir, self.adminDir)): |
2900 dia = HgDialog(self.trUtf8("Create Unversioned Archive"), self) |
2979 dia = HgDialog(self.trUtf8("Create Unversioned Archive"), self) |
2901 res = dia.startProcess(args, repodir) |
2980 res = dia.startProcess(args, repodir) |
2902 if res: |
2981 if res: |
2903 dia.exec_() |
2982 dia.exec_() |
2904 |
2983 |
2905 ############################################################################ |
2984 ########################################################################### |
2906 ## Methods to deal with subrepositories are below. |
2985 ## Methods to deal with subrepositories are below. |
2907 ############################################################################ |
2986 ########################################################################### |
2908 |
2987 |
2909 def getHgSubPath(self): |
2988 def getHgSubPath(self): |
2910 """ |
2989 """ |
2911 Public method to get the path to the .hgsub file containing the definitions |
2990 Public method to get the path to the .hgsub file containing the |
2912 of sub-repositories. |
2991 definitions of sub-repositories. |
2913 |
2992 |
2914 @return full path of the .hgsub file (string) |
2993 @return full path of the .hgsub file (string) |
2915 """ |
2994 """ |
2916 ppath = self.__projectHelper.getProject().getProjectPath() |
2995 ppath = self.__projectHelper.getProject().getProjectPath() |
2917 return os.path.join(ppath, ".hgsub") |
2996 return os.path.join(ppath, ".hgsub") |
2950 contents = f.readlines() |
3029 contents = f.readlines() |
2951 f.close() |
3030 f.close() |
2952 except IOError as err: |
3031 except IOError as err: |
2953 E5MessageBox.critical(self.__ui, |
3032 E5MessageBox.critical(self.__ui, |
2954 self.trUtf8("Add Sub-repository"), |
3033 self.trUtf8("Add Sub-repository"), |
2955 self.trUtf8("""<p>The sub-repositories file .hgsub could not""" |
3034 self.trUtf8( |
2956 """ be read.</p><p>Reason: {0}</p>""") |
3035 """<p>The sub-repositories file .hgsub could not""" |
2957 .format(str(err))) |
3036 """ be read.</p><p>Reason: {0}</p>""") |
|
3037 .format(str(err))) |
2958 return |
3038 return |
2959 |
3039 |
2960 if entry in contents: |
3040 if entry in contents: |
2961 E5MessageBox.critical(self.__ui, |
3041 E5MessageBox.critical(self.__ui, |
2962 self.trUtf8("Add Sub-repository"), |
3042 self.trUtf8("Add Sub-repository"), |
2963 self.trUtf8("""<p>The sub-repositories file .hgsub already""" |
3043 self.trUtf8( |
2964 """ contains an entry <b>{0}</b>. Aborting...</p>""") |
3044 """<p>The sub-repositories file .hgsub already""" |
2965 .format(entry)) |
3045 """ contains an entry <b>{0}</b>.""" |
|
3046 """ Aborting...</p>""").format(entry)) |
2966 return |
3047 return |
2967 else: |
3048 else: |
2968 needsAdd = True |
3049 needsAdd = True |
2969 |
3050 |
2970 if contents and not contents[-1].endswith("\n"): |
3051 if contents and not contents[-1].endswith("\n"): |
2975 f.writelines(contents) |
3056 f.writelines(contents) |
2976 f.close() |
3057 f.close() |
2977 except IOError as err: |
3058 except IOError as err: |
2978 E5MessageBox.critical(self.__ui, |
3059 E5MessageBox.critical(self.__ui, |
2979 self.trUtf8("Add Sub-repository"), |
3060 self.trUtf8("Add Sub-repository"), |
2980 self.trUtf8("""<p>The sub-repositories file .hgsub could not""" |
3061 self.trUtf8( |
2981 """ be written to.</p><p>Reason: {0}</p>""") |
3062 """<p>The sub-repositories file .hgsub could not""" |
2982 .format(str(err))) |
3063 """ be written to.</p><p>Reason: {0}</p>""") |
|
3064 .format(str(err))) |
2983 return |
3065 return |
2984 |
3066 |
2985 if needsAdd: |
3067 if needsAdd: |
2986 self.vcsAdd(hgsub) |
3068 self.vcsAdd(hgsub) |
2987 self.__projectHelper.getProject().appendFile(hgsub) |
3069 self.__projectHelper.getProject().appendFile(hgsub) |
3010 self.trUtf8("""<p>The sub-repositories file .hgsub could not""" |
3092 self.trUtf8("""<p>The sub-repositories file .hgsub could not""" |
3011 """ be read.</p><p>Reason: {0}</p>""") |
3093 """ be read.</p><p>Reason: {0}</p>""") |
3012 .format(str(err))) |
3094 .format(str(err))) |
3013 return |
3095 return |
3014 |
3096 |
3015 from .HgRemoveSubrepositoriesDialog import HgRemoveSubrepositoriesDialog |
3097 from .HgRemoveSubrepositoriesDialog import \ |
|
3098 HgRemoveSubrepositoriesDialog |
3016 dlg = HgRemoveSubrepositoriesDialog(subrepositories) |
3099 dlg = HgRemoveSubrepositoriesDialog(subrepositories) |
3017 if dlg.exec_() == QDialog.Accepted: |
3100 if dlg.exec_() == QDialog.Accepted: |
3018 subrepositories, removedSubrepos, deleteSubrepos = dlg.getData() |
3101 subrepositories, removedSubrepos, deleteSubrepos = dlg.getData() |
3019 contents = "\n".join(subrepositories) + "\n" |
3102 contents = "\n".join(subrepositories) + "\n" |
3020 try: |
3103 try: |
3022 f.write(contents) |
3105 f.write(contents) |
3023 f.close() |
3106 f.close() |
3024 except IOError as err: |
3107 except IOError as err: |
3025 E5MessageBox.critical(self.__ui, |
3108 E5MessageBox.critical(self.__ui, |
3026 self.trUtf8("Remove Sub-repositories"), |
3109 self.trUtf8("Remove Sub-repositories"), |
3027 self.trUtf8("""<p>The sub-repositories file .hgsub could not""" |
3110 self.trUtf8( |
3028 """ be written to.</p><p>Reason: {0}</p>""") |
3111 """<p>The sub-repositories file .hgsub could not""" |
3029 .format(str(err))) |
3112 """ be written to.</p><p>Reason: {0}</p>""") |
|
3113 .format(str(err))) |
3030 return |
3114 return |
3031 |
3115 |
3032 if deleteSubrepos: |
3116 if deleteSubrepos: |
3033 ppath = self.__projectHelper.getProject().getProjectPath() |
3117 ppath = self.__projectHelper.getProject().getProjectPath() |
3034 for removedSubrepo in removedSubrepos: |
3118 for removedSubrepo in removedSubrepos: |
3035 subrepoPath = removedSubrepo.split("=", 1)[0].strip() |
3119 subrepoPath = removedSubrepo.split("=", 1)[0].strip() |
3036 subrepoAbsPath = os.path.join(ppath, subrepoPath) |
3120 subrepoAbsPath = os.path.join(ppath, subrepoPath) |
3037 shutil.rmtree(subrepoAbsPath, True) |
3121 shutil.rmtree(subrepoAbsPath, True) |
3038 |
3122 |
3039 ############################################################################ |
3123 ########################################################################### |
3040 ## Methods to handle extensions are below. |
3124 ## Methods to handle extensions are below. |
3041 ############################################################################ |
3125 ########################################################################### |
3042 |
3126 |
3043 def __iniFileChanged(self, path): |
3127 def __iniFileChanged(self, path): |
3044 """ |
3128 """ |
3045 Private slot to handle a change of the Mercurial configuration file. |
3129 Private slot to handle a change of the Mercurial configuration file. |
3046 |
3130 |
3051 if self.__client: |
3135 if self.__client: |
3052 ok, err = self.__client.restartServer() |
3136 ok, err = self.__client.restartServer() |
3053 if not ok: |
3137 if not ok: |
3054 E5MessageBox.warning(None, |
3138 E5MessageBox.warning(None, |
3055 self.trUtf8("Mercurial Command Server"), |
3139 self.trUtf8("Mercurial Command Server"), |
3056 self.trUtf8("""<p>The Mercurial Command Server could not be""" |
3140 self.trUtf8( |
3057 """ restarted.</p><p>Reason: {0}</p>""").format(err)) |
3141 """<p>The Mercurial Command Server could not be""" |
|
3142 """ restarted.</p><p>Reason: {0}</p>""").format(err)) |
3058 self.__client = None |
3143 self.__client = None |
3059 |
3144 |
3060 def __monitorRepoIniFile(self, name): |
3145 def __monitorRepoIniFile(self, name): |
3061 """ |
3146 """ |
3062 Private slot to add a repository configuration file to the list of monitored |
3147 Private slot to add a repository configuration file to the list of |
3063 files. |
3148 monitored files. |
3064 |
3149 |
3065 @param name directory name pointing into the repository (string) |
3150 @param name directory name pointing into the repository (string) |
3066 """ |
3151 """ |
3067 dname, fname = self.splitPath(name) |
3152 dname, fname = self.splitPath(name) |
3068 |
3153 |
3101 else: |
3186 else: |
3102 output, error = self.__client.runcommand(args) |
3187 output, error = self.__client.runcommand(args) |
3103 |
3188 |
3104 if output: |
3189 if output: |
3105 for line in output.splitlines(): |
3190 for line in output.splitlines(): |
3106 extensionName = line.split("=", 1)[0].strip().split(".")[-1].strip() |
3191 extensionName = \ |
|
3192 line.split("=", 1)[0].strip().split(".")[-1].strip() |
3107 self.__activeExtensions.append(extensionName) |
3193 self.__activeExtensions.append(extensionName) |
3108 |
3194 |
3109 if self.version >= (1, 8): |
3195 if self.version >= (1, 8): |
3110 if "bookmarks" not in self.__activeExtensions: |
3196 if "bookmarks" not in self.__activeExtensions: |
3111 self.__activeExtensions.append("bookmarks") |
3197 self.__activeExtensions.append("bookmarks") |
3135 @param extensionName name of the extension (string) |
3223 @param extensionName name of the extension (string) |
3136 @return reference to the extension object (boolean) |
3224 @return reference to the extension object (boolean) |
3137 """ |
3225 """ |
3138 return self.__extensions[extensionName] |
3226 return self.__extensions[extensionName] |
3139 |
3227 |
3140 ############################################################################ |
3228 ########################################################################### |
3141 ## Methods to get the helper objects are below. |
3229 ## Methods to get the helper objects are below. |
3142 ############################################################################ |
3230 ########################################################################### |
3143 |
3231 |
3144 def vcsGetProjectBrowserHelper(self, browser, project, isTranslationsBrowser=False): |
3232 def vcsGetProjectBrowserHelper(self, browser, project, |
3145 """ |
3233 isTranslationsBrowser=False): |
3146 Public method to instantiate a helper object for the different project browsers. |
3234 """ |
|
3235 Public method to instantiate a helper object for the different |
|
3236 project browsers. |
3147 |
3237 |
3148 @param browser reference to the project browser object |
3238 @param browser reference to the project browser object |
3149 @param project reference to the project object |
3239 @param project reference to the project object |
3150 @param isTranslationsBrowser flag indicating, the helper is requested for the |
3240 @param isTranslationsBrowser flag indicating, the helper is requested |
3151 translations browser (this needs some special treatment) |
3241 for the translations browser (this needs some special treatment) |
3152 @return the project browser helper object |
3242 @return the project browser helper object |
3153 """ |
3243 """ |
3154 from .ProjectBrowserHelper import HgProjectBrowserHelper |
3244 from .ProjectBrowserHelper import HgProjectBrowserHelper |
3155 return HgProjectBrowserHelper(self, browser, project, isTranslationsBrowser) |
3245 return HgProjectBrowserHelper(self, browser, project, |
|
3246 isTranslationsBrowser) |
3156 |
3247 |
3157 def vcsGetProjectHelper(self, project): |
3248 def vcsGetProjectHelper(self, project): |
3158 """ |
3249 """ |
3159 Public method to instantiate a helper object for the project. |
3250 Public method to instantiate a helper object for the project. |
3160 |
3251 |
3180 if ok: |
3271 if ok: |
3181 self.__client = client |
3272 self.__client = client |
3182 else: |
3273 else: |
3183 E5MessageBox.warning(None, |
3274 E5MessageBox.warning(None, |
3184 self.trUtf8("Mercurial Command Server"), |
3275 self.trUtf8("Mercurial Command Server"), |
3185 self.trUtf8("""<p>The Mercurial Command Server could not be""" |
3276 self.trUtf8( |
3186 """ started.</p><p>Reason: {0}</p>""").format(err)) |
3277 """<p>The Mercurial Command Server could not be""" |
|
3278 """ started.</p><p>Reason: {0}</p>""").format(err)) |
3187 |
3279 |
3188 return self.__projectHelper |
3280 return self.__projectHelper |
3189 |
3281 |
3190 ############################################################################ |
3282 ########################################################################### |
3191 ## Status Monitor Thread methods |
3283 ## Status Monitor Thread methods |
3192 ############################################################################ |
3284 ########################################################################### |
3193 |
3285 |
3194 def _createStatusMonitorThread(self, interval, project): |
3286 def _createStatusMonitorThread(self, interval, project): |
3195 """ |
3287 """ |
3196 Protected method to create an instance of the VCS status monitor thread. |
3288 Protected method to create an instance of the VCS status monitor |
3197 |
3289 thread. |
|
3290 |
|
3291 @param interval check interval for the monitor thread in seconds |
|
3292 (integer) |
3198 @param project reference to the project object (Project) |
3293 @param project reference to the project object (Project) |
3199 @param interval check interval for the monitor thread in seconds (integer) |
|
3200 @return reference to the monitor thread (QThread) |
3294 @return reference to the monitor thread (QThread) |
3201 """ |
3295 """ |
3202 from .HgStatusMonitorThread import HgStatusMonitorThread |
3296 from .HgStatusMonitorThread import HgStatusMonitorThread |
3203 return HgStatusMonitorThread(interval, project, self) |
3297 return HgStatusMonitorThread(interval, project, self) |