Plugins/VcsPlugins/vcsMercurial/hg.py

changeset 945
8cd4d08fa9f6
parent 882
34b86be88bf0
child 963
b672d2191a04
equal deleted inserted replaced
944:1b59c4ba121e 945:8cd4d08fa9f6
7 Module implementing the version control systems interface to Mercurial. 7 Module implementing the version control systems interface to Mercurial.
8 """ 8 """
9 9
10 import os 10 import os
11 import shutil 11 import shutil
12 import urllib.request, urllib.parse, urllib.error 12 import urllib.request
13 import urllib.parse
14 import urllib.error
13 15
14 from PyQt4.QtCore import QProcess, pyqtSignal, QFileInfo 16 from PyQt4.QtCore import QProcess, pyqtSignal, QFileInfo
15 from PyQt4.QtGui import QApplication, QDialog, QInputDialog 17 from PyQt4.QtGui import QApplication, QDialog, QInputDialog
16 18
17 from E5Gui.E5Application import e5App 19 from E5Gui.E5Application import e5App
46 from .ProjectBrowserHelper import HgProjectBrowserHelper 48 from .ProjectBrowserHelper import HgProjectBrowserHelper
47 49
48 import Preferences 50 import Preferences
49 import Utilities 51 import Utilities
50 52
53
51 class Hg(VersionControl): 54 class Hg(VersionControl):
52 """ 55 """
53 Class implementing the version control systems interface to Mercurial. 56 Class implementing the version control systems interface to Mercurial.
54 57
55 @signal committed() emitted after the commit action has completed 58 @signal committed() emitted after the commit action has completed
56 """ 59 """
57 committed = pyqtSignal() 60 committed = pyqtSignal()
58 61
59 def __init__(self, plugin, parent = None, name = None): 62 def __init__(self, plugin, parent=None, name=None):
60 """ 63 """
61 Constructor 64 Constructor
62 65
63 @param plugin reference to the plugin object 66 @param plugin reference to the plugin object
64 @param parent parent widget (QWidget) 67 @param parent parent widget (QWidget)
65 @param name name of this object (string) 68 @param name name of this object (string)
66 """ 69 """
67 VersionControl.__init__(self, parent, name) 70 VersionControl.__init__(self, parent, name)
68 self.defaultOptions = { 71 self.defaultOptions = {
69 'global' : [''], 72 'global': [''],
70 'commit' : [''], 73 'commit': [''],
71 'checkout' : [''], 74 'checkout': [''],
72 'update' : [''], 75 'update': [''],
73 'add' : [''], 76 'add': [''],
74 'remove' : [''], 77 'remove': [''],
75 'diff' : [''], 78 'diff': [''],
76 'log' : [''], 79 'log': [''],
77 'history' : [''], 80 'history': [''],
78 'status' : [''], 81 'status': [''],
79 'tag' : [''], 82 'tag': [''],
80 'export' : [''] 83 'export': ['']
81 } 84 }
82 85
83 self.__plugin = plugin 86 self.__plugin = plugin
84 self.__ui = parent 87 self.__ui = parent
85 88
89 self.allTagsBranchesList = [] 92 self.allTagsBranchesList = []
90 self.showedTags = False 93 self.showedTags = False
91 self.showedBranches = False 94 self.showedBranches = False
92 95
93 self.tagTypeList = [ 96 self.tagTypeList = [
94 'tags', 97 'tags',
95 'branches', 98 'branches',
96 ] 99 ]
97 100
98 self.commandHistory = [] 101 self.commandHistory = []
99 102
100 if "HG_ASP_DOT_NET_HACK" in os.environ: 103 if "HG_ASP_DOT_NET_HACK" in os.environ:
176 else: 179 else:
177 errMsg = self.trUtf8("Could not start the hg executable.") 180 errMsg = self.trUtf8("Could not start the hg executable.")
178 181
179 return False, errMsg 182 return False, errMsg
180 183
181 def vcsInit(self, vcsDir, noDialog = False): 184 def vcsInit(self, vcsDir, noDialog=False):
182 """ 185 """
183 Public method used to initialize the mercurial repository. 186 Public method used to initialize the mercurial repository.
184 187
185 The initialization is done, when a project is converted into a Mercurial 188 The initialization is done, when a project is converted into a Mercurial
186 controlled project. Therefore we always return TRUE without doing anything. 189 controlled project. Therefore we always return TRUE without doing anything.
187 190
188 @param vcsDir name of the VCS directory (string) 191 @param vcsDir name of the VCS directory (string)
189 @param noDialog flag indicating quiet operations (boolean) 192 @param noDialog flag indicating quiet operations (boolean)
190 @return always TRUE 193 @return always TRUE
208 if not os.path.isfile(pfn): 211 if not os.path.isfile(pfn):
209 pfn += "z" 212 pfn += "z"
210 project.closeProject() 213 project.closeProject()
211 project.openProject(pfn) 214 project.openProject(pfn)
212 215
213 def vcsImport(self, vcsDataDict, projectDir, noDialog = False): 216 def vcsImport(self, vcsDataDict, projectDir, noDialog=False):
214 """ 217 """
215 Public method used to import the project into the Subversion repository. 218 Public method used to import the project into the Subversion repository.
216 219
217 @param vcsDataDict dictionary of data required for the import 220 @param vcsDataDict dictionary of data required for the import
218 @param projectDir project directory (string) 221 @param projectDir project directory (string)
249 dia.exec_() 252 dia.exec_()
250 status = dia.normalExit() 253 status = dia.normalExit()
251 254
252 return status, False 255 return status, False
253 256
254 def vcsCheckout(self, vcsDataDict, projectDir, noDialog = False): 257 def vcsCheckout(self, vcsDataDict, projectDir, noDialog=False):
255 """ 258 """
256 Public method used to check the project out of a Mercurial repository (clone). 259 Public method used to check the project out of a Mercurial repository (clone).
257 260
258 @param vcsDataDict dictionary of data required for the checkout 261 @param vcsDataDict dictionary of data required for the checkout
259 @param projectDir project directory to create (string) 262 @param projectDir project directory to create (string)
302 shutil.rmtree(os.path.join(projectDir, self.adminDir), True) 305 shutil.rmtree(os.path.join(projectDir, self.adminDir), True)
303 if os.path.exists(os.path.join(projectDir, '.hgignore')): 306 if os.path.exists(os.path.join(projectDir, '.hgignore')):
304 os.remove(os.path.join(projectDir, '.hgignore')) 307 os.remove(os.path.join(projectDir, '.hgignore'))
305 return status 308 return status
306 309
307 def vcsCommit(self, name, message, noDialog = False, closeBranch = False): 310 def vcsCommit(self, name, message, noDialog=False, closeBranch=False):
308 """ 311 """
309 Public method used to make the change of a file/directory permanent in the 312 Public method used to make the change of a file/directory permanent in the
310 Mercurial repository. 313 Mercurial repository.
311 314
312 @param name file/directory name to be committed (string or list of strings) 315 @param name file/directory name to be committed (string or list of strings)
390 for name in self.__forgotNames: 393 for name in self.__forgotNames:
391 model.updateVCSStatus(name) 394 model.updateVCSStatus(name)
392 self.__forgotNames = [] 395 self.__forgotNames = []
393 self.checkVCSStatus() 396 self.checkVCSStatus()
394 397
395 def vcsUpdate(self, name, noDialog = False, revision = None): 398 def vcsUpdate(self, name, noDialog=False, revision=None):
396 """ 399 """
397 Public method used to update a file/directory with the Mercurial repository. 400 Public method used to update a file/directory with the Mercurial repository.
398 401
399 @param name file/directory name to be updated (string or list of strings) 402 @param name file/directory name to be updated (string or list of strings)
400 @param noDialog flag indicating quiet operations (boolean) 403 @param noDialog flag indicating quiet operations (boolean)
434 dia.exec_() 437 dia.exec_()
435 res = dia.hasAddOrDelete() 438 res = dia.hasAddOrDelete()
436 self.checkVCSStatus() 439 self.checkVCSStatus()
437 return res 440 return res
438 441
439 def vcsAdd(self, name, isDir = False, noDialog = False): 442 def vcsAdd(self, name, isDir=False, noDialog=False):
440 """ 443 """
441 Public method used to add a file/directory to the Mercurial repository. 444 Public method used to add a file/directory to the Mercurial repository.
442 445
443 @param name file/directory name to be added (string) 446 @param name file/directory name to be added (string)
444 @param isDir flag indicating name is a directory (boolean) 447 @param isDir flag indicating name is a directory (boolean)
480 self.trUtf8('Adding files/directories to the Mercurial repository')) 483 self.trUtf8('Adding files/directories to the Mercurial repository'))
481 res = dia.startProcess(args, repodir) 484 res = dia.startProcess(args, repodir)
482 if res: 485 if res:
483 dia.exec_() 486 dia.exec_()
484 487
485 def vcsAddBinary(self, name, isDir = False): 488 def vcsAddBinary(self, name, isDir=False):
486 """ 489 """
487 Public method used to add a file/directory in binary mode to the 490 Public method used to add a file/directory in binary mode to the
488 Mercurial repository. 491 Mercurial repository.
489 492
490 @param name file/directory name to be added (string) 493 @param name file/directory name to be added (string)
496 """ 499 """
497 Public method to add a directory tree rooted at path to the Mercurial repository. 500 Public method to add a directory tree rooted at path to the Mercurial repository.
498 501
499 @param path root directory of the tree to be added (string or list of strings)) 502 @param path root directory of the tree to be added (string or list of strings))
500 """ 503 """
501 self.vcsAdd(path, isDir = False) 504 self.vcsAdd(path, isDir=False)
502 505
503 def vcsRemove(self, name, project = False, noDialog = False): 506 def vcsRemove(self, name, project=False, noDialog=False):
504 """ 507 """
505 Public method used to remove a file/directory from the Mercurial repository. 508 Public method used to remove a file/directory from the Mercurial repository.
506 509
507 The default operation is to remove the local copy as well. 510 The default operation is to remove the local copy as well.
508 511
543 dia.exec_() 546 dia.exec_()
544 res = dia.normalExitWithoutErrors() 547 res = dia.normalExitWithoutErrors()
545 548
546 return res 549 return res
547 550
548 def vcsMove(self, name, project, target = None, noDialog = False): 551 def vcsMove(self, name, project, target=None, noDialog=False):
549 """ 552 """
550 Public method used to move a file/directory. 553 Public method used to move a file/directory.
551 554
552 @param name file/directory name to be moved (string) 555 @param name file/directory name to be moved (string)
553 @param project reference to the project object 556 @param project reference to the project object
612 project.removeFile(name) 615 project.removeFile(name)
613 return res 616 return res
614 617
615 def vcsLog(self, name): 618 def vcsLog(self, name):
616 """ 619 """
617 Public method used to view the log of a file/directory from the 620 Public method used to view the log of a file/directory from the
618 Mercurial repository. 621 Mercurial repository.
619 622
620 @param name file/directory name to show the log of (string) 623 @param name file/directory name to show the log of (string)
621 """ 624 """
622 self.log = HgLogDialog(self) 625 self.log = HgLogDialog(self)
623 self.log.show() 626 self.log.show()
624 self.log.start(name) 627 self.log.start(name)
625 628
626 def vcsDiff(self, name): 629 def vcsDiff(self, name):
627 """ 630 """
628 Public method used to view the difference of a file/directory to the 631 Public method used to view the difference of a file/directory to the
629 Mercurial repository. 632 Mercurial repository.
630 633
631 If name is a directory and is the project directory, all project files 634 If name is a directory and is the project directory, all project files
632 are saved first. If name is a file (or list of files), which is/are being edited 635 are saved first. If name is a file (or list of files), which is/are being edited
633 and has unsaved modification, they can be saved or the operation may be aborted. 636 and has unsaved modification, they can be saved or the operation may be aborted.
634 637
635 @param name file/directory name to be diffed (string) 638 @param name file/directory name to be diffed (string)
636 """ 639 """
637 if isinstance(name, list): 640 if isinstance(name, list):
639 else: 642 else:
640 names = [name] 643 names = [name]
641 for nam in names: 644 for nam in names:
642 if os.path.isfile(nam): 645 if os.path.isfile(nam):
643 editor = e5App().getObject("ViewManager").getOpenEditor(nam) 646 editor = e5App().getObject("ViewManager").getOpenEditor(nam)
644 if editor and not editor.checkDirty() : 647 if editor and not editor.checkDirty():
645 return 648 return
646 else: 649 else:
647 project = e5App().getObject("Project") 650 project = e5App().getObject("Project")
648 if nam == project.ppath and not project.saveAllScripts(): 651 if nam == project.ppath and not project.saveAllScripts():
649 return 652 return
652 QApplication.processEvents() 655 QApplication.processEvents()
653 self.diff.start(name) 656 self.diff.start(name)
654 657
655 def vcsStatus(self, name): 658 def vcsStatus(self, name):
656 """ 659 """
657 Public method used to view the status of files/directories in the 660 Public method used to view the status of files/directories in the
658 Mercurial repository. 661 Mercurial repository.
659 662
660 @param name file/directory name(s) to show the status of 663 @param name file/directory name(s) to show the status of
661 (string or list of strings) 664 (string or list of strings)
662 """ 665 """
786 @param name directory name to be switched (string) 789 @param name directory name to be switched (string)
787 """ 790 """
788 dlg = HgRevisionSelectionDialog(self.tagsList, self.branchesList) 791 dlg = HgRevisionSelectionDialog(self.tagsList, self.branchesList)
789 if dlg.exec_() == QDialog.Accepted: 792 if dlg.exec_() == QDialog.Accepted:
790 rev = dlg.getRevision() 793 rev = dlg.getRevision()
791 self.vcsUpdate(name, revision = rev) 794 self.vcsUpdate(name, revision=rev)
792 795
793 def vcsRegisteredState(self, name): 796 def vcsRegisteredState(self, name):
794 """ 797 """
795 Public method used to get the registered state of a file in the vcs. 798 Public method used to get the registered state of a file in the vcs.
796 799
842 if absname == name: 845 if absname == name:
843 return self.canBeCommitted 846 return self.canBeCommitted
844 847
845 return self.canBeAdded 848 return self.canBeAdded
846 849
847 def vcsAllRegisteredStates(self, names, dname, shortcut = True): 850 def vcsAllRegisteredStates(self, names, dname, shortcut=True):
848 """ 851 """
849 Public method used to get the registered states of a number of files in the vcs. 852 Public method used to get the registered states of a number of files in the vcs.
850 853
851 <b>Note:</b> If a shortcut is to be taken, the code will only check, if the named 854 <b>Note:</b> If a shortcut is to be taken, the code will only check, if the named
852 directory has been scanned already. If so, it is assumed, that the states for 855 directory has been scanned already. If so, it is assumed, that the states for
853 all files have been populated by the previous run. 856 all files have been populated by the previous run.
854 857
855 @param names dictionary with all filenames to be checked as keys 858 @param names dictionary with all filenames to be checked as keys
856 @param dname directory to check in (string) 859 @param dname directory to check in (string)
857 @param shortcut flag indicating a shortcut should be taken (boolean) 860 @param shortcut flag indicating a shortcut should be taken (boolean)
858 @return the received dictionary completed with a combination of 861 @return the received dictionary completed with a combination of
859 canBeCommited and canBeAdded or None in order to signal an error 862 canBeCommited and canBeAdded or None in order to signal an error
860 """ 863 """
861 if dname.endswith(os.sep): 864 if dname.endswith(os.sep):
862 dname = dname[:-1] 865 dname = dname[:-1]
863 dname = os.path.normcase(dname) 866 dname = os.path.normcase(dname)
979 dia = HgDialog(self.trUtf8('Mercurial command')) 982 dia = HgDialog(self.trUtf8('Mercurial command'))
980 res = dia.startProcess(args, repodir) 983 res = dia.startProcess(args, repodir)
981 if res: 984 if res:
982 dia.exec_() 985 dia.exec_()
983 986
984 def vcsOptionsDialog(self, project, archive, editable = False, parent = None): 987 def vcsOptionsDialog(self, project, archive, editable=False, parent=None):
985 """ 988 """
986 Public method to get a dialog to enter repository info. 989 Public method to get a dialog to enter repository info.
987 990
988 @param project reference to the project object 991 @param project reference to the project object
989 @param archive name of the project in the repository (string) 992 @param archive name of the project in the repository (string)
990 @param editable flag indicating that the project name is editable (boolean) 993 @param editable flag indicating that the project name is editable (boolean)
991 @param parent parent widget (QWidget) 994 @param parent parent widget (QWidget)
992 """ 995 """
993 return HgOptionsDialog(self, project, parent) 996 return HgOptionsDialog(self, project, parent)
994 997
995 def vcsNewProjectOptionsDialog(self, parent = None): 998 def vcsNewProjectOptionsDialog(self, parent=None):
996 """ 999 """
997 Public method to get a dialog to enter repository info for getting a new project. 1000 Public method to get a dialog to enter repository info for getting a new project.
998 1001
999 @param parent parent widget (QWidget) 1002 @param parent parent widget (QWidget)
1000 """ 1003 """
1019 process.start('hg', args) 1022 process.start('hg', args)
1020 procStarted = process.waitForStarted() 1023 procStarted = process.waitForStarted()
1021 if procStarted: 1024 if procStarted:
1022 finished = process.waitForFinished(30000) 1025 finished = process.waitForFinished(30000)
1023 if finished and process.exitCode() == 0: 1026 if finished and process.exitCode() == 0:
1024 output = str(process.readAllStandardOutput(), 1027 output = str(process.readAllStandardOutput(),
1025 Preferences.getSystem("IOEncoding"), 'replace') 1028 Preferences.getSystem("IOEncoding"), 'replace')
1026 index = 0 1029 index = 0
1027 for line in output.splitlines(): 1030 for line in output.splitlines():
1028 index += 1 1031 index += 1
1029 changeset, tags, author, date, branches = line.split("@@@") 1032 changeset, tags, author, date, branches = line.split("@@@")
1030 cdate, ctime = date.split()[:2] 1033 cdate, ctime = date.split()[:2]
1031 info.append("""<p><table>""") 1034 info.append("""<p><table>""")
1032 info.append(QApplication.translate("mercurial", 1035 info.append(QApplication.translate("mercurial",
1033 """<tr><td><b>Parent #{0}</b></td><td></td></tr>\n""" 1036 """<tr><td><b>Parent #{0}</b></td><td></td></tr>\n"""
1034 """<tr><td><b>Changeset</b></td><td>{1}</td></tr>""")\ 1037 """<tr><td><b>Changeset</b></td><td>{1}</td></tr>""")\
1035 .format(index, changeset)) 1038 .format(index, changeset))
1036 if tags: 1039 if tags:
1037 info.append(QApplication.translate("mercurial", 1040 info.append(QApplication.translate("mercurial",
1038 """<tr><td><b>Tags</b></td><td>{0}</td></tr>""")\ 1041 """<tr><td><b>Tags</b></td><td>{0}</td></tr>""")\
1039 .format('<br/>'.join(tags.split()))) 1042 .format('<br/>'.join(tags.split())))
1040 if branches: 1043 if branches:
1041 info.append(QApplication.translate("mercurial", 1044 info.append(QApplication.translate("mercurial",
1042 """<tr><td><b>Branches</b></td><td>{0}</td></tr>""")\ 1045 """<tr><td><b>Branches</b></td><td>{0}</td></tr>""")\
1043 .format('<br/>'.join(branches.split()))) 1046 .format('<br/>'.join(branches.split())))
1044 info.append(QApplication.translate("mercurial", 1047 info.append(QApplication.translate("mercurial",
1045 """<tr><td><b>Last author</b></td><td>{0}</td></tr>\n""" 1048 """<tr><td><b>Last author</b></td><td>{0}</td></tr>\n"""
1046 """<tr><td><b>Committed date</b></td><td>{1}</td></tr>\n""" 1049 """<tr><td><b>Committed date</b></td><td>{1}</td></tr>\n"""
1047 """<tr><td><b>Committed time</b></td><td>{2}</td></tr>""")\ 1050 """<tr><td><b>Committed time</b></td><td>{2}</td></tr>""")\
1048 .format(author, cdate, ctime)) 1051 .format(author, cdate, ctime))
1049 info.append("""</table></p>""") 1052 info.append("""</table></p>""")
1050 1053
1051 url = "" 1054 url = ""
1052 args = [] 1055 args = []
1053 args.append('showconfig') 1056 args.append('showconfig')
1054 args.append('paths.default') 1057 args.append('paths.default')
1055 process.setWorkingDirectory(ppath) 1058 process.setWorkingDirectory(ppath)
1056 process.start('hg', args) 1059 process.start('hg', args)
1057 procStarted = process.waitForStarted() 1060 procStarted = process.waitForStarted()
1058 if procStarted: 1061 if procStarted:
1059 finished = process.waitForFinished(30000) 1062 finished = process.waitForFinished(30000)
1060 if finished and process.exitCode() == 0: 1063 if finished and process.exitCode() == 0:
1061 output = str(process.readAllStandardOutput(), 1064 output = str(process.readAllStandardOutput(),
1062 Preferences.getSystem("IOEncoding"), 'replace') 1065 Preferences.getSystem("IOEncoding"), 'replace')
1063 if output: 1066 if output:
1064 url = output.splitlines()[0].strip() 1067 url = output.splitlines()[0].strip()
1065 else: 1068 else:
1066 url = "" 1069 url = ""
1090 url = url.split(':', 2) 1093 url = url.split(':', 2)
1091 if len(url) == 4: 1094 if len(url) == 4:
1092 scheme = url[0] 1095 scheme = url[0]
1093 user = url[1] 1096 user = url[1]
1094 host = url[2] 1097 host = url[2]
1095 port, path = url[3].split("/",1) 1098 port, path = url[3].split("/", 1)
1096 return "{0}:{1}:{2}:{3}/{4}".format( 1099 return "{0}:{1}:{2}:{3}/{4}".format(
1097 scheme, user, host, port, urllib.parse.quote(path)) 1100 scheme, user, host, port, urllib.parse.quote(path))
1098 elif len(url) == 3: 1101 elif len(url) == 3:
1099 scheme = url[0] 1102 scheme = url[0]
1100 host = url[1] 1103 host = url[1]
1101 port, path = url[2].split("/",1) 1104 port, path = url[2].split("/", 1)
1102 return "{0}:{1}:{2}/{3}".format(scheme, host, port, urllib.parse.quote(path)) 1105 return "{0}:{1}:{2}/{3}".format(scheme, host, port, urllib.parse.quote(path))
1103 else: 1106 else:
1104 scheme = url[0] 1107 scheme = url[0]
1105 if scheme == "file": 1108 if scheme == "file":
1106 return "{0}:{1}".format(scheme, urllib.parse.quote(url[1])) 1109 return "{0}:{1}".format(scheme, urllib.parse.quote(url[1]))
1107 else: 1110 else:
1108 host, path = url[1][2:].split("/",1) 1111 host, path = url[1][2:].split("/", 1)
1109 return "{0}://{1}/{2}".format(scheme, host, urllib.parse.quote(path)) 1112 return "{0}://{1}/{2}".format(scheme, host, urllib.parse.quote(path))
1110 1113
1111 def hgNormalizeURL(self, url): 1114 def hgNormalizeURL(self, url):
1112 """ 1115 """
1113 Public method to normalize a url for Mercurial. 1116 Public method to normalize a url for Mercurial.
1161 project.copyDirectory(name, target) 1164 project.copyDirectory(name, target)
1162 else: 1165 else:
1163 project.appendFile(target) 1166 project.appendFile(target)
1164 return res 1167 return res
1165 1168
1166 def hgListTagBranch(self, path, tags = True): 1169 def hgListTagBranch(self, path, tags=True):
1167 """ 1170 """
1168 Public method used to list the available tags or branches. 1171 Public method used to list the available tags or branches.
1169 1172
1170 @param path directory name of the project (string) 1173 @param path directory name of the project (string)
1171 @param tags flag indicating listing of branches or tags 1174 @param tags flag indicating listing of branches or tags
1178 self.showedTags = True 1181 self.showedTags = True
1179 allTagsBranchesList = self.allTagsBranchesList 1182 allTagsBranchesList = self.allTagsBranchesList
1180 else: 1183 else:
1181 self.tagsList = [] 1184 self.tagsList = []
1182 allTagsBranchesList = None 1185 allTagsBranchesList = None
1183 self.tagbranchList.start(path, tags, 1186 self.tagbranchList.start(path, tags,
1184 self.tagsList, allTagsBranchesList) 1187 self.tagsList, allTagsBranchesList)
1185 else: 1188 else:
1186 if not self.showedBranches: 1189 if not self.showedBranches:
1187 self.showedBranches = True 1190 self.showedBranches = True
1188 allTagsBranchesList = self.allTagsBranchesList 1191 allTagsBranchesList = self.allTagsBranchesList
1189 else: 1192 else:
1190 self.branchesList = [] 1193 self.branchesList = []
1191 allTagsBranchesList = None 1194 allTagsBranchesList = None
1192 self.tagbranchList.start(path, tags, 1195 self.tagbranchList.start(path, tags,
1193 self.branchesList, self.allTagsBranchesList) 1196 self.branchesList, self.allTagsBranchesList)
1194 1197
1195 def hgAnnotate(self, name): 1198 def hgAnnotate(self, name):
1196 """ 1199 """
1197 Public method to show the output of the hg annotate command. 1200 Public method to show the output of the hg annotate command.
1202 self.annotate.show() 1205 self.annotate.show()
1203 self.annotate.start(name) 1206 self.annotate.start(name)
1204 1207
1205 def hgExtendedDiff(self, name): 1208 def hgExtendedDiff(self, name):
1206 """ 1209 """
1207 Public method used to view the difference of a file/directory to the 1210 Public method used to view the difference of a file/directory to the
1208 Mercurial repository. 1211 Mercurial repository.
1209 1212
1210 If name is a directory and is the project directory, all project files 1213 If name is a directory and is the project directory, all project files
1211 are saved first. If name is a file (or list of files), which is/are being edited 1214 are saved first. If name is a file (or list of files), which is/are being edited
1212 and has unsaved modification, they can be saved or the operation may be aborted. 1215 and has unsaved modification, they can be saved or the operation may be aborted.
1213 1216
1214 This method gives the chance to enter the revisions to be compared. 1217 This method gives the chance to enter the revisions to be compared.
1215 1218
1216 @param name file/directory name to be diffed (string) 1219 @param name file/directory name to be diffed (string)
1220 else: 1223 else:
1221 names = [name] 1224 names = [name]
1222 for nam in names: 1225 for nam in names:
1223 if os.path.isfile(nam): 1226 if os.path.isfile(nam):
1224 editor = e5App().getObject("ViewManager").getOpenEditor(nam) 1227 editor = e5App().getObject("ViewManager").getOpenEditor(nam)
1225 if editor and not editor.checkDirty() : 1228 if editor and not editor.checkDirty():
1226 return 1229 return
1227 else: 1230 else:
1228 project = e5App().getObject("Project") 1231 project = e5App().getObject("Project")
1229 if nam == project.ppath and not project.saveAllScripts(): 1232 if nam == project.ppath and not project.saveAllScripts():
1230 return 1233 return
1235 self.diff.show() 1238 self.diff.show()
1236 self.diff.start(name, revisions) 1239 self.diff.start(name, revisions)
1237 1240
1238 def hgLogLimited(self, name): 1241 def hgLogLimited(self, name):
1239 """ 1242 """
1240 Public method used to view the (limited) log of a file/directory from the 1243 Public method used to view the (limited) log of a file/directory from the
1241 Mercurial repository. 1244 Mercurial repository.
1242 1245
1243 @param name file/directory name to show the log of (string) 1246 @param name file/directory name to show the log of (string)
1244 """ 1247 """
1245 noEntries, ok = QInputDialog.getInteger( 1248 noEntries, ok = QInputDialog.getInteger(
1252 self.log.show() 1255 self.log.show()
1253 self.log.start(name, noEntries) 1256 self.log.start(name, noEntries)
1254 1257
1255 def hgLogBrowser(self, path): 1258 def hgLogBrowser(self, path):
1256 """ 1259 """
1257 Public method used to browse the log of a file/directory from the 1260 Public method used to browse the log of a file/directory from the
1258 Mercurial repository. 1261 Mercurial repository.
1259 1262
1260 @param path file/directory name to show the log of (string) 1263 @param path file/directory name to show the log of (string)
1261 """ 1264 """
1262 self.logBrowser = HgLogBrowserDialog(self) 1265 self.logBrowser = HgLogBrowserDialog(self)
1263 self.logBrowser.show() 1266 self.logBrowser.show()
1264 self.logBrowser.start(path) 1267 self.logBrowser.start(path)
1265 1268
1266 def hgIncoming(self, name): 1269 def hgIncoming(self, name):
1267 """ 1270 """
1268 Public method used to view the log of incoming changes from the 1271 Public method used to view the log of incoming changes from the
1269 Mercurial repository. 1272 Mercurial repository.
1270 1273
1271 @param name file/directory name to show the log of (string) 1274 @param name file/directory name to show the log of (string)
1272 """ 1275 """
1273 if self.getPlugin().getPreferences("UseLogBrowser"): 1276 if self.getPlugin().getPreferences("UseLogBrowser"):
1274 self.logBrowser = HgLogBrowserDialog(self, mode = "incoming") 1277 self.logBrowser = HgLogBrowserDialog(self, mode="incoming")
1275 self.logBrowser.show() 1278 self.logBrowser.show()
1276 self.logBrowser.start(name) 1279 self.logBrowser.start(name)
1277 else: 1280 else:
1278 self.log = HgLogDialog(self, mode = "incoming") 1281 self.log = HgLogDialog(self, mode="incoming")
1279 self.log.show() 1282 self.log.show()
1280 self.log.start(name) 1283 self.log.start(name)
1281 1284
1282 def hgOutgoing(self, name): 1285 def hgOutgoing(self, name):
1283 """ 1286 """
1284 Public method used to view the log of outgoing changes from the 1287 Public method used to view the log of outgoing changes from the
1285 Mercurial repository. 1288 Mercurial repository.
1286 1289
1287 @param name file/directory name to show the log of (string) 1290 @param name file/directory name to show the log of (string)
1288 """ 1291 """
1289 if self.getPlugin().getPreferences("UseLogBrowser"): 1292 if self.getPlugin().getPreferences("UseLogBrowser"):
1290 self.logBrowser = HgLogBrowserDialog(self, mode = "outgoing") 1293 self.logBrowser = HgLogBrowserDialog(self, mode="outgoing")
1291 self.logBrowser.show() 1294 self.logBrowser.show()
1292 self.logBrowser.start(name) 1295 self.logBrowser.start(name)
1293 else: 1296 else:
1294 self.log = HgLogDialog(self, mode = "outgoing") 1297 self.log = HgLogDialog(self, mode="outgoing")
1295 self.log.show() 1298 self.log.show()
1296 self.log.start(name) 1299 self.log.start(name)
1297 1300
1298 def hgPull(self, name): 1301 def hgPull(self, name):
1299 """ 1302 """
1323 dia.exec_() 1326 dia.exec_()
1324 res = dia.hasAddOrDelete() 1327 res = dia.hasAddOrDelete()
1325 self.checkVCSStatus() 1328 self.checkVCSStatus()
1326 return res 1329 return res
1327 1330
1328 def hgPush(self, name, force = False): 1331 def hgPush(self, name, force=False):
1329 """ 1332 """
1330 Public method used to push changes to a remote Mercurial repository. 1333 Public method used to push changes to a remote Mercurial repository.
1331 1334
1332 @param name directory name of the project to be pushed from (string) 1335 @param name directory name of the project to be pushed from (string)
1333 @keyparam force flag indicating a forced push (boolean) 1336 @keyparam force flag indicating a forced push (boolean)
1351 if res: 1354 if res:
1352 dia.exec_() 1355 dia.exec_()
1353 res = dia.hasAddOrDelete() 1356 res = dia.hasAddOrDelete()
1354 self.checkVCSStatus() 1357 self.checkVCSStatus()
1355 1358
1356 def hgInfo(self, ppath, mode = "heads"): 1359 def hgInfo(self, ppath, mode="heads"):
1357 """ 1360 """
1358 Public method to show information about the heads of the repository. 1361 Public method to show information about the heads of the repository.
1359 1362
1360 @param ppath local path to get the repository infos (string) 1363 @param ppath local path to get the repository infos (string)
1361 @keyparam mode mode of the operation (string, one of heads, parents, tip) 1364 @keyparam mode mode of the operation (string, one of heads, parents, tip)
1383 process.start('hg', args) 1386 process.start('hg', args)
1384 procStarted = process.waitForStarted() 1387 procStarted = process.waitForStarted()
1385 if procStarted: 1388 if procStarted:
1386 finished = process.waitForFinished(30000) 1389 finished = process.waitForFinished(30000)
1387 if finished and process.exitCode() == 0: 1390 if finished and process.exitCode() == 0:
1388 output = str(process.readAllStandardOutput(), 1391 output = str(process.readAllStandardOutput(),
1389 Preferences.getSystem("IOEncoding"), 'replace') 1392 Preferences.getSystem("IOEncoding"), 'replace')
1390 index = 0 1393 index = 0
1391 for line in output.splitlines(): 1394 for line in output.splitlines():
1392 index += 1 1395 index += 1
1393 changeset, tags, author, date, branches, parents = line.split("@@@") 1396 changeset, tags, author, date, branches, parents = line.split("@@@")
1394 cdate, ctime = date.split()[:2] 1397 cdate, ctime = date.split()[:2]
1395 info.append("""<p><table>""") 1398 info.append("""<p><table>""")
1396 if mode == "heads": 1399 if mode == "heads":
1397 info.append(QApplication.translate("mercurial", 1400 info.append(QApplication.translate("mercurial",
1398 """<tr><td><b>Head #{0}</b></td><td></td></tr>\n""" 1401 """<tr><td><b>Head #{0}</b></td><td></td></tr>\n"""
1399 .format(index, changeset))) 1402 .format(index, changeset)))
1400 elif mode == "parents": 1403 elif mode == "parents":
1401 info.append(QApplication.translate("mercurial", 1404 info.append(QApplication.translate("mercurial",
1402 """<tr><td><b>Parent #{0}</b></td><td></td></tr>\n""" 1405 """<tr><td><b>Parent #{0}</b></td><td></td></tr>\n"""
1403 .format(index, changeset))) 1406 .format(index, changeset)))
1404 elif mode == "tip": 1407 elif mode == "tip":
1405 info.append(QApplication.translate("mercurial", 1408 info.append(QApplication.translate("mercurial",
1406 """<tr><td><b>Tip</b></td><td></td></tr>\n""")) 1409 """<tr><td><b>Tip</b></td><td></td></tr>\n"""))
1407 info.append(QApplication.translate("mercurial", 1410 info.append(QApplication.translate("mercurial",
1408 """<tr><td><b>Changeset</b></td><td>{0}</td></tr>""")\ 1411 """<tr><td><b>Changeset</b></td><td>{0}</td></tr>""")\
1409 .format(changeset)) 1412 .format(changeset))
1410 if tags: 1413 if tags:
1411 info.append(QApplication.translate("mercurial", 1414 info.append(QApplication.translate("mercurial",
1412 """<tr><td><b>Tags</b></td><td>{0}</td></tr>""")\ 1415 """<tr><td><b>Tags</b></td><td>{0}</td></tr>""")\
1413 .format('<br/>'.join(tags.split()))) 1416 .format('<br/>'.join(tags.split())))
1414 if branches: 1417 if branches:
1415 info.append(QApplication.translate("mercurial", 1418 info.append(QApplication.translate("mercurial",
1416 """<tr><td><b>Branches</b></td><td>{0}</td></tr>""")\ 1419 """<tr><td><b>Branches</b></td><td>{0}</td></tr>""")\
1417 .format('<br/>'.join(branches.split()))) 1420 .format('<br/>'.join(branches.split())))
1418 if parents: 1421 if parents:
1419 info.append(QApplication.translate("mercurial", 1422 info.append(QApplication.translate("mercurial",
1420 """<tr><td><b>Parents</b></td><td>{0}</td></tr>""")\ 1423 """<tr><td><b>Parents</b></td><td>{0}</td></tr>""")\
1421 .format('<br/>'.join(parents.split()))) 1424 .format('<br/>'.join(parents.split())))
1422 info.append(QApplication.translate("mercurial", 1425 info.append(QApplication.translate("mercurial",
1423 """<tr><td><b>Last author</b></td><td>{0}</td></tr>\n""" 1426 """<tr><td><b>Last author</b></td><td>{0}</td></tr>\n"""
1424 """<tr><td><b>Committed date</b></td><td>{1}</td></tr>\n""" 1427 """<tr><td><b>Committed date</b></td><td>{1}</td></tr>\n"""
1425 """<tr><td><b>Committed time</b></td><td>{2}</td></tr>\n""" 1428 """<tr><td><b>Committed time</b></td><td>{2}</td></tr>\n"""
1426 """</table></p>""")\ 1429 """</table></p>""")\
1427 .format(author, cdate, ctime)) 1430 .format(author, cdate, ctime))
1655 dia = HgDialog(self.trUtf8('Identifying project directory')) 1658 dia = HgDialog(self.trUtf8('Identifying project directory'))
1656 res = dia.startProcess(args, repodir, False) 1659 res = dia.startProcess(args, repodir, False)
1657 if res: 1660 if res:
1658 dia.exec_() 1661 dia.exec_()
1659 1662
1660 def hgCreateIgnoreFile(self, name, autoAdd = False): 1663 def hgCreateIgnoreFile(self, name, autoAdd=False):
1661 """ 1664 """
1662 Public method to create the ignore file. 1665 Public method to create the ignore file.
1663 1666
1664 @param name directory name to create the ignore file in (string) 1667 @param name directory name to create the ignore file in (string)
1665 @param autoAdd flag indicating to add it automatically (boolean) 1668 @param autoAdd flag indicating to add it automatically (boolean)
1666 @return flag indicating success 1669 @return flag indicating success
1667 """ 1670 """
1668 status = False 1671 status = False
1669 ignorePatterns = [ 1672 ignorePatterns = [
1670 "glob:.eric5project", 1673 "glob:.eric5project",
1671 "glob:.ropeproject", 1674 "glob:.ropeproject",
1672 "glob:.directory", 1675 "glob:.directory",
1673 "glob:**.pyc", 1676 "glob:**.pyc",
1674 "glob:**.orig", 1677 "glob:**.orig",
1675 "glob:**.bak", 1678 "glob:**.bak",
1676 ] 1679 ]
1677 1680
1678 ignoreName = os.path.join(name, ".hgignore") 1681 ignoreName = os.path.join(name, ".hgignore")
1679 if os.path.exists(ignoreName): 1682 if os.path.exists(ignoreName):
1680 res = E5MessageBox.yesNo(self.__ui, 1683 res = E5MessageBox.yesNo(self.__ui,
1681 self.trUtf8("Create .hgignore file"), 1684 self.trUtf8("Create .hgignore file"),
1682 self.trUtf8("""<p>The file <b>{0}</b> exists already.""" 1685 self.trUtf8("""<p>The file <b>{0}</b> exists already."""
1683 """ Overwrite it?</p>""").format(ignoreName), 1686 """ Overwrite it?</p>""").format(ignoreName),
1684 icon = E5MessageBox.Warning) 1687 icon=E5MessageBox.Warning)
1685 else: 1688 else:
1686 res = True 1689 res = True
1687 if res: 1690 if res:
1688 try: 1691 try:
1689 # create a .hgignore file 1692 # create a .hgignore file
1694 status = True 1697 status = True
1695 except IOError: 1698 except IOError:
1696 status = False 1699 status = False
1697 1700
1698 if status and autoAdd: 1701 if status and autoAdd:
1699 self.vcsAdd(ignoreName, noDialog = True) 1702 self.vcsAdd(ignoreName, noDialog=True)
1700 project = e5App().getObject("Project") 1703 project = e5App().getObject("Project")
1701 project.appendFile(ignoreName) 1704 project.appendFile(ignoreName)
1702 1705
1703 return status 1706 return status
1704 1707
1741 res = E5MessageBox.yesNo(self.__ui, 1744 res = E5MessageBox.yesNo(self.__ui,
1742 self.trUtf8("Create changegroup"), 1745 self.trUtf8("Create changegroup"),
1743 self.trUtf8("<p>The Mercurial changegroup file <b>{0}</b> " 1746 self.trUtf8("<p>The Mercurial changegroup file <b>{0}</b> "
1744 "already exists. Overwrite it?</p>") 1747 "already exists. Overwrite it?</p>")
1745 .format(fname), 1748 .format(fname),
1746 icon = E5MessageBox.Warning) 1749 icon=E5MessageBox.Warning)
1747 if not res: 1750 if not res:
1748 return 1751 return
1749 fname = Utilities.toNativeSeparators(fname) 1752 fname = Utilities.toNativeSeparators(fname)
1750 1753
1751 args = [] 1754 args = []
1787 repodir, 1790 repodir,
1788 self.trUtf8("Mercurial Changegroup Files (*.hg);;All Files (*)")) 1791 self.trUtf8("Mercurial Changegroup Files (*.hg);;All Files (*)"))
1789 if file: 1792 if file:
1790 if self.getPlugin().getPreferences("UseLogBrowser"): 1793 if self.getPlugin().getPreferences("UseLogBrowser"):
1791 self.logBrowser = \ 1794 self.logBrowser = \
1792 HgLogBrowserDialog(self, mode = "incoming", bundle = file) 1795 HgLogBrowserDialog(self, mode="incoming", bundle=file)
1793 self.logBrowser.show() 1796 self.logBrowser.show()
1794 self.logBrowser.start(name) 1797 self.logBrowser.start(name)
1795 else: 1798 else:
1796 self.log = HgLogDialog(self, mode = "incoming", bundle = file) 1799 self.log = HgLogDialog(self, mode="incoming", bundle=file)
1797 self.log.show() 1800 self.log.show()
1798 self.log.start(name) 1801 self.log.start(name)
1799 1802
1800 def hgIdentifyBundle(self, name): 1803 def hgIdentifyBundle(self, name):
1801 """ 1804 """
1849 self.trUtf8("Mercurial Changegroup Files (*.hg);;All Files (*)")) 1852 self.trUtf8("Mercurial Changegroup Files (*.hg);;All Files (*)"))
1850 if files: 1853 if files:
1851 update = E5MessageBox.yesNo(self.__ui, 1854 update = E5MessageBox.yesNo(self.__ui,
1852 self.trUtf8("Apply changegroups"), 1855 self.trUtf8("Apply changegroups"),
1853 self.trUtf8("""Shall the working directory be updated?"""), 1856 self.trUtf8("""Shall the working directory be updated?"""),
1854 yesDefault = True) 1857 yesDefault=True)
1855 1858
1856 args = [] 1859 args = []
1857 args.append('unbundle') 1860 args.append('unbundle')
1858 if update: 1861 if update:
1859 args.append("--update") 1862 args.append("--update")
1885 if repodir == os.sep: 1888 if repodir == os.sep:
1886 return 1889 return
1887 1890
1888 rev = "" 1891 rev = ""
1889 if subcommand in ("good", "bad"): 1892 if subcommand in ("good", "bad"):
1890 dlg = HgRevisionSelectionDialog(self.tagsList, self.branchesList, 1893 dlg = HgRevisionSelectionDialog(self.tagsList, self.branchesList,
1891 showNone =True) 1894 showNone=True)
1892 if dlg.exec_() == QDialog.Accepted: 1895 if dlg.exec_() == QDialog.Accepted:
1893 rev = dlg.getRevision() 1896 rev = dlg.getRevision()
1894 else: 1897 else:
1895 return 1898 return
1896 1899
2006 2009
2007 ############################################################################ 2010 ############################################################################
2008 ## Methods to get the helper objects are below. 2011 ## Methods to get the helper objects are below.
2009 ############################################################################ 2012 ############################################################################
2010 2013
2011 def vcsGetProjectBrowserHelper(self, browser, project, isTranslationsBrowser = False): 2014 def vcsGetProjectBrowserHelper(self, browser, project, isTranslationsBrowser=False):
2012 """ 2015 """
2013 Public method to instanciate a helper object for the different project browsers. 2016 Public method to instanciate a helper object for the different project browsers.
2014 2017
2015 @param browser reference to the project browser object 2018 @param browser reference to the project browser object
2016 @param project reference to the project object 2019 @param project reference to the project object

eric ide

mercurial