Plugins/VcsPlugins/vcsMercurial/hg.py

branch
Py2 comp.
changeset 3484
645c12de6b0c
parent 3178
f25fc1364c88
parent 3434
9b874ca09bb3
child 3515
1b8381afe38f
equal deleted inserted replaced
3456:96232974dcdb 3484:645c12de6b0c
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 from __future__ import unicode_literals 10 from __future__ import unicode_literals
11 try: 11 try:
12 str = unicode # __IGNORE_WARNING__ 12 str = unicode
13 except (NameError): 13 except NameError:
14 pass 14 pass
15 15
16 import os 16 import os
17 import shutil 17 import shutil
18 import re 18 import re
19 19
20 from PyQt4.QtCore import QProcess, pyqtSignal, QFileInfo, QFileSystemWatcher 20 from PyQt4.QtCore import QProcess, pyqtSignal, QFileInfo, QFileSystemWatcher
21 from PyQt4.QtGui import QApplication, QDialog, QInputDialog 21 from PyQt4.QtGui import QApplication, QDialog
22 22
23 from E5Gui.E5Application import e5App 23 from E5Gui.E5Application import e5App
24 from E5Gui import E5MessageBox, E5FileDialog 24 from E5Gui import E5MessageBox, E5FileDialog
25 25
26 from QScintilla.MiniEditor import MiniEditor 26 from QScintilla.MiniEditor import MiniEditor
28 from VCS.VersionControl import VersionControl 28 from VCS.VersionControl import VersionControl
29 from VCS.RepositoryInfoDialog import VcsRepositoryInfoDialog 29 from VCS.RepositoryInfoDialog import VcsRepositoryInfoDialog
30 30
31 from .HgDialog import HgDialog 31 from .HgDialog import HgDialog
32 32
33 import Preferences
34 import Utilities 33 import Utilities
35 34
36 35
37 class Hg(VersionControl): 36 class Hg(VersionControl):
38 """ 37 """
39 Class implementing the version control systems interface to Mercurial. 38 Class implementing the version control systems interface to Mercurial.
40 39
41 @signal committed() emitted after the commit action has completed 40 @signal committed() emitted after the commit action has completed
42 @signal activeExtensionsChanged() emitted when the list of active 41 @signal activeExtensionsChanged() emitted when the list of active
43 extensions has changed 42 extensions has changed
43 @signal iniFileChanged() emitted when a Mercurial/repo configuration file
44 has changed
44 """ 45 """
45 committed = pyqtSignal() 46 committed = pyqtSignal()
46 activeExtensionsChanged = pyqtSignal() 47 activeExtensionsChanged = pyqtSignal()
48 iniFileChanged = pyqtSignal()
47 49
48 IgnoreFileName = ".hgignore" 50 IgnoreFileName = ".hgignore"
49 51
50 def __init__(self, plugin, parent=None, name=None): 52 def __init__(self, plugin, parent=None, name=None):
51 """ 53 """
55 @param parent parent widget (QWidget) 57 @param parent parent widget (QWidget)
56 @param name name of this object (string) 58 @param name name of this object (string)
57 """ 59 """
58 VersionControl.__init__(self, parent, name) 60 VersionControl.__init__(self, parent, name)
59 self.defaultOptions = { 61 self.defaultOptions = {
60 'global': [''], 62 'global': [''],
61 'commit': [''], 63 'commit': [''],
62 'checkout': [''], 64 'checkout': [''],
63 'update': [''], 65 'update': [''],
64 'add': [''], 66 'add': [''],
65 'remove': [''], 67 'remove': [''],
66 'diff': [''], 68 'diff': [''],
67 'log': [''], 69 'log': [''],
68 'history': [''], 70 'history': [''],
69 'status': [''], 71 'status': [''],
70 'tag': [''], 72 'tag': [''],
71 'export': [''] 73 'export': ['']
72 } 74 }
73 75
74 self.__plugin = plugin 76 self.__plugin = plugin
75 self.__ui = parent 77 self.__ui = parent
76 78
93 else: 95 else:
94 self.adminDir = '.hg' 96 self.adminDir = '.hg'
95 97
96 self.log = None 98 self.log = None
97 self.logBrowser = None 99 self.logBrowser = None
100 self.logBrowserIncoming = None
101 self.logBrowserOutgoing = None
98 self.diff = None 102 self.diff = None
99 self.sbsDiff = None 103 self.sbsDiff = None
100 self.status = None 104 self.status = None
101 self.summary = None 105 self.summary = None
102 self.tagbranchList = None 106 self.tagbranchList = None
124 if os.path.exists(cfgFile): 128 if os.path.exists(cfgFile):
125 self.__iniWatcher.addPath(cfgFile) 129 self.__iniWatcher.addPath(cfgFile)
126 130
127 self.__client = None 131 self.__client = None
128 132
133 self.__repoDir = ""
134 self.__repoIniFile = ""
135 self.__defaultConfigured = False
136 self.__defaultPushConfigured = False
137
129 # instantiate the extensions 138 # instantiate the extensions
130 from .BookmarksExtension.bookmarks import Bookmarks 139 from .BookmarksExtension.bookmarks import Bookmarks
131 from .QueuesExtension.queues import Queues 140 from .QueuesExtension.queues import Queues
132 from .FetchExtension.fetch import Fetch 141 from .FetchExtension.fetch import Fetch
133 from .PurgeExtension.purge import Purge 142 from .PurgeExtension.purge import Purge
134 from .GpgExtension.gpg import Gpg 143 from .GpgExtension.gpg import Gpg
135 from .TransplantExtension.transplant import Transplant 144 from .TransplantExtension.transplant import Transplant
136 from .RebaseExtension.rebase import Rebase 145 from .RebaseExtension.rebase import Rebase
146 from .ShelveExtension.shelve import Shelve
147 from .LargefilesExtension.largefiles import Largefiles
137 self.__extensions = { 148 self.__extensions = {
138 "bookmarks": Bookmarks(self), 149 "bookmarks": Bookmarks(self),
139 "mq": Queues(self), 150 "mq": Queues(self),
140 "fetch": Fetch(self), 151 "fetch": Fetch(self),
141 "purge": Purge(self), 152 "purge": Purge(self),
142 "gpg": Gpg(self), 153 "gpg": Gpg(self),
143 "transplant": Transplant(self), 154 "transplant": Transplant(self),
144 "rebase": Rebase(self), 155 "rebase": Rebase(self),
156 "shelve": Shelve(self),
157 "largefiles": Largefiles(self)
145 } 158 }
146 159
147 def getPlugin(self): 160 def getPlugin(self):
148 """ 161 """
149 Public method to get a reference to the plugin object. 162 Public method to get a reference to the plugin object.
150 163
151 @return reference to the plugin object (VcsMercurialPlugin) 164 @return reference to the plugin object (VcsMercurialPlugin)
152 """ 165 """
153 return self.__plugin 166 return self.__plugin
167
168 def getEncoding(self):
169 """
170 Public method to get the encoding to be used by Mercurial.
171
172 @return encoding (string)
173 """
174 return self.__plugin.getPreferences("Encoding")
154 175
155 def vcsShutdown(self): 176 def vcsShutdown(self):
156 """ 177 """
157 Public method used to shutdown the Mercurial interface. 178 Public method used to shutdown the Mercurial interface.
158 """ 179 """
159 if self.log is not None: 180 if self.log is not None:
160 self.log.close() 181 self.log.close()
161 if self.logBrowser is not None: 182 if self.logBrowser is not None:
162 self.logBrowser.close() 183 self.logBrowser.close()
184 if self.logBrowserIncoming is not None:
185 self.logBrowserIncoming.close()
186 if self.logBrowserOutgoing is not None:
187 self.logBrowserOutgoing.close()
163 if self.diff is not None: 188 if self.diff is not None:
164 self.diff.close() 189 self.diff.close()
165 if self.sbsDiff is not None: 190 if self.sbsDiff is not None:
166 self.sbsDiff.close() 191 self.sbsDiff.close()
167 if self.status is not None: 192 if self.status is not None:
194 219
195 @return reference to the client (HgClient) 220 @return reference to the client (HgClient)
196 """ 221 """
197 return self.__client 222 return self.__client
198 223
224 def initCommand(self, command):
225 """
226 Public method to initialize a command arguments list.
227
228 @param command command name (string)
229 @return list of command options (list of string)
230 """
231 args = [command]
232 self.addArguments(args, self.__plugin.getGlobalOptions())
233 return args
234
199 def vcsExists(self): 235 def vcsExists(self):
200 """ 236 """
201 Public method used to test for the presence of the hg executable. 237 Public method used to test for the presence of the hg executable.
202 238
203 @return flag indicating the existance (boolean) and an error message 239 @return flag indicating the existance (boolean) and an error message
204 (string) 240 (string)
205 """ 241 """
206 self.versionStr = '' 242 self.versionStr = ''
207 errMsg = "" 243 errMsg = ""
208 ioEncoding = Preferences.getSystem("IOEncoding") 244
209 245 args = self.initCommand("version")
210 process = QProcess() 246 process = QProcess()
211 process.start('hg', ['version']) 247 process.start('hg', args)
212 procStarted = process.waitForStarted(5000) 248 procStarted = process.waitForStarted(5000)
213 if procStarted: 249 if procStarted:
214 finished = process.waitForFinished(30000) 250 finished = process.waitForFinished(30000)
215 if finished and process.exitCode() == 0: 251 if finished and process.exitCode() == 0:
216 output = \ 252 output = str(process.readAllStandardOutput(),
217 str(process.readAllStandardOutput(), ioEncoding, 'replace') 253 self.getEncoding(), 'replace')
218 self.versionStr = output.splitlines()[0].split()[-1][0:-1] 254 self.versionStr = output.splitlines()[0].split()[-1][0:-1]
219 v = list(re.match(r'.*?(\d+)\.(\d+)\.?(\d+)?(\+[0-9a-f-]+)?', 255 v = list(re.match(r'.*?(\d+)\.(\d+)\.?(\d+)?(\+[0-9a-f-]+)?',
220 self.versionStr).groups()) 256 self.versionStr).groups())
221 for i in range(3): 257 for i in range(3):
222 try: 258 try:
228 self.version = tuple(v) 264 self.version = tuple(v)
229 self.__getExtensionsInfo() 265 self.__getExtensionsInfo()
230 return True, errMsg 266 return True, errMsg
231 else: 267 else:
232 if finished: 268 if finished:
233 errMsg = self.trUtf8( 269 errMsg = self.tr(
234 "The hg process finished with the exit code {0}")\ 270 "The hg process finished with the exit code {0}")\
235 .format(process.exitCode()) 271 .format(process.exitCode())
236 else: 272 else:
237 errMsg = self.trUtf8( 273 errMsg = self.tr(
238 "The hg process did not finish within 30s.") 274 "The hg process did not finish within 30s.")
239 else: 275 else:
240 errMsg = self.trUtf8("Could not start the hg executable.") 276 errMsg = self.tr("Could not start the hg executable.")
241 277
242 return False, errMsg 278 return False, errMsg
243 279
244 def vcsInit(self, vcsDir, noDialog=False): 280 def vcsInit(self, vcsDir, noDialog=False):
245 """ 281 """
265 """ 301 """
266 success = self.vcsImport(vcsDataDict, project.ppath)[0] 302 success = self.vcsImport(vcsDataDict, project.ppath)[0]
267 if not success: 303 if not success:
268 E5MessageBox.critical( 304 E5MessageBox.critical(
269 self.__ui, 305 self.__ui,
270 self.trUtf8("Create project repository"), 306 self.tr("Create project repository"),
271 self.trUtf8( 307 self.tr(
272 """The project repository could not be created.""")) 308 """The project repository could not be created."""))
273 else: 309 else:
274 pfn = project.pfile 310 pfn = project.pfile
275 if not os.path.isfile(pfn): 311 if not os.path.isfile(pfn):
276 pfn += "z" 312 pfn += "z"
289 """ 325 """
290 msg = vcsDataDict["message"] 326 msg = vcsDataDict["message"]
291 if not msg: 327 if not msg:
292 msg = '***' 328 msg = '***'
293 329
294 args = [] 330 args = self.initCommand("init")
295 args.append('init')
296 args.append(projectDir) 331 args.append(projectDir)
297 # init is not possible with the command server 332 # init is not possible with the command server
298 dia = HgDialog(self.trUtf8('Creating Mercurial repository'), self) 333 dia = HgDialog(self.tr('Creating Mercurial repository'), self)
299 res = dia.startProcess(args) 334 res = dia.startProcess(args)
300 if res: 335 if res:
301 dia.exec_() 336 dia.exec_()
302 status = dia.normalExit() 337 status = dia.normalExit()
303 338
305 ignoreName = os.path.join(projectDir, Hg.IgnoreFileName) 340 ignoreName = os.path.join(projectDir, Hg.IgnoreFileName)
306 if not os.path.exists(ignoreName): 341 if not os.path.exists(ignoreName):
307 status = self.hgCreateIgnoreFile(projectDir) 342 status = self.hgCreateIgnoreFile(projectDir)
308 343
309 if status: 344 if status:
310 args = [] 345 args = self.initCommand("commit")
311 args.append('commit')
312 args.append('--addremove') 346 args.append('--addremove')
313 args.append('--message') 347 args.append('--message')
314 args.append(msg) 348 args.append(msg)
315 dia = HgDialog( 349 dia = HgDialog(
316 self.trUtf8('Initial commit to Mercurial repository'), 350 self.tr('Initial commit to Mercurial repository'),
317 self) 351 self)
318 res = dia.startProcess(args, projectDir) 352 res = dia.startProcess(args, projectDir)
319 if res: 353 if res:
320 dia.exec_() 354 dia.exec_()
321 status = dia.normalExit() 355 status = dia.normalExit()
341 if vcsUrl.startswith('/'): 375 if vcsUrl.startswith('/'):
342 vcsUrl = 'file://{0}'.format(vcsUrl) 376 vcsUrl = 'file://{0}'.format(vcsUrl)
343 elif vcsUrl[1] in ['|', ':']: 377 elif vcsUrl[1] in ['|', ':']:
344 vcsUrl = 'file:///{0}'.format(vcsUrl) 378 vcsUrl = 'file:///{0}'.format(vcsUrl)
345 379
346 args = [] 380 args = self.initCommand("clone")
347 args.append('clone')
348 self.addArguments(args, self.options['global'])
349 self.addArguments(args, self.options['checkout'])
350 if rev: 381 if rev:
351 args.append("--rev") 382 args.append("--rev")
352 args.append(rev) 383 args.append(rev)
384 if vcsDataDict["largefiles"]:
385 args.append("--all-largefiles")
353 args.append(self.__hgURL(vcsUrl)) 386 args.append(self.__hgURL(vcsUrl))
354 args.append(projectDir) 387 args.append(projectDir)
355 388
356 if noDialog: 389 if noDialog:
357 if self.__client is None: 390 if self.__client is None:
359 else: 392 else:
360 out, err = self.__client.runcommand(args) 393 out, err = self.__client.runcommand(args)
361 return err == "" 394 return err == ""
362 else: 395 else:
363 dia = HgDialog( 396 dia = HgDialog(
364 self.trUtf8('Cloning project from a Mercurial repository'), 397 self.tr('Cloning project from a Mercurial repository'),
365 self) 398 self)
366 res = dia.startProcess(args) 399 res = dia.startProcess(args)
367 if res: 400 if res:
368 dia.exec_() 401 dia.exec_()
369 return dia.normalExit() 402 return dia.normalExit()
376 @param projectDir project directory to create (string) 409 @param projectDir project directory to create (string)
377 @return flag indicating an execution without errors (boolean) 410 @return flag indicating an execution without errors (boolean)
378 """ 411 """
379 status = self.vcsCheckout(vcsDataDict, projectDir) 412 status = self.vcsCheckout(vcsDataDict, projectDir)
380 shutil.rmtree(os.path.join(projectDir, self.adminDir), True) 413 shutil.rmtree(os.path.join(projectDir, self.adminDir), True)
381 if os.path.exists(os.path.join(projectDir, '.hgignore')): 414 if os.path.exists(os.path.join(projectDir, Hg.IgnoreFileName)):
382 os.remove(os.path.join(projectDir, '.hgignore')) 415 os.remove(os.path.join(projectDir, Hg.IgnoreFileName))
383 return status 416 return status
384 417
385 def vcsCommit(self, name, message, noDialog=False, closeBranch=False, 418 def vcsCommit(self, name, message, noDialog=False, closeBranch=False,
386 mq=False): 419 mq=False):
387 """ 420 """
399 432
400 if mq: 433 if mq:
401 # ensure dialog is shown for a queue commit 434 # ensure dialog is shown for a queue commit
402 noDialog = False 435 noDialog = False
403 436
404 if not noDialog and not msg: 437 if not noDialog:
405 # call CommitDialog and get message from there 438 # call CommitDialog and get message from there
406 if self.__commitDialog is None: 439 if self.__commitDialog is None:
407 from .HgCommitDialog import HgCommitDialog 440 from .HgCommitDialog import HgCommitDialog
408 self.__commitDialog = HgCommitDialog(self, mq, self.__ui) 441 self.__commitDialog = HgCommitDialog(self, msg, mq, self.__ui)
409 self.__commitDialog.accepted.connect(self.__vcsCommit_Step2) 442 self.__commitDialog.accepted.connect(self.__vcsCommit_Step2)
410 self.__commitDialog.show() 443 self.__commitDialog.show()
411 self.__commitDialog.raise_() 444 self.__commitDialog.raise_()
412 self.__commitDialog.activateWindow() 445 self.__commitDialog.activateWindow()
413 446
456 break 489 break
457 490
458 if not ok: 491 if not ok:
459 res = E5MessageBox.yesNo( 492 res = E5MessageBox.yesNo(
460 self.__ui, 493 self.__ui,
461 self.trUtf8("Commit Changes"), 494 self.tr("Commit Changes"),
462 self.trUtf8( 495 self.tr(
463 """The commit affects files, that have unsaved""" 496 """The commit affects files, that have unsaved"""
464 """ changes. Shall the commit be continued?"""), 497 """ changes. Shall the commit be continued?"""),
465 icon=E5MessageBox.Warning) 498 icon=E5MessageBox.Warning)
466 if not res: 499 if not res:
467 return 500 return
477 commitSubrepositories = False 510 commitSubrepositories = False
478 511
479 if not msg and not amend: 512 if not msg and not amend:
480 msg = '***' 513 msg = '***'
481 514
482 args = [] 515 args = self.initCommand("commit")
483 args.append('commit')
484 self.addArguments(args, self.options['global'])
485 self.addArguments(args, self.options['commit'])
486 args.append("-v") 516 args.append("-v")
487 if mq: 517 if mq:
488 args.append("--mq") 518 args.append("--mq")
489 else: 519 else:
490 if closeBranch: 520 if closeBranch:
523 553
524 if noDialog: 554 if noDialog:
525 self.startSynchronizedProcess(QProcess(), "hg", args, dname) 555 self.startSynchronizedProcess(QProcess(), "hg", args, dname)
526 else: 556 else:
527 dia = HgDialog( 557 dia = HgDialog(
528 self.trUtf8('Committing changes to Mercurial repository'), 558 self.tr('Committing changes to Mercurial repository'),
529 self) 559 self)
530 res = dia.startProcess(args, dname) 560 res = dia.startProcess(args, dname)
531 if res: 561 if res:
532 dia.exec_() 562 dia.exec_()
533 self.committed.emit() 563 self.committed.emit()
548 @param noDialog flag indicating quiet operations (boolean) 578 @param noDialog flag indicating quiet operations (boolean)
549 @keyparam revision revision to update to (string) 579 @keyparam revision revision to update to (string)
550 @return flag indicating, that the update contained an add 580 @return flag indicating, that the update contained an add
551 or delete (boolean) 581 or delete (boolean)
552 """ 582 """
553 args = [] 583 args = self.initCommand("update")
554 args.append('update')
555 self.addArguments(args, self.options['global'])
556 self.addArguments(args, self.options['update'])
557 if "-v" not in args and "--verbose" not in args: 584 if "-v" not in args and "--verbose" not in args:
558 args.append("-v") 585 args.append("-v")
559 if revision is not None: 586 if revision:
560 args.append("-r") 587 args.append("-r")
561 args.append(revision) 588 args.append(revision)
562 589
563 if isinstance(name, list): 590 if isinstance(name, list):
564 dname, fnames = self.splitPathList(name) 591 dname, fnames = self.splitPathList(name)
577 self.startSynchronizedProcess(QProcess(), 'hg', args, repodir) 604 self.startSynchronizedProcess(QProcess(), 'hg', args, repodir)
578 else: 605 else:
579 out, err = self.__client.runcommand(args) 606 out, err = self.__client.runcommand(args)
580 res = False 607 res = False
581 else: 608 else:
582 dia = HgDialog(self.trUtf8( 609 dia = HgDialog(self.tr(
583 'Synchronizing with the Mercurial repository'), 610 'Synchronizing with the Mercurial repository'),
584 self) 611 self)
585 res = dia.startProcess(args, repodir) 612 res = dia.startProcess(args, repodir)
586 if res: 613 if res:
587 dia.exec_() 614 dia.exec_()
595 622
596 @param name file/directory name to be added (string) 623 @param name file/directory name to be added (string)
597 @param isDir flag indicating name is a directory (boolean) 624 @param isDir flag indicating name is a directory (boolean)
598 @param noDialog flag indicating quiet operations 625 @param noDialog flag indicating quiet operations
599 """ 626 """
600 args = [] 627 args = self.initCommand("add")
601 args.append('add')
602 self.addArguments(args, self.options['global'])
603 self.addArguments(args, self.options['add'])
604 args.append("-v") 628 args.append("-v")
605 629
606 if isinstance(name, list): 630 if isinstance(name, list):
607 if isDir: 631 if isDir:
608 dname, fname = os.path.split(name[0]) 632 dname, fname = os.path.split(name[0])
631 self.startSynchronizedProcess(QProcess(), 'hg', args, repodir) 655 self.startSynchronizedProcess(QProcess(), 'hg', args, repodir)
632 else: 656 else:
633 out, err = self.__client.runcommand(args) 657 out, err = self.__client.runcommand(args)
634 else: 658 else:
635 dia = HgDialog( 659 dia = HgDialog(
636 self.trUtf8( 660 self.tr(
637 'Adding files/directories to the Mercurial repository'), 661 'Adding files/directories to the Mercurial repository'),
638 self) 662 self)
639 res = dia.startProcess(args, repodir) 663 res = dia.startProcess(args, repodir)
640 if res: 664 if res:
641 dia.exec_() 665 dia.exec_()
672 @param project flag indicating deletion of a project tree (boolean) 696 @param project flag indicating deletion of a project tree (boolean)
673 (not needed) 697 (not needed)
674 @param noDialog flag indicating quiet operations 698 @param noDialog flag indicating quiet operations
675 @return flag indicating successfull operation (boolean) 699 @return flag indicating successfull operation (boolean)
676 """ 700 """
677 args = [] 701 args = self.initCommand("remove")
678 args.append('remove')
679 self.addArguments(args, self.options['global'])
680 self.addArguments(args, self.options['remove'])
681 args.append("-v") 702 args.append("-v")
682 if noDialog and '--force' not in args: 703 if noDialog and '--force' not in args:
683 args.append('--force') 704 args.append('--force')
684 705
685 if isinstance(name, list): 706 if isinstance(name, list):
703 else: 724 else:
704 out, err = self.__client.runcommand(args) 725 out, err = self.__client.runcommand(args)
705 res = err == "" 726 res = err == ""
706 else: 727 else:
707 dia = HgDialog( 728 dia = HgDialog(
708 self.trUtf8( 729 self.tr(
709 'Removing files/directories from the Mercurial' 730 'Removing files/directories from the Mercurial'
710 ' repository'), 731 ' repository'),
711 self) 732 self)
712 res = dia.startProcess(args, repodir) 733 res = dia.startProcess(args, repodir)
713 if res: 734 if res:
725 @param target new name of the file/directory (string) 746 @param target new name of the file/directory (string)
726 @param noDialog flag indicating quiet operations 747 @param noDialog flag indicating quiet operations
727 @return flag indicating successfull operation (boolean) 748 @return flag indicating successfull operation (boolean)
728 """ 749 """
729 isDir = os.path.isdir(name) 750 isDir = os.path.isdir(name)
730 opts = self.options['global'][:]
731 force = '--force' in opts
732 if force:
733 opts.remove('--force')
734 751
735 res = False 752 res = False
736 if noDialog: 753 if noDialog:
737 if target is None: 754 if target is None:
738 return False 755 return False
739 force = True 756 force = True
740 accepted = True 757 accepted = True
741 else: 758 else:
742 from .HgCopyDialog import HgCopyDialog 759 from .HgCopyDialog import HgCopyDialog
743 dlg = HgCopyDialog(name, None, True, force) 760 dlg = HgCopyDialog(name, None, True)
744 accepted = dlg.exec_() == QDialog.Accepted 761 accepted = dlg.exec_() == QDialog.Accepted
745 if accepted: 762 if accepted:
746 target, force = dlg.getData() 763 target, force = dlg.getData()
747 764
748 if accepted: 765 if accepted:
749 args = [] 766 args = self.initCommand("rename")
750 args.append('rename')
751 self.addArguments(args, opts)
752 args.append("-v") 767 args.append("-v")
753 if force: 768 if force:
754 args.append('--force') 769 args.append('--force')
755 args.append(name) 770 args.append(name)
756 args.append(target) 771 args.append(target)
769 QProcess(), 'hg', args, repodir) 784 QProcess(), 'hg', args, repodir)
770 else: 785 else:
771 out, err = self.__client.runcommand(args) 786 out, err = self.__client.runcommand(args)
772 res = err == "" 787 res = err == ""
773 else: 788 else:
774 dia = HgDialog(self.trUtf8('Renaming {0}').format(name), self) 789 dia = HgDialog(self.tr('Renaming {0}').format(name), self)
775 res = dia.startProcess(args, repodir) 790 res = dia.startProcess(args, repodir)
776 if res: 791 if res:
777 dia.exec_() 792 dia.exec_()
778 res = dia.normalExit() 793 res = dia.normalExit()
779 if res: 794 if res:
871 from .HgStatusDialog import HgStatusDialog 886 from .HgStatusDialog import HgStatusDialog
872 self.status = HgStatusDialog(self) 887 self.status = HgStatusDialog(self)
873 self.status.show() 888 self.status.show()
874 self.status.start(name) 889 self.status.start(name)
875 890
876 def hgSummary(self, mq=False): 891 def hgSummary(self, mq=False, largefiles=False):
877 """ 892 """
878 Public method used to show some summary information of the 893 Public method used to show some summary information of the
879 working directory state. 894 working directory state.
880 895
881 @param mq flag indicating to show the queue status as well (boolean) 896 @param mq flag indicating to show the queue status as well (boolean)
897 @param largefiles flag indicating to show the largefiles status as
898 well (boolean)
882 """ 899 """
883 from .HgSummaryDialog import HgSummaryDialog 900 from .HgSummaryDialog import HgSummaryDialog
884 self.summary = HgSummaryDialog(self) 901 self.summary = HgSummaryDialog(self)
885 self.summary.show() 902 self.summary.show()
886 self.summary.start(self.__projectHelper.getProject().getProjectPath(), 903 self.summary.start(self.__projectHelper.getProject().getProjectPath(),
887 mq=mq) 904 mq=mq, largefiles=largefiles)
888 905
889 def vcsTag(self, name): 906 def vcsTag(self, name, revision=None, tagName=None):
890 """ 907 """
891 Public method used to set the tag in the Mercurial repository. 908 Public method used to set/remove a tag in the Mercurial repository.
892 909
893 @param name file/directory name to be tagged (string) 910 @param name file/directory name to determine the repo root from
911 (string)
912 @param revision revision to set tag for (string)
913 @param tagName name of the tag (string)
914 @return flag indicating a performed tag action (boolean)
894 """ 915 """
895 dname, fname = self.splitPath(name) 916 dname, fname = self.splitPath(name)
896 917
897 # find the root of the repo 918 # find the root of the repo
898 repodir = dname 919 repodir = dname
900 repodir = os.path.dirname(repodir) 921 repodir = os.path.dirname(repodir)
901 if os.path.splitdrive(repodir)[1] == os.sep: 922 if os.path.splitdrive(repodir)[1] == os.sep:
902 return 923 return
903 924
904 from .HgTagDialog import HgTagDialog 925 from .HgTagDialog import HgTagDialog
905 dlg = HgTagDialog(self.hgGetTagsList(repodir)) 926 dlg = HgTagDialog(self.hgGetTagsList(repodir, withType=True),
927 revision, tagName)
906 if dlg.exec_() == QDialog.Accepted: 928 if dlg.exec_() == QDialog.Accepted:
907 tag, tagOp = dlg.getParameters() 929 tag, revision, tagOp = dlg.getParameters()
908 else: 930 else:
909 return 931 return False
910 932
911 args = [] 933 args = self.initCommand("tag")
912 args.append('tag') 934 msgPart = ""
913 if tagOp == HgTagDialog.CreateLocalTag: 935 if tagOp in [HgTagDialog.CreateLocalTag, HgTagDialog.DeleteLocalTag]:
914 args.append('--local') 936 args.append('--local')
915 elif tagOp == HgTagDialog.DeleteTag: 937 msgPart = "local "
938 else:
939 msgPart = "global "
940 if tagOp in [HgTagDialog.DeleteGlobalTag, HgTagDialog.DeleteLocalTag]:
916 args.append('--remove') 941 args.append('--remove')
942 if tagOp in [HgTagDialog.CreateGlobalTag, HgTagDialog.CreateLocalTag]:
943 if revision:
944 args.append("--rev")
945 args.append(revision)
917 args.append('--message') 946 args.append('--message')
918 if tagOp != HgTagDialog.DeleteTag: 947 if tagOp in [HgTagDialog.CreateGlobalTag, HgTagDialog.CreateLocalTag]:
919 tag = tag.strip().replace(" ", "_") 948 tag = tag.strip().replace(" ", "_")
920 args.append("Created tag <{0}>.".format(tag)) 949 args.append("Created {1}tag <{0}>.".format(tag, msgPart))
921 else: 950 else:
922 args.append("Removed tag <{0}>.".format(tag)) 951 args.append("Removed {1}tag <{0}>.".format(tag, msgPart))
923 args.append(tag) 952 args.append(tag)
924 953
925 dia = HgDialog(self.trUtf8('Taging in the Mercurial repository'), self) 954 dia = HgDialog(self.tr('Tagging in the Mercurial repository'),
955 self)
926 res = dia.startProcess(args, repodir) 956 res = dia.startProcess(args, repodir)
927 if res: 957 if res:
928 dia.exec_() 958 dia.exec_()
959
960 return True
929 961
930 def hgRevert(self, name): 962 def hgRevert(self, name):
931 """ 963 """
932 Public method used to revert changes made to a file/directory. 964 Public method used to revert changes made to a file/directory.
933 965
934 @param name file/directory name to be reverted (string) 966 @param name file/directory name to be reverted (string)
935 @return flag indicating, that the update contained an add 967 @return flag indicating, that the update contained an add
936 or delete (boolean) 968 or delete (boolean)
937 """ 969 """
938 args = [] 970 args = self.initCommand("revert")
939 args.append('revert')
940 self.addArguments(args, self.options['global'])
941 if not self.getPlugin().getPreferences("CreateBackup"): 971 if not self.getPlugin().getPreferences("CreateBackup"):
942 args.append("--no-backup") 972 args.append("--no-backup")
943 args.append("-v") 973 args.append("-v")
944 if isinstance(name, list): 974 if isinstance(name, list):
945 dname, fnames = self.splitPathList(name) 975 dname, fnames = self.splitPathList(name)
962 if names[0]: 992 if names[0]:
963 from UI.DeleteFilesConfirmationDialog import \ 993 from UI.DeleteFilesConfirmationDialog import \
964 DeleteFilesConfirmationDialog 994 DeleteFilesConfirmationDialog
965 dlg = DeleteFilesConfirmationDialog( 995 dlg = DeleteFilesConfirmationDialog(
966 self.parent(), 996 self.parent(),
967 self.trUtf8("Revert changes"), 997 self.tr("Revert changes"),
968 self.trUtf8( 998 self.tr(
969 "Do you really want to revert all changes to these files" 999 "Do you really want to revert all changes to these files"
970 " or directories?"), 1000 " or directories?"),
971 names) 1001 names)
972 yes = dlg.exec_() == QDialog.Accepted 1002 yes = dlg.exec_() == QDialog.Accepted
973 else: 1003 else:
974 yes = E5MessageBox.yesNo( 1004 yes = E5MessageBox.yesNo(
975 None, 1005 None,
976 self.trUtf8("Revert changes"), 1006 self.tr("Revert changes"),
977 self.trUtf8("""Do you really want to revert all changes of""" 1007 self.tr("""Do you really want to revert all changes of"""
978 """ the project?""")) 1008 """ the project?"""))
979 if yes: 1009 if yes:
980 dia = HgDialog(self.trUtf8('Reverting changes'), self) 1010 dia = HgDialog(self.tr('Reverting changes'), self)
981 res = dia.startProcess(args, repodir) 1011 res = dia.startProcess(args, repodir)
982 if res: 1012 if res:
983 dia.exec_() 1013 dia.exec_()
984 res = dia.hasAddOrDelete() 1014 res = dia.hasAddOrDelete()
985 self.checkVCSStatus() 1015 self.checkVCSStatus()
1001 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 1031 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
1002 repodir = os.path.dirname(repodir) 1032 repodir = os.path.dirname(repodir)
1003 if os.path.splitdrive(repodir)[1] == os.sep: 1033 if os.path.splitdrive(repodir)[1] == os.sep:
1004 return 1034 return
1005 1035
1006 opts = self.options['global'][:]
1007 force = '--force' in opts
1008 if force:
1009 del opts[opts.index('--force')]
1010
1011 if self.isExtensionActive("bookmarks"): 1036 if self.isExtensionActive("bookmarks"):
1012 bookmarksList = \ 1037 bookmarksList = \
1013 self.getExtensionObject("bookmarks")\ 1038 self.getExtensionObject("bookmarks")\
1014 .hgGetBookmarksList(repodir) 1039 .hgGetBookmarksList(repodir)
1015 else: 1040 else:
1016 bookmarksList = None 1041 bookmarksList = None
1017 from .HgMergeDialog import HgMergeDialog 1042 from .HgMergeDialog import HgMergeDialog
1018 dlg = HgMergeDialog(force, self.hgGetTagsList(repodir), 1043 dlg = HgMergeDialog(self.hgGetTagsList(repodir),
1019 self.hgGetBranchesList(repodir), 1044 self.hgGetBranchesList(repodir),
1020 bookmarksList) 1045 bookmarksList)
1021 if dlg.exec_() == QDialog.Accepted: 1046 if dlg.exec_() == QDialog.Accepted:
1022 rev, force = dlg.getParameters() 1047 rev, force = dlg.getParameters()
1023 else: 1048 else:
1024 return 1049 return
1025 1050
1026 args = [] 1051 args = self.initCommand("merge")
1027 args.append('merge')
1028 self.addArguments(args, opts)
1029 if force: 1052 if force:
1030 args.append("--force") 1053 args.append("--force")
1054 if self.getPlugin().getPreferences("InternalMerge"):
1055 args.append("--tool")
1056 args.append("internal:merge")
1031 if rev: 1057 if rev:
1032 args.append("--rev") 1058 args.append("--rev")
1033 args.append(rev) 1059 args.append(rev)
1034 1060
1035 dia = HgDialog(self.trUtf8('Merging').format(name), self) 1061 dia = HgDialog(self.tr('Merging').format(name), self)
1036 res = dia.startProcess(args, repodir) 1062 res = dia.startProcess(args, repodir)
1037 if res: 1063 if res:
1038 dia.exec_() 1064 dia.exec_()
1039 self.checkVCSStatus() 1065 self.checkVCSStatus()
1040 1066
1063 else: 1089 else:
1064 bookmarksList = None 1090 bookmarksList = None
1065 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog 1091 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog
1066 dlg = HgRevisionSelectionDialog(self.hgGetTagsList(repodir), 1092 dlg = HgRevisionSelectionDialog(self.hgGetTagsList(repodir),
1067 self.hgGetBranchesList(repodir), 1093 self.hgGetBranchesList(repodir),
1068 bookmarksList) 1094 bookmarksList,
1095 self.tr("Current branch tip"))
1069 if dlg.exec_() == QDialog.Accepted: 1096 if dlg.exec_() == QDialog.Accepted:
1070 rev = dlg.getRevision() 1097 rev = dlg.getRevision()
1071 return self.vcsUpdate(name, revision=rev) 1098 return self.vcsUpdate(name, revision=rev)
1072 1099
1073 return False 1100 return False
1095 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 1122 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
1096 repodir = os.path.dirname(repodir) 1123 repodir = os.path.dirname(repodir)
1097 if os.path.splitdrive(repodir)[1] == os.sep: 1124 if os.path.splitdrive(repodir)[1] == os.sep:
1098 return 0 1125 return 0
1099 1126
1100 args = [] 1127 args = self.initCommand("status")
1101 args.append('status')
1102 args.append('--all') 1128 args.append('--all')
1103 args.append('--noninteractive') 1129 args.append('--noninteractive')
1104 1130
1105 output = "" 1131 output = ""
1106 if self.__client is None: 1132 if self.__client is None:
1109 process.start('hg', args) 1135 process.start('hg', args)
1110 procStarted = process.waitForStarted(5000) 1136 procStarted = process.waitForStarted(5000)
1111 if procStarted: 1137 if procStarted:
1112 finished = process.waitForFinished(30000) 1138 finished = process.waitForFinished(30000)
1113 if finished and process.exitCode() == 0: 1139 if finished and process.exitCode() == 0:
1114 output = \ 1140 output = str(process.readAllStandardOutput(),
1115 str(process.readAllStandardOutput(), 1141 self.getEncoding(), 'replace')
1116 Preferences.getSystem("IOEncoding"),
1117 'replace')
1118 else: 1142 else:
1119 output, error = self.__client.runcommand(args) 1143 output, error = self.__client.runcommand(args)
1120 1144
1121 if output: 1145 if output:
1122 for line in output.splitlines(): 1146 for line in output.splitlines():
1165 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 1189 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
1166 repodir = os.path.dirname(repodir) 1190 repodir = os.path.dirname(repodir)
1167 if os.path.splitdrive(repodir)[1] == os.sep: 1191 if os.path.splitdrive(repodir)[1] == os.sep:
1168 return names 1192 return names
1169 1193
1170 args = [] 1194 args = self.initCommand("status")
1171 args.append('status')
1172 args.append('--all') 1195 args.append('--all')
1173 args.append('--noninteractive') 1196 args.append('--noninteractive')
1174 1197
1175 output = "" 1198 output = ""
1176 if self.__client is None: 1199 if self.__client is None:
1179 process.start('hg', args) 1202 process.start('hg', args)
1180 procStarted = process.waitForStarted(5000) 1203 procStarted = process.waitForStarted(5000)
1181 if procStarted: 1204 if procStarted:
1182 finished = process.waitForFinished(30000) 1205 finished = process.waitForFinished(30000)
1183 if finished and process.exitCode() == 0: 1206 if finished and process.exitCode() == 0:
1184 output = str( 1207 output = str(process.readAllStandardOutput(),
1185 process.readAllStandardOutput(), 1208 self.getEncoding(), 'replace')
1186 Preferences.getSystem("IOEncoding"),
1187 'replace')
1188 else: 1209 else:
1189 output, error = self.__client.runcommand(args) 1210 output, error = self.__client.runcommand(args)
1190 1211
1191 if output: 1212 if output:
1192 dirs = [x for x in names.keys() if os.path.isdir(x)] 1213 dirs = [x for x in names.keys() if os.path.isdir(x)]
1288 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 1309 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
1289 repodir = os.path.dirname(repodir) 1310 repodir = os.path.dirname(repodir)
1290 if os.path.splitdrive(repodir)[1] == os.sep: 1311 if os.path.splitdrive(repodir)[1] == os.sep:
1291 return 1312 return
1292 1313
1293 dia = HgDialog(self.trUtf8('Mercurial command'), self) 1314 dia = HgDialog(self.tr('Mercurial command'), self)
1294 res = dia.startProcess(args, repodir) 1315 res = dia.startProcess(args, repodir)
1295 if res: 1316 if res:
1296 dia.exec_() 1317 dia.exec_()
1297 1318
1298 def vcsOptionsDialog(self, project, archive, editable=False, parent=None): 1319 def vcsOptionsDialog(self, project, archive, editable=False, parent=None):
1326 Public method to retrieve information about the repository. 1347 Public method to retrieve information about the repository.
1327 1348
1328 @param ppath local path to get the repository infos (string) 1349 @param ppath local path to get the repository infos (string)
1329 @return string with ready formated info for display (string) 1350 @return string with ready formated info for display (string)
1330 """ 1351 """
1331 args = [] 1352 args = self.initCommand("parents")
1332 args.append('parents')
1333 args.append('--template') 1353 args.append('--template')
1334 args.append('{rev}:{node|short}@@@{tags}@@@{author|xmlescape}@@@' 1354 args.append('{rev}:{node|short}@@@{tags}@@@{author|xmlescape}@@@'
1335 '{date|isodate}@@@{branches}@@@{bookmarks}\n') 1355 '{date|isodate}@@@{branches}@@@{bookmarks}\n')
1336 1356
1337 output = "" 1357 output = ""
1341 process.start('hg', args) 1361 process.start('hg', args)
1342 procStarted = process.waitForStarted(5000) 1362 procStarted = process.waitForStarted(5000)
1343 if procStarted: 1363 if procStarted:
1344 finished = process.waitForFinished(30000) 1364 finished = process.waitForFinished(30000)
1345 if finished and process.exitCode() == 0: 1365 if finished and process.exitCode() == 0:
1346 output = str( 1366 output = str(process.readAllStandardOutput(),
1347 process.readAllStandardOutput(), 1367 self.getEncoding(), 'replace')
1348 Preferences.getSystem("IOEncoding"), 'replace')
1349 else: 1368 else:
1350 output, error = self.__client.runcommand(args) 1369 output, error = self.__client.runcommand(args)
1351 1370
1352 infoBlock = [] 1371 infoBlock = []
1353 if output: 1372 if output:
1389 infoStr = """<tr></tr>{0}""".format("<tr></tr>".join(infoBlock)) 1408 infoStr = """<tr></tr>{0}""".format("<tr></tr>".join(infoBlock))
1390 else: 1409 else:
1391 infoStr = "" 1410 infoStr = ""
1392 1411
1393 url = "" 1412 url = ""
1394 args = [] 1413 args = self.initCommand("showconfig")
1395 args.append('showconfig')
1396 args.append('paths.default') 1414 args.append('paths.default')
1397 1415
1398 output = "" 1416 output = ""
1399 if self.__client is None: 1417 if self.__client is None:
1400 process.setWorkingDirectory(ppath) 1418 process.setWorkingDirectory(ppath)
1401 process.start('hg', args) 1419 process.start('hg', args)
1402 procStarted = process.waitForStarted(5000) 1420 procStarted = process.waitForStarted(5000)
1403 if procStarted: 1421 if procStarted:
1404 finished = process.waitForFinished(30000) 1422 finished = process.waitForFinished(30000)
1405 if finished and process.exitCode() == 0: 1423 if finished and process.exitCode() == 0:
1406 output = str( 1424 output = str(process.readAllStandardOutput(),
1407 process.readAllStandardOutput(), 1425 self.getEncoding(), 'replace')
1408 Preferences.getSystem("IOEncoding"), 'replace')
1409 else: 1426 else:
1410 output, error = self.__client.runcommand(args) 1427 output, error = self.__client.runcommand(args)
1411 1428
1412 if output: 1429 if output:
1413 url = output.splitlines()[0].strip() 1430 url = output.splitlines()[0].strip()
1422 """<tr></tr>\n""" 1439 """<tr></tr>\n"""
1423 """<tr><td><b>URL</b></td><td>{1}</td></tr>\n""" 1440 """<tr><td><b>URL</b></td><td>{1}</td></tr>\n"""
1424 """{2}""" 1441 """{2}"""
1425 """</table></p>\n""" 1442 """</table></p>\n"""
1426 ).format(self.versionStr, url, infoStr) 1443 ).format(self.versionStr, url, infoStr)
1427 1444
1445 def vcsSupportCommandOptions(self):
1446 """
1447 Public method to signal the support of user settable command options.
1448
1449 @return flag indicating the support of user settable command options
1450 (boolean)
1451 """
1452 return False
1453
1428 ########################################################################### 1454 ###########################################################################
1429 ## Private Mercurial specific methods are below. 1455 ## Private Mercurial specific methods are below.
1430 ########################################################################### 1456 ###########################################################################
1431 1457
1432 def __hgURL(self, url): 1458 def __hgURL(self, url):
1485 dlg = HgCopyDialog(name) 1511 dlg = HgCopyDialog(name)
1486 res = False 1512 res = False
1487 if dlg.exec_() == QDialog.Accepted: 1513 if dlg.exec_() == QDialog.Accepted:
1488 target, force = dlg.getData() 1514 target, force = dlg.getData()
1489 1515
1490 args = [] 1516 args = self.initCommand("copy")
1491 args.append('copy')
1492 self.addArguments(args, self.options['global'])
1493 args.append("-v") 1517 args.append("-v")
1494 args.append(name) 1518 args.append(name)
1495 args.append(target) 1519 args.append(target)
1496 1520
1497 dname, fname = self.splitPath(name) 1521 dname, fname = self.splitPath(name)
1501 repodir = os.path.dirname(repodir) 1525 repodir = os.path.dirname(repodir)
1502 if os.path.splitdrive(repodir)[1] == os.sep: 1526 if os.path.splitdrive(repodir)[1] == os.sep:
1503 return False 1527 return False
1504 1528
1505 dia = HgDialog( 1529 dia = HgDialog(
1506 self.trUtf8('Copying {0}').format(name), self) 1530 self.tr('Copying {0}').format(name), self)
1507 res = dia.startProcess(args, repodir) 1531 res = dia.startProcess(args, repodir)
1508 if res: 1532 if res:
1509 dia.exec_() 1533 dia.exec_()
1510 res = dia.normalExit() 1534 res = dia.normalExit()
1511 if res and \ 1535 if res and \
1514 project.copyDirectory(name, target) 1538 project.copyDirectory(name, target)
1515 else: 1539 else:
1516 project.appendFile(target) 1540 project.appendFile(target)
1517 return res 1541 return res
1518 1542
1519 def hgGetTagsList(self, repodir): 1543 def hgGetTagsList(self, repodir, withType=False):
1520 """ 1544 """
1521 Public method to get the list of tags. 1545 Public method to get the list of tags.
1522 1546
1523 @param repodir directory name of the repository (string) 1547 @param repodir directory name of the repository (string)
1524 @return list of tags (list of string) 1548 @param withType flag indicating to get the tag type as well (boolean)
1525 """ 1549 @return list of tags (list of string) or list of tuples of
1526 args = [] 1550 tag name and flag indicating a local tag (list of tuple of string
1527 args.append('tags') 1551 and boolean), if withType is True
1552 """
1553 args = self.initCommand("tags")
1528 args.append('--verbose') 1554 args.append('--verbose')
1529 1555
1530 output = "" 1556 output = ""
1531 if self.__client is None: 1557 if self.__client is None:
1532 process = QProcess() 1558 process = QProcess()
1534 process.start('hg', args) 1560 process.start('hg', args)
1535 procStarted = process.waitForStarted(5000) 1561 procStarted = process.waitForStarted(5000)
1536 if procStarted: 1562 if procStarted:
1537 finished = process.waitForFinished(30000) 1563 finished = process.waitForFinished(30000)
1538 if finished and process.exitCode() == 0: 1564 if finished and process.exitCode() == 0:
1539 output = \ 1565 output = str(process.readAllStandardOutput(),
1540 str(process.readAllStandardOutput(), 1566 self.getEncoding(), 'replace')
1541 Preferences.getSystem("IOEncoding"),
1542 'replace')
1543 else: 1567 else:
1544 output, error = self.__client.runcommand(args) 1568 output, error = self.__client.runcommand(args)
1545 1569
1570 tagsList = []
1546 if output: 1571 if output:
1547 self.tagsList = []
1548 for line in output.splitlines(): 1572 for line in output.splitlines():
1549 li = line.strip().split() 1573 li = line.strip().split()
1550 if li[-1][0] in "1234567890": 1574 if li[-1][0] in "1234567890":
1551 # last element is a rev:changeset 1575 # last element is a rev:changeset
1552 del li[-1] 1576 del li[-1]
1577 isLocal = False
1553 else: 1578 else:
1554 del li[-2:] 1579 del li[-2:]
1580 isLocal = True
1555 name = " ".join(li) 1581 name = " ".join(li)
1556 if name not in ["tip", "default"]: 1582 if name not in ["tip", "default"]:
1557 self.tagsList.append(name) 1583 if withType:
1558 1584 tagsList.append((name, isLocal))
1559 return self.tagsList[:] 1585 else:
1586 tagsList.append(name)
1587
1588 if withType:
1589 return tagsList
1590 else:
1591 if tagsList:
1592 self.tagsList = tagsList
1593 return self.tagsList[:]
1560 1594
1561 def hgGetBranchesList(self, repodir): 1595 def hgGetBranchesList(self, repodir):
1562 """ 1596 """
1563 Public method to get the list of branches. 1597 Public method to get the list of branches.
1564 1598
1565 @param repodir directory name of the repository (string) 1599 @param repodir directory name of the repository (string)
1566 @return list of branches (list of string) 1600 @return list of branches (list of string)
1567 """ 1601 """
1568 args = [] 1602 args = self.initCommand("branches")
1569 args.append('branches')
1570 args.append('--closed') 1603 args.append('--closed')
1571 1604
1572 output = "" 1605 output = ""
1573 if self.__client is None: 1606 if self.__client is None:
1574 process = QProcess() 1607 process = QProcess()
1576 process.start('hg', args) 1609 process.start('hg', args)
1577 procStarted = process.waitForStarted(5000) 1610 procStarted = process.waitForStarted(5000)
1578 if procStarted: 1611 if procStarted:
1579 finished = process.waitForFinished(30000) 1612 finished = process.waitForFinished(30000)
1580 if finished and process.exitCode() == 0: 1613 if finished and process.exitCode() == 0:
1581 output = \ 1614 output = str(process.readAllStandardOutput(),
1582 str(process.readAllStandardOutput(), 1615 self.getEncoding(), 'replace')
1583 Preferences.getSystem("IOEncoding"),
1584 'replace')
1585 else: 1616 else:
1586 output, error = self.__client.runcommand(args) 1617 output, error = self.__client.runcommand(args)
1587 1618
1588 if output: 1619 if output:
1589 self.branchesList = [] 1620 self.branchesList = []
1703 1734
1704 @param name file name to get from the repository (string) 1735 @param name file name to get from the repository (string)
1705 @keyparam rev revision to retrieve (string) 1736 @keyparam rev revision to retrieve (string)
1706 @return contents of the file (string) and an error message (string) 1737 @return contents of the file (string) and an error message (string)
1707 """ 1738 """
1708 args = [] 1739 args = self.initCommand("cat")
1709 args.append("cat")
1710 if rev: 1740 if rev:
1711 args.append("--rev") 1741 args.append("--rev")
1712 args.append(rev) 1742 args.append(rev)
1713 args.append(name) 1743 args.append(name)
1714 1744
1729 procStarted = process.waitForStarted(5000) 1759 procStarted = process.waitForStarted(5000)
1730 if procStarted: 1760 if procStarted:
1731 finished = process.waitForFinished(30000) 1761 finished = process.waitForFinished(30000)
1732 if finished: 1762 if finished:
1733 if process.exitCode() == 0: 1763 if process.exitCode() == 0:
1734 output = str( 1764 output = str(process.readAllStandardOutput(),
1735 process.readAllStandardOutput(), 1765 self.getEncoding(), 'replace')
1736 Preferences.getSystem("IOEncoding"), 'replace')
1737 else: 1766 else:
1738 error = str( 1767 error = str(process.readAllStandardError(),
1739 process.readAllStandardError(), 1768 self.getEncoding(), 'replace')
1740 Preferences.getSystem("IOEncoding"), 'replace')
1741 else: 1769 else:
1742 error = self.trUtf8( 1770 error = self.tr(
1743 "The hg process did not finish within 30s.") 1771 "The hg process did not finish within 30s.")
1744 else: 1772 else:
1745 error = self.trUtf8( 1773 error = self.tr(
1746 'The process {0} could not be started. ' 1774 'The process {0} could not be started. '
1747 'Ensure, that it is in the search path.').format('hg') 1775 'Ensure, that it is in the search path.').format('hg')
1748 else: 1776 else:
1749 output, error = self.__client.runcommand(args) 1777 output, error = self.__client.runcommand(args)
1750 1778
1751 return output, error 1779 # return file contents with 'universal newlines'
1780 return output.replace('\r\n', '\n').replace('\r', '\n'), error
1752 1781
1753 def hgSbsDiff(self, name, extended=False, revisions=None): 1782 def hgSbsDiff(self, name, extended=False, revisions=None):
1754 """ 1783 """
1755 Public method used to view the difference of a file to the Mercurial 1784 Public method used to view the difference of a file to the Mercurial
1756 repository side-by-side. 1785 repository side-by-side.
1791 1820
1792 output1, error = self.__hgGetFileForRevision(name, rev=rev1) 1821 output1, error = self.__hgGetFileForRevision(name, rev=rev1)
1793 if error: 1822 if error:
1794 E5MessageBox.critical( 1823 E5MessageBox.critical(
1795 self.__ui, 1824 self.__ui,
1796 self.trUtf8("Mercurial Side-by-Side Difference"), 1825 self.tr("Mercurial Side-by-Side Difference"),
1797 error) 1826 error)
1798 return 1827 return
1799 name1 = "{0} (rev. {1})".format(name, rev1 and rev1 or ".") 1828 name1 = "{0} (rev. {1})".format(name, rev1 and rev1 or ".")
1800 1829
1801 if rev2: 1830 if rev2:
1802 output2, error = self.__hgGetFileForRevision(name, rev=rev2) 1831 output2, error = self.__hgGetFileForRevision(name, rev=rev2)
1803 if error: 1832 if error:
1804 E5MessageBox.critical( 1833 E5MessageBox.critical(
1805 self.__ui, 1834 self.__ui,
1806 self.trUtf8("Mercurial Side-by-Side Difference"), 1835 self.tr("Mercurial Side-by-Side Difference"),
1807 error) 1836 error)
1808 return 1837 return
1809 name2 = "{0} (rev. {1})".format(name, rev2) 1838 name2 = "{0} (rev. {1})".format(name, rev2)
1810 else: 1839 else:
1811 try: 1840 try:
1814 f1.close() 1843 f1.close()
1815 name2 = name 1844 name2 = name
1816 except IOError: 1845 except IOError:
1817 E5MessageBox.critical( 1846 E5MessageBox.critical(
1818 self.__ui, 1847 self.__ui,
1819 self.trUtf8("Mercurial Side-by-Side Difference"), 1848 self.tr("Mercurial Side-by-Side Difference"),
1820 self.trUtf8( 1849 self.tr(
1821 """<p>The file <b>{0}</b> could not be read.</p>""") 1850 """<p>The file <b>{0}</b> could not be read.</p>""")
1822 .format(name)) 1851 .format(name))
1823 return 1852 return
1824 1853
1825 if self.sbsDiff is None: 1854 if self.sbsDiff is None:
1826 from UI.CompareDialog import CompareDialog 1855 from UI.CompareDialog import CompareDialog
1827 self.sbsDiff = CompareDialog() 1856 self.sbsDiff = CompareDialog()
1828 self.sbsDiff.show() 1857 self.sbsDiff.show()
1829 self.sbsDiff.compare(output1, output2, name1, name2) 1858 self.sbsDiff.compare(output1, output2, name1, name2)
1830 1859
1831 def hgLogBrowser(self, path, isFile=False): 1860 def vcsLogBrowser(self, name, isFile=False):
1832 """ 1861 """
1833 Public method used to browse the log of a file/directory from the 1862 Public method used to browse the log of a file/directory from the
1834 Mercurial repository. 1863 Mercurial repository.
1835 1864
1836 @param path file/directory name to show the log of (string) 1865 @param name file/directory name to show the log of (string)
1837 @keyparam isFile flag indicating log for a file is to be shown 1866 @keyparam isFile flag indicating log for a file is to be shown
1838 (boolean) 1867 (boolean)
1839 """ 1868 """
1840 from .HgLogBrowserDialog import HgLogBrowserDialog 1869 if self.logBrowser is None:
1841 self.logBrowser = HgLogBrowserDialog(self, isFile=isFile) 1870 from .HgLogBrowserDialog import HgLogBrowserDialog
1871 self.logBrowser = HgLogBrowserDialog(self)
1842 self.logBrowser.show() 1872 self.logBrowser.show()
1843 self.logBrowser.start(path) 1873 self.logBrowser.start(name, isFile=isFile)
1844 1874
1845 def hgIncoming(self, name): 1875 def hgIncoming(self, name):
1846 """ 1876 """
1847 Public method used to view the log of incoming changes from the 1877 Public method used to view the log of incoming changes from the
1848 Mercurial repository. 1878 Mercurial repository.
1849 1879
1850 @param name file/directory name to show the log of (string) 1880 @param name file/directory name to show the log of (string)
1851 """ 1881 """
1852 if self.getPlugin().getPreferences("UseLogBrowser"): 1882 if self.getPlugin().getPreferences("UseLogBrowser"):
1853 from .HgLogBrowserDialog import HgLogBrowserDialog 1883 if self.logBrowserIncoming is None:
1854 self.logBrowser = HgLogBrowserDialog(self, mode="incoming") 1884 from .HgLogBrowserDialog import HgLogBrowserDialog
1855 self.logBrowser.show() 1885 self.logBrowserIncoming = HgLogBrowserDialog(
1856 self.logBrowser.start(name) 1886 self, mode="incoming")
1887 self.logBrowserIncoming.show()
1888 self.logBrowserIncoming.start(name)
1857 else: 1889 else:
1858 from .HgLogDialog import HgLogDialog 1890 from .HgLogDialog import HgLogDialog
1859 self.log = HgLogDialog(self, mode="incoming") 1891 self.log = HgLogDialog(self, mode="incoming")
1860 self.log.show() 1892 self.log.show()
1861 self.log.start(name) 1893 self.log.start(name)
1866 Mercurial repository. 1898 Mercurial repository.
1867 1899
1868 @param name file/directory name to show the log of (string) 1900 @param name file/directory name to show the log of (string)
1869 """ 1901 """
1870 if self.getPlugin().getPreferences("UseLogBrowser"): 1902 if self.getPlugin().getPreferences("UseLogBrowser"):
1871 from .HgLogBrowserDialog import HgLogBrowserDialog 1903 if self.logBrowserOutgoing is None:
1872 self.logBrowser = HgLogBrowserDialog(self, mode="outgoing") 1904 from .HgLogBrowserDialog import HgLogBrowserDialog
1873 self.logBrowser.show() 1905 self.logBrowserOutgoing = HgLogBrowserDialog(
1874 self.logBrowser.start(name) 1906 self, mode="outgoing")
1907 self.logBrowserOutgoing.show()
1908 self.logBrowserOutgoing.start(name)
1875 else: 1909 else:
1876 from .HgLogDialog import HgLogDialog 1910 from .HgLogDialog import HgLogDialog
1877 self.log = HgLogDialog(self, mode="outgoing") 1911 self.log = HgLogDialog(self, mode="outgoing")
1878 self.log.show() 1912 self.log.show()
1879 self.log.start(name) 1913 self.log.start(name)
1888 """ 1922 """
1889 if self.getPlugin().getPreferences("PreferUnbundle") and \ 1923 if self.getPlugin().getPreferences("PreferUnbundle") and \
1890 self.bundleFile and \ 1924 self.bundleFile and \
1891 os.path.exists(self.bundleFile): 1925 os.path.exists(self.bundleFile):
1892 command = "unbundle" 1926 command = "unbundle"
1893 title = self.trUtf8('Apply changegroups') 1927 title = self.tr('Apply changegroups')
1894 else: 1928 else:
1895 command = "pull" 1929 command = "pull"
1896 title = self.trUtf8('Pulling from a remote Mercurial repository') 1930 title = self.tr('Pulling from a remote Mercurial repository')
1897 1931
1898 args = [] 1932 args = self.initCommand(command)
1899 args.append(command)
1900 self.addArguments(args, self.options['global'])
1901 args.append('-v') 1933 args.append('-v')
1902 if self.getPlugin().getPreferences("PullUpdate"): 1934 if self.getPlugin().getPreferences("PullUpdate"):
1903 args.append('--update') 1935 args.append('--update')
1904 if command == "unbundle": 1936 if command == "unbundle":
1905 args.append(self.bundleFile) 1937 args.append(self.bundleFile)
1914 dia = HgDialog(title, self) 1946 dia = HgDialog(title, self)
1915 res = dia.startProcess(args, repodir) 1947 res = dia.startProcess(args, repodir)
1916 if res: 1948 if res:
1917 dia.exec_() 1949 dia.exec_()
1918 res = dia.hasAddOrDelete() 1950 res = dia.hasAddOrDelete()
1919 if command == "unbundle": 1951 if self.bundleFile and \
1952 os.path.exists(self.bundleFile):
1920 os.remove(self.bundleFile) 1953 os.remove(self.bundleFile)
1921 self.bundleFile = None 1954 self.bundleFile = None
1922 self.checkVCSStatus() 1955 self.checkVCSStatus()
1923 return res 1956 return res
1924 1957
1928 1961
1929 @param name directory name of the project to be pushed from (string) 1962 @param name directory name of the project to be pushed from (string)
1930 @keyparam force flag indicating a forced push (boolean) 1963 @keyparam force flag indicating a forced push (boolean)
1931 @keyparam newBranch flag indicating to push a new branch (boolean) 1964 @keyparam newBranch flag indicating to push a new branch (boolean)
1932 """ 1965 """
1933 args = [] 1966 args = self.initCommand("push")
1934 args.append('push')
1935 self.addArguments(args, self.options['global'])
1936 args.append('-v') 1967 args.append('-v')
1937 if force: 1968 if force:
1938 args.append('-f') 1969 args.append('-f')
1939 if newBranch: 1970 if newBranch:
1940 args.append('--new-branch') 1971 args.append('--new-branch')
1945 repodir = os.path.dirname(repodir) 1976 repodir = os.path.dirname(repodir)
1946 if os.path.splitdrive(repodir)[1] == os.sep: 1977 if os.path.splitdrive(repodir)[1] == os.sep:
1947 return 1978 return
1948 1979
1949 dia = HgDialog( 1980 dia = HgDialog(
1950 self.trUtf8('Pushing to a remote Mercurial repository'), self) 1981 self.tr('Pushing to a remote Mercurial repository'), self)
1951 res = dia.startProcess(args, repodir) 1982 res = dia.startProcess(args, repodir)
1952 if res: 1983 if res:
1953 dia.exec_() 1984 dia.exec_()
1954 res = dia.hasAddOrDelete() 1985 res = dia.hasAddOrDelete()
1955 self.checkVCSStatus() 1986 self.checkVCSStatus()
1965 if mode not in ("heads", "parents", "tip"): 1996 if mode not in ("heads", "parents", "tip"):
1966 mode = "heads" 1997 mode = "heads"
1967 1998
1968 info = [] 1999 info = []
1969 2000
1970 args = [] 2001 args = self.initCommand(mode)
1971 args.append(mode)
1972 args.append('--template') 2002 args.append('--template')
1973 args.append('{rev}:{node|short}@@@{tags}@@@{author|xmlescape}@@@' 2003 args.append('{rev}:{node|short}@@@{tags}@@@{author|xmlescape}@@@'
1974 '{date|isodate}@@@{branches}@@@{parents}@@@{bookmarks}\n') 2004 '{date|isodate}@@@{branches}@@@{parents}@@@{bookmarks}\n')
1975 2005
1976 output = "" 2006 output = ""
1987 process.start('hg', args) 2017 process.start('hg', args)
1988 procStarted = process.waitForStarted(5000) 2018 procStarted = process.waitForStarted(5000)
1989 if procStarted: 2019 if procStarted:
1990 finished = process.waitForFinished(30000) 2020 finished = process.waitForFinished(30000)
1991 if finished and process.exitCode() == 0: 2021 if finished and process.exitCode() == 0:
1992 output = str( 2022 output = str(process.readAllStandardOutput(),
1993 process.readAllStandardOutput(), 2023 self.getEncoding(), 'replace')
1994 Preferences.getSystem("IOEncoding"), 'replace')
1995 else: 2024 else:
1996 output, error = self.__client.runcommand(args) 2025 output, error = self.__client.runcommand(args)
1997 2026
1998 if output: 2027 if output:
1999 index = 0 2028 index = 0
2056 """ 2085 """
2057 Public method used to resolve conflicts of a file/directory. 2086 Public method used to resolve conflicts of a file/directory.
2058 2087
2059 @param name file/directory name to be resolved (string) 2088 @param name file/directory name to be resolved (string)
2060 """ 2089 """
2061 args = [] 2090 args = self.initCommand("resolve")
2062 args.append('resolve')
2063 self.addArguments(args, self.options['global'])
2064 args.append("--mark") 2091 args.append("--mark")
2065 2092
2066 if isinstance(name, list): 2093 if isinstance(name, list):
2067 dname, fnames = self.splitPathList(name) 2094 dname, fnames = self.splitPathList(name)
2068 self.addArguments(args, name) 2095 self.addArguments(args, name)
2075 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 2102 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
2076 repodir = os.path.dirname(repodir) 2103 repodir = os.path.dirname(repodir)
2077 if os.path.splitdrive(repodir)[1] == os.sep: 2104 if os.path.splitdrive(repodir)[1] == os.sep:
2078 return 2105 return
2079 2106
2080 dia = HgDialog(self.trUtf8('Resolving files/directories'), self) 2107 dia = HgDialog(self.tr('Resolving files/directories'), self)
2081 res = dia.startProcess(args, repodir) 2108 res = dia.startProcess(args, repodir)
2082 if res: 2109 if res:
2083 dia.exec_() 2110 dia.exec_()
2084 self.checkVCSStatus() 2111 self.checkVCSStatus()
2085 2112
2096 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 2123 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
2097 repodir = os.path.dirname(repodir) 2124 repodir = os.path.dirname(repodir)
2098 if os.path.splitdrive(repodir)[1] == os.sep: 2125 if os.path.splitdrive(repodir)[1] == os.sep:
2099 return 2126 return
2100 2127
2101 name, ok = QInputDialog.getItem( 2128 from .HgBranchInputDialog import HgBranchInputDialog
2102 None, 2129 dlg = HgBranchInputDialog(self.hgGetBranchesList(repodir))
2103 self.trUtf8("Create Branch"), 2130 if dlg.exec_() == QDialog.Accepted:
2104 self.trUtf8("Enter branch name"), 2131 name, commit = dlg.getData()
2105 sorted(self.hgGetBranchesList(repodir)), 2132 name = name.strip().replace(" ", "_")
2106 0, True) 2133 args = self.initCommand("branch")
2107 if ok and name: 2134 args.append(name)
2108 args = []
2109 args.append('branch')
2110 args.append(name.strip().replace(" ", "_"))
2111 2135
2112 dia = HgDialog( 2136 dia = HgDialog(
2113 self.trUtf8('Creating branch in the Mercurial repository'), 2137 self.tr('Creating branch in the Mercurial repository'),
2114 self) 2138 self)
2115 res = dia.startProcess(args, repodir) 2139 res = dia.startProcess(args, repodir)
2116 if res: 2140 if res:
2117 dia.exec_() 2141 dia.exec_()
2142 if commit:
2143 self.vcsCommit(
2144 repodir,
2145 self.tr("Created new branch <{0}>.").format(
2146 name))
2118 2147
2119 def hgShowBranch(self, name): 2148 def hgShowBranch(self, name):
2120 """ 2149 """
2121 Public method used to show the current branch the working directory. 2150 Public method used to show the current branch the working directory.
2122 2151
2129 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 2158 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
2130 repodir = os.path.dirname(repodir) 2159 repodir = os.path.dirname(repodir)
2131 if os.path.splitdrive(repodir)[1] == os.sep: 2160 if os.path.splitdrive(repodir)[1] == os.sep:
2132 return 2161 return
2133 2162
2134 args = [] 2163 args = self.initCommand("branch")
2135 args.append("branch") 2164
2136 2165 dia = HgDialog(self.tr('Showing current branch'), self)
2137 dia = HgDialog(self.trUtf8('Showing current branch'), self)
2138 res = dia.startProcess(args, repodir, False) 2166 res = dia.startProcess(args, repodir, False)
2139 if res: 2167 if res:
2140 dia.exec_() 2168 dia.exec_()
2141 2169
2142 def hgEditUserConfig(self): 2170 def hgEditUserConfig(self):
2144 Public method used to edit the user configuration file. 2172 Public method used to edit the user configuration file.
2145 """ 2173 """
2146 from .HgUtilities import getConfigPath 2174 from .HgUtilities import getConfigPath
2147 cfgFile = getConfigPath() 2175 cfgFile = getConfigPath()
2148 if not os.path.exists(cfgFile): 2176 if not os.path.exists(cfgFile):
2177 # open dialog to enter the initial data
2178 from .HgUserConfigDataDialog import HgUserConfigDataDialog
2179 dlg = HgUserConfigDataDialog(version=self.version)
2180 if dlg.exec_() == QDialog.Accepted:
2181 firstName, lastName, email, extensions, extensionsData = \
2182 dlg.getData()
2183 else:
2184 firstName, lastName, email, extensions, extensionsData = (
2185 "Firstname", "Lastname", "email_address", [], {})
2149 try: 2186 try:
2150 f = open(cfgFile, "w") 2187 f = open(cfgFile, "w")
2151 f.write("[ui]\nusername = Firstname Lastname" 2188 f.write("[ui]\n")
2152 " <email_address>\n") 2189 f.write("username = {0} {1} <{2}>\n".format(
2190 firstName, lastName, email))
2191 if extensions:
2192 f.write("\n[extensions]\n")
2193 f.write(" =\n".join(extensions))
2194 f.write(" =\n") # complete the last line
2195 if "largefiles" in extensionsData:
2196 dataDict = extensionsData["largefiles"]
2197 f.write("\n[largefiles]\n")
2198 if "minsize" in dataDict:
2199 f.write("minsize = {0}\n".format(dataDict["minsize"]))
2200 if "patterns" in dataDict:
2201 f.write("patterns =\n")
2202 f.write(" {0}\n".format(
2203 "\n ".join(dataDict["patterns"])))
2153 f.close() 2204 f.close()
2154 except (IOError, OSError): 2205 except (IOError, OSError):
2155 # ignore these 2206 # ignore these
2156 pass 2207 pass
2157 self.userEditor = MiniEditor(cfgFile, "Properties") 2208 self.userEditor = MiniEditor(cfgFile, "Properties")
2158 self.userEditor.show() 2209 self.userEditor.show()
2159 2210
2160 def hgEditConfig(self, name): 2211 def hgEditConfig(self, name, withLargefiles=True, largefilesData=None):
2161 """ 2212 """
2162 Public method used to edit the repository configuration file. 2213 Public method used to edit the repository configuration file.
2163 2214
2164 @param name file/directory name (string) 2215 @param name file/directory name (string)
2216 @param withLargefiles flag indicating to configure the largefiles
2217 section (boolean)
2218 @param largefilesData dictionary with data for the largefiles
2219 section of the data dialog (dict)
2165 """ 2220 """
2166 dname, fname = self.splitPath(name) 2221 dname, fname = self.splitPath(name)
2167 2222
2168 # find the root of the repo 2223 # find the root of the repo
2169 repodir = dname 2224 repodir = dname
2172 if os.path.splitdrive(repodir)[1] == os.sep: 2227 if os.path.splitdrive(repodir)[1] == os.sep:
2173 return 2228 return
2174 2229
2175 cfgFile = os.path.join(repodir, self.adminDir, "hgrc") 2230 cfgFile = os.path.join(repodir, self.adminDir, "hgrc")
2176 if not os.path.exists(cfgFile): 2231 if not os.path.exists(cfgFile):
2232 # open dialog to enter the initial data
2233 withLargefiles = (self.isExtensionActive("largefiles") and
2234 withLargefiles)
2235 from .HgRepoConfigDataDialog import HgRepoConfigDataDialog
2236 dlg = HgRepoConfigDataDialog(withLargefiles=withLargefiles,
2237 largefilesData=largefilesData)
2238 if dlg.exec_() == QDialog.Accepted:
2239 createContents = True
2240 defaultUrl, defaultPushUrl = dlg.getData()
2241 if withLargefiles:
2242 lfMinSize, lfPattern = dlg.getLargefilesData()
2243 else:
2244 createContents = False
2177 try: 2245 try:
2178 cfg = open(cfgFile, "w") 2246 cfg = open(cfgFile, "w")
2247 if createContents:
2248 # write the data entered
2249 cfg.write("[paths]\n")
2250 if defaultUrl:
2251 cfg.write("default = {0}\n".format(defaultUrl))
2252 if defaultPushUrl:
2253 cfg.write("default-push = {0}\n".format(
2254 defaultPushUrl))
2255 if withLargefiles and \
2256 (lfMinSize, lfPattern) != (None, None):
2257 cfg.write("\n[largefiles]\n")
2258 if lfMinSize is not None:
2259 cfg.write("minsize = {0}\n".format(lfMinSize))
2260 if lfPattern is not None:
2261 cfg.write("patterns =\n")
2262 cfg.write(" {0}\n".format(
2263 "\n ".join(lfPattern)))
2179 cfg.close() 2264 cfg.close()
2180 self.__monitorRepoIniFile(repodir) 2265 self.__monitorRepoIniFile(repodir)
2266 self.__iniFileChanged(cfgFile)
2181 except IOError: 2267 except IOError:
2182 pass 2268 pass
2183 self.repoEditor = MiniEditor(cfgFile, "Properties") 2269 self.repoEditor = MiniEditor(cfgFile, "Properties")
2184 self.repoEditor.show() 2270 self.repoEditor.show()
2185 2271
2196 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 2282 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
2197 repodir = os.path.dirname(repodir) 2283 repodir = os.path.dirname(repodir)
2198 if os.path.splitdrive(repodir)[1] == os.sep: 2284 if os.path.splitdrive(repodir)[1] == os.sep:
2199 return 2285 return
2200 2286
2201 args = [] 2287 args = self.initCommand("verify")
2202 args.append('verify')
2203 2288
2204 dia = HgDialog( 2289 dia = HgDialog(
2205 self.trUtf8('Verifying the integrity of the Mercurial repository'), 2290 self.tr('Verifying the integrity of the Mercurial repository'),
2206 self) 2291 self)
2207 res = dia.startProcess(args, repodir) 2292 res = dia.startProcess(args, repodir)
2208 if res: 2293 if res:
2209 dia.exec_() 2294 dia.exec_()
2210 2295
2221 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 2306 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
2222 repodir = os.path.dirname(repodir) 2307 repodir = os.path.dirname(repodir)
2223 if os.path.splitdrive(repodir)[1] == os.sep: 2308 if os.path.splitdrive(repodir)[1] == os.sep:
2224 return 2309 return
2225 2310
2226 args = [] 2311 args = self.initCommand("showconfig")
2227 args.append('showconfig')
2228 args.append("--untrusted") 2312 args.append("--untrusted")
2229 2313
2230 dia = HgDialog( 2314 dia = HgDialog(
2231 self.trUtf8('Showing the combined configuration settings'), 2315 self.tr('Showing the combined configuration settings'),
2232 self) 2316 self)
2233 res = dia.startProcess(args, repodir, False) 2317 res = dia.startProcess(args, repodir, False)
2234 if res: 2318 if res:
2235 dia.exec_() 2319 dia.exec_()
2236 2320
2247 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 2331 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
2248 repodir = os.path.dirname(repodir) 2332 repodir = os.path.dirname(repodir)
2249 if os.path.splitdrive(repodir)[1] == os.sep: 2333 if os.path.splitdrive(repodir)[1] == os.sep:
2250 return 2334 return
2251 2335
2252 args = [] 2336 args = self.initCommand("paths")
2253 args.append('paths')
2254 2337
2255 dia = HgDialog( 2338 dia = HgDialog(
2256 self.trUtf8('Showing aliases for remote repositories'), 2339 self.tr('Showing aliases for remote repositories'),
2257 self) 2340 self)
2258 res = dia.startProcess(args, repodir, False) 2341 res = dia.startProcess(args, repodir, False)
2259 if res: 2342 if res:
2260 dia.exec_() 2343 dia.exec_()
2261 2344
2272 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 2355 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
2273 repodir = os.path.dirname(repodir) 2356 repodir = os.path.dirname(repodir)
2274 if os.path.splitdrive(repodir)[1] == os.sep: 2357 if os.path.splitdrive(repodir)[1] == os.sep:
2275 return 2358 return
2276 2359
2277 args = [] 2360 args = self.initCommand("recover")
2278 args.append('recover')
2279 2361
2280 dia = HgDialog( 2362 dia = HgDialog(
2281 self.trUtf8('Recovering from interrupted transaction'), 2363 self.tr('Recovering from interrupted transaction'),
2282 self) 2364 self)
2283 res = dia.startProcess(args, repodir, False) 2365 res = dia.startProcess(args, repodir, False)
2284 if res: 2366 if res:
2285 dia.exec_() 2367 dia.exec_()
2286 2368
2297 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 2379 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
2298 repodir = os.path.dirname(repodir) 2380 repodir = os.path.dirname(repodir)
2299 if os.path.splitdrive(repodir)[1] == os.sep: 2381 if os.path.splitdrive(repodir)[1] == os.sep:
2300 return 2382 return
2301 2383
2302 args = [] 2384 args = self.initCommand("identify")
2303 args.append('identify') 2385
2304 2386 dia = HgDialog(self.tr('Identifying project directory'), self)
2305 dia = HgDialog(self.trUtf8('Identifying project directory'), self)
2306 res = dia.startProcess(args, repodir, False) 2387 res = dia.startProcess(args, repodir, False)
2307 if res: 2388 if res:
2308 dia.exec_() 2389 dia.exec_()
2309 2390
2310 def hgCreateIgnoreFile(self, name, autoAdd=False): 2391 def hgCreateIgnoreFile(self, name, autoAdd=False):
2338 2419
2339 ignoreName = os.path.join(name, Hg.IgnoreFileName) 2420 ignoreName = os.path.join(name, Hg.IgnoreFileName)
2340 if os.path.exists(ignoreName): 2421 if os.path.exists(ignoreName):
2341 res = E5MessageBox.yesNo( 2422 res = E5MessageBox.yesNo(
2342 self.__ui, 2423 self.__ui,
2343 self.trUtf8("Create .hgignore file"), 2424 self.tr("Create .hgignore file"),
2344 self.trUtf8("""<p>The file <b>{0}</b> exists already.""" 2425 self.tr("""<p>The file <b>{0}</b> exists already."""
2345 """ Overwrite it?</p>""").format(ignoreName), 2426 """ Overwrite it?</p>""").format(ignoreName),
2346 icon=E5MessageBox.Warning) 2427 icon=E5MessageBox.Warning)
2347 else: 2428 else:
2348 res = True 2429 res = True
2349 if res: 2430 if res:
2350 try: 2431 try:
2392 if dlg.exec_() == QDialog.Accepted: 2473 if dlg.exec_() == QDialog.Accepted:
2393 revs, baseRevs, compression, all = dlg.getParameters() 2474 revs, baseRevs, compression, all = dlg.getParameters()
2394 2475
2395 fname, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( 2476 fname, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
2396 None, 2477 None,
2397 self.trUtf8("Create changegroup"), 2478 self.tr("Create changegroup"),
2398 self.__lastChangeGroupPath or repodir, 2479 self.__lastChangeGroupPath or repodir,
2399 self.trUtf8("Mercurial Changegroup Files (*.hg)"), 2480 self.tr("Mercurial Changegroup Files (*.hg)"),
2400 None, 2481 None,
2401 E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)) 2482 E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
2402 2483
2403 if not fname: 2484 if not fname:
2404 return # user aborted 2485 return # user aborted
2409 if ex: 2490 if ex:
2410 fname += ex 2491 fname += ex
2411 if QFileInfo(fname).exists(): 2492 if QFileInfo(fname).exists():
2412 res = E5MessageBox.yesNo( 2493 res = E5MessageBox.yesNo(
2413 self.__ui, 2494 self.__ui,
2414 self.trUtf8("Create changegroup"), 2495 self.tr("Create changegroup"),
2415 self.trUtf8("<p>The Mercurial changegroup file <b>{0}</b> " 2496 self.tr("<p>The Mercurial changegroup file <b>{0}</b> "
2416 "already exists. Overwrite it?</p>") 2497 "already exists. Overwrite it?</p>")
2417 .format(fname), 2498 .format(fname),
2418 icon=E5MessageBox.Warning) 2499 icon=E5MessageBox.Warning)
2419 if not res: 2500 if not res:
2420 return 2501 return
2421 fname = Utilities.toNativeSeparators(fname) 2502 fname = Utilities.toNativeSeparators(fname)
2422 self.__lastChangeGroupPath = os.path.dirname(fname) 2503 self.__lastChangeGroupPath = os.path.dirname(fname)
2423 2504
2424 args = [] 2505 args = self.initCommand("bundle")
2425 args.append('bundle')
2426 if all: 2506 if all:
2427 args.append("--all") 2507 args.append("--all")
2428 for rev in revs: 2508 for rev in revs:
2429 args.append("--rev") 2509 args.append("--rev")
2430 args.append(rev) 2510 args.append(rev)
2434 if compression: 2514 if compression:
2435 args.append("--type") 2515 args.append("--type")
2436 args.append(compression) 2516 args.append(compression)
2437 args.append(fname) 2517 args.append(fname)
2438 2518
2439 dia = HgDialog(self.trUtf8('Create changegroup'), self) 2519 dia = HgDialog(self.tr('Create changegroup'), self)
2440 res = dia.startProcess(args, repodir) 2520 res = dia.startProcess(args, repodir)
2441 if res: 2521 if res:
2442 dia.exec_() 2522 dia.exec_()
2443 2523
2444 def hgPreviewBundle(self, name): 2524 def hgPreviewBundle(self, name):
2457 if os.path.splitdrive(repodir)[1] == os.sep: 2537 if os.path.splitdrive(repodir)[1] == os.sep:
2458 return 2538 return
2459 2539
2460 file = E5FileDialog.getOpenFileName( 2540 file = E5FileDialog.getOpenFileName(
2461 None, 2541 None,
2462 self.trUtf8("Preview changegroup"), 2542 self.tr("Preview changegroup"),
2463 self.__lastChangeGroupPath or repodir, 2543 self.__lastChangeGroupPath or repodir,
2464 self.trUtf8("Mercurial Changegroup Files (*.hg);;All Files (*)")) 2544 self.tr("Mercurial Changegroup Files (*.hg);;All Files (*)"))
2465 if file: 2545 if file:
2466 self.__lastChangeGroupPath = os.path.dirname(file) 2546 self.__lastChangeGroupPath = os.path.dirname(file)
2467 2547
2468 if self.getPlugin().getPreferences("UseLogBrowser"): 2548 if self.getPlugin().getPreferences("UseLogBrowser"):
2469 from .HgLogBrowserDialog import HgLogBrowserDialog 2549 if self.logBrowserIncoming is None:
2470 self.logBrowser = \ 2550 from .HgLogBrowserDialog import HgLogBrowserDialog
2471 HgLogBrowserDialog(self, mode="incoming", bundle=file) 2551 self.logBrowserIncoming = \
2472 self.logBrowser.show() 2552 HgLogBrowserDialog(self, mode="incoming")
2473 self.logBrowser.start(name) 2553 self.logBrowserIncoming.show()
2554 self.logBrowserIncoming.start(name, bundle=file)
2474 else: 2555 else:
2475 from .HgLogDialog import HgLogDialog 2556 from .HgLogDialog import HgLogDialog
2476 self.log = HgLogDialog(self, mode="incoming", bundle=file) 2557 self.log = HgLogDialog(self, mode="incoming", bundle=file)
2477 self.log.show() 2558 self.log.show()
2478 self.log.start(name) 2559 self.log.start(name)
2479 2560
2480 def hgIdentifyBundle(self, name):
2481 """
2482 Public method used to identify a changegroup file.
2483
2484 @param name directory name on which to base the changegroup (string)
2485 """
2486 dname, fname = self.splitPath(name)
2487
2488 # find the root of the repo
2489 repodir = dname
2490 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
2491 repodir = os.path.dirname(repodir)
2492 if os.path.splitdrive(repodir)[1] == os.sep:
2493 return
2494
2495 file = E5FileDialog.getOpenFileName(
2496 None,
2497 self.trUtf8("Preview changegroup"),
2498 self.__lastChangeGroupPath or repodir,
2499 self.trUtf8("Mercurial Changegroup Files (*.hg);;All Files (*)"))
2500 if file:
2501 self.__lastChangeGroupPath = os.path.dirname(file)
2502
2503 args = []
2504 args.append('identify')
2505 args.append(file)
2506
2507 dia = HgDialog(self.trUtf8('Identifying changegroup file'), self)
2508 res = dia.startProcess(args, repodir, False)
2509 if res:
2510 dia.exec_()
2511
2512 def hgUnbundle(self, name): 2561 def hgUnbundle(self, name):
2513 """ 2562 """
2514 Public method to apply changegroup files. 2563 Public method to apply changegroup files.
2515 2564
2516 @param name directory name (string) 2565 @param name directory name (string)
2527 return 2576 return
2528 2577
2529 res = False 2578 res = False
2530 files = E5FileDialog.getOpenFileNames( 2579 files = E5FileDialog.getOpenFileNames(
2531 None, 2580 None,
2532 self.trUtf8("Apply changegroups"), 2581 self.tr("Apply changegroups"),
2533 self.__lastChangeGroupPath or repodir, 2582 self.__lastChangeGroupPath or repodir,
2534 self.trUtf8("Mercurial Changegroup Files (*.hg);;All Files (*)")) 2583 self.tr("Mercurial Changegroup Files (*.hg);;All Files (*)"))
2535 if files: 2584 if files:
2536 self.__lastChangeGroupPath = os.path.dirname(files[0]) 2585 self.__lastChangeGroupPath = os.path.dirname(files[0])
2537 2586
2538 update = E5MessageBox.yesNo( 2587 update = E5MessageBox.yesNo(
2539 self.__ui, 2588 self.__ui,
2540 self.trUtf8("Apply changegroups"), 2589 self.tr("Apply changegroups"),
2541 self.trUtf8("""Shall the working directory be updated?"""), 2590 self.tr("""Shall the working directory be updated?"""),
2542 yesDefault=True) 2591 yesDefault=True)
2543 2592
2544 args = [] 2593 args = self.initCommand("unbundle")
2545 args.append('unbundle')
2546 if update: 2594 if update:
2547 args.append("--update") 2595 args.append("--update")
2548 args.append("--verbose") 2596 args.append("--verbose")
2549 args.extend(files) 2597 args.extend(files)
2550 2598
2551 dia = HgDialog(self.trUtf8('Apply changegroups'), self) 2599 dia = HgDialog(self.tr('Apply changegroups'), self)
2552 res = dia.startProcess(args, repodir) 2600 res = dia.startProcess(args, repodir)
2553 if res: 2601 if res:
2554 dia.exec_() 2602 dia.exec_()
2555 res = dia.hasAddOrDelete() 2603 res = dia.hasAddOrDelete()
2556 self.checkVCSStatus() 2604 self.checkVCSStatus()
2565 'skip' or 'reset') 2613 'skip' or 'reset')
2566 @exception ValueError raised to indicate an invalid bisect subcommand 2614 @exception ValueError raised to indicate an invalid bisect subcommand
2567 """ 2615 """
2568 if subcommand not in ("good", "bad", "skip", "reset"): 2616 if subcommand not in ("good", "bad", "skip", "reset"):
2569 raise ValueError( 2617 raise ValueError(
2570 self.trUtf8("Bisect subcommand ({0}) invalid.") 2618 self.tr("Bisect subcommand ({0}) invalid.")
2571 .format(subcommand)) 2619 .format(subcommand))
2572 2620
2573 dname, fname = self.splitPath(name) 2621 dname, fname = self.splitPath(name)
2574 2622
2575 # find the root of the repo 2623 # find the root of the repo
2588 else: 2636 else:
2589 bookmarksList = None 2637 bookmarksList = None
2590 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog 2638 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog
2591 dlg = HgRevisionSelectionDialog(self.hgGetTagsList(repodir), 2639 dlg = HgRevisionSelectionDialog(self.hgGetTagsList(repodir),
2592 self.hgGetBranchesList(repodir), 2640 self.hgGetBranchesList(repodir),
2593 bookmarksList, 2641 bookmarksList)
2594 showNone=True)
2595 if dlg.exec_() == QDialog.Accepted: 2642 if dlg.exec_() == QDialog.Accepted:
2596 rev = dlg.getRevision() 2643 rev = dlg.getRevision()
2597 else: 2644 else:
2598 return 2645 return
2599 2646
2600 args = [] 2647 args = self.initCommand("bisect")
2601 args.append("bisect")
2602 args.append("--{0}".format(subcommand)) 2648 args.append("--{0}".format(subcommand))
2603 if rev: 2649 if rev:
2604 args.append(rev) 2650 args.append(rev)
2605 2651
2606 dia = HgDialog( 2652 dia = HgDialog(
2607 self.trUtf8('Mercurial Bisect ({0})').format(subcommand), self) 2653 self.tr('Mercurial Bisect ({0})').format(subcommand), self)
2608 res = dia.startProcess(args, repodir) 2654 res = dia.startProcess(args, repodir)
2609 if res: 2655 if res:
2610 dia.exec_() 2656 dia.exec_()
2611 2657
2612 def hgForget(self, name): 2658 def hgForget(self, name):
2616 This will not remove the file from the project directory. 2662 This will not remove the file from the project directory.
2617 2663
2618 @param name file/directory name to be removed (string or list of 2664 @param name file/directory name to be removed (string or list of
2619 strings)) 2665 strings))
2620 """ 2666 """
2621 args = [] 2667 args = self.initCommand("forget")
2622 args.append('forget')
2623 self.addArguments(args, self.options['global'])
2624 args.append('-v') 2668 args.append('-v')
2625 2669
2626 if isinstance(name, list): 2670 if isinstance(name, list):
2627 dname, fnames = self.splitPathList(name) 2671 dname, fnames = self.splitPathList(name)
2628 self.addArguments(args, name) 2672 self.addArguments(args, name)
2636 repodir = os.path.dirname(repodir) 2680 repodir = os.path.dirname(repodir)
2637 if os.path.splitdrive(repodir)[1] == os.sep: 2681 if os.path.splitdrive(repodir)[1] == os.sep:
2638 return 2682 return
2639 2683
2640 dia = HgDialog( 2684 dia = HgDialog(
2641 self.trUtf8('Removing files from the Mercurial repository only'), 2685 self.tr('Removing files from the Mercurial repository only'),
2642 self) 2686 self)
2643 res = dia.startProcess(args, repodir) 2687 res = dia.startProcess(args, repodir)
2644 if res: 2688 if res:
2645 dia.exec_() 2689 dia.exec_()
2646 if isinstance(name, list): 2690 if isinstance(name, list):
2677 if dlg.exec_() == QDialog.Accepted: 2721 if dlg.exec_() == QDialog.Accepted:
2678 rev, merge, date, user, message = dlg.getParameters() 2722 rev, merge, date, user, message = dlg.getParameters()
2679 if not rev: 2723 if not rev:
2680 E5MessageBox.warning( 2724 E5MessageBox.warning(
2681 self.__ui, 2725 self.__ui,
2682 self.trUtf8("Backing out changeset"), 2726 self.tr("Backing out changeset"),
2683 self.trUtf8("""No revision given. Aborting...""")) 2727 self.tr("""No revision given. Aborting..."""))
2684 return 2728 return
2685 2729
2686 args = [] 2730 args = self.initCommand("backout")
2687 args.append('backout')
2688 args.append('-v') 2731 args.append('-v')
2689 if merge: 2732 if merge:
2690 args.append('--merge') 2733 args.append('--merge')
2691 if date: 2734 if date:
2692 args.append('--date') 2735 args.append('--date')
2696 args.append(user) 2739 args.append(user)
2697 args.append('--message') 2740 args.append('--message')
2698 args.append(message) 2741 args.append(message)
2699 args.append(rev) 2742 args.append(rev)
2700 2743
2701 dia = HgDialog(self.trUtf8('Backing out changeset'), self) 2744 dia = HgDialog(self.tr('Backing out changeset'), self)
2702 res = dia.startProcess(args, repodir) 2745 res = dia.startProcess(args, repodir)
2703 if res: 2746 if res:
2704 dia.exec_() 2747 dia.exec_()
2705 2748
2706 def hgRollback(self, name): 2749 def hgRollback(self, name):
2718 if os.path.splitdrive(repodir)[1] == os.sep: 2761 if os.path.splitdrive(repodir)[1] == os.sep:
2719 return 2762 return
2720 2763
2721 res = E5MessageBox.yesNo( 2764 res = E5MessageBox.yesNo(
2722 None, 2765 None,
2723 self.trUtf8("Rollback last transaction"), 2766 self.tr("Rollback last transaction"),
2724 self.trUtf8("""Are you sure you want to rollback the last""" 2767 self.tr("""Are you sure you want to rollback the last"""
2725 """ transaction?"""), 2768 """ transaction?"""),
2726 icon=E5MessageBox.Warning) 2769 icon=E5MessageBox.Warning)
2727 if res: 2770 if res:
2728 dia = HgDialog(self.trUtf8('Rollback last transaction'), self) 2771 dia = HgDialog(self.tr('Rollback last transaction'), self)
2729 res = dia.startProcess(["rollback"], repodir) 2772 res = dia.startProcess(["rollback"], repodir)
2730 if res: 2773 if res:
2731 dia.exec_() 2774 dia.exec_()
2732 2775
2733 def hgServe(self, name): 2776 def hgServe(self, name):
2770 dlg = HgImportDialog() 2813 dlg = HgImportDialog()
2771 if dlg.exec_() == QDialog.Accepted: 2814 if dlg.exec_() == QDialog.Accepted:
2772 patchFile, noCommit, message, date, user, stripCount, force = \ 2815 patchFile, noCommit, message, date, user, stripCount, force = \
2773 dlg.getParameters() 2816 dlg.getParameters()
2774 2817
2775 args = [] 2818 args = self.initCommand("import")
2776 args.append("import")
2777 args.append("--verbose") 2819 args.append("--verbose")
2778 if noCommit: 2820 if noCommit:
2779 args.append("--no-commit") 2821 args.append("--no-commit")
2780 else: 2822 else:
2781 if message: 2823 if message:
2792 args.append(str(stripCount)) 2834 args.append(str(stripCount))
2793 if force: 2835 if force:
2794 args.append("--force") 2836 args.append("--force")
2795 args.append(patchFile) 2837 args.append(patchFile)
2796 2838
2797 dia = HgDialog(self.trUtf8("Import Patch"), self) 2839 dia = HgDialog(self.tr("Import Patch"), self)
2798 res = dia.startProcess(args, repodir) 2840 res = dia.startProcess(args, repodir)
2799 if res: 2841 if res:
2800 dia.exec_() 2842 dia.exec_()
2801 res = dia.hasAddOrDelete() 2843 res = dia.hasAddOrDelete()
2802 self.checkVCSStatus() 2844 self.checkVCSStatus()
2824 dlg = HgExportDialog() 2866 dlg = HgExportDialog()
2825 if dlg.exec_() == QDialog.Accepted: 2867 if dlg.exec_() == QDialog.Accepted:
2826 filePattern, revisions, switchParent, allText, noDates, git = \ 2868 filePattern, revisions, switchParent, allText, noDates, git = \
2827 dlg.getParameters() 2869 dlg.getParameters()
2828 2870
2829 args = [] 2871 args = self.initCommand("export")
2830 args.append("export")
2831 args.append("--output") 2872 args.append("--output")
2832 args.append(filePattern) 2873 args.append(filePattern)
2833 args.append("--verbose") 2874 args.append("--verbose")
2834 if switchParent: 2875 if switchParent:
2835 args.append("--switch-parent") 2876 args.append("--switch-parent")
2840 if git: 2881 if git:
2841 args.append("--git") 2882 args.append("--git")
2842 for rev in revisions: 2883 for rev in revisions:
2843 args.append(rev) 2884 args.append(rev)
2844 2885
2845 dia = HgDialog(self.trUtf8("Export Patches"), self) 2886 dia = HgDialog(self.tr("Export Patches"), self)
2846 res = dia.startProcess(args, repodir) 2887 res = dia.startProcess(args, repodir)
2847 if res: 2888 if res:
2848 dia.exec_() 2889 dia.exec_()
2849 2890
2850 def hgPhase(self, name, data=None): 2891 def hgPhase(self, name, data=None):
2873 data = dlg.getData() 2914 data = dlg.getData()
2874 2915
2875 if data: 2916 if data:
2876 revs, phase, force = data 2917 revs, phase, force = data
2877 2918
2878 args = [] 2919 args = self.initCommand("phase")
2879 args.append("phase")
2880 if phase == "p": 2920 if phase == "p":
2881 args.append("--public") 2921 args.append("--public")
2882 elif phase == "d": 2922 elif phase == "d":
2883 args.append("--draft") 2923 args.append("--draft")
2884 elif phase == "s": 2924 elif phase == "s":
2888 if force: 2928 if force:
2889 args.append("--force") 2929 args.append("--force")
2890 for rev in revs: 2930 for rev in revs:
2891 args.append(rev) 2931 args.append(rev)
2892 2932
2893 dia = HgDialog(self.trUtf8("Change Phase"), self) 2933 dia = HgDialog(self.tr("Change Phase"), self)
2894 res = dia.startProcess(args, repodir) 2934 res = dia.startProcess(args, repodir)
2895 if res: 2935 if res:
2896 dia.exec_() 2936 dia.exec_()
2897 res = dia.normalExitWithoutErrors() 2937 res = dia.normalExitWithoutErrors()
2898 else: 2938 else:
2921 dlg = HgGraftDialog(self, revs) 2961 dlg = HgGraftDialog(self, revs)
2922 if dlg.exec_() == QDialog.Accepted: 2962 if dlg.exec_() == QDialog.Accepted:
2923 revs, (userData, currentUser, userName), \ 2963 revs, (userData, currentUser, userName), \
2924 (dateData, currentDate, dateStr), log, dryrun = dlg.getData() 2964 (dateData, currentDate, dateStr), log, dryrun = dlg.getData()
2925 2965
2926 args = [] 2966 args = self.initCommand("graft")
2927 args.append("graft")
2928 args.append("--verbose") 2967 args.append("--verbose")
2929 if userData: 2968 if userData:
2930 if currentUser: 2969 if currentUser:
2931 args.append("--currentuser") 2970 args.append("--currentuser")
2932 else: 2971 else:
2942 args.append("--log") 2981 args.append("--log")
2943 if dryrun: 2982 if dryrun:
2944 args.append("--dry-run") 2983 args.append("--dry-run")
2945 args.extend(revs) 2984 args.extend(revs)
2946 2985
2947 dia = HgDialog(self.trUtf8('Copy Changesets'), self) 2986 dia = HgDialog(self.tr('Copy Changesets'), self)
2948 res = dia.startProcess(args, repodir) 2987 res = dia.startProcess(args, repodir)
2949 if res: 2988 if res:
2950 dia.exec_() 2989 dia.exec_()
2951 res = dia.hasAddOrDelete() 2990 res = dia.hasAddOrDelete()
2952 self.checkVCSStatus() 2991 self.checkVCSStatus()
2964 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 3003 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
2965 repodir = os.path.dirname(repodir) 3004 repodir = os.path.dirname(repodir)
2966 if os.path.splitdrive(repodir)[1] == os.sep: 3005 if os.path.splitdrive(repodir)[1] == os.sep:
2967 return 3006 return
2968 3007
2969 args = [] 3008 args = self.initCommand("graft")
2970 args.append("graft")
2971 args.append("--continue") 3009 args.append("--continue")
2972 args.append("--verbose") 3010 args.append("--verbose")
2973 3011
2974 dia = HgDialog(self.trUtf8('Copy Changesets (Continue)'), self) 3012 dia = HgDialog(self.tr('Copy Changesets (Continue)'), self)
2975 res = dia.startProcess(args, repodir) 3013 res = dia.startProcess(args, repodir)
2976 if res: 3014 if res:
2977 dia.exec_() 3015 dia.exec_()
2978 res = dia.hasAddOrDelete() 3016 res = dia.hasAddOrDelete()
2979 self.checkVCSStatus() 3017 self.checkVCSStatus()
2993 from .HgArchiveDialog import HgArchiveDialog 3031 from .HgArchiveDialog import HgArchiveDialog
2994 dlg = HgArchiveDialog(self) 3032 dlg = HgArchiveDialog(self)
2995 if dlg.exec_() == QDialog.Accepted: 3033 if dlg.exec_() == QDialog.Accepted:
2996 archive, type_, prefix, subrepos = dlg.getData() 3034 archive, type_, prefix, subrepos = dlg.getData()
2997 3035
2998 args = [] 3036 args = self.initCommand("archive")
2999 args.append("archive")
3000 if type_: 3037 if type_:
3001 args.append("--type") 3038 args.append("--type")
3002 args.append(type_) 3039 args.append(type_)
3003 if prefix: 3040 if prefix:
3004 args.append("--prefix") 3041 args.append("--prefix")
3005 args.append(prefix) 3042 args.append(prefix)
3006 if subrepos: 3043 if subrepos:
3007 args.append("--subrepos") 3044 args.append("--subrepos")
3008 args.append(archive) 3045 args.append(archive)
3009 3046
3010 dia = HgDialog(self.trUtf8("Create Unversioned Archive"), self) 3047 dia = HgDialog(self.tr("Create Unversioned Archive"), self)
3011 res = dia.startProcess(args, repodir) 3048 res = dia.startProcess(args, repodir)
3012 if res: 3049 if res:
3013 dia.exec_() 3050 dia.exec_()
3014 3051
3015 ########################################################################### 3052 ###########################################################################
3060 contents = f.readlines() 3097 contents = f.readlines()
3061 f.close() 3098 f.close()
3062 except IOError as err: 3099 except IOError as err:
3063 E5MessageBox.critical( 3100 E5MessageBox.critical(
3064 self.__ui, 3101 self.__ui,
3065 self.trUtf8("Add Sub-repository"), 3102 self.tr("Add Sub-repository"),
3066 self.trUtf8( 3103 self.tr(
3067 """<p>The sub-repositories file .hgsub could not""" 3104 """<p>The sub-repositories file .hgsub could not"""
3068 """ be read.</p><p>Reason: {0}</p>""") 3105 """ be read.</p><p>Reason: {0}</p>""")
3069 .format(str(err))) 3106 .format(str(err)))
3070 return 3107 return
3071 3108
3072 if entry in contents: 3109 if entry in contents:
3073 E5MessageBox.critical( 3110 E5MessageBox.critical(
3074 self.__ui, 3111 self.__ui,
3075 self.trUtf8("Add Sub-repository"), 3112 self.tr("Add Sub-repository"),
3076 self.trUtf8( 3113 self.tr(
3077 """<p>The sub-repositories file .hgsub already""" 3114 """<p>The sub-repositories file .hgsub already"""
3078 """ contains an entry <b>{0}</b>.""" 3115 """ contains an entry <b>{0}</b>."""
3079 """ Aborting...</p>""").format(entry)) 3116 """ Aborting...</p>""").format(entry))
3080 return 3117 return
3081 else: 3118 else:
3089 f.writelines(contents) 3126 f.writelines(contents)
3090 f.close() 3127 f.close()
3091 except IOError as err: 3128 except IOError as err:
3092 E5MessageBox.critical( 3129 E5MessageBox.critical(
3093 self.__ui, 3130 self.__ui,
3094 self.trUtf8("Add Sub-repository"), 3131 self.tr("Add Sub-repository"),
3095 self.trUtf8( 3132 self.tr(
3096 """<p>The sub-repositories file .hgsub could not""" 3133 """<p>The sub-repositories file .hgsub could not"""
3097 """ be written to.</p><p>Reason: {0}</p>""") 3134 """ be written to.</p><p>Reason: {0}</p>""")
3098 .format(str(err))) 3135 .format(str(err)))
3099 return 3136 return
3100 3137
3110 3147
3111 subrepositories = [] 3148 subrepositories = []
3112 if not os.path.isfile(hgsub): 3149 if not os.path.isfile(hgsub):
3113 E5MessageBox.critical( 3150 E5MessageBox.critical(
3114 self.__ui, 3151 self.__ui,
3115 self.trUtf8("Remove Sub-repositories"), 3152 self.tr("Remove Sub-repositories"),
3116 self.trUtf8("""<p>The sub-repositories file .hgsub does not""" 3153 self.tr("""<p>The sub-repositories file .hgsub does not"""
3117 """ exist. Aborting...</p>""")) 3154 """ exist. Aborting...</p>"""))
3118 return 3155 return
3119 3156
3120 try: 3157 try:
3121 f = open(hgsub, "r") 3158 f = open(hgsub, "r")
3122 subrepositories = [line.strip() for line in f.readlines()] 3159 subrepositories = [line.strip() for line in f.readlines()]
3123 f.close() 3160 f.close()
3124 except IOError as err: 3161 except IOError as err:
3125 E5MessageBox.critical( 3162 E5MessageBox.critical(
3126 self.__ui, 3163 self.__ui,
3127 self.trUtf8("Remove Sub-repositories"), 3164 self.tr("Remove Sub-repositories"),
3128 self.trUtf8("""<p>The sub-repositories file .hgsub could not""" 3165 self.tr("""<p>The sub-repositories file .hgsub could not"""
3129 """ be read.</p><p>Reason: {0}</p>""") 3166 """ be read.</p><p>Reason: {0}</p>""")
3130 .format(str(err))) 3167 .format(str(err)))
3131 return 3168 return
3132 3169
3133 from .HgRemoveSubrepositoriesDialog import \ 3170 from .HgRemoveSubrepositoriesDialog import \
3134 HgRemoveSubrepositoriesDialog 3171 HgRemoveSubrepositoriesDialog
3141 f.write(contents) 3178 f.write(contents)
3142 f.close() 3179 f.close()
3143 except IOError as err: 3180 except IOError as err:
3144 E5MessageBox.critical( 3181 E5MessageBox.critical(
3145 self.__ui, 3182 self.__ui,
3146 self.trUtf8("Remove Sub-repositories"), 3183 self.tr("Remove Sub-repositories"),
3147 self.trUtf8( 3184 self.tr(
3148 """<p>The sub-repositories file .hgsub could not""" 3185 """<p>The sub-repositories file .hgsub could not"""
3149 """ be written to.</p><p>Reason: {0}</p>""") 3186 """ be written to.</p><p>Reason: {0}</p>""")
3150 .format(str(err))) 3187 .format(str(err)))
3151 return 3188 return
3152 3189
3156 subrepoPath = removedSubrepo.split("=", 1)[0].strip() 3193 subrepoPath = removedSubrepo.split("=", 1)[0].strip()
3157 subrepoAbsPath = os.path.join(ppath, subrepoPath) 3194 subrepoAbsPath = os.path.join(ppath, subrepoPath)
3158 shutil.rmtree(subrepoAbsPath, True) 3195 shutil.rmtree(subrepoAbsPath, True)
3159 3196
3160 ########################################################################### 3197 ###########################################################################
3161 ## Methods to handle extensions are below. 3198 ## Methods to handle configuration dependent stuff are below.
3162 ########################################################################### 3199 ###########################################################################
3163 3200
3201 def __checkDefaults(self):
3202 """
3203 Private method to check, if the default and default-push URLs
3204 have been configured.
3205 """
3206 args = self.initCommand("showconfig")
3207 args.append('paths')
3208
3209 output = ""
3210 if self.__client is None:
3211 process = QProcess()
3212 self.__repoDir and process.setWorkingDirectory(self.__repoDir)
3213 process.start('hg', args)
3214 procStarted = process.waitForStarted(5000)
3215 if procStarted:
3216 finished = process.waitForFinished(30000)
3217 if finished and process.exitCode() == 0:
3218 output = str(process.readAllStandardOutput(),
3219 self.getEncoding(), 'replace')
3220 else:
3221 output, error = self.__client.runcommand(args)
3222
3223 self.__defaultConfigured = False
3224 self.__defaultPushConfigured = False
3225 if output:
3226 for line in output.splitlines():
3227 if line.startswith("paths.default=") and \
3228 not line.strip().endswith("="):
3229 self.__defaultConfigured = True
3230 if line.startswith("paths.default-push=") and \
3231 not line.strip().endswith("="):
3232 self.__defaultPushConfigured = True
3233
3234 def canPull(self):
3235 """
3236 Public method to check, if pull is possible.
3237
3238 @return flag indicating pull capability (boolean)
3239 """
3240 return self.__defaultConfigured
3241
3242 def canPush(self):
3243 """
3244 Public method to check, if push is possible.
3245
3246 @return flag indicating push capability (boolean)
3247 """
3248 return self.__defaultPushConfigured or self.__defaultConfigured
3249
3164 def __iniFileChanged(self, path): 3250 def __iniFileChanged(self, path):
3165 """ 3251 """
3166 Private slot to handle a change of the Mercurial configuration file. 3252 Private slot to handle a change of the Mercurial configuration file.
3167 3253
3168 @param path name of the changed file (string) 3254 @param path name of the changed file (string)
3169 """ 3255 """
3170 self.__getExtensionsInfo()
3171
3172 if self.__client: 3256 if self.__client:
3173 ok, err = self.__client.restartServer() 3257 ok, err = self.__client.restartServer()
3174 if not ok: 3258 if not ok:
3175 E5MessageBox.warning( 3259 E5MessageBox.warning(
3176 None, 3260 None,
3177 self.trUtf8("Mercurial Command Server"), 3261 self.tr("Mercurial Command Server"),
3178 self.trUtf8( 3262 self.tr(
3179 """<p>The Mercurial Command Server could not be""" 3263 """<p>The Mercurial Command Server could not be"""
3180 """ restarted.</p><p>Reason: {0}</p>""").format(err)) 3264 """ restarted.</p><p>Reason: {0}</p>""").format(err))
3181 self.__client = None 3265 self.__client = None
3266
3267 self.__getExtensionsInfo()
3268
3269 if self.__repoIniFile and path == self.__repoIniFile:
3270 self.__checkDefaults()
3271
3272 self.iniFileChanged.emit()
3182 3273
3183 def __monitorRepoIniFile(self, name): 3274 def __monitorRepoIniFile(self, name):
3184 """ 3275 """
3185 Private slot to add a repository configuration file to the list of 3276 Private slot to add a repository configuration file to the list of
3186 monitored files. 3277 monitored files.
3197 return 3288 return
3198 3289
3199 cfgFile = os.path.join(repodir, self.adminDir, "hgrc") 3290 cfgFile = os.path.join(repodir, self.adminDir, "hgrc")
3200 if os.path.exists(cfgFile): 3291 if os.path.exists(cfgFile):
3201 self.__iniWatcher.addPath(cfgFile) 3292 self.__iniWatcher.addPath(cfgFile)
3293 self.__repoIniFile = cfgFile
3294 self.__checkDefaults()
3295
3296 ###########################################################################
3297 ## Methods to handle extensions are below.
3298 ###########################################################################
3202 3299
3203 def __getExtensionsInfo(self): 3300 def __getExtensionsInfo(self):
3204 """ 3301 """
3205 Private method to get the active extensions from Mercurial. 3302 Private method to get the active extensions from Mercurial.
3206 """ 3303 """
3207 activeExtensions = sorted(self.__activeExtensions) 3304 activeExtensions = sorted(self.__activeExtensions)
3208 self.__activeExtensions = [] 3305 self.__activeExtensions = []
3209 3306
3210 args = [] 3307 args = self.initCommand("showconfig")
3211 args.append('showconfig')
3212 args.append('extensions') 3308 args.append('extensions')
3213 3309
3214 output = "" 3310 output = ""
3215 if self.__client is None: 3311 if self.__client is None:
3216 process = QProcess() 3312 process = QProcess()
3313 self.__repoDir and process.setWorkingDirectory(self.__repoDir)
3217 process.start('hg', args) 3314 process.start('hg', args)
3218 procStarted = process.waitForStarted(5000) 3315 procStarted = process.waitForStarted(5000)
3219 if procStarted: 3316 if procStarted:
3220 finished = process.waitForFinished(30000) 3317 finished = process.waitForFinished(30000)
3221 if finished and process.exitCode() == 0: 3318 if finished and process.exitCode() == 0:
3222 output = str( 3319 output = str(process.readAllStandardOutput(),
3223 process.readAllStandardOutput(), 3320 self.getEncoding(), 'replace')
3224 Preferences.getSystem("IOEncoding"), 'replace')
3225 else: 3321 else:
3226 output, error = self.__client.runcommand(args) 3322 output, error = self.__client.runcommand(args)
3227 3323
3228 if output: 3324 if output:
3229 for line in output.splitlines(): 3325 for line in output.splitlines():
3246 @return flag indicating an active extension (boolean) 3342 @return flag indicating an active extension (boolean)
3247 """ 3343 """
3248 extensionName = extensionName.strip() 3344 extensionName = extensionName.strip()
3249 isActive = extensionName in self.__activeExtensions 3345 isActive = extensionName in self.__activeExtensions
3250 if isActive and \ 3346 if isActive and \
3251 extensionName == "transplant" and \ 3347 extensionName == "transplant" and \
3252 self.version >= (2, 3): 3348 self.version >= (2, 3):
3253 # transplant extension is deprecated as of Mercurial 2.3.0 3349 # transplant extension is deprecated as of Mercurial 2.3.0
3350 isActive = False
3351 if isActive and \
3352 extensionName == "shelve" and \
3353 self.version < (2, 8):
3354 # shelve extension was added as of Mercurial 2.8.0
3355 isActive = False
3356 if isActive and \
3357 extensionName == "largefiles" and \
3358 self.version < (2, 0):
3359 # largefiles extension was added as of Mercurial 2.0.0
3254 isActive = False 3360 isActive = False
3255 3361
3256 return isActive 3362 return isActive
3257 3363
3258 def getExtensionObject(self, extensionName): 3364 def getExtensionObject(self, extensionName):
3289 Public method to instantiate a helper object for the project. 3395 Public method to instantiate a helper object for the project.
3290 3396
3291 @param project reference to the project object 3397 @param project reference to the project object
3292 @return the project helper object 3398 @return the project helper object
3293 """ 3399 """
3400 # find the root of the repo
3401 repodir = project.getProjectPath()
3402 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
3403 repodir = os.path.dirname(repodir)
3404 if not repodir or os.path.splitdrive(repodir)[1] == os.sep:
3405 repodir = ""
3406 break
3407 if repodir:
3408 self.__repoDir = repodir
3409
3294 self.__projectHelper = self.__plugin.getProjectHelper() 3410 self.__projectHelper = self.__plugin.getProjectHelper()
3295 self.__projectHelper.setObjects(self, project) 3411 self.__projectHelper.setObjects(self, project)
3296 self.__monitorRepoIniFile(project.getProjectPath()) 3412 self.__monitorRepoIniFile(project.getProjectPath())
3297 3413
3298 if not Utilities.isMacPlatform() and self.version >= (1, 9): 3414 if not Utilities.isMacPlatform() and \
3299 # find the root of the repo 3415 self.version >= (1, 9) and \
3300 repodir = project.getProjectPath() 3416 repodir:
3301 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 3417 from .HgClient import HgClient
3302 repodir = os.path.dirname(repodir) 3418 client = HgClient(repodir, "utf-8", self)
3303 if not repodir or os.path.splitdrive(repodir)[1] == os.sep: 3419 ok, err = client.startServer()
3304 repodir = "" 3420 if ok:
3305 break 3421 self.__client = client
3306 if repodir: 3422 else:
3307 from .HgClient import HgClient 3423 E5MessageBox.warning(
3308 client = HgClient(repodir, "utf-8", self) 3424 None,
3309 ok, err = client.startServer() 3425 self.tr("Mercurial Command Server"),
3310 if ok: 3426 self.tr(
3311 self.__client = client 3427 """<p>The Mercurial Command Server could not be"""
3312 else: 3428 """ started.</p><p>Reason: {0}</p>""").format(err))
3313 E5MessageBox.warning(
3314 None,
3315 self.trUtf8("Mercurial Command Server"),
3316 self.trUtf8(
3317 """<p>The Mercurial Command Server could not be"""
3318 """ started.</p><p>Reason: {0}</p>""").format(err))
3319 3429
3320 return self.__projectHelper 3430 return self.__projectHelper
3321 3431
3322 ########################################################################### 3432 ###########################################################################
3323 ## Status Monitor Thread methods 3433 ## Status Monitor Thread methods

eric ide

mercurial