src/eric7/Plugins/VcsPlugins/vcsMercurial/hg.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9242
e406ed611e03
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
31 31
32 32
33 class Hg(VersionControl): 33 class Hg(VersionControl):
34 """ 34 """
35 Class implementing the version control systems interface to Mercurial. 35 Class implementing the version control systems interface to Mercurial.
36 36
37 @signal committed() emitted after the commit action has completed 37 @signal committed() emitted after the commit action has completed
38 @signal activeExtensionsChanged() emitted when the list of active 38 @signal activeExtensionsChanged() emitted when the list of active
39 extensions has changed 39 extensions has changed
40 @signal iniFileChanged() emitted when a Mercurial/repo configuration file 40 @signal iniFileChanged() emitted when a Mercurial/repo configuration file
41 has changed 41 has changed
42 """ 42 """
43
43 committed = pyqtSignal() 44 committed = pyqtSignal()
44 activeExtensionsChanged = pyqtSignal() 45 activeExtensionsChanged = pyqtSignal()
45 iniFileChanged = pyqtSignal() 46 iniFileChanged = pyqtSignal()
46 47
47 IgnoreFileName = ".hgignore" 48 IgnoreFileName = ".hgignore"
48 49
49 def __init__(self, plugin, parent=None, name=None): 50 def __init__(self, plugin, parent=None, name=None):
50 """ 51 """
51 Constructor 52 Constructor
52 53
53 @param plugin reference to the plugin object 54 @param plugin reference to the plugin object
54 @param parent parent widget (QWidget) 55 @param parent parent widget (QWidget)
55 @param name name of this object (string) 56 @param name name of this object (string)
56 """ 57 """
57 VersionControl.__init__(self, parent, name) 58 VersionControl.__init__(self, parent, name)
58 self.defaultOptions = { 59 self.defaultOptions = {
59 'global': [''], 60 "global": [""],
60 'commit': [''], 61 "commit": [""],
61 'checkout': [''], 62 "checkout": [""],
62 'update': [''], 63 "update": [""],
63 'add': [''], 64 "add": [""],
64 'remove': [''], 65 "remove": [""],
65 'diff': [''], 66 "diff": [""],
66 'log': [''], 67 "log": [""],
67 'history': [''], 68 "history": [""],
68 'status': [''], 69 "status": [""],
69 'tag': [''], 70 "tag": [""],
70 'export': [''] 71 "export": [""],
71 } 72 }
72 73
73 self.__plugin = plugin 74 self.__plugin = plugin
74 self.__ui = parent 75 self.__ui = parent
75 76
76 self.options = self.defaultOptions 77 self.options = self.defaultOptions
77 self.tagsList = [] 78 self.tagsList = []
78 self.branchesList = [] 79 self.branchesList = []
79 self.allTagsBranchesList = [] 80 self.allTagsBranchesList = []
80 self.bookmarksList = [] 81 self.bookmarksList = []
81 self.showedTags = False 82 self.showedTags = False
82 self.showedBranches = False 83 self.showedBranches = False
83 84
84 self.tagTypeList = [ 85 self.tagTypeList = [
85 'tags', 86 "tags",
86 'branches', 87 "branches",
87 ] 88 ]
88 89
89 self.commandHistory = [] 90 self.commandHistory = []
90 91
91 if "HG_ASP_DOT_NET_HACK" in os.environ: 92 if "HG_ASP_DOT_NET_HACK" in os.environ:
92 self.adminDir = '_hg' 93 self.adminDir = "_hg"
93 else: 94 else:
94 self.adminDir = '.hg' 95 self.adminDir = ".hg"
95 96
96 self.logBrowser = None 97 self.logBrowser = None
97 self.logBrowserIncoming = None 98 self.logBrowserIncoming = None
98 self.logBrowserOutgoing = None 99 self.logBrowserOutgoing = None
99 self.diff = None 100 self.diff = None
100 self.sbsDiff = None 101 self.sbsDiff = None
105 self.repoEditor = None 106 self.repoEditor = None
106 self.serveDlg = None 107 self.serveDlg = None
107 self.bookmarksListDlg = None 108 self.bookmarksListDlg = None
108 self.bookmarksInOutDlg = None 109 self.bookmarksInOutDlg = None
109 self.conflictsDlg = None 110 self.conflictsDlg = None
110 111
111 self.bundleFile = None 112 self.bundleFile = None
112 self.__lastChangeGroupPath = None 113 self.__lastChangeGroupPath = None
113 114
114 self.statusCache = {} 115 self.statusCache = {}
115 116
116 self.__commitData = {} 117 self.__commitData = {}
117 self.__commitDialog = None 118 self.__commitDialog = None
118 119
119 self.__forgotNames = [] 120 self.__forgotNames = []
120 121
121 self.__activeExtensions = [] 122 self.__activeExtensions = []
122 123
123 from .HgUtilities import getConfigPath 124 from .HgUtilities import getConfigPath
125
124 self.__iniWatcher = QFileSystemWatcher(self) 126 self.__iniWatcher = QFileSystemWatcher(self)
125 self.__iniWatcher.fileChanged.connect(self.__iniFileChanged) 127 self.__iniWatcher.fileChanged.connect(self.__iniFileChanged)
126 cfgFile = getConfigPath() 128 cfgFile = getConfigPath()
127 if os.path.exists(cfgFile): 129 if os.path.exists(cfgFile):
128 self.__iniWatcher.addPath(cfgFile) 130 self.__iniWatcher.addPath(cfgFile)
129 131
130 self.__client = None 132 self.__client = None
131 self.__createClient() 133 self.__createClient()
132 self.__projectHelper = None 134 self.__projectHelper = None
133 135
134 self.__repoDir = "" 136 self.__repoDir = ""
135 self.__repoIniFile = "" 137 self.__repoIniFile = ""
136 self.__defaultConfigured = False 138 self.__defaultConfigured = False
137 self.__defaultPushConfigured = False 139 self.__defaultPushConfigured = False
138 140
139 # instantiate the extensions 141 # instantiate the extensions
140 from .QueuesExtension.queues import Queues 142 from .QueuesExtension.queues import Queues
141 from .PurgeExtension.purge import Purge 143 from .PurgeExtension.purge import Purge
142 from .GpgExtension.gpg import Gpg 144 from .GpgExtension.gpg import Gpg
143 from .RebaseExtension.rebase import Rebase 145 from .RebaseExtension.rebase import Rebase
144 from .ShelveExtension.shelve import Shelve 146 from .ShelveExtension.shelve import Shelve
145 from .LargefilesExtension.largefiles import Largefiles 147 from .LargefilesExtension.largefiles import Largefiles
146 from .StripExtension.strip import Strip 148 from .StripExtension.strip import Strip
147 from .HisteditExtension.histedit import Histedit 149 from .HisteditExtension.histedit import Histedit
148 from .CloseheadExtension.closehead import Closehead 150 from .CloseheadExtension.closehead import Closehead
151
149 self.__extensions = { 152 self.__extensions = {
150 "mq": Queues(self), 153 "mq": Queues(self),
151 "purge": Purge(self), 154 "purge": Purge(self),
152 "gpg": Gpg(self), 155 "gpg": Gpg(self),
153 "rebase": Rebase(self), 156 "rebase": Rebase(self),
155 "largefiles": Largefiles(self), 158 "largefiles": Largefiles(self),
156 "strip": Strip(self), 159 "strip": Strip(self),
157 "histedit": Histedit(self), 160 "histedit": Histedit(self),
158 "closehead": Closehead(self), 161 "closehead": Closehead(self),
159 } 162 }
160 163
161 def getPlugin(self): 164 def getPlugin(self):
162 """ 165 """
163 Public method to get a reference to the plugin object. 166 Public method to get a reference to the plugin object.
164 167
165 @return reference to the plugin object (VcsMercurialPlugin) 168 @return reference to the plugin object (VcsMercurialPlugin)
166 """ 169 """
167 return self.__plugin 170 return self.__plugin
168 171
169 def getEncoding(self): 172 def getEncoding(self):
170 """ 173 """
171 Public method to get the encoding to be used by Mercurial. 174 Public method to get the encoding to be used by Mercurial.
172 175
173 @return encoding (string) 176 @return encoding (string)
174 """ 177 """
175 return self.__plugin.getPreferences("Encoding") 178 return self.__plugin.getPreferences("Encoding")
176 179
177 def vcsShutdown(self): 180 def vcsShutdown(self):
178 """ 181 """
179 Public method used to shutdown the Mercurial interface. 182 Public method used to shutdown the Mercurial interface.
180 """ 183 """
181 if self.logBrowser is not None: 184 if self.logBrowser is not None:
196 self.tagbranchList.close() 199 self.tagbranchList.close()
197 if self.annotate is not None: 200 if self.annotate is not None:
198 self.annotate.close() 201 self.annotate.close()
199 if self.serveDlg is not None: 202 if self.serveDlg is not None:
200 self.serveDlg.close() 203 self.serveDlg.close()
201 204
202 if self.bookmarksListDlg is not None: 205 if self.bookmarksListDlg is not None:
203 self.bookmarksListDlg.close() 206 self.bookmarksListDlg.close()
204 if self.bookmarksInOutDlg is not None: 207 if self.bookmarksInOutDlg is not None:
205 self.bookmarksInOutDlg.close() 208 self.bookmarksInOutDlg.close()
206 209
207 if self.conflictsDlg is not None: 210 if self.conflictsDlg is not None:
208 self.conflictsDlg.close() 211 self.conflictsDlg.close()
209 212
210 if self.bundleFile and os.path.exists(self.bundleFile): 213 if self.bundleFile and os.path.exists(self.bundleFile):
211 os.remove(self.bundleFile) 214 os.remove(self.bundleFile)
212 215
213 # shut down the project helpers 216 # shut down the project helpers
214 if self.__projectHelper is not None: 217 if self.__projectHelper is not None:
215 self.__projectHelper.shutdown() 218 self.__projectHelper.shutdown()
216 219
217 # shut down the extensions 220 # shut down the extensions
218 for extension in self.__extensions.values(): 221 for extension in self.__extensions.values():
219 extension.shutdown() 222 extension.shutdown()
220 223
221 # shut down the client 224 # shut down the client
222 self.__client and self.__client.stopServer() 225 self.__client and self.__client.stopServer()
223 226
224 def initCommand(self, command): 227 def initCommand(self, command):
225 """ 228 """
226 Public method to initialize a command arguments list. 229 Public method to initialize a command arguments list.
227 230
228 @param command command name (string) 231 @param command command name (string)
229 @return list of command options (list of string) 232 @return list of command options (list of string)
230 """ 233 """
231 args = [command] 234 args = [command]
232 self.addArguments(args, self.__plugin.getGlobalOptions()) 235 self.addArguments(args, self.__plugin.getGlobalOptions())
233 return args 236 return args
234 237
235 def vcsExists(self): 238 def vcsExists(self):
236 """ 239 """
237 Public method used to test for the presence of the hg executable. 240 Public method used to test for the presence of the hg executable.
238 241
239 @return flag indicating the existence (boolean) and an error message 242 @return flag indicating the existence (boolean) and an error message
240 (string) 243 (string)
241 """ 244 """
242 from .HgUtilities import hgVersion 245 from .HgUtilities import hgVersion
243 246
244 self.versionStr, self.version, errMsg = hgVersion(self.__plugin) 247 self.versionStr, self.version, errMsg = hgVersion(self.__plugin)
245 hgExists = errMsg == "" 248 hgExists = errMsg == ""
246 if hgExists: 249 if hgExists:
247 self.__getExtensionsInfo() 250 self.__getExtensionsInfo()
248 return hgExists, errMsg 251 return hgExists, errMsg
249 252
250 def vcsInit(self, vcsDir, noDialog=False): 253 def vcsInit(self, vcsDir, noDialog=False):
251 """ 254 """
252 Public method used to initialize the mercurial repository. 255 Public method used to initialize the mercurial repository.
253 256
254 The initialization is done, when a project is converted into a 257 The initialization is done, when a project is converted into a
255 Mercurial controlled project. Therefore we always return TRUE without 258 Mercurial controlled project. Therefore we always return TRUE without
256 doing anything. 259 doing anything.
257 260
258 @param vcsDir name of the VCS directory (string) 261 @param vcsDir name of the VCS directory (string)
259 @param noDialog flag indicating quiet operations (boolean) 262 @param noDialog flag indicating quiet operations (boolean)
260 @return always TRUE 263 @return always TRUE
261 """ 264 """
262 return True 265 return True
263 266
264 def vcsConvertProject(self, vcsDataDict, project, addAll=True): 267 def vcsConvertProject(self, vcsDataDict, project, addAll=True):
265 """ 268 """
266 Public method to convert an uncontrolled project to a version 269 Public method to convert an uncontrolled project to a version
267 controlled project. 270 controlled project.
268 271
269 @param vcsDataDict dictionary of data required for the conversion 272 @param vcsDataDict dictionary of data required for the conversion
270 @type dict 273 @type dict
271 @param project reference to the project object 274 @param project reference to the project object
272 @type Project 275 @type Project
273 @param addAll flag indicating to add all files to the repository 276 @param addAll flag indicating to add all files to the repository
276 success = self.vcsImport(vcsDataDict, project.ppath, addAll=addAll)[0] 279 success = self.vcsImport(vcsDataDict, project.ppath, addAll=addAll)[0]
277 if not success: 280 if not success:
278 EricMessageBox.critical( 281 EricMessageBox.critical(
279 self.__ui, 282 self.__ui,
280 self.tr("Create project repository"), 283 self.tr("Create project repository"),
281 self.tr( 284 self.tr("""The project repository could not be created."""),
282 """The project repository could not be created.""")) 285 )
283 else: 286 else:
284 pfn = project.pfile 287 pfn = project.pfile
285 if not os.path.isfile(pfn): 288 if not os.path.isfile(pfn):
286 pfn += "z" 289 pfn += "z"
287 project.closeProject() 290 project.closeProject()
288 project.openProject(pfn) 291 project.openProject(pfn)
289 292
290 def vcsImport(self, vcsDataDict, projectDir, noDialog=False, addAll=True): 293 def vcsImport(self, vcsDataDict, projectDir, noDialog=False, addAll=True):
291 """ 294 """
292 Public method used to import the project into the Mercurial repository. 295 Public method used to import the project into the Mercurial repository.
293 296
294 @param vcsDataDict dictionary of data required for the import 297 @param vcsDataDict dictionary of data required for the import
295 @type dict 298 @type dict
296 @param projectDir project directory (string) 299 @param projectDir project directory (string)
297 @type str 300 @type str
298 @param noDialog flag indicating quiet operations 301 @param noDialog flag indicating quiet operations
303 and a flag indicating the version controll status 306 and a flag indicating the version controll status
304 @rtype tuple of (bool, bool) 307 @rtype tuple of (bool, bool)
305 """ 308 """
306 msg = vcsDataDict["message"] 309 msg = vcsDataDict["message"]
307 if not msg: 310 if not msg:
308 msg = '***' 311 msg = "***"
309 312
310 args = self.initCommand("init") 313 args = self.initCommand("init")
311 args.append(projectDir) 314 args.append(projectDir)
312 dia = HgDialog(self.tr('Creating Mercurial repository'), self) 315 dia = HgDialog(self.tr("Creating Mercurial repository"), self)
313 res = dia.startProcess(args) 316 res = dia.startProcess(args)
314 if res: 317 if res:
315 dia.exec() 318 dia.exec()
316 status = dia.normalExit() 319 status = dia.normalExit()
317 320
318 if status: 321 if status:
319 self.stopClient() 322 self.stopClient()
320 self.__repoDir = projectDir 323 self.__repoDir = projectDir
321 324
322 ignoreName = os.path.join(projectDir, Hg.IgnoreFileName) 325 ignoreName = os.path.join(projectDir, Hg.IgnoreFileName)
323 if not os.path.exists(ignoreName): 326 if not os.path.exists(ignoreName):
324 status = self.hgCreateIgnoreFile(projectDir) 327 status = self.hgCreateIgnoreFile(projectDir)
325 328
326 if status and addAll: 329 if status and addAll:
327 args = self.initCommand("commit") 330 args = self.initCommand("commit")
328 args.append('--addremove') 331 args.append("--addremove")
329 args.append('--message') 332 args.append("--message")
330 args.append(msg) 333 args.append(msg)
331 dia = HgDialog( 334 dia = HgDialog(self.tr("Initial commit to Mercurial repository"), self)
332 self.tr('Initial commit to Mercurial repository'),
333 self)
334 res = dia.startProcess(args) 335 res = dia.startProcess(args)
335 if res: 336 if res:
336 dia.exec() 337 dia.exec()
337 status = dia.normalExit() 338 status = dia.normalExit()
338 339
339 return status, False 340 return status, False
340 341
341 def vcsCheckout(self, vcsDataDict, projectDir, noDialog=False): 342 def vcsCheckout(self, vcsDataDict, projectDir, noDialog=False):
342 """ 343 """
343 Public method used to check the project out of a Mercurial repository 344 Public method used to check the project out of a Mercurial repository
344 (clone). 345 (clone).
345 346
346 @param vcsDataDict dictionary of data required for the checkout 347 @param vcsDataDict dictionary of data required for the checkout
347 @param projectDir project directory to create (string) 348 @param projectDir project directory to create (string)
348 @param noDialog flag indicating quiet operations 349 @param noDialog flag indicating quiet operations
349 @return flag indicating an execution without errors (boolean) 350 @return flag indicating an execution without errors (boolean)
350 """ 351 """
352 try: 353 try:
353 rev = vcsDataDict["revision"] 354 rev = vcsDataDict["revision"]
354 except KeyError: 355 except KeyError:
355 rev = None 356 rev = None
356 vcsUrl = self.hgNormalizeURL(vcsDataDict["url"]) 357 vcsUrl = self.hgNormalizeURL(vcsDataDict["url"])
357 358
358 args = self.initCommand("clone") 359 args = self.initCommand("clone")
359 if rev: 360 if rev:
360 args.append("--rev") 361 args.append("--rev")
361 args.append(rev) 362 args.append(rev)
362 if vcsDataDict["largefiles"]: 363 if vcsDataDict["largefiles"]:
363 args.append("--all-largefiles") 364 args.append("--all-largefiles")
364 args.append(vcsUrl) 365 args.append(vcsUrl)
365 args.append(projectDir) 366 args.append(projectDir)
366 367
367 if noDialog: 368 if noDialog:
368 out, err = self.__client.runcommand(args) 369 out, err = self.__client.runcommand(args)
369 return err == "" 370 return err == ""
370 else: 371 else:
371 dia = HgDialog( 372 dia = HgDialog(self.tr("Cloning project from a Mercurial repository"), self)
372 self.tr('Cloning project from a Mercurial repository'),
373 self)
374 res = dia.startProcess(args) 373 res = dia.startProcess(args)
375 if res: 374 if res:
376 dia.exec() 375 dia.exec()
377 return dia.normalExit() 376 return dia.normalExit()
378 377
379 def vcsExport(self, vcsDataDict, projectDir): 378 def vcsExport(self, vcsDataDict, projectDir):
380 """ 379 """
381 Public method used to export a directory from the Mercurial repository. 380 Public method used to export a directory from the Mercurial repository.
382 381
383 @param vcsDataDict dictionary of data required for the checkout 382 @param vcsDataDict dictionary of data required for the checkout
384 @param projectDir project directory to create (string) 383 @param projectDir project directory to create (string)
385 @return flag indicating an execution without errors (boolean) 384 @return flag indicating an execution without errors (boolean)
386 """ 385 """
387 status = self.vcsCheckout(vcsDataDict, projectDir) 386 status = self.vcsCheckout(vcsDataDict, projectDir)
388 shutil.rmtree(os.path.join(projectDir, self.adminDir), True) 387 shutil.rmtree(os.path.join(projectDir, self.adminDir), True)
389 if os.path.exists(os.path.join(projectDir, Hg.IgnoreFileName)): 388 if os.path.exists(os.path.join(projectDir, Hg.IgnoreFileName)):
390 os.remove(os.path.join(projectDir, Hg.IgnoreFileName)) 389 os.remove(os.path.join(projectDir, Hg.IgnoreFileName))
391 return status 390 return status
392 391
393 def vcsCommit(self, name, message, noDialog=False, closeBranch=False, 392 def vcsCommit(
394 mq=False, merge=False): 393 self, name, message, noDialog=False, closeBranch=False, mq=False, merge=False
394 ):
395 """ 395 """
396 Public method used to make the change of a file/directory permanent 396 Public method used to make the change of a file/directory permanent
397 in the Mercurial repository. 397 in the Mercurial repository.
398 398
399 @param name file/directory name to be committed (string or list of 399 @param name file/directory name to be committed (string or list of
400 strings) 400 strings)
401 @param message message for this operation (string) 401 @param message message for this operation (string)
402 @param noDialog flag indicating quiet operations 402 @param noDialog flag indicating quiet operations
403 @param closeBranch flag indicating a close branch commit (boolean) 403 @param closeBranch flag indicating a close branch commit (boolean)
404 @param mq flag indicating a queue commit (boolean) 404 @param mq flag indicating a queue commit (boolean)
405 @param merge flag indicating a merge commit (boolean) 405 @param merge flag indicating a merge commit (boolean)
406 """ 406 """
407 msg = message 407 msg = message
408 408
409 if mq or merge: 409 if mq or merge:
410 # ensure dialog is shown for a queue commit 410 # ensure dialog is shown for a queue commit
411 noDialog = False 411 noDialog = False
412 412
413 if not noDialog: 413 if not noDialog:
414 # call CommitDialog and get message from there 414 # call CommitDialog and get message from there
415 if self.__commitDialog is None: 415 if self.__commitDialog is None:
416 from .HgCommitDialog import HgCommitDialog 416 from .HgCommitDialog import HgCommitDialog
417 self.__commitDialog = HgCommitDialog(self, msg, mq, merge, 417
418 self.__ui) 418 self.__commitDialog = HgCommitDialog(self, msg, mq, merge, self.__ui)
419 self.__commitDialog.accepted.connect(self.__vcsCommit_Step2) 419 self.__commitDialog.accepted.connect(self.__vcsCommit_Step2)
420 self.__commitDialog.show() 420 self.__commitDialog.show()
421 self.__commitDialog.raise_() 421 self.__commitDialog.raise_()
422 self.__commitDialog.activateWindow() 422 self.__commitDialog.activateWindow()
423 423
424 self.__commitData["name"] = name 424 self.__commitData["name"] = name
425 self.__commitData["msg"] = msg 425 self.__commitData["msg"] = msg
426 self.__commitData["noDialog"] = noDialog 426 self.__commitData["noDialog"] = noDialog
427 self.__commitData["closeBranch"] = closeBranch 427 self.__commitData["closeBranch"] = closeBranch
428 self.__commitData["mq"] = mq 428 self.__commitData["mq"] = mq
429 self.__commitData["merge"] = merge 429 self.__commitData["merge"] = merge
430 430
431 if noDialog: 431 if noDialog:
432 self.__vcsCommit_Step2() 432 self.__vcsCommit_Step2()
433 433
434 def __vcsCommit_Step2(self): 434 def __vcsCommit_Step2(self):
435 """ 435 """
436 Private slot performing the second step of the commit action. 436 Private slot performing the second step of the commit action.
437 """ 437 """
438 name = self.__commitData["name"] 438 name = self.__commitData["name"]
439 msg = self.__commitData["msg"] 439 msg = self.__commitData["msg"]
440 noDialog = self.__commitData["noDialog"] 440 noDialog = self.__commitData["noDialog"]
441 closeBranch = self.__commitData["closeBranch"] 441 closeBranch = self.__commitData["closeBranch"]
442 mq = self.__commitData["mq"] 442 mq = self.__commitData["mq"]
443 merge = self.__commitData["merge"] 443 merge = self.__commitData["merge"]
444 444
445 if not noDialog: 445 if not noDialog:
446 # check, if there are unsaved changes, that should be committed 446 # check, if there are unsaved changes, that should be committed
447 if isinstance(name, list): 447 if isinstance(name, list):
448 nameList = name 448 nameList = name
449 else: 449 else:
453 # check for commit of the project 453 # check for commit of the project
454 if os.path.isdir(nam): 454 if os.path.isdir(nam):
455 project = ericApp().getObject("Project") 455 project = ericApp().getObject("Project")
456 if nam == project.getProjectPath(): 456 if nam == project.getProjectPath():
457 ok &= ( 457 ok &= (
458 project.checkAllScriptsDirty( 458 project.checkAllScriptsDirty(reportSyntaxErrors=True)
459 reportSyntaxErrors=True) and 459 and project.checkDirty()
460 project.checkDirty()
461 ) 460 )
462 continue 461 continue
463 elif os.path.isfile(nam): 462 elif os.path.isfile(nam):
464 editor = ( 463 editor = ericApp().getObject("ViewManager").getOpenEditor(nam)
465 ericApp().getObject("ViewManager").getOpenEditor(nam)
466 )
467 if editor: 464 if editor:
468 ok &= editor.checkDirty() 465 ok &= editor.checkDirty()
469 if not ok: 466 if not ok:
470 break 467 break
471 468
472 if not ok: 469 if not ok:
473 res = EricMessageBox.yesNo( 470 res = EricMessageBox.yesNo(
474 self.__ui, 471 self.__ui,
475 self.tr("Commit Changes"), 472 self.tr("Commit Changes"),
476 self.tr( 473 self.tr(
477 """The commit affects files, that have unsaved""" 474 """The commit affects files, that have unsaved"""
478 """ changes. Shall the commit be continued?"""), 475 """ changes. Shall the commit be continued?"""
479 icon=EricMessageBox.Warning) 476 ),
477 icon=EricMessageBox.Warning,
478 )
480 if not res: 479 if not res:
481 return 480 return
482 481
483 if self.__commitDialog is not None: 482 if self.__commitDialog is not None:
484 (msg, amend, commitSubrepositories, author, 483 (
485 dateTime) = self.__commitDialog.getCommitData() 484 msg,
485 amend,
486 commitSubrepositories,
487 author,
488 dateTime,
489 ) = self.__commitDialog.getCommitData()
486 self.__commitDialog.deleteLater() 490 self.__commitDialog.deleteLater()
487 self.__commitDialog = None 491 self.__commitDialog = None
488 if amend and not msg: 492 if amend and not msg:
489 msg = self.__getMostRecentCommitMessage() 493 msg = self.__getMostRecentCommitMessage()
490 else: 494 else:
491 amend = False 495 amend = False
492 commitSubrepositories = False 496 commitSubrepositories = False
493 author = "" 497 author = ""
494 dateTime = "" 498 dateTime = ""
495 499
496 if not msg and not amend: 500 if not msg and not amend:
497 msg = '***' 501 msg = "***"
498 502
499 args = self.initCommand("commit") 503 args = self.initCommand("commit")
500 args.append("-v") 504 args.append("-v")
501 if mq: 505 if mq:
502 args.append("--mq") 506 args.append("--mq")
503 elif merge: 507 elif merge:
525 args.append(msg) 529 args.append(msg)
526 if isinstance(name, list): 530 if isinstance(name, list):
527 self.addArguments(args, name) 531 self.addArguments(args, name)
528 else: 532 else:
529 args.append(name) 533 args.append(name)
530 534
531 dia = HgDialog( 535 dia = HgDialog(self.tr("Committing changes to Mercurial repository"), self)
532 self.tr('Committing changes to Mercurial repository'),
533 self)
534 res = dia.startProcess(args) 536 res = dia.startProcess(args)
535 if res: 537 if res:
536 dia.exec() 538 dia.exec()
537 self.committed.emit() 539 self.committed.emit()
538 if self.__forgotNames: 540 if self.__forgotNames:
539 model = ericApp().getObject("Project").getModel() 541 model = ericApp().getObject("Project").getModel()
540 for name in self.__forgotNames: 542 for name in self.__forgotNames:
541 model.updateVCSStatus(name) 543 model.updateVCSStatus(name)
542 self.__forgotNames = [] 544 self.__forgotNames = []
543 self.checkVCSStatus() 545 self.checkVCSStatus()
544 546
545 def vcsCommitMessages(self): 547 def vcsCommitMessages(self):
546 """ 548 """
547 Public method to get the list of saved commit messages. 549 Public method to get the list of saved commit messages.
548 550
549 @return list of saved commit messages 551 @return list of saved commit messages
550 @rtype list of str 552 @rtype list of str
551 """ 553 """
552 # try per project commit history first 554 # try per project commit history first
553 messages = self._vcsProjectCommitMessages() 555 messages = self._vcsProjectCommitMessages()
554 if not messages: 556 if not messages:
555 # empty list returned, try the vcs specific one 557 # empty list returned, try the vcs specific one
556 messages = self.getPlugin().getPreferences('Commits') 558 messages = self.getPlugin().getPreferences("Commits")
557 559
558 return messages 560 return messages
559 561
560 def vcsAddCommitMessage(self, message): 562 def vcsAddCommitMessage(self, message):
561 """ 563 """
562 Public method to add a commit message to the list of saved messages. 564 Public method to add a commit message to the list of saved messages.
563 565
564 @param message message to be added 566 @param message message to be added
565 @type str 567 @type str
566 """ 568 """
567 if not self._vcsAddProjectCommitMessage(message): 569 if not self._vcsAddProjectCommitMessage(message):
568 commitMessages = self.vcsCommitMessages() 570 commitMessages = self.vcsCommitMessages()
569 if message in commitMessages: 571 if message in commitMessages:
570 commitMessages.remove(message) 572 commitMessages.remove(message)
571 commitMessages.insert(0, message) 573 commitMessages.insert(0, message)
572 no = Preferences.getVCS("CommitMessages") 574 no = Preferences.getVCS("CommitMessages")
573 del commitMessages[no:] 575 del commitMessages[no:]
574 self.getPlugin().setPreferences('Commits', commitMessages) 576 self.getPlugin().setPreferences("Commits", commitMessages)
575 577
576 def vcsClearCommitMessages(self): 578 def vcsClearCommitMessages(self):
577 """ 579 """
578 Public method to clear the list of saved messages. 580 Public method to clear the list of saved messages.
579 """ 581 """
580 if not self._vcsClearProjectCommitMessages(): 582 if not self._vcsClearProjectCommitMessages():
581 self.getPlugin().setPreferences('Commits', []) 583 self.getPlugin().setPreferences("Commits", [])
582 584
583 def __getMostRecentCommitMessage(self): 585 def __getMostRecentCommitMessage(self):
584 """ 586 """
585 Private method to get the most recent commit message. 587 Private method to get the most recent commit message.
586 588
587 Note: This message is extracted from the parent commit of the 589 Note: This message is extracted from the parent commit of the
588 working directory. 590 working directory.
589 591
590 @return most recent commit message 592 @return most recent commit message
591 @rtype str 593 @rtype str
592 """ 594 """
593 args = self.initCommand("log") 595 args = self.initCommand("log")
594 args.append("--rev") 596 args.append("--rev")
595 args.append(".") 597 args.append(".")
596 args.append('--template') 598 args.append("--template")
597 args.append('{desc}') 599 args.append("{desc}")
598 600
599 output, error = self.__client.runcommand(args) 601 output, error = self.__client.runcommand(args)
600 602
601 return output 603 return output
602 604
603 def vcsUpdate(self, name=None, noDialog=False, revision=None): 605 def vcsUpdate(self, name=None, noDialog=False, revision=None):
604 """ 606 """
605 Public method used to update a file/directory with the Mercurial 607 Public method used to update a file/directory with the Mercurial
606 repository. 608 repository.
607 609
608 @param name file/directory name to be updated (not used) 610 @param name file/directory name to be updated (not used)
609 @param noDialog flag indicating quiet operations (boolean) 611 @param noDialog flag indicating quiet operations (boolean)
610 @param revision revision to update to (string) 612 @param revision revision to update to (string)
611 @return flag indicating, that the update contained an add 613 @return flag indicating, that the update contained an add
612 or delete (boolean) 614 or delete (boolean)
615 if "-v" not in args and "--verbose" not in args: 617 if "-v" not in args and "--verbose" not in args:
616 args.append("-v") 618 args.append("-v")
617 if revision: 619 if revision:
618 args.append("-r") 620 args.append("-r")
619 args.append(revision) 621 args.append(revision)
620 622
621 if noDialog: 623 if noDialog:
622 out, err = self.__client.runcommand(args) 624 out, err = self.__client.runcommand(args)
623 res = False 625 res = False
624 else: 626 else:
625 dia = HgDialog(self.tr( 627 dia = HgDialog(self.tr("Synchronizing with the Mercurial repository"), self)
626 'Synchronizing with the Mercurial repository'),
627 self)
628 res = dia.startProcess(args) 628 res = dia.startProcess(args)
629 if res: 629 if res:
630 dia.exec() 630 dia.exec()
631 res = dia.hasAddOrDelete() 631 res = dia.hasAddOrDelete()
632 self.checkVCSStatus() 632 self.checkVCSStatus()
633 return res 633 return res
634 634
635 def vcsAdd(self, name, isDir=False, noDialog=False): 635 def vcsAdd(self, name, isDir=False, noDialog=False):
636 """ 636 """
637 Public method used to add a file/directory to the Mercurial repository. 637 Public method used to add a file/directory to the Mercurial repository.
638 638
639 @param name file/directory name to be added (string) 639 @param name file/directory name to be added (string)
640 @param isDir flag indicating name is a directory (boolean) 640 @param isDir flag indicating name is a directory (boolean)
641 @param noDialog flag indicating quiet operations 641 @param noDialog flag indicating quiet operations
642 """ 642 """
643 args = self.initCommand("add") 643 args = self.initCommand("add")
644 args.append("-v") 644 args.append("-v")
645 645
646 if isinstance(name, list): 646 if isinstance(name, list):
647 self.addArguments(args, name) 647 self.addArguments(args, name)
648 else: 648 else:
649 args.append(name) 649 args.append(name)
650 650
651 if noDialog: 651 if noDialog:
652 out, err = self.__client.runcommand(args) 652 out, err = self.__client.runcommand(args)
653 else: 653 else:
654 dia = HgDialog( 654 dia = HgDialog(
655 self.tr( 655 self.tr("Adding files/directories to the Mercurial repository"), self
656 'Adding files/directories to the Mercurial repository'), 656 )
657 self)
658 res = dia.startProcess(args) 657 res = dia.startProcess(args)
659 if res: 658 if res:
660 dia.exec() 659 dia.exec()
661 660
662 def vcsAddBinary(self, name, isDir=False): 661 def vcsAddBinary(self, name, isDir=False):
663 """ 662 """
664 Public method used to add a file/directory in binary mode to the 663 Public method used to add a file/directory in binary mode to the
665 Mercurial repository. 664 Mercurial repository.
666 665
667 @param name file/directory name to be added (string) 666 @param name file/directory name to be added (string)
668 @param isDir flag indicating name is a directory (boolean) 667 @param isDir flag indicating name is a directory (boolean)
669 """ 668 """
670 self.vcsAdd(name, isDir) 669 self.vcsAdd(name, isDir)
671 670
672 def vcsAddTree(self, path): 671 def vcsAddTree(self, path):
673 """ 672 """
674 Public method to add a directory tree rooted at path to the Mercurial 673 Public method to add a directory tree rooted at path to the Mercurial
675 repository. 674 repository.
676 675
677 @param path root directory of the tree to be added (string or list of 676 @param path root directory of the tree to be added (string or list of
678 strings)) 677 strings))
679 """ 678 """
680 self.vcsAdd(path, isDir=False) 679 self.vcsAdd(path, isDir=False)
681 680
682 def vcsRemove(self, name, project=False, noDialog=False): 681 def vcsRemove(self, name, project=False, noDialog=False):
683 """ 682 """
684 Public method used to remove a file/directory from the Mercurial 683 Public method used to remove a file/directory from the Mercurial
685 repository. 684 repository.
686 685
687 The default operation is to remove the local copy as well. 686 The default operation is to remove the local copy as well.
688 687
689 @param name file/directory name to be removed (string or list of 688 @param name file/directory name to be removed (string or list of
690 strings)) 689 strings))
691 @param project flag indicating deletion of a project tree (boolean) 690 @param project flag indicating deletion of a project tree (boolean)
692 (not needed) 691 (not needed)
693 @param noDialog flag indicating quiet operations 692 @param noDialog flag indicating quiet operations
694 @return flag indicating successfull operation (boolean) 693 @return flag indicating successfull operation (boolean)
695 """ 694 """
696 args = self.initCommand("remove") 695 args = self.initCommand("remove")
697 args.append("-v") 696 args.append("-v")
698 if noDialog and '--force' not in args: 697 if noDialog and "--force" not in args:
699 args.append('--force') 698 args.append("--force")
700 699
701 if isinstance(name, list): 700 if isinstance(name, list):
702 self.addArguments(args, name) 701 self.addArguments(args, name)
703 else: 702 else:
704 args.append(name) 703 args.append(name)
705 704
706 if noDialog: 705 if noDialog:
707 out, err = self.__client.runcommand(args) 706 out, err = self.__client.runcommand(args)
708 res = err == "" 707 res = err == ""
709 else: 708 else:
710 dia = HgDialog( 709 dia = HgDialog(
711 self.tr( 710 self.tr("Removing files/directories from the Mercurial" " repository"),
712 'Removing files/directories from the Mercurial' 711 self,
713 ' repository'), 712 )
714 self)
715 res = dia.startProcess(args) 713 res = dia.startProcess(args)
716 if res: 714 if res:
717 dia.exec() 715 dia.exec()
718 res = dia.normalExitWithoutErrors() 716 res = dia.normalExitWithoutErrors()
719 717
720 return res 718 return res
721 719
722 def vcsMove(self, name, project, target=None, noDialog=False): 720 def vcsMove(self, name, project, target=None, noDialog=False):
723 """ 721 """
724 Public method used to move a file/directory. 722 Public method used to move a file/directory.
725 723
726 @param name file/directory name to be moved (string) 724 @param name file/directory name to be moved (string)
727 @param project reference to the project object 725 @param project reference to the project object
728 @param target new name of the file/directory (string) 726 @param target new name of the file/directory (string)
729 @param noDialog flag indicating quiet operations 727 @param noDialog flag indicating quiet operations
730 @return flag indicating successfull operation (boolean) 728 @return flag indicating successfull operation (boolean)
731 """ 729 """
732 isDir = os.path.isdir(name) 730 isDir = os.path.isdir(name)
733 731
734 res = False 732 res = False
735 if noDialog: 733 if noDialog:
736 if target is None: 734 if target is None:
737 return False 735 return False
738 force = True 736 force = True
739 accepted = True 737 accepted = True
740 else: 738 else:
741 from .HgCopyDialog import HgCopyDialog 739 from .HgCopyDialog import HgCopyDialog
740
742 dlg = HgCopyDialog(name, None, True) 741 dlg = HgCopyDialog(name, None, True)
743 accepted = dlg.exec() == QDialog.DialogCode.Accepted 742 accepted = dlg.exec() == QDialog.DialogCode.Accepted
744 if accepted: 743 if accepted:
745 target, force = dlg.getData() 744 target, force = dlg.getData()
746 745
747 if accepted: 746 if accepted:
748 args = self.initCommand("rename") 747 args = self.initCommand("rename")
749 args.append("-v") 748 args.append("-v")
750 if force: 749 if force:
751 args.append('--force') 750 args.append("--force")
752 args.append(name) 751 args.append(name)
753 args.append(target) 752 args.append(target)
754 753
755 if noDialog: 754 if noDialog:
756 out, err = self.__client.runcommand(args) 755 out, err = self.__client.runcommand(args)
757 res = err == "" 756 res = err == ""
758 else: 757 else:
759 dia = HgDialog(self.tr('Renaming {0}').format(name), self) 758 dia = HgDialog(self.tr("Renaming {0}").format(name), self)
760 res = dia.startProcess(args) 759 res = dia.startProcess(args)
761 if res: 760 if res:
762 dia.exec() 761 dia.exec()
763 res = dia.normalExit() 762 res = dia.normalExit()
764 if res: 763 if res:
771 if isDir: 770 if isDir:
772 project.removeDirectory(name) 771 project.removeDirectory(name)
773 else: 772 else:
774 project.removeFile(name) 773 project.removeFile(name)
775 return res 774 return res
776 775
777 def vcsDiff(self, name): 776 def vcsDiff(self, name):
778 """ 777 """
779 Public method used to view the difference of a file/directory to the 778 Public method used to view the difference of a file/directory to the
780 Mercurial repository. 779 Mercurial repository.
781 780
782 If name is a directory and is the project directory, all project files 781 If name is a directory and is the project directory, all project files
783 are saved first. If name is a file (or list of files), which is/are 782 are saved first. If name is a file (or list of files), which is/are
784 being edited and has unsaved modification, they can be saved or the 783 being edited and has unsaved modification, they can be saved or the
785 operation may be aborted. 784 operation may be aborted.
786 785
787 @param name file/directory name to be diffed (string) 786 @param name file/directory name to be diffed (string)
788 """ 787 """
789 names = name[:] if isinstance(name, list) else [name] 788 names = name[:] if isinstance(name, list) else [name]
790 for nam in names: 789 for nam in names:
791 if os.path.isfile(nam): 790 if os.path.isfile(nam):
796 project = ericApp().getObject("Project") 795 project = ericApp().getObject("Project")
797 if nam == project.ppath and not project.saveAllScripts(): 796 if nam == project.ppath and not project.saveAllScripts():
798 return 797 return
799 if self.diff is None: 798 if self.diff is None:
800 from .HgDiffDialog import HgDiffDialog 799 from .HgDiffDialog import HgDiffDialog
800
801 self.diff = HgDiffDialog(self) 801 self.diff = HgDiffDialog(self)
802 self.diff.show() 802 self.diff.show()
803 self.diff.raise_() 803 self.diff.raise_()
804 QApplication.processEvents() 804 QApplication.processEvents()
805 self.diff.start(name, refreshable=True) 805 self.diff.start(name, refreshable=True)
806 806
807 def vcsStatus(self, name): 807 def vcsStatus(self, name):
808 """ 808 """
809 Public method used to view the status of files/directories in the 809 Public method used to view the status of files/directories in the
810 Mercurial repository. 810 Mercurial repository.
811 811
812 @param name file/directory name(s) to show the status of 812 @param name file/directory name(s) to show the status of
813 (string or list of strings) 813 (string or list of strings)
814 """ 814 """
815 if self.status is None: 815 if self.status is None:
816 from .HgStatusDialog import HgStatusDialog 816 from .HgStatusDialog import HgStatusDialog
817
817 self.status = HgStatusDialog(self) 818 self.status = HgStatusDialog(self)
818 self.status.show() 819 self.status.show()
819 self.status.raise_() 820 self.status.raise_()
820 self.status.start(name) 821 self.status.start(name)
821 822
822 def hgSummary(self, mq=False, largefiles=False): 823 def hgSummary(self, mq=False, largefiles=False):
823 """ 824 """
824 Public method used to show some summary information of the 825 Public method used to show some summary information of the
825 working directory state. 826 working directory state.
826 827
827 @param mq flag indicating to show the queue status as well (boolean) 828 @param mq flag indicating to show the queue status as well (boolean)
828 @param largefiles flag indicating to show the largefiles status as 829 @param largefiles flag indicating to show the largefiles status as
829 well (boolean) 830 well (boolean)
830 """ 831 """
831 if self.summary is None: 832 if self.summary is None:
832 from .HgSummaryDialog import HgSummaryDialog 833 from .HgSummaryDialog import HgSummaryDialog
834
833 self.summary = HgSummaryDialog(self) 835 self.summary = HgSummaryDialog(self)
834 self.summary.show() 836 self.summary.show()
835 self.summary.raise_() 837 self.summary.raise_()
836 self.summary.start(mq=mq, largefiles=largefiles) 838 self.summary.start(mq=mq, largefiles=largefiles)
837 839
838 def vcsTag(self, name=None, revision=None, tagName=None): 840 def vcsTag(self, name=None, revision=None, tagName=None):
839 """ 841 """
840 Public method used to set/remove a tag in the Mercurial repository. 842 Public method used to set/remove a tag in the Mercurial repository.
841 843
842 @param name file/directory name to determine the repo root from 844 @param name file/directory name to determine the repo root from
843 (string) 845 (string)
844 @param revision revision to set tag for (string) 846 @param revision revision to set tag for (string)
845 @param tagName name of the tag (string) 847 @param tagName name of the tag (string)
846 @return flag indicating a performed tag action (boolean) 848 @return flag indicating a performed tag action (boolean)
847 """ 849 """
848 from .HgTagDialog import HgTagDialog 850 from .HgTagDialog import HgTagDialog
849 dlg = HgTagDialog(self.hgGetTagsList(withType=True), 851
850 revision, tagName) 852 dlg = HgTagDialog(self.hgGetTagsList(withType=True), revision, tagName)
851 if dlg.exec() == QDialog.DialogCode.Accepted: 853 if dlg.exec() == QDialog.DialogCode.Accepted:
852 tag, revision, tagOp, force = dlg.getParameters() 854 tag, revision, tagOp, force = dlg.getParameters()
853 else: 855 else:
854 return False 856 return False
855 857
856 args = self.initCommand("tag") 858 args = self.initCommand("tag")
857 msgPart = "" 859 msgPart = ""
858 if tagOp in [HgTagDialog.CreateLocalTag, HgTagDialog.DeleteLocalTag]: 860 if tagOp in [HgTagDialog.CreateLocalTag, HgTagDialog.DeleteLocalTag]:
859 args.append('--local') 861 args.append("--local")
860 msgPart = "local " 862 msgPart = "local "
861 else: 863 else:
862 msgPart = "global " 864 msgPart = "global "
863 if tagOp in [HgTagDialog.DeleteGlobalTag, HgTagDialog.DeleteLocalTag]: 865 if tagOp in [HgTagDialog.DeleteGlobalTag, HgTagDialog.DeleteLocalTag]:
864 args.append('--remove') 866 args.append("--remove")
865 if ( 867 if (
866 tagOp in [ 868 tagOp in [HgTagDialog.CreateGlobalTag, HgTagDialog.CreateLocalTag]
867 HgTagDialog.CreateGlobalTag, HgTagDialog.CreateLocalTag] and 869 and revision
868 revision
869 ): 870 ):
870 args.append("--rev") 871 args.append("--rev")
871 args.append(revision) 872 args.append(revision)
872 if force: 873 if force:
873 args.append("--force") 874 args.append("--force")
874 args.append('--message') 875 args.append("--message")
875 if tagOp in [HgTagDialog.CreateGlobalTag, HgTagDialog.CreateLocalTag]: 876 if tagOp in [HgTagDialog.CreateGlobalTag, HgTagDialog.CreateLocalTag]:
876 tag = tag.strip().replace(" ", "_") 877 tag = tag.strip().replace(" ", "_")
877 args.append("Created {1}tag <{0}>.".format(tag, msgPart)) 878 args.append("Created {1}tag <{0}>.".format(tag, msgPart))
878 else: 879 else:
879 args.append("Removed {1}tag <{0}>.".format(tag, msgPart)) 880 args.append("Removed {1}tag <{0}>.".format(tag, msgPart))
880 args.append(tag) 881 args.append(tag)
881 882
882 dia = HgDialog(self.tr('Tagging in the Mercurial repository'), 883 dia = HgDialog(self.tr("Tagging in the Mercurial repository"), self)
883 self)
884 res = dia.startProcess(args) 884 res = dia.startProcess(args)
885 if res: 885 if res:
886 dia.exec() 886 dia.exec()
887 887
888 return True 888 return True
889 889
890 def vcsRevert(self, name): 890 def vcsRevert(self, name):
891 """ 891 """
892 Public method used to revert changes made to a file/directory. 892 Public method used to revert changes made to a file/directory.
893 893
894 @param name file/directory name to be reverted 894 @param name file/directory name to be reverted
895 @type str 895 @type str
896 @return flag indicating, that the update contained an add 896 @return flag indicating, that the update contained an add
897 or delete 897 or delete
898 @rtype bool 898 @rtype bool
905 self.addArguments(args, name) 905 self.addArguments(args, name)
906 names = name[:] 906 names = name[:]
907 else: 907 else:
908 args.append(name) 908 args.append(name)
909 names = [name] 909 names = [name]
910 910
911 project = ericApp().getObject("Project") 911 project = ericApp().getObject("Project")
912 names = [project.getRelativePath(nam) for nam in names] 912 names = [project.getRelativePath(nam) for nam in names]
913 if names[0]: 913 if names[0]:
914 from UI.DeleteFilesConfirmationDialog import ( 914 from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog
915 DeleteFilesConfirmationDialog 915
916 )
917 dlg = DeleteFilesConfirmationDialog( 916 dlg = DeleteFilesConfirmationDialog(
918 self.parent(), 917 self.parent(),
919 self.tr("Revert changes"), 918 self.tr("Revert changes"),
920 self.tr( 919 self.tr(
921 "Do you really want to revert all changes to these files" 920 "Do you really want to revert all changes to these files"
922 " or directories?"), 921 " or directories?"
923 names) 922 ),
923 names,
924 )
924 yes = dlg.exec() == QDialog.DialogCode.Accepted 925 yes = dlg.exec() == QDialog.DialogCode.Accepted
925 else: 926 else:
926 yes = EricMessageBox.yesNo( 927 yes = EricMessageBox.yesNo(
927 None, 928 None,
928 self.tr("Revert changes"), 929 self.tr("Revert changes"),
929 self.tr("""Do you really want to revert all changes of""" 930 self.tr(
930 """ the project?""")) 931 """Do you really want to revert all changes of"""
932 """ the project?"""
933 ),
934 )
931 if yes: 935 if yes:
932 dia = HgDialog(self.tr('Reverting changes'), self) 936 dia = HgDialog(self.tr("Reverting changes"), self)
933 res = dia.startProcess(args) 937 res = dia.startProcess(args)
934 if res: 938 if res:
935 dia.exec() 939 dia.exec()
936 res = dia.hasAddOrDelete() 940 res = dia.hasAddOrDelete()
937 self.checkVCSStatus() 941 self.checkVCSStatus()
938 else: 942 else:
939 res = False 943 res = False
940 944
941 return res 945 return res
942 946
943 def vcsMerge(self, name, rev=""): 947 def vcsMerge(self, name, rev=""):
944 """ 948 """
945 Public method used to merge a URL/revision into the local project. 949 Public method used to merge a URL/revision into the local project.
946 950
947 @param name file/directory name to be merged 951 @param name file/directory name to be merged
948 @type str 952 @type str
949 @param rev revision to merge with 953 @param rev revision to merge with
950 @type str 954 @type str
951 """ 955 """
952 if not rev: 956 if not rev:
953 from .HgMergeDialog import HgMergeDialog 957 from .HgMergeDialog import HgMergeDialog
954 dlg = HgMergeDialog(self.hgGetTagsList(), 958
955 self.hgGetBranchesList(), 959 dlg = HgMergeDialog(
956 self.hgGetBookmarksList()) 960 self.hgGetTagsList(),
961 self.hgGetBranchesList(),
962 self.hgGetBookmarksList(),
963 )
957 if dlg.exec() == QDialog.DialogCode.Accepted: 964 if dlg.exec() == QDialog.DialogCode.Accepted:
958 rev, force = dlg.getParameters() 965 rev, force = dlg.getParameters()
959 else: 966 else:
960 return 967 return
961 else: 968 else:
962 force = False 969 force = False
963 970
964 args = self.initCommand("merge") 971 args = self.initCommand("merge")
965 if force: 972 if force:
966 args.append("--force") 973 args.append("--force")
967 if self.getPlugin().getPreferences("InternalMerge"): 974 if self.getPlugin().getPreferences("InternalMerge"):
968 args.append("--tool") 975 args.append("--tool")
969 args.append("internal:merge") 976 args.append("internal:merge")
970 if rev: 977 if rev:
971 args.append("--rev") 978 args.append("--rev")
972 args.append(rev) 979 args.append(rev)
973 980
974 dia = HgDialog(self.tr('Merging'), self) 981 dia = HgDialog(self.tr("Merging"), self)
975 res = dia.startProcess(args) 982 res = dia.startProcess(args)
976 if res: 983 if res:
977 dia.exec() 984 dia.exec()
978 self.checkVCSStatus() 985 self.checkVCSStatus()
979 986
980 def hgReMerge(self, name): 987 def hgReMerge(self, name):
981 """ 988 """
982 Public method used to merge a URL/revision into the local project. 989 Public method used to merge a URL/revision into the local project.
983 990
984 @param name file/directory name to be merged (string) 991 @param name file/directory name to be merged (string)
985 """ 992 """
986 args = self.initCommand("resolve") 993 args = self.initCommand("resolve")
987 if self.getPlugin().getPreferences("InternalMerge"): 994 if self.getPlugin().getPreferences("InternalMerge"):
988 args.append("--tool") 995 args.append("--tool")
991 self.addArguments(args, name) 998 self.addArguments(args, name)
992 names = name[:] 999 names = name[:]
993 else: 1000 else:
994 args.append(name) 1001 args.append(name)
995 names = [name] 1002 names = [name]
996 1003
997 project = ericApp().getObject("Project") 1004 project = ericApp().getObject("Project")
998 names = [project.getRelativePath(nam) for nam in names] 1005 names = [project.getRelativePath(nam) for nam in names]
999 if names[0]: 1006 if names[0]:
1000 from UI.DeleteFilesConfirmationDialog import ( 1007 from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog
1001 DeleteFilesConfirmationDialog 1008
1002 )
1003 dlg = DeleteFilesConfirmationDialog( 1009 dlg = DeleteFilesConfirmationDialog(
1004 self.parent(), 1010 self.parent(),
1005 self.tr("Re-Merge"), 1011 self.tr("Re-Merge"),
1006 self.tr( 1012 self.tr(
1007 "Do you really want to re-merge these files" 1013 "Do you really want to re-merge these files" " or directories?"
1008 " or directories?"), 1014 ),
1009 names) 1015 names,
1016 )
1010 yes = dlg.exec() == QDialog.DialogCode.Accepted 1017 yes = dlg.exec() == QDialog.DialogCode.Accepted
1011 else: 1018 else:
1012 yes = EricMessageBox.yesNo( 1019 yes = EricMessageBox.yesNo(
1013 None, 1020 None,
1014 self.tr("Re-Merge"), 1021 self.tr("Re-Merge"),
1015 self.tr("""Do you really want to re-merge the project?""")) 1022 self.tr("""Do you really want to re-merge the project?"""),
1023 )
1016 if yes: 1024 if yes:
1017 dia = HgDialog(self.tr('Re-Merging').format(name), self) 1025 dia = HgDialog(self.tr("Re-Merging").format(name), self)
1018 res = dia.startProcess(args) 1026 res = dia.startProcess(args)
1019 if res: 1027 if res:
1020 dia.exec() 1028 dia.exec()
1021 self.checkVCSStatus() 1029 self.checkVCSStatus()
1022 1030
1023 def vcsSwitch(self, name): 1031 def vcsSwitch(self, name):
1024 """ 1032 """
1025 Public method used to switch a working directory to a different 1033 Public method used to switch a working directory to a different
1026 revision. 1034 revision.
1027 1035
1028 @param name directory name to be switched (string) 1036 @param name directory name to be switched (string)
1029 @return flag indicating, that the switch contained an add 1037 @return flag indicating, that the switch contained an add
1030 or delete (boolean) 1038 or delete (boolean)
1031 """ 1039 """
1032 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog 1040 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog
1041
1033 dlg = HgRevisionSelectionDialog( 1042 dlg = HgRevisionSelectionDialog(
1034 self.hgGetTagsList(), 1043 self.hgGetTagsList(),
1035 self.hgGetBranchesList(), 1044 self.hgGetBranchesList(),
1036 bookmarksList=self.hgGetBookmarksList(), 1045 bookmarksList=self.hgGetBookmarksList(),
1037 noneLabel=self.tr("Current branch tip") 1046 noneLabel=self.tr("Current branch tip"),
1038 ) 1047 )
1039 if dlg.exec() == QDialog.DialogCode.Accepted: 1048 if dlg.exec() == QDialog.DialogCode.Accepted:
1040 rev = dlg.getRevision() 1049 rev = dlg.getRevision()
1041 return self.vcsUpdate(name, revision=rev) 1050 return self.vcsUpdate(name, revision=rev)
1042 1051
1043 return False 1052 return False
1044 1053
1045 def vcsRegisteredState(self, name): 1054 def vcsRegisteredState(self, name):
1046 """ 1055 """
1047 Public method used to get the registered state of a file in the vcs. 1056 Public method used to get the registered state of a file in the vcs.
1048 1057
1049 @param name file or directory name to check 1058 @param name file or directory name to check
1050 @type str 1059 @type str
1051 @return a combination of canBeCommited and canBeAdded 1060 @return a combination of canBeCommited and canBeAdded
1052 @rtype int 1061 @rtype int
1053 """ 1062 """
1054 if name.endswith(os.sep): 1063 if name.endswith(os.sep):
1055 name = name[:-1] 1064 name = name[:-1]
1056 name = os.path.normcase(name) 1065 name = os.path.normcase(name)
1057 1066
1058 if ( 1067 if os.path.isdir(name) and os.path.isdir(os.path.join(name, self.adminDir)):
1059 os.path.isdir(name) and
1060 os.path.isdir(os.path.join(name, self.adminDir))
1061 ):
1062 return self.canBeCommitted 1068 return self.canBeCommitted
1063 1069
1064 if name in self.statusCache: 1070 if name in self.statusCache:
1065 return self.statusCache[name] 1071 return self.statusCache[name]
1066 args = self.initCommand("status") 1072 args = self.initCommand("status")
1067 args.append('--all') 1073 args.append("--all")
1068 args.append('--noninteractive') 1074 args.append("--noninteractive")
1069 1075
1070 output, error = self.__client.runcommand(args) 1076 output, error = self.__client.runcommand(args)
1071 1077
1072 if output: 1078 if output:
1073 repodir = self.getClient().getRepository() 1079 repodir = self.getClient().getRepository()
1074 for line in output.splitlines(): 1080 for line in output.splitlines():
1075 if len(line) > 2 and line[0] in "MARC!?I" and line[1] == " ": 1081 if len(line) > 2 and line[0] in "MARC!?I" and line[1] == " ":
1076 flag, path = line.split(" ", 1) 1082 flag, path = line.split(" ", 1)
1077 absname = Utilities.normcasepath( 1083 absname = Utilities.normcasepath(os.path.join(repodir, path))
1078 os.path.join(repodir, path))
1079 if flag not in "?I" and absname == name: 1084 if flag not in "?I" and absname == name:
1080 return self.canBeCommitted 1085 return self.canBeCommitted
1081 1086
1082 return self.canBeAdded 1087 return self.canBeAdded
1083 1088
1084 def vcsAllRegisteredStates(self, names, dname, shortcut=True): 1089 def vcsAllRegisteredStates(self, names, dname, shortcut=True):
1085 """ 1090 """
1086 Public method used to get the registered states of a number of files 1091 Public method used to get the registered states of a number of files
1087 in the vcs. 1092 in the vcs.
1088 1093
1089 <b>Note:</b> If a shortcut is to be taken, the code will only check, 1094 <b>Note:</b> If a shortcut is to be taken, the code will only check,
1090 if the named directory has been scanned already. If so, it is assumed, 1095 if the named directory has been scanned already. If so, it is assumed,
1091 that the states for all files have been populated by the previous run. 1096 that the states for all files have been populated by the previous run.
1092 1097
1093 @param names dictionary with all filenames to be checked as keys 1098 @param names dictionary with all filenames to be checked as keys
1094 @param dname directory to check in (string) 1099 @param dname directory to check in (string)
1095 @param shortcut flag indicating a shortcut should be taken (boolean) 1100 @param shortcut flag indicating a shortcut should be taken (boolean)
1096 @return the received dictionary completed with a combination of 1101 @return the received dictionary completed with a combination of
1097 canBeCommited and canBeAdded or None in order to signal an error 1102 canBeCommited and canBeAdded or None in order to signal an error
1098 """ 1103 """
1099 if dname.endswith(os.sep): 1104 if dname.endswith(os.sep):
1100 dname = dname[:-1] 1105 dname = dname[:-1]
1101 dname = os.path.normcase(dname) 1106 dname = os.path.normcase(dname)
1102 1107
1103 found = False 1108 found = False
1104 for name in list(self.statusCache.keys()): 1109 for name in list(self.statusCache.keys()):
1105 if name in names: 1110 if name in names:
1106 found = True 1111 found = True
1107 names[name] = self.statusCache[name] 1112 names[name] = self.statusCache[name]
1108 1113
1109 if not found: 1114 if not found:
1110 args = self.initCommand("status") 1115 args = self.initCommand("status")
1111 args.append('--all') 1116 args.append("--all")
1112 args.append('--noninteractive') 1117 args.append("--noninteractive")
1113 1118
1114 output, error = self.__client.runcommand(args) 1119 output, error = self.__client.runcommand(args)
1115 1120
1116 if output: 1121 if output:
1117 repoPath = self.getClient().getRepository() 1122 repoPath = self.getClient().getRepository()
1118 dirs = [x for x in names.keys() if os.path.isdir(x)] 1123 dirs = [x for x in names.keys() if os.path.isdir(x)]
1119 for line in output.splitlines(): 1124 for line in output.splitlines():
1120 if line and line[0] in "MARC!?I": 1125 if line and line[0] in "MARC!?I":
1137 self.statusCache[dirName] = self.canBeCommitted 1142 self.statusCache[dirName] = self.canBeCommitted
1138 else: 1143 else:
1139 self.statusCache[name] = self.canBeAdded 1144 self.statusCache[name] = self.canBeAdded
1140 if dirName not in self.statusCache: 1145 if dirName not in self.statusCache:
1141 self.statusCache[dirName] = self.canBeAdded 1146 self.statusCache[dirName] = self.canBeAdded
1142 1147
1143 return names 1148 return names
1144 1149
1145 def clearStatusCache(self): 1150 def clearStatusCache(self):
1146 """ 1151 """
1147 Public method to clear the status cache. 1152 Public method to clear the status cache.
1148 """ 1153 """
1149 self.statusCache = {} 1154 self.statusCache = {}
1150 1155
1151 def vcsName(self): 1156 def vcsName(self):
1152 """ 1157 """
1153 Public method returning the name of the vcs. 1158 Public method returning the name of the vcs.
1154 1159
1155 @return always 'Mercurial' (string) 1160 @return always 'Mercurial' (string)
1156 """ 1161 """
1157 return "Mercurial" 1162 return "Mercurial"
1158 1163
1159 def vcsInitConfig(self, project): 1164 def vcsInitConfig(self, project):
1160 """ 1165 """
1161 Public method to initialize the VCS configuration. 1166 Public method to initialize the VCS configuration.
1162 1167
1163 This method ensures, that an ignore file exists. 1168 This method ensures, that an ignore file exists.
1164 1169
1165 @param project reference to the project (Project) 1170 @param project reference to the project (Project)
1166 """ 1171 """
1167 ppath = project.getProjectPath() 1172 ppath = project.getProjectPath()
1168 if ppath: 1173 if ppath:
1169 ignoreName = os.path.join(ppath, Hg.IgnoreFileName) 1174 ignoreName = os.path.join(ppath, Hg.IgnoreFileName)
1170 if not os.path.exists(ignoreName): 1175 if not os.path.exists(ignoreName):
1171 self.hgCreateIgnoreFile(project.getProjectPath(), autoAdd=True) 1176 self.hgCreateIgnoreFile(project.getProjectPath(), autoAdd=True)
1172 1177
1173 def vcsCleanup(self, name): 1178 def vcsCleanup(self, name):
1174 """ 1179 """
1175 Public method used to cleanup the working directory. 1180 Public method used to cleanup the working directory.
1176 1181
1177 @param name directory name to be cleaned up (string) 1182 @param name directory name to be cleaned up (string)
1178 """ 1183 """
1179 patterns = self.getPlugin().getPreferences("CleanupPatterns").split() 1184 patterns = self.getPlugin().getPreferences("CleanupPatterns").split()
1180 1185
1181 entries = [] 1186 entries = []
1182 for pat in patterns: 1187 for pat in patterns:
1183 entries.extend(Utilities.direntries(name, True, pat)) 1188 entries.extend(Utilities.direntries(name, True, pat))
1184 1189
1185 for entry in entries: 1190 for entry in entries:
1186 with contextlib.suppress(OSError): 1191 with contextlib.suppress(OSError):
1187 os.remove(entry) 1192 os.remove(entry)
1188 1193
1189 def vcsCommandLine(self, name): 1194 def vcsCommandLine(self, name):
1190 """ 1195 """
1191 Public method used to execute arbitrary mercurial commands. 1196 Public method used to execute arbitrary mercurial commands.
1192 1197
1193 @param name directory name of the working directory (string) 1198 @param name directory name of the working directory (string)
1194 """ 1199 """
1195 from .HgCommandDialog import HgCommandDialog 1200 from .HgCommandDialog import HgCommandDialog
1201
1196 dlg = HgCommandDialog(self.commandHistory, name) 1202 dlg = HgCommandDialog(self.commandHistory, name)
1197 if dlg.exec() == QDialog.DialogCode.Accepted: 1203 if dlg.exec() == QDialog.DialogCode.Accepted:
1198 command = dlg.getData() 1204 command = dlg.getData()
1199 commandList = Utilities.parseOptionString(command) 1205 commandList = Utilities.parseOptionString(command)
1200 1206
1201 # This moves any previous occurrence of these arguments to the head 1207 # This moves any previous occurrence of these arguments to the head
1202 # of the list. 1208 # of the list.
1203 if command in self.commandHistory: 1209 if command in self.commandHistory:
1204 self.commandHistory.remove(command) 1210 self.commandHistory.remove(command)
1205 self.commandHistory.insert(0, command) 1211 self.commandHistory.insert(0, command)
1206 1212
1207 args = [] 1213 args = []
1208 self.addArguments(args, commandList) 1214 self.addArguments(args, commandList)
1209 1215
1210 dia = HgDialog(self.tr('Mercurial command'), self) 1216 dia = HgDialog(self.tr("Mercurial command"), self)
1211 res = dia.startProcess(args) 1217 res = dia.startProcess(args)
1212 if res: 1218 if res:
1213 dia.exec() 1219 dia.exec()
1214 1220
1215 def vcsOptionsDialog(self, project, archive, editable=False, parent=None): 1221 def vcsOptionsDialog(self, project, archive, editable=False, parent=None):
1216 """ 1222 """
1217 Public method to get a dialog to enter repository info. 1223 Public method to get a dialog to enter repository info.
1218 1224
1219 @param project reference to the project object 1225 @param project reference to the project object
1220 @param archive name of the project in the repository (string) 1226 @param archive name of the project in the repository (string)
1221 @param editable flag indicating that the project name is editable 1227 @param editable flag indicating that the project name is editable
1222 (boolean) 1228 (boolean)
1223 @param parent parent widget (QWidget) 1229 @param parent parent widget (QWidget)
1224 @return reference to the instantiated options dialog (HgOptionsDialog) 1230 @return reference to the instantiated options dialog (HgOptionsDialog)
1225 """ 1231 """
1226 from .HgOptionsDialog import HgOptionsDialog 1232 from .HgOptionsDialog import HgOptionsDialog
1233
1227 return HgOptionsDialog(self, project, parent) 1234 return HgOptionsDialog(self, project, parent)
1228 1235
1229 def vcsNewProjectOptionsDialog(self, parent=None): 1236 def vcsNewProjectOptionsDialog(self, parent=None):
1230 """ 1237 """
1231 Public method to get a dialog to enter repository info for getting a 1238 Public method to get a dialog to enter repository info for getting a
1232 new project. 1239 new project.
1233 1240
1234 @param parent parent widget (QWidget) 1241 @param parent parent widget (QWidget)
1235 @return reference to the instantiated options dialog 1242 @return reference to the instantiated options dialog
1236 (HgNewProjectOptionsDialog) 1243 (HgNewProjectOptionsDialog)
1237 """ 1244 """
1238 from .HgNewProjectOptionsDialog import HgNewProjectOptionsDialog 1245 from .HgNewProjectOptionsDialog import HgNewProjectOptionsDialog
1246
1239 return HgNewProjectOptionsDialog(self, parent) 1247 return HgNewProjectOptionsDialog(self, parent)
1240 1248
1241 def vcsRepositoryInfos(self, ppath): 1249 def vcsRepositoryInfos(self, ppath):
1242 """ 1250 """
1243 Public method to retrieve information about the repository. 1251 Public method to retrieve information about the repository.
1244 1252
1245 @param ppath local path to get the repository infos (string) 1253 @param ppath local path to get the repository infos (string)
1246 @return string with ready formated info for display (string) 1254 @return string with ready formated info for display (string)
1247 """ 1255 """
1248 args = self.initCommand("parents") 1256 args = self.initCommand("parents")
1249 args.append('--template') 1257 args.append("--template")
1250 args.append('{rev}:{node|short}@@@{tags}@@@{author|xmlescape}@@@' 1258 args.append(
1251 '{date|isodate}@@@{branches}@@@{bookmarks}\n') 1259 "{rev}:{node|short}@@@{tags}@@@{author|xmlescape}@@@"
1252 1260 "{date|isodate}@@@{branches}@@@{bookmarks}\n"
1261 )
1262
1253 output, error = self.__client.runcommand(args) 1263 output, error = self.__client.runcommand(args)
1254 1264
1255 infoBlock = [] 1265 infoBlock = []
1256 if output: 1266 if output:
1257 for index, line in enumerate(output.splitlines(), start=1): 1267 for index, line in enumerate(output.splitlines(), start=1):
1258 (changeset, tags, author, date, branches, 1268 (changeset, tags, author, date, branches, bookmarks) = line.split("@@@")
1259 bookmarks) = line.split("@@@")
1260 cdate, ctime = date.split()[:2] 1269 cdate, ctime = date.split()[:2]
1261 info = [] 1270 info = []
1262 info.append(QCoreApplication.translate( 1271 info.append(
1263 "mercurial", 1272 QCoreApplication.translate(
1264 """<tr><td><b>Parent #{0}</b></td><td></td></tr>\n""" 1273 "mercurial",
1265 """<tr><td><b>Changeset</b></td><td>{1}</td></tr>""") 1274 """<tr><td><b>Parent #{0}</b></td><td></td></tr>\n"""
1266 .format(index, changeset)) 1275 """<tr><td><b>Changeset</b></td><td>{1}</td></tr>""",
1276 ).format(index, changeset)
1277 )
1267 if tags: 1278 if tags:
1268 info.append(QCoreApplication.translate( 1279 info.append(
1280 QCoreApplication.translate(
1281 "mercurial", """<tr><td><b>Tags</b></td><td>{0}</td></tr>"""
1282 ).format("<br/>".join(tags.split()))
1283 )
1284 if bookmarks:
1285 info.append(
1286 QCoreApplication.translate(
1287 "mercurial",
1288 """<tr><td><b>Bookmarks</b></td><td>{0}</td></tr>""",
1289 ).format("<br/>".join(bookmarks.split()))
1290 )
1291 if branches:
1292 info.append(
1293 QCoreApplication.translate(
1294 "mercurial",
1295 """<tr><td><b>Branches</b></td><td>{0}</td></tr>""",
1296 ).format("<br/>".join(branches.split()))
1297 )
1298 info.append(
1299 QCoreApplication.translate(
1269 "mercurial", 1300 "mercurial",
1270 """<tr><td><b>Tags</b></td><td>{0}</td></tr>""") 1301 """<tr><td><b>Last author</b></td><td>{0}</td></tr>\n"""
1271 .format('<br/>'.join(tags.split()))) 1302 """<tr><td><b>Committed date</b></td><td>{1}</td></tr>\n"""
1272 if bookmarks: 1303 """<tr><td><b>Committed time</b></td><td>{2}</td></tr>""",
1273 info.append(QCoreApplication.translate( 1304 ).format(author, cdate, ctime)
1274 "mercurial", 1305 )
1275 """<tr><td><b>Bookmarks</b></td><td>{0}</td></tr>""")
1276 .format('<br/>'.join(bookmarks.split())))
1277 if branches:
1278 info.append(QCoreApplication.translate(
1279 "mercurial",
1280 """<tr><td><b>Branches</b></td><td>{0}</td></tr>""")
1281 .format('<br/>'.join(branches.split())))
1282 info.append(QCoreApplication.translate(
1283 "mercurial",
1284 """<tr><td><b>Last author</b></td><td>{0}</td></tr>\n"""
1285 """<tr><td><b>Committed date</b></td><td>{1}</td></tr>\n"""
1286 """<tr><td><b>Committed time</b></td><td>{2}</td></tr>""")
1287 .format(author, cdate, ctime))
1288 infoBlock.append("\n".join(info)) 1306 infoBlock.append("\n".join(info))
1289 infoStr = ( 1307 infoStr = (
1290 """<tr></tr>{0}""".format("<tr></tr>".join(infoBlock)) 1308 """<tr></tr>{0}""".format("<tr></tr>".join(infoBlock)) if infoBlock else ""
1291 if infoBlock else
1292 ""
1293 ) 1309 )
1294 1310
1295 url = "" 1311 url = ""
1296 args = self.initCommand("showconfig") 1312 args = self.initCommand("showconfig")
1297 args.append('paths.default') 1313 args.append("paths.default")
1298 1314
1299 output, error = self.__client.runcommand(args) 1315 output, error = self.__client.runcommand(args)
1300 url = output.splitlines()[0].strip() if output else "" 1316 url = output.splitlines()[0].strip() if output else ""
1301 1317
1302 return QCoreApplication.translate( 1318 return QCoreApplication.translate(
1303 'mercurial', 1319 "mercurial",
1304 """<h3>Repository information</h3>\n""" 1320 """<h3>Repository information</h3>\n"""
1305 """<p><table>\n""" 1321 """<p><table>\n"""
1306 """<tr><td><b>Mercurial V.</b></td><td>{0}</td></tr>\n""" 1322 """<tr><td><b>Mercurial V.</b></td><td>{0}</td></tr>\n"""
1307 """<tr></tr>\n""" 1323 """<tr></tr>\n"""
1308 """<tr><td><b>URL</b></td><td>{1}</td></tr>\n""" 1324 """<tr><td><b>URL</b></td><td>{1}</td></tr>\n"""
1309 """{2}""" 1325 """{2}"""
1310 """</table></p>\n""" 1326 """</table></p>\n""",
1311 ).format(self.versionStr, url, infoStr) 1327 ).format(self.versionStr, url, infoStr)
1312 1328
1313 def vcsSupportCommandOptions(self): 1329 def vcsSupportCommandOptions(self):
1314 """ 1330 """
1315 Public method to signal the support of user settable command options. 1331 Public method to signal the support of user settable command options.
1316 1332
1317 @return flag indicating the support of user settable command options 1333 @return flag indicating the support of user settable command options
1318 (boolean) 1334 (boolean)
1319 """ 1335 """
1320 return False 1336 return False
1321 1337
1322 ########################################################################### 1338 ###########################################################################
1323 ## Private Mercurial specific methods are below. 1339 ## Private Mercurial specific methods are below.
1324 ########################################################################### 1340 ###########################################################################
1325 1341
1326 def hgNormalizeURL(self, url): 1342 def hgNormalizeURL(self, url):
1327 """ 1343 """
1328 Public method to normalize a url for Mercurial. 1344 Public method to normalize a url for Mercurial.
1329 1345
1330 @param url url string (string) 1346 @param url url string (string)
1331 @return properly normalized url for mercurial (string) 1347 @return properly normalized url for mercurial (string)
1332 """ 1348 """
1333 url = url.replace('\\', '/') 1349 url = url.replace("\\", "/")
1334 if url.endswith('/'): 1350 if url.endswith("/"):
1335 url = url[:-1] 1351 url = url[:-1]
1336 urll = url.split('//') 1352 urll = url.split("//")
1337 return "{0}//{1}".format(urll[0], '/'.join(urll[1:])) 1353 return "{0}//{1}".format(urll[0], "/".join(urll[1:]))
1338 1354
1339 def hgCopy(self, name, project): 1355 def hgCopy(self, name, project):
1340 """ 1356 """
1341 Public method used to copy a file/directory. 1357 Public method used to copy a file/directory.
1342 1358
1343 @param name file/directory name to be copied (string) 1359 @param name file/directory name to be copied (string)
1344 @param project reference to the project object 1360 @param project reference to the project object
1345 @return flag indicating successful operation (boolean) 1361 @return flag indicating successful operation (boolean)
1346 """ 1362 """
1347 from .HgCopyDialog import HgCopyDialog 1363 from .HgCopyDialog import HgCopyDialog
1364
1348 dlg = HgCopyDialog(name) 1365 dlg = HgCopyDialog(name)
1349 res = False 1366 res = False
1350 if dlg.exec() == QDialog.DialogCode.Accepted: 1367 if dlg.exec() == QDialog.DialogCode.Accepted:
1351 target, force = dlg.getData() 1368 target, force = dlg.getData()
1352 1369
1353 args = self.initCommand("copy") 1370 args = self.initCommand("copy")
1354 args.append("-v") 1371 args.append("-v")
1355 args.append(name) 1372 args.append(name)
1356 args.append(target) 1373 args.append(target)
1357 1374
1358 dia = HgDialog( 1375 dia = HgDialog(self.tr("Copying {0}").format(name), self)
1359 self.tr('Copying {0}').format(name), self)
1360 res = dia.startProcess(args) 1376 res = dia.startProcess(args)
1361 if res: 1377 if res:
1362 dia.exec() 1378 dia.exec()
1363 res = dia.normalExit() 1379 res = dia.normalExit()
1364 if ( 1380 if res and target.startswith(project.getProjectPath()):
1365 res and
1366 target.startswith(project.getProjectPath())
1367 ):
1368 if os.path.isdir(name): 1381 if os.path.isdir(name):
1369 project.copyDirectory(name, target) 1382 project.copyDirectory(name, target)
1370 else: 1383 else:
1371 project.appendFile(target) 1384 project.appendFile(target)
1372 return res 1385 return res
1373 1386
1374 def hgGetTagsList(self, withType=False): 1387 def hgGetTagsList(self, withType=False):
1375 """ 1388 """
1376 Public method to get the list of tags. 1389 Public method to get the list of tags.
1377 1390
1378 @param withType flag indicating to get the tag type as well (boolean) 1391 @param withType flag indicating to get the tag type as well (boolean)
1379 @return list of tags (list of string) or list of tuples of 1392 @return list of tags (list of string) or list of tuples of
1380 tag name and flag indicating a local tag (list of tuple of string 1393 tag name and flag indicating a local tag (list of tuple of string
1381 and boolean), if withType is True 1394 and boolean), if withType is True
1382 """ 1395 """
1383 args = self.initCommand("tags") 1396 args = self.initCommand("tags")
1384 args.append('--verbose') 1397 args.append("--verbose")
1385 1398
1386 output, error = self.__client.runcommand(args) 1399 output, error = self.__client.runcommand(args)
1387 1400
1388 tagsList = [] 1401 tagsList = []
1389 if output: 1402 if output:
1390 for line in output.splitlines(): 1403 for line in output.splitlines():
1391 li = line.strip().split() 1404 li = line.strip().split()
1392 if li[-1][0] in "1234567890": 1405 if li[-1][0] in "1234567890":
1400 if name not in ["tip", "default"]: 1413 if name not in ["tip", "default"]:
1401 if withType: 1414 if withType:
1402 tagsList.append((name, isLocal)) 1415 tagsList.append((name, isLocal))
1403 else: 1416 else:
1404 tagsList.append(name) 1417 tagsList.append(name)
1405 1418
1406 if withType: 1419 if withType:
1407 return tagsList 1420 return tagsList
1408 else: 1421 else:
1409 if tagsList: 1422 if tagsList:
1410 self.tagsList = tagsList 1423 self.tagsList = tagsList
1411 return self.tagsList[:] 1424 return self.tagsList[:]
1412 1425
1413 def hgGetBranchesList(self): 1426 def hgGetBranchesList(self):
1414 """ 1427 """
1415 Public method to get the list of branches. 1428 Public method to get the list of branches.
1416 1429
1417 @return list of branches (list of string) 1430 @return list of branches (list of string)
1418 """ 1431 """
1419 args = self.initCommand("branches") 1432 args = self.initCommand("branches")
1420 args.append('--closed') 1433 args.append("--closed")
1421 1434
1422 output, error = self.__client.runcommand(args) 1435 output, error = self.__client.runcommand(args)
1423 1436
1424 if output: 1437 if output:
1425 self.branchesList = [] 1438 self.branchesList = []
1426 for line in output.splitlines(): 1439 for line in output.splitlines():
1427 li = line.strip().split() 1440 li = line.strip().split()
1428 if li[-1][0] in "1234567890": 1441 if li[-1][0] in "1234567890":
1431 else: 1444 else:
1432 del li[-2:] 1445 del li[-2:]
1433 name = " ".join(li) 1446 name = " ".join(li)
1434 if name not in ["tip", "default"]: 1447 if name not in ["tip", "default"]:
1435 self.branchesList.append(name) 1448 self.branchesList.append(name)
1436 1449
1437 return self.branchesList[:] 1450 return self.branchesList[:]
1438 1451
1439 def hgListTagBranch(self, tags=True): 1452 def hgListTagBranch(self, tags=True):
1440 """ 1453 """
1441 Public method used to list the available tags or branches. 1454 Public method used to list the available tags or branches.
1442 1455
1443 @param tags flag indicating listing of branches or tags 1456 @param tags flag indicating listing of branches or tags
1444 (False = branches, True = tags) 1457 (False = branches, True = tags)
1445 """ 1458 """
1446 from .HgTagBranchListDialog import HgTagBranchListDialog 1459 from .HgTagBranchListDialog import HgTagBranchListDialog
1460
1447 self.tagbranchList = HgTagBranchListDialog(self) 1461 self.tagbranchList = HgTagBranchListDialog(self)
1448 self.tagbranchList.show() 1462 self.tagbranchList.show()
1449 if tags: 1463 if tags:
1450 if not self.showedTags: 1464 if not self.showedTags:
1451 self.showedTags = True 1465 self.showedTags = True
1452 allTagsBranchesList = self.allTagsBranchesList 1466 allTagsBranchesList = self.allTagsBranchesList
1453 else: 1467 else:
1454 self.tagsList = [] 1468 self.tagsList = []
1455 allTagsBranchesList = None 1469 allTagsBranchesList = None
1456 self.tagbranchList.start( 1470 self.tagbranchList.start(tags, self.tagsList, allTagsBranchesList)
1457 tags, self.tagsList, allTagsBranchesList)
1458 else: 1471 else:
1459 if not self.showedBranches: 1472 if not self.showedBranches:
1460 self.showedBranches = True 1473 self.showedBranches = True
1461 allTagsBranchesList = self.allTagsBranchesList 1474 allTagsBranchesList = self.allTagsBranchesList
1462 else: 1475 else:
1463 self.branchesList = [] 1476 self.branchesList = []
1464 allTagsBranchesList = None 1477 allTagsBranchesList = None
1465 self.tagbranchList.start( 1478 self.tagbranchList.start(tags, self.branchesList, self.allTagsBranchesList)
1466 tags, self.branchesList, self.allTagsBranchesList) 1479
1467
1468 def hgAnnotate(self, name): 1480 def hgAnnotate(self, name):
1469 """ 1481 """
1470 Public method to show the output of the hg annotate command. 1482 Public method to show the output of the hg annotate command.
1471 1483
1472 @param name file name to show the annotations for (string) 1484 @param name file name to show the annotations for (string)
1473 """ 1485 """
1474 if self.annotate is None: 1486 if self.annotate is None:
1475 from .HgAnnotateDialog import HgAnnotateDialog 1487 from .HgAnnotateDialog import HgAnnotateDialog
1488
1476 self.annotate = HgAnnotateDialog(self) 1489 self.annotate = HgAnnotateDialog(self)
1477 self.annotate.show() 1490 self.annotate.show()
1478 self.annotate.raise_() 1491 self.annotate.raise_()
1479 self.annotate.start(name) 1492 self.annotate.start(name)
1480 1493
1481 def hgExtendedDiff(self, name): 1494 def hgExtendedDiff(self, name):
1482 """ 1495 """
1483 Public method used to view the difference of a file/directory to the 1496 Public method used to view the difference of a file/directory to the
1484 Mercurial repository. 1497 Mercurial repository.
1485 1498
1486 If name is a directory and is the project directory, all project files 1499 If name is a directory and is the project directory, all project files
1487 are saved first. If name is a file (or list of files), which is/are 1500 are saved first. If name is a file (or list of files), which is/are
1488 being edited and has unsaved modification, they can be saved or the 1501 being edited and has unsaved modification, they can be saved or the
1489 operation may be aborted. 1502 operation may be aborted.
1490 1503
1491 This method gives the chance to enter the revisions to be compared. 1504 This method gives the chance to enter the revisions to be compared.
1492 1505
1493 @param name file/directory name to be diffed (string) 1506 @param name file/directory name to be diffed (string)
1494 """ 1507 """
1495 names = name[:] if isinstance(name, list) else [name] 1508 names = name[:] if isinstance(name, list) else [name]
1496 for nam in names: 1509 for nam in names:
1497 if os.path.isfile(nam): 1510 if os.path.isfile(nam):
1500 return 1513 return
1501 else: 1514 else:
1502 project = ericApp().getObject("Project") 1515 project = ericApp().getObject("Project")
1503 if nam == project.ppath and not project.saveAllScripts(): 1516 if nam == project.ppath and not project.saveAllScripts():
1504 return 1517 return
1505 1518
1506 from .HgRevisionsSelectionDialog import HgRevisionsSelectionDialog 1519 from .HgRevisionsSelectionDialog import HgRevisionsSelectionDialog
1520
1507 dlg = HgRevisionsSelectionDialog( 1521 dlg = HgRevisionsSelectionDialog(
1508 self.hgGetTagsList(), 1522 self.hgGetTagsList(),
1509 self.hgGetBranchesList(), 1523 self.hgGetBranchesList(),
1510 bookmarksList=self.hgGetBookmarksList() 1524 bookmarksList=self.hgGetBookmarksList(),
1511 ) 1525 )
1512 if dlg.exec() == QDialog.DialogCode.Accepted: 1526 if dlg.exec() == QDialog.DialogCode.Accepted:
1513 revisions = dlg.getRevisions() 1527 revisions = dlg.getRevisions()
1514 if self.diff is None: 1528 if self.diff is None:
1515 from .HgDiffDialog import HgDiffDialog 1529 from .HgDiffDialog import HgDiffDialog
1530
1516 self.diff = HgDiffDialog(self) 1531 self.diff = HgDiffDialog(self)
1517 self.diff.show() 1532 self.diff.show()
1518 self.diff.raise_() 1533 self.diff.raise_()
1519 self.diff.start(name, revisions) 1534 self.diff.start(name, revisions)
1520 1535
1521 def __hgGetFileForRevision(self, name, rev=""): 1536 def __hgGetFileForRevision(self, name, rev=""):
1522 """ 1537 """
1523 Private method to get a file for a specific revision from the 1538 Private method to get a file for a specific revision from the
1524 repository. 1539 repository.
1525 1540
1526 @param name file name to get from the repository (string) 1541 @param name file name to get from the repository (string)
1527 @param rev revision to retrieve (string) 1542 @param rev revision to retrieve (string)
1528 @return contents of the file (string) and an error message (string) 1543 @return contents of the file (string) and an error message (string)
1529 """ 1544 """
1530 args = self.initCommand("cat") 1545 args = self.initCommand("cat")
1531 if rev: 1546 if rev:
1532 args.append("--rev") 1547 args.append("--rev")
1533 args.append(rev) 1548 args.append(rev)
1534 args.append(name) 1549 args.append(name)
1535 1550
1536 output, error = self.__client.runcommand(args) 1551 output, error = self.__client.runcommand(args)
1537 1552
1538 # return file contents with 'universal newlines' 1553 # return file contents with 'universal newlines'
1539 return output.replace('\r\n', '\n').replace('\r', '\n'), error 1554 return output.replace("\r\n", "\n").replace("\r", "\n"), error
1540 1555
1541 def vcsSbsDiff(self, name, extended=False, revisions=None): 1556 def vcsSbsDiff(self, name, extended=False, revisions=None):
1542 """ 1557 """
1543 Public method used to view the difference of a file to the Mercurial 1558 Public method used to view the difference of a file to the Mercurial
1544 repository side-by-side. 1559 repository side-by-side.
1545 1560
1546 @param name file name to be diffed (string) 1561 @param name file name to be diffed (string)
1547 @param extended flag indicating the extended variant (boolean) 1562 @param extended flag indicating the extended variant (boolean)
1548 @param revisions tuple of two revisions (tuple of strings) 1563 @param revisions tuple of two revisions (tuple of strings)
1549 @exception ValueError raised to indicate an invalid name parameter 1564 @exception ValueError raised to indicate an invalid name parameter
1550 """ 1565 """
1551 if isinstance(name, list): 1566 if isinstance(name, list):
1552 raise ValueError("Wrong parameter type") 1567 raise ValueError("Wrong parameter type")
1553 1568
1554 if extended: 1569 if extended:
1555 from .HgRevisionsSelectionDialog import HgRevisionsSelectionDialog 1570 from .HgRevisionsSelectionDialog import HgRevisionsSelectionDialog
1571
1556 dlg = HgRevisionsSelectionDialog( 1572 dlg = HgRevisionsSelectionDialog(
1557 self.hgGetTagsList(), 1573 self.hgGetTagsList(),
1558 self.hgGetBranchesList(), 1574 self.hgGetBranchesList(),
1559 bookmarksList=self.hgGetBookmarksList() 1575 bookmarksList=self.hgGetBookmarksList(),
1560 ) 1576 )
1561 if dlg.exec() == QDialog.DialogCode.Accepted: 1577 if dlg.exec() == QDialog.DialogCode.Accepted:
1562 rev1, rev2 = dlg.getRevisions() 1578 rev1, rev2 = dlg.getRevisions()
1563 else: 1579 else:
1564 return 1580 return
1565 elif revisions: 1581 elif revisions:
1566 rev1, rev2 = revisions[0], revisions[1] 1582 rev1, rev2 = revisions[0], revisions[1]
1567 else: 1583 else:
1568 rev1, rev2 = "", "" 1584 rev1, rev2 = "", ""
1569 1585
1570 output1, error = self.__hgGetFileForRevision(name, rev=rev1) 1586 output1, error = self.__hgGetFileForRevision(name, rev=rev1)
1571 if error: 1587 if error:
1572 EricMessageBox.critical( 1588 EricMessageBox.critical(
1573 self.__ui, 1589 self.__ui, self.tr("Mercurial Side-by-Side Difference"), error
1574 self.tr("Mercurial Side-by-Side Difference"), 1590 )
1575 error)
1576 return 1591 return
1577 name1 = "{0} (rev. {1})".format(name, rev1 and rev1 or ".") 1592 name1 = "{0} (rev. {1})".format(name, rev1 and rev1 or ".")
1578 1593
1579 if rev2: 1594 if rev2:
1580 output2, error = self.__hgGetFileForRevision(name, rev=rev2) 1595 output2, error = self.__hgGetFileForRevision(name, rev=rev2)
1581 if error: 1596 if error:
1582 EricMessageBox.critical( 1597 EricMessageBox.critical(
1583 self.__ui, 1598 self.__ui, self.tr("Mercurial Side-by-Side Difference"), error
1584 self.tr("Mercurial Side-by-Side Difference"), 1599 )
1585 error)
1586 return 1600 return
1587 name2 = "{0} (rev. {1})".format(name, rev2) 1601 name2 = "{0} (rev. {1})".format(name, rev2)
1588 else: 1602 else:
1589 try: 1603 try:
1590 with open(name, "r", encoding="utf-8") as f1: 1604 with open(name, "r", encoding="utf-8") as f1:
1592 name2 = "{0} (Work)".format(name) 1606 name2 = "{0} (Work)".format(name)
1593 except OSError: 1607 except OSError:
1594 EricMessageBox.critical( 1608 EricMessageBox.critical(
1595 self.__ui, 1609 self.__ui,
1596 self.tr("Mercurial Side-by-Side Difference"), 1610 self.tr("Mercurial Side-by-Side Difference"),
1597 self.tr( 1611 self.tr("""<p>The file <b>{0}</b> could not be read.</p>""").format(
1598 """<p>The file <b>{0}</b> could not be read.</p>""") 1612 name
1599 .format(name)) 1613 ),
1614 )
1600 return 1615 return
1601 1616
1602 if self.sbsDiff is None: 1617 if self.sbsDiff is None:
1603 from UI.CompareDialog import CompareDialog 1618 from UI.CompareDialog import CompareDialog
1619
1604 self.sbsDiff = CompareDialog() 1620 self.sbsDiff = CompareDialog()
1605 self.sbsDiff.show() 1621 self.sbsDiff.show()
1606 self.sbsDiff.raise_() 1622 self.sbsDiff.raise_()
1607 self.sbsDiff.compare(output1, output2, name1, name2) 1623 self.sbsDiff.compare(output1, output2, name1, name2)
1608 1624
1609 def vcsLogBrowser(self, name=None, isFile=False): 1625 def vcsLogBrowser(self, name=None, isFile=False):
1610 """ 1626 """
1611 Public method used to browse the log of a file/directory from the 1627 Public method used to browse the log of a file/directory from the
1612 Mercurial repository. 1628 Mercurial repository.
1613 1629
1614 @param name file/directory name to show the log of (string) 1630 @param name file/directory name to show the log of (string)
1615 @param isFile flag indicating log for a file is to be shown 1631 @param isFile flag indicating log for a file is to be shown
1616 (boolean) 1632 (boolean)
1617 """ 1633 """
1618 if name == self.getClient().getRepository(): 1634 if name == self.getClient().getRepository():
1619 name = None 1635 name = None
1620 1636
1621 if self.logBrowser is None: 1637 if self.logBrowser is None:
1622 from .HgLogBrowserDialog import HgLogBrowserDialog 1638 from .HgLogBrowserDialog import HgLogBrowserDialog
1639
1623 self.logBrowser = HgLogBrowserDialog(self) 1640 self.logBrowser = HgLogBrowserDialog(self)
1624 self.logBrowser.show() 1641 self.logBrowser.show()
1625 self.logBrowser.raise_() 1642 self.logBrowser.raise_()
1626 self.logBrowser.start(name=name, isFile=isFile) 1643 self.logBrowser.start(name=name, isFile=isFile)
1627 1644
1628 def hgIncoming(self): 1645 def hgIncoming(self):
1629 """ 1646 """
1630 Public method used to view the log of incoming changes from the 1647 Public method used to view the log of incoming changes from the
1631 Mercurial repository. 1648 Mercurial repository.
1632 """ 1649 """
1633 if self.logBrowserIncoming is None: 1650 if self.logBrowserIncoming is None:
1634 from .HgLogBrowserDialog import HgLogBrowserDialog 1651 from .HgLogBrowserDialog import HgLogBrowserDialog
1635 self.logBrowserIncoming = HgLogBrowserDialog( 1652
1636 self, mode="incoming") 1653 self.logBrowserIncoming = HgLogBrowserDialog(self, mode="incoming")
1637 self.logBrowserIncoming.show() 1654 self.logBrowserIncoming.show()
1638 self.logBrowserIncoming.raise_() 1655 self.logBrowserIncoming.raise_()
1639 self.logBrowserIncoming.start() 1656 self.logBrowserIncoming.start()
1640 1657
1641 def hgOutgoing(self): 1658 def hgOutgoing(self):
1642 """ 1659 """
1643 Public method used to view the log of outgoing changes from the 1660 Public method used to view the log of outgoing changes from the
1644 Mercurial repository. 1661 Mercurial repository.
1645 """ 1662 """
1646 if self.logBrowserOutgoing is None: 1663 if self.logBrowserOutgoing is None:
1647 from .HgLogBrowserDialog import HgLogBrowserDialog 1664 from .HgLogBrowserDialog import HgLogBrowserDialog
1648 self.logBrowserOutgoing = HgLogBrowserDialog( 1665
1649 self, mode="outgoing") 1666 self.logBrowserOutgoing = HgLogBrowserDialog(self, mode="outgoing")
1650 self.logBrowserOutgoing.show() 1667 self.logBrowserOutgoing.show()
1651 self.logBrowserOutgoing.raise_() 1668 self.logBrowserOutgoing.raise_()
1652 self.logBrowserOutgoing.start() 1669 self.logBrowserOutgoing.start()
1653 1670
1654 def hgPull(self, revisions=None): 1671 def hgPull(self, revisions=None):
1655 """ 1672 """
1656 Public method used to pull changes from a remote Mercurial repository. 1673 Public method used to pull changes from a remote Mercurial repository.
1657 1674
1658 @param revisions list of revisions to be pulled 1675 @param revisions list of revisions to be pulled
1659 @type list of str 1676 @type list of str
1660 @return flag indicating, that the update contained an add 1677 @return flag indicating, that the update contained an add
1661 or delete 1678 or delete
1662 @rtype bool 1679 @rtype bool
1663 """ 1680 """
1664 if ( 1681 if (
1665 self.getPlugin().getPreferences("PreferUnbundle") and 1682 self.getPlugin().getPreferences("PreferUnbundle")
1666 self.bundleFile and 1683 and self.bundleFile
1667 os.path.exists(self.bundleFile) and 1684 and os.path.exists(self.bundleFile)
1668 revisions is None 1685 and revisions is None
1669 ): 1686 ):
1670 command = "unbundle" 1687 command = "unbundle"
1671 title = self.tr('Apply changegroups') 1688 title = self.tr("Apply changegroups")
1672 else: 1689 else:
1673 command = "pull" 1690 command = "pull"
1674 title = self.tr('Pulling from a remote Mercurial repository') 1691 title = self.tr("Pulling from a remote Mercurial repository")
1675 1692
1676 args = self.initCommand(command) 1693 args = self.initCommand(command)
1677 args.append('-v') 1694 args.append("-v")
1678 if self.getPlugin().getPreferences("PullUpdate"): 1695 if self.getPlugin().getPreferences("PullUpdate"):
1679 args.append('--update') 1696 args.append("--update")
1680 if command == "unbundle": 1697 if command == "unbundle":
1681 args.append(self.bundleFile) 1698 args.append(self.bundleFile)
1682 if revisions: 1699 if revisions:
1683 for rev in revisions: 1700 for rev in revisions:
1684 args.append("--rev") 1701 args.append("--rev")
1685 args.append(rev) 1702 args.append(rev)
1686 1703
1687 dia = HgDialog(title, self) 1704 dia = HgDialog(title, self)
1688 res = dia.startProcess(args) 1705 res = dia.startProcess(args)
1689 if res: 1706 if res:
1690 dia.exec() 1707 dia.exec()
1691 res = dia.hasAddOrDelete() 1708 res = dia.hasAddOrDelete()
1692 if ( 1709 if self.bundleFile and os.path.exists(self.bundleFile):
1693 self.bundleFile and
1694 os.path.exists(self.bundleFile)
1695 ):
1696 os.remove(self.bundleFile) 1710 os.remove(self.bundleFile)
1697 self.bundleFile = None 1711 self.bundleFile = None
1698 self.checkVCSStatus() 1712 self.checkVCSStatus()
1699 return res 1713 return res
1700 1714
1701 def hgPush(self, force=False, newBranch=False, rev=None): 1715 def hgPush(self, force=False, newBranch=False, rev=None):
1702 """ 1716 """
1703 Public method used to push changes to a remote Mercurial repository. 1717 Public method used to push changes to a remote Mercurial repository.
1704 1718
1705 @param force flag indicating a forced push (boolean) 1719 @param force flag indicating a forced push (boolean)
1706 @param newBranch flag indicating to push a new branch (boolean) 1720 @param newBranch flag indicating to push a new branch (boolean)
1707 @param rev revision to be pushed (including all ancestors) (string) 1721 @param rev revision to be pushed (including all ancestors) (string)
1708 """ 1722 """
1709 args = self.initCommand("push") 1723 args = self.initCommand("push")
1710 args.append('-v') 1724 args.append("-v")
1711 if force: 1725 if force:
1712 args.append('-f') 1726 args.append("-f")
1713 if newBranch: 1727 if newBranch:
1714 args.append('--new-branch') 1728 args.append("--new-branch")
1715 if rev: 1729 if rev:
1716 args.append('--rev') 1730 args.append("--rev")
1717 args.append(rev) 1731 args.append(rev)
1718 1732
1719 dia = HgDialog( 1733 dia = HgDialog(self.tr("Pushing to a remote Mercurial repository"), self)
1720 self.tr('Pushing to a remote Mercurial repository'), self)
1721 res = dia.startProcess(args) 1734 res = dia.startProcess(args)
1722 if res: 1735 if res:
1723 dia.exec() 1736 dia.exec()
1724 self.checkVCSStatus() 1737 self.checkVCSStatus()
1725 1738
1726 def hgInfo(self, mode="heads"): 1739 def hgInfo(self, mode="heads"):
1727 """ 1740 """
1728 Public method to show information about the heads of the repository. 1741 Public method to show information about the heads of the repository.
1729 1742
1730 @param mode mode of the operation (string, one of heads, parents, 1743 @param mode mode of the operation (string, one of heads, parents,
1731 tip) 1744 tip)
1732 """ 1745 """
1733 if mode not in ("heads", "parents", "tip"): 1746 if mode not in ("heads", "parents", "tip"):
1734 mode = "heads" 1747 mode = "heads"
1735 1748
1736 info = [] 1749 info = []
1737 1750
1738 args = self.initCommand(mode) 1751 args = self.initCommand(mode)
1739 args.append('--template') 1752 args.append("--template")
1740 args.append('{rev}:{node|short}@@@{tags}@@@{author|xmlescape}@@@' 1753 args.append(
1741 '{date|isodate}@@@{branches}@@@{parents}@@@{bookmarks}\n') 1754 "{rev}:{node|short}@@@{tags}@@@{author|xmlescape}@@@"
1742 1755 "{date|isodate}@@@{branches}@@@{parents}@@@{bookmarks}\n"
1756 )
1757
1743 output, error = self.__client.runcommand(args) 1758 output, error = self.__client.runcommand(args)
1744 1759
1745 if output: 1760 if output:
1746 for index, line in enumerate(output.splitlines(), start=1): 1761 for index, line in enumerate(output.splitlines(), start=1):
1747 (changeset, tags, author, date, branches, parents, 1762 (
1748 bookmarks) = line.split("@@@") 1763 changeset,
1764 tags,
1765 author,
1766 date,
1767 branches,
1768 parents,
1769 bookmarks,
1770 ) = line.split("@@@")
1749 cdate, ctime = date.split()[:2] 1771 cdate, ctime = date.split()[:2]
1750 info.append("""<p><table>""") 1772 info.append("""<p><table>""")
1751 if mode == "heads": 1773 if mode == "heads":
1752 info.append(QCoreApplication.translate( 1774 info.append(
1775 QCoreApplication.translate(
1776 "mercurial",
1777 """<tr><td><b>Head #{0}</b></td><td></td></tr>\n""",
1778 ).format(index)
1779 )
1780 elif mode == "parents":
1781 info.append(
1782 QCoreApplication.translate(
1783 "mercurial",
1784 """<tr><td><b>Parent #{0}</b></td><td></td></tr>\n""",
1785 ).format(index)
1786 )
1787 elif mode == "tip":
1788 info.append(
1789 QCoreApplication.translate(
1790 "mercurial", """<tr><td><b>Tip</b></td><td></td></tr>\n"""
1791 )
1792 )
1793 info.append(
1794 QCoreApplication.translate(
1753 "mercurial", 1795 "mercurial",
1754 """<tr><td><b>Head #{0}</b></td><td></td></tr>\n""") 1796 """<tr><td><b>Changeset</b></td><td>{0}</td></tr>""",
1755 .format(index)) 1797 ).format(changeset)
1756 elif mode == "parents": 1798 )
1757 info.append(QCoreApplication.translate( 1799 if tags:
1800 info.append(
1801 QCoreApplication.translate(
1802 "mercurial", """<tr><td><b>Tags</b></td><td>{0}</td></tr>"""
1803 ).format("<br/>".join(tags.split()))
1804 )
1805 if bookmarks:
1806 info.append(
1807 QCoreApplication.translate(
1808 "mercurial",
1809 """<tr><td><b>Bookmarks</b></td><td>{0}</td></tr>""",
1810 ).format("<br/>".join(bookmarks.split()))
1811 )
1812 if branches:
1813 info.append(
1814 QCoreApplication.translate(
1815 "mercurial",
1816 """<tr><td><b>Branches</b></td><td>{0}</td></tr>""",
1817 ).format("<br/>".join(branches.split()))
1818 )
1819 if parents:
1820 info.append(
1821 QCoreApplication.translate(
1822 "mercurial",
1823 """<tr><td><b>Parents</b></td><td>{0}</td></tr>""",
1824 ).format("<br/>".join(parents.split()))
1825 )
1826 info.append(
1827 QCoreApplication.translate(
1758 "mercurial", 1828 "mercurial",
1759 """<tr><td><b>Parent #{0}</b></td><td></td></tr>\n""") 1829 """<tr><td><b>Last author</b></td><td>{0}</td></tr>\n"""
1760 .format(index)) 1830 """<tr><td><b>Committed date</b></td><td>{1}</td></tr>\n"""
1761 elif mode == "tip": 1831 """<tr><td><b>Committed time</b></td><td>{2}</td></tr>\n"""
1762 info.append(QCoreApplication.translate( 1832 """</table></p>""",
1763 "mercurial", 1833 ).format(author, cdate, ctime)
1764 """<tr><td><b>Tip</b></td><td></td></tr>\n""")) 1834 )
1765 info.append(QCoreApplication.translate( 1835
1766 "mercurial",
1767 """<tr><td><b>Changeset</b></td><td>{0}</td></tr>""")
1768 .format(changeset))
1769 if tags:
1770 info.append(QCoreApplication.translate(
1771 "mercurial",
1772 """<tr><td><b>Tags</b></td><td>{0}</td></tr>""")
1773 .format('<br/>'.join(tags.split())))
1774 if bookmarks:
1775 info.append(QCoreApplication.translate(
1776 "mercurial",
1777 """<tr><td><b>Bookmarks</b></td><td>{0}</td></tr>""")
1778 .format('<br/>'.join(bookmarks.split())))
1779 if branches:
1780 info.append(QCoreApplication.translate(
1781 "mercurial",
1782 """<tr><td><b>Branches</b></td><td>{0}</td></tr>""")
1783 .format('<br/>'.join(branches.split())))
1784 if parents:
1785 info.append(QCoreApplication.translate(
1786 "mercurial",
1787 """<tr><td><b>Parents</b></td><td>{0}</td></tr>""")
1788 .format('<br/>'.join(parents.split())))
1789 info.append(QCoreApplication.translate(
1790 "mercurial",
1791 """<tr><td><b>Last author</b></td><td>{0}</td></tr>\n"""
1792 """<tr><td><b>Committed date</b></td><td>{1}</td></tr>\n"""
1793 """<tr><td><b>Committed time</b></td><td>{2}</td></tr>\n"""
1794 """</table></p>""")
1795 .format(author, cdate, ctime))
1796
1797 dlg = VcsRepositoryInfoDialog(None, "\n".join(info)) 1836 dlg = VcsRepositoryInfoDialog(None, "\n".join(info))
1798 dlg.exec() 1837 dlg.exec()
1799 1838
1800 def hgConflicts(self): 1839 def hgConflicts(self):
1801 """ 1840 """
1802 Public method used to show a list of files containing conflicts. 1841 Public method used to show a list of files containing conflicts.
1803 """ 1842 """
1804 if self.conflictsDlg is None: 1843 if self.conflictsDlg is None:
1805 from .HgConflictsListDialog import HgConflictsListDialog 1844 from .HgConflictsListDialog import HgConflictsListDialog
1845
1806 self.conflictsDlg = HgConflictsListDialog(self) 1846 self.conflictsDlg = HgConflictsListDialog(self)
1807 self.conflictsDlg.show() 1847 self.conflictsDlg.show()
1808 self.conflictsDlg.raise_() 1848 self.conflictsDlg.raise_()
1809 self.conflictsDlg.start() 1849 self.conflictsDlg.start()
1810 1850
1811 def vcsResolved(self, name, unresolve=False): 1851 def vcsResolved(self, name, unresolve=False):
1812 """ 1852 """
1813 Public method used to resolve conflicts of a file/directory. 1853 Public method used to resolve conflicts of a file/directory.
1814 1854
1815 @param name file/directory name to be resolved (string) 1855 @param name file/directory name to be resolved (string)
1816 @param unresolve flag indicating to mark the file/directory as 1856 @param unresolve flag indicating to mark the file/directory as
1817 unresolved (boolean) 1857 unresolved (boolean)
1818 """ 1858 """
1819 args = self.initCommand("resolve") 1859 args = self.initCommand("resolve")
1820 if unresolve: 1860 if unresolve:
1821 args.append("--unmark") 1861 args.append("--unmark")
1822 else: 1862 else:
1823 args.append("--mark") 1863 args.append("--mark")
1824 1864
1825 if isinstance(name, list): 1865 if isinstance(name, list):
1826 self.addArguments(args, name) 1866 self.addArguments(args, name)
1827 else: 1867 else:
1828 args.append(name) 1868 args.append(name)
1829 1869
1830 title = ( 1870 title = (
1831 self.tr("Marking as 'unresolved'") 1871 self.tr("Marking as 'unresolved'")
1832 if unresolve else 1872 if unresolve
1833 self.tr("Marking as 'resolved'") 1873 else self.tr("Marking as 'resolved'")
1834 ) 1874 )
1835 dia = HgDialog(title, self) 1875 dia = HgDialog(title, self)
1836 res = dia.startProcess(args) 1876 res = dia.startProcess(args)
1837 if res: 1877 if res:
1838 dia.exec() 1878 dia.exec()
1839 self.checkVCSStatus() 1879 self.checkVCSStatus()
1840 1880
1841 def hgAbortMerge(self): 1881 def hgAbortMerge(self):
1842 """ 1882 """
1843 Public method to abort an uncommitted merge. 1883 Public method to abort an uncommitted merge.
1844 1884
1845 @return flag indicating, that the abortion contained an add 1885 @return flag indicating, that the abortion contained an add
1846 or delete (boolean) 1886 or delete (boolean)
1847 """ 1887 """
1848 if self.version >= (4, 5, 0): 1888 if self.version >= (4, 5, 0):
1849 args = self.initCommand("merge") 1889 args = self.initCommand("merge")
1850 args.append("--abort") 1890 args.append("--abort")
1851 else: 1891 else:
1852 args = self.initCommand("update") 1892 args = self.initCommand("update")
1853 args.append("--clean") 1893 args.append("--clean")
1854 1894
1855 dia = HgDialog( 1895 dia = HgDialog(self.tr("Aborting uncommitted merge"), self)
1856 self.tr('Aborting uncommitted merge'),
1857 self)
1858 res = dia.startProcess(args, showArgs=False) 1896 res = dia.startProcess(args, showArgs=False)
1859 if res: 1897 if res:
1860 dia.exec() 1898 dia.exec()
1861 res = dia.hasAddOrDelete() 1899 res = dia.hasAddOrDelete()
1862 self.checkVCSStatus() 1900 self.checkVCSStatus()
1863 return res 1901 return res
1864 1902
1865 def hgBranch(self): 1903 def hgBranch(self):
1866 """ 1904 """
1867 Public method used to create a branch in the Mercurial repository. 1905 Public method used to create a branch in the Mercurial repository.
1868 """ 1906 """
1869 from .HgBranchInputDialog import HgBranchInputDialog 1907 from .HgBranchInputDialog import HgBranchInputDialog
1908
1870 dlg = HgBranchInputDialog(self.hgGetBranchesList()) 1909 dlg = HgBranchInputDialog(self.hgGetBranchesList())
1871 if dlg.exec() == QDialog.DialogCode.Accepted: 1910 if dlg.exec() == QDialog.DialogCode.Accepted:
1872 name, commit, force = dlg.getData() 1911 name, commit, force = dlg.getData()
1873 name = name.strip().replace(" ", "_") 1912 name = name.strip().replace(" ", "_")
1874 args = self.initCommand("branch") 1913 args = self.initCommand("branch")
1875 if force: 1914 if force:
1876 args.append("--force") 1915 args.append("--force")
1877 args.append(name) 1916 args.append(name)
1878 1917
1879 dia = HgDialog( 1918 dia = HgDialog(self.tr("Creating branch in the Mercurial repository"), self)
1880 self.tr('Creating branch in the Mercurial repository'),
1881 self)
1882 res = dia.startProcess(args) 1919 res = dia.startProcess(args)
1883 if res: 1920 if res:
1884 dia.exec() 1921 dia.exec()
1885 if commit: 1922 if commit:
1886 project = ericApp().getObject("Project") 1923 project = ericApp().getObject("Project")
1887 self.vcsCommit( 1924 self.vcsCommit(
1888 project.getProjectPath(), 1925 project.getProjectPath(),
1889 self.tr("Created new branch <{0}>.").format( 1926 self.tr("Created new branch <{0}>.").format(name),
1890 name)) 1927 )
1891 1928
1892 def hgShowBranch(self): 1929 def hgShowBranch(self):
1893 """ 1930 """
1894 Public method used to show the current branch of the working directory. 1931 Public method used to show the current branch of the working directory.
1895 """ 1932 """
1896 args = self.initCommand("branch") 1933 args = self.initCommand("branch")
1897 1934
1898 dia = HgDialog(self.tr('Showing current branch'), self) 1935 dia = HgDialog(self.tr("Showing current branch"), self)
1899 res = dia.startProcess(args, showArgs=False) 1936 res = dia.startProcess(args, showArgs=False)
1900 if res: 1937 if res:
1901 dia.exec() 1938 dia.exec()
1902 1939
1903 def hgGetCurrentBranch(self): 1940 def hgGetCurrentBranch(self):
1904 """ 1941 """
1905 Public method to get the current branch of the working directory. 1942 Public method to get the current branch of the working directory.
1906 1943
1907 @return name of the current branch 1944 @return name of the current branch
1908 @rtype str 1945 @rtype str
1909 """ 1946 """
1910 args = self.initCommand("branch") 1947 args = self.initCommand("branch")
1911 1948
1912 output, error = self.__client.runcommand(args) 1949 output, error = self.__client.runcommand(args)
1913 1950
1914 return output.strip() 1951 return output.strip()
1915 1952
1916 def hgEditUserConfig(self): 1953 def hgEditUserConfig(self):
1917 """ 1954 """
1918 Public method used to edit the user configuration file. 1955 Public method used to edit the user configuration file.
1919 """ 1956 """
1920 from .HgUserConfigDialog import HgUserConfigDialog 1957 from .HgUserConfigDialog import HgUserConfigDialog
1958
1921 dlg = HgUserConfigDialog(version=self.version) 1959 dlg = HgUserConfigDialog(version=self.version)
1922 dlg.exec() 1960 dlg.exec()
1923 1961
1924 def hgEditConfig(self, repoName=None, 1962 def hgEditConfig(self, repoName=None, withLargefiles=True, largefilesData=None):
1925 withLargefiles=True, largefilesData=None):
1926 """ 1963 """
1927 Public method used to edit the repository configuration file. 1964 Public method used to edit the repository configuration file.
1928 1965
1929 @param repoName directory name containing the repository 1966 @param repoName directory name containing the repository
1930 @type str 1967 @type str
1931 @param withLargefiles flag indicating to configure the largefiles 1968 @param withLargefiles flag indicating to configure the largefiles
1932 section 1969 section
1933 @type bool 1970 @type bool
1935 section of the data dialog 1972 section of the data dialog
1936 @type dict 1973 @type dict
1937 """ 1974 """
1938 if repoName is None: 1975 if repoName is None:
1939 repoName = self.getClient().getRepository() 1976 repoName = self.getClient().getRepository()
1940 1977
1941 cfgFile = os.path.join(repoName, self.adminDir, "hgrc") 1978 cfgFile = os.path.join(repoName, self.adminDir, "hgrc")
1942 if not os.path.exists(cfgFile): 1979 if not os.path.exists(cfgFile):
1943 # open dialog to enter the initial data 1980 # open dialog to enter the initial data
1944 withLargefiles = (self.isExtensionActive("largefiles") and 1981 withLargefiles = self.isExtensionActive("largefiles") and withLargefiles
1945 withLargefiles)
1946 from .HgRepoConfigDataDialog import HgRepoConfigDataDialog 1982 from .HgRepoConfigDataDialog import HgRepoConfigDataDialog
1947 dlg = HgRepoConfigDataDialog(withLargefiles=withLargefiles, 1983
1948 largefilesData=largefilesData) 1984 dlg = HgRepoConfigDataDialog(
1985 withLargefiles=withLargefiles, largefilesData=largefilesData
1986 )
1949 if dlg.exec() == QDialog.DialogCode.Accepted: 1987 if dlg.exec() == QDialog.DialogCode.Accepted:
1950 createContents = True 1988 createContents = True
1951 defaultUrl, defaultPushUrl = dlg.getData() 1989 defaultUrl, defaultPushUrl = dlg.getData()
1952 if withLargefiles: 1990 if withLargefiles:
1953 lfMinSize, lfPattern = dlg.getLargefilesData() 1991 lfMinSize, lfPattern = dlg.getLargefilesData()
1959 # write the data entered 1997 # write the data entered
1960 cfg.write("[paths]\n") 1998 cfg.write("[paths]\n")
1961 if defaultUrl: 1999 if defaultUrl:
1962 cfg.write("default = {0}\n".format(defaultUrl)) 2000 cfg.write("default = {0}\n".format(defaultUrl))
1963 if defaultPushUrl: 2001 if defaultPushUrl:
1964 cfg.write("default-push = {0}\n".format( 2002 cfg.write("default-push = {0}\n".format(defaultPushUrl))
1965 defaultPushUrl)) 2003 if withLargefiles and (lfMinSize, lfPattern) != (None, None):
1966 if (
1967 withLargefiles and
1968 (lfMinSize, lfPattern) != (None, None)
1969 ):
1970 cfg.write("\n[largefiles]\n") 2004 cfg.write("\n[largefiles]\n")
1971 if lfMinSize is not None: 2005 if lfMinSize is not None:
1972 cfg.write("minsize = {0}\n".format(lfMinSize)) 2006 cfg.write("minsize = {0}\n".format(lfMinSize))
1973 if lfPattern is not None: 2007 if lfPattern is not None:
1974 cfg.write("patterns =\n") 2008 cfg.write("patterns =\n")
1975 cfg.write(" {0}\n".format( 2009 cfg.write(" {0}\n".format("\n ".join(lfPattern)))
1976 "\n ".join(lfPattern)))
1977 self.__monitorRepoIniFile(repoName) 2010 self.__monitorRepoIniFile(repoName)
1978 self.__iniFileChanged(cfgFile) 2011 self.__iniFileChanged(cfgFile)
1979 self.repoEditor = MiniEditor(cfgFile, "Properties") 2012 self.repoEditor = MiniEditor(cfgFile, "Properties")
1980 self.repoEditor.show() 2013 self.repoEditor.show()
1981 2014
1982 def hgVerify(self): 2015 def hgVerify(self):
1983 """ 2016 """
1984 Public method to verify the integrity of the repository. 2017 Public method to verify the integrity of the repository.
1985 """ 2018 """
1986 args = self.initCommand("verify") 2019 args = self.initCommand("verify")
1987 2020
1988 dia = HgDialog( 2021 dia = HgDialog(
1989 self.tr('Verifying the integrity of the Mercurial repository'), 2022 self.tr("Verifying the integrity of the Mercurial repository"), self
1990 self) 2023 )
1991 res = dia.startProcess(args) 2024 res = dia.startProcess(args)
1992 if res: 2025 if res:
1993 dia.exec() 2026 dia.exec()
1994 2027
1995 def hgShowConfig(self): 2028 def hgShowConfig(self):
1996 """ 2029 """
1997 Public method to show the combined configuration. 2030 Public method to show the combined configuration.
1998 """ 2031 """
1999 args = self.initCommand("showconfig") 2032 args = self.initCommand("showconfig")
2000 args.append("--untrusted") 2033 args.append("--untrusted")
2001 2034
2002 dia = HgDialog( 2035 dia = HgDialog(self.tr("Showing the combined configuration settings"), self)
2003 self.tr('Showing the combined configuration settings'),
2004 self)
2005 res = dia.startProcess(args, showArgs=False) 2036 res = dia.startProcess(args, showArgs=False)
2006 if res: 2037 if res:
2007 dia.exec() 2038 dia.exec()
2008 2039
2009 def hgShowPaths(self): 2040 def hgShowPaths(self):
2010 """ 2041 """
2011 Public method to show the path aliases for remote repositories. 2042 Public method to show the path aliases for remote repositories.
2012 """ 2043 """
2013 args = self.initCommand("paths") 2044 args = self.initCommand("paths")
2014 2045
2015 dia = HgDialog( 2046 dia = HgDialog(self.tr("Showing aliases for remote repositories"), self)
2016 self.tr('Showing aliases for remote repositories'),
2017 self)
2018 res = dia.startProcess(args, showArgs=False) 2047 res = dia.startProcess(args, showArgs=False)
2019 if res: 2048 if res:
2020 dia.exec() 2049 dia.exec()
2021 2050
2022 def hgRecover(self): 2051 def hgRecover(self):
2023 """ 2052 """
2024 Public method to recover an interrupted transaction. 2053 Public method to recover an interrupted transaction.
2025 """ 2054 """
2026 args = self.initCommand("recover") 2055 args = self.initCommand("recover")
2027 2056
2028 dia = HgDialog( 2057 dia = HgDialog(self.tr("Recovering from interrupted transaction"), self)
2029 self.tr('Recovering from interrupted transaction'),
2030 self)
2031 res = dia.startProcess(args, showArgs=False) 2058 res = dia.startProcess(args, showArgs=False)
2032 if res: 2059 if res:
2033 dia.exec() 2060 dia.exec()
2034 2061
2035 def hgIdentify(self): 2062 def hgIdentify(self):
2036 """ 2063 """
2037 Public method to identify the current working directory. 2064 Public method to identify the current working directory.
2038 """ 2065 """
2039 args = self.initCommand("identify") 2066 args = self.initCommand("identify")
2040 2067
2041 dia = HgDialog(self.tr('Identifying project directory'), self) 2068 dia = HgDialog(self.tr("Identifying project directory"), self)
2042 res = dia.startProcess(args, showArgs=False) 2069 res = dia.startProcess(args, showArgs=False)
2043 if res: 2070 if res:
2044 dia.exec() 2071 dia.exec()
2045 2072
2046 def hgCreateIgnoreFile(self, name, autoAdd=False): 2073 def hgCreateIgnoreFile(self, name, autoAdd=False):
2047 """ 2074 """
2048 Public method to create the ignore file. 2075 Public method to create the ignore file.
2049 2076
2050 @param name directory name to create the ignore file in (string) 2077 @param name directory name to create the ignore file in (string)
2051 @param autoAdd flag indicating to add it automatically (boolean) 2078 @param autoAdd flag indicating to add it automatically (boolean)
2052 @return flag indicating success 2079 @return flag indicating success
2053 """ 2080 """
2054 status = False 2081 status = False
2067 "glob:cur", 2094 "glob:cur",
2068 "glob:tmp", 2095 "glob:tmp",
2069 "glob:__pycache__", 2096 "glob:__pycache__",
2070 "glob:**.DS_Store", 2097 "glob:**.DS_Store",
2071 ] 2098 ]
2072 2099
2073 ignoreName = os.path.join(name, Hg.IgnoreFileName) 2100 ignoreName = os.path.join(name, Hg.IgnoreFileName)
2074 res = ( 2101 res = (
2075 EricMessageBox.yesNo( 2102 EricMessageBox.yesNo(
2076 self.__ui, 2103 self.__ui,
2077 self.tr("Create .hgignore file"), 2104 self.tr("Create .hgignore file"),
2078 self.tr("""<p>The file <b>{0}</b> exists already.""" 2105 self.tr(
2079 """ Overwrite it?</p>""").format(ignoreName), 2106 """<p>The file <b>{0}</b> exists already."""
2080 icon=EricMessageBox.Warning) 2107 """ Overwrite it?</p>"""
2081 if os.path.exists(ignoreName) else 2108 ).format(ignoreName),
2082 True 2109 icon=EricMessageBox.Warning,
2110 )
2111 if os.path.exists(ignoreName)
2112 else True
2083 ) 2113 )
2084 if res: 2114 if res:
2085 try: 2115 try:
2086 # create a .hgignore file 2116 # create a .hgignore file
2087 with open(ignoreName, "w") as ignore: 2117 with open(ignoreName, "w") as ignore:
2088 ignore.write("\n".join(ignorePatterns)) 2118 ignore.write("\n".join(ignorePatterns))
2089 ignore.write("\n") 2119 ignore.write("\n")
2090 status = True 2120 status = True
2091 except OSError: 2121 except OSError:
2092 status = False 2122 status = False
2093 2123
2094 if status and autoAdd: 2124 if status and autoAdd:
2095 self.vcsAdd(ignoreName, noDialog=True) 2125 self.vcsAdd(ignoreName, noDialog=True)
2096 project = ericApp().getObject("Project") 2126 project = ericApp().getObject("Project")
2097 project.appendFile(ignoreName) 2127 project.appendFile(ignoreName)
2098 2128
2099 return status 2129 return status
2100 2130
2101 def hgBundle(self, bundleData=None): 2131 def hgBundle(self, bundleData=None):
2102 """ 2132 """
2103 Public method to create a changegroup file. 2133 Public method to create a changegroup file.
2104 2134
2105 @param bundleData dictionary containing the bundle creation information 2135 @param bundleData dictionary containing the bundle creation information
2106 @type dict 2136 @type dict
2107 """ 2137 """
2108 if bundleData is None: 2138 if bundleData is None:
2109 from .HgBundleDialog import HgBundleDialog 2139 from .HgBundleDialog import HgBundleDialog
2110 dlg = HgBundleDialog(self.hgGetTagsList(), 2140
2111 self.hgGetBranchesList(), 2141 dlg = HgBundleDialog(
2112 self.hgGetBookmarksList(), 2142 self.hgGetTagsList(),
2113 version=self.version) 2143 self.hgGetBranchesList(),
2144 self.hgGetBookmarksList(),
2145 version=self.version,
2146 )
2114 if dlg.exec() != QDialog.DialogCode.Accepted: 2147 if dlg.exec() != QDialog.DialogCode.Accepted:
2115 return 2148 return
2116 2149
2117 revs, baseRevs, compression, bundleAll = dlg.getParameters() 2150 revs, baseRevs, compression, bundleAll = dlg.getParameters()
2118 else: 2151 else:
2119 revs = bundleData["revs"] 2152 revs = bundleData["revs"]
2120 if bundleData["base"]: 2153 if bundleData["base"]:
2121 baseRevs = [bundleData["base"]] 2154 baseRevs = [bundleData["base"]]
2122 else: 2155 else:
2123 baseRevs = [] 2156 baseRevs = []
2124 compression = "" 2157 compression = ""
2125 bundleAll = bundleData["all"] 2158 bundleAll = bundleData["all"]
2126 2159
2127 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( 2160 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter(
2128 None, 2161 None,
2129 self.tr("Create changegroup"), 2162 self.tr("Create changegroup"),
2130 self.__lastChangeGroupPath, 2163 self.__lastChangeGroupPath,
2131 self.tr("Mercurial Changegroup Files (*.hg)"), 2164 self.tr("Mercurial Changegroup Files (*.hg)"),
2132 None, 2165 None,
2133 EricFileDialog.DontConfirmOverwrite) 2166 EricFileDialog.DontConfirmOverwrite,
2134 2167 )
2168
2135 if not fname: 2169 if not fname:
2136 return # user aborted 2170 return # user aborted
2137 2171
2138 fpath = pathlib.Path(fname) 2172 fpath = pathlib.Path(fname)
2139 if not fpath.suffix: 2173 if not fpath.suffix:
2140 ex = selectedFilter.split("(*")[1].split(")")[0] 2174 ex = selectedFilter.split("(*")[1].split(")")[0]
2141 if ex: 2175 if ex:
2142 fpath = fpath.with_suffix(ex) 2176 fpath = fpath.with_suffix(ex)
2143 if fpath.exists(): 2177 if fpath.exists():
2144 res = EricMessageBox.yesNo( 2178 res = EricMessageBox.yesNo(
2145 self.__ui, 2179 self.__ui,
2146 self.tr("Create changegroup"), 2180 self.tr("Create changegroup"),
2147 self.tr("<p>The Mercurial changegroup file <b>{0}</b> " 2181 self.tr(
2148 "already exists. Overwrite it?</p>") 2182 "<p>The Mercurial changegroup file <b>{0}</b> "
2149 .format(fpath), 2183 "already exists. Overwrite it?</p>"
2150 icon=EricMessageBox.Warning) 2184 ).format(fpath),
2185 icon=EricMessageBox.Warning,
2186 )
2151 if not res: 2187 if not res:
2152 return 2188 return
2153 2189
2154 self.__lastChangeGroupPath = str(fpath.parent) 2190 self.__lastChangeGroupPath = str(fpath.parent)
2155 2191
2156 args = self.initCommand("bundle") 2192 args = self.initCommand("bundle")
2157 if bundleAll: 2193 if bundleAll:
2158 args.append("--all") 2194 args.append("--all")
2159 for rev in revs: 2195 for rev in revs:
2160 args.append("--rev") 2196 args.append("--rev")
2164 args.append(baseRev) 2200 args.append(baseRev)
2165 if compression: 2201 if compression:
2166 args.append("--type") 2202 args.append("--type")
2167 args.append(compression) 2203 args.append(compression)
2168 args.append(str(fpath)) 2204 args.append(str(fpath))
2169 2205
2170 dia = HgDialog(self.tr('Create changegroup'), self) 2206 dia = HgDialog(self.tr("Create changegroup"), self)
2171 res = dia.startProcess(args) 2207 res = dia.startProcess(args)
2172 if res: 2208 if res:
2173 dia.exec() 2209 dia.exec()
2174 2210
2175 def hgPreviewBundle(self): 2211 def hgPreviewBundle(self):
2176 """ 2212 """
2177 Public method used to view the log of incoming changes from a 2213 Public method used to view the log of incoming changes from a
2178 changegroup file. 2214 changegroup file.
2179 """ 2215 """
2180 file = EricFileDialog.getOpenFileName( 2216 file = EricFileDialog.getOpenFileName(
2181 None, 2217 None,
2182 self.tr("Preview changegroup"), 2218 self.tr("Preview changegroup"),
2183 self.__lastChangeGroupPath, 2219 self.__lastChangeGroupPath,
2184 self.tr("Mercurial Changegroup Files (*.hg);;All Files (*)")) 2220 self.tr("Mercurial Changegroup Files (*.hg);;All Files (*)"),
2221 )
2185 if file: 2222 if file:
2186 self.__lastChangeGroupPath = os.path.dirname(file) 2223 self.__lastChangeGroupPath = os.path.dirname(file)
2187 2224
2188 if self.logBrowserIncoming is None: 2225 if self.logBrowserIncoming is None:
2189 from .HgLogBrowserDialog import HgLogBrowserDialog 2226 from .HgLogBrowserDialog import HgLogBrowserDialog
2190 self.logBrowserIncoming = HgLogBrowserDialog( 2227
2191 self, mode="incoming") 2228 self.logBrowserIncoming = HgLogBrowserDialog(self, mode="incoming")
2192 self.logBrowserIncoming.show() 2229 self.logBrowserIncoming.show()
2193 self.logBrowserIncoming.raise_() 2230 self.logBrowserIncoming.raise_()
2194 self.logBrowserIncoming.start(bundle=file) 2231 self.logBrowserIncoming.start(bundle=file)
2195 2232
2196 def hgUnbundle(self, files=None): 2233 def hgUnbundle(self, files=None):
2197 """ 2234 """
2198 Public method to apply changegroup files. 2235 Public method to apply changegroup files.
2199 2236
2200 @param files list of bundle files to be applied 2237 @param files list of bundle files to be applied
2201 @type list of str 2238 @type list of str
2202 @return flag indicating, that the update contained an add 2239 @return flag indicating, that the update contained an add
2203 or delete 2240 or delete
2204 @rtype bool 2241 @rtype bool
2207 if not files: 2244 if not files:
2208 files = EricFileDialog.getOpenFileNames( 2245 files = EricFileDialog.getOpenFileNames(
2209 None, 2246 None,
2210 self.tr("Apply changegroups"), 2247 self.tr("Apply changegroups"),
2211 self.__lastChangeGroupPath, 2248 self.__lastChangeGroupPath,
2212 self.tr("Mercurial Changegroup Files (*.hg);;All Files (*)")) 2249 self.tr("Mercurial Changegroup Files (*.hg);;All Files (*)"),
2213 2250 )
2251
2214 if files: 2252 if files:
2215 self.__lastChangeGroupPath = os.path.dirname(files[0]) 2253 self.__lastChangeGroupPath = os.path.dirname(files[0])
2216 2254
2217 update = EricMessageBox.yesNo( 2255 update = EricMessageBox.yesNo(
2218 self.__ui, 2256 self.__ui,
2219 self.tr("Apply changegroups"), 2257 self.tr("Apply changegroups"),
2220 self.tr("""Shall the working directory be updated?"""), 2258 self.tr("""Shall the working directory be updated?"""),
2221 yesDefault=True) 2259 yesDefault=True,
2222 2260 )
2261
2223 args = self.initCommand("unbundle") 2262 args = self.initCommand("unbundle")
2224 if update: 2263 if update:
2225 args.append("--update") 2264 args.append("--update")
2226 args.append("--verbose") 2265 args.append("--verbose")
2227 args.extend(files) 2266 args.extend(files)
2228 2267
2229 dia = HgDialog(self.tr('Apply changegroups'), self) 2268 dia = HgDialog(self.tr("Apply changegroups"), self)
2230 res = dia.startProcess(args) 2269 res = dia.startProcess(args)
2231 if res: 2270 if res:
2232 dia.exec() 2271 dia.exec()
2233 res = dia.hasAddOrDelete() 2272 res = dia.hasAddOrDelete()
2234 self.checkVCSStatus() 2273 self.checkVCSStatus()
2235 2274
2236 return res 2275 return res
2237 2276
2238 def hgBisect(self, subcommand): 2277 def hgBisect(self, subcommand):
2239 """ 2278 """
2240 Public method to perform bisect commands. 2279 Public method to perform bisect commands.
2241 2280
2242 @param subcommand name of the subcommand (one of 'good', 'bad', 2281 @param subcommand name of the subcommand (one of 'good', 'bad',
2243 'skip' or 'reset') 2282 'skip' or 'reset')
2244 @type str 2283 @type str
2245 @exception ValueError raised to indicate an invalid bisect subcommand 2284 @exception ValueError raised to indicate an invalid bisect subcommand
2246 """ 2285 """
2247 if subcommand not in ("good", "bad", "skip", "reset"): 2286 if subcommand not in ("good", "bad", "skip", "reset"):
2248 raise ValueError( 2287 raise ValueError(
2249 self.tr("Bisect subcommand ({0}) invalid.") 2288 self.tr("Bisect subcommand ({0}) invalid.").format(subcommand)
2250 .format(subcommand)) 2289 )
2251 2290
2252 rev = "" 2291 rev = ""
2253 if subcommand in ("good", "bad", "skip"): 2292 if subcommand in ("good", "bad", "skip"):
2254 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog 2293 from .HgRevisionSelectionDialog import HgRevisionSelectionDialog
2294
2255 dlg = HgRevisionSelectionDialog( 2295 dlg = HgRevisionSelectionDialog(
2256 self.hgGetTagsList(), 2296 self.hgGetTagsList(),
2257 self.hgGetBranchesList(), 2297 self.hgGetBranchesList(),
2258 bookmarksList=self.hgGetBookmarksList() 2298 bookmarksList=self.hgGetBookmarksList(),
2259 ) 2299 )
2260 if dlg.exec() == QDialog.DialogCode.Accepted: 2300 if dlg.exec() == QDialog.DialogCode.Accepted:
2261 rev = dlg.getRevision() 2301 rev = dlg.getRevision()
2262 else: 2302 else:
2263 return 2303 return
2264 2304
2265 args = self.initCommand("bisect") 2305 args = self.initCommand("bisect")
2266 args.append("--{0}".format(subcommand)) 2306 args.append("--{0}".format(subcommand))
2267 if rev: 2307 if rev:
2268 args.append(rev) 2308 args.append(rev)
2269 2309
2270 dia = HgDialog( 2310 dia = HgDialog(self.tr("Mercurial Bisect ({0})").format(subcommand), self)
2271 self.tr('Mercurial Bisect ({0})').format(subcommand), self)
2272 res = dia.startProcess(args) 2311 res = dia.startProcess(args)
2273 if res: 2312 if res:
2274 dia.exec() 2313 dia.exec()
2275 2314
2276 def vcsForget(self, name): 2315 def vcsForget(self, name):
2277 """ 2316 """
2278 Public method used to remove a file from the Mercurial repository. 2317 Public method used to remove a file from the Mercurial repository.
2279 2318
2280 This will not remove the file from the project directory. 2319 This will not remove the file from the project directory.
2281 2320
2282 @param name file/directory name to be removed 2321 @param name file/directory name to be removed
2283 @type str or list of str 2322 @type str or list of str
2284 """ 2323 """
2285 args = self.initCommand("forget") 2324 args = self.initCommand("forget")
2286 args.append('-v') 2325 args.append("-v")
2287 2326
2288 if isinstance(name, list): 2327 if isinstance(name, list):
2289 self.addArguments(args, name) 2328 self.addArguments(args, name)
2290 else: 2329 else:
2291 args.append(name) 2330 args.append(name)
2292 2331
2293 dia = HgDialog( 2332 dia = HgDialog(
2294 self.tr('Removing files from the Mercurial repository only'), 2333 self.tr("Removing files from the Mercurial repository only"), self
2295 self) 2334 )
2296 res = dia.startProcess(args) 2335 res = dia.startProcess(args)
2297 if res: 2336 if res:
2298 dia.exec() 2337 dia.exec()
2299 if isinstance(name, list): 2338 if isinstance(name, list):
2300 self.__forgotNames.extend(name) 2339 self.__forgotNames.extend(name)
2301 else: 2340 else:
2302 self.__forgotNames.append(name) 2341 self.__forgotNames.append(name)
2303 2342
2304 def hgBackout(self): 2343 def hgBackout(self):
2305 """ 2344 """
2306 Public method used to backout an earlier changeset from the Mercurial 2345 Public method used to backout an earlier changeset from the Mercurial
2307 repository. 2346 repository.
2308 """ 2347 """
2309 from .HgBackoutDialog import HgBackoutDialog 2348 from .HgBackoutDialog import HgBackoutDialog
2310 dlg = HgBackoutDialog(self.hgGetTagsList(), 2349
2311 self.hgGetBranchesList(), 2350 dlg = HgBackoutDialog(
2312 self.hgGetBookmarksList()) 2351 self.hgGetTagsList(), self.hgGetBranchesList(), self.hgGetBookmarksList()
2352 )
2313 if dlg.exec() == QDialog.DialogCode.Accepted: 2353 if dlg.exec() == QDialog.DialogCode.Accepted:
2314 rev, merge, date, user, message = dlg.getParameters() 2354 rev, merge, date, user, message = dlg.getParameters()
2315 if not rev: 2355 if not rev:
2316 EricMessageBox.warning( 2356 EricMessageBox.warning(
2317 self.__ui, 2357 self.__ui,
2318 self.tr("Backing out changeset"), 2358 self.tr("Backing out changeset"),
2319 self.tr("""No revision given. Aborting...""")) 2359 self.tr("""No revision given. Aborting..."""),
2360 )
2320 return 2361 return
2321 2362
2322 args = self.initCommand("backout") 2363 args = self.initCommand("backout")
2323 args.append('-v') 2364 args.append("-v")
2324 if merge: 2365 if merge:
2325 args.append('--merge') 2366 args.append("--merge")
2326 if date: 2367 if date:
2327 args.append('--date') 2368 args.append("--date")
2328 args.append(date) 2369 args.append(date)
2329 if user: 2370 if user:
2330 args.append('--user') 2371 args.append("--user")
2331 args.append(user) 2372 args.append(user)
2332 args.append('--message') 2373 args.append("--message")
2333 args.append(message) 2374 args.append(message)
2334 args.append(rev) 2375 args.append(rev)
2335 2376
2336 dia = HgDialog(self.tr('Backing out changeset'), self) 2377 dia = HgDialog(self.tr("Backing out changeset"), self)
2337 res = dia.startProcess(args) 2378 res = dia.startProcess(args)
2338 if res: 2379 if res:
2339 dia.exec() 2380 dia.exec()
2340 2381
2341 def hgRollback(self): 2382 def hgRollback(self):
2342 """ 2383 """
2343 Public method used to rollback the last transaction. 2384 Public method used to rollback the last transaction.
2344 """ 2385 """
2345 res = EricMessageBox.yesNo( 2386 res = EricMessageBox.yesNo(
2346 None, 2387 None,
2347 self.tr("Rollback last transaction"), 2388 self.tr("Rollback last transaction"),
2348 self.tr("""Are you sure you want to rollback the last""" 2389 self.tr(
2349 """ transaction?"""), 2390 """Are you sure you want to rollback the last""" """ transaction?"""
2350 icon=EricMessageBox.Warning) 2391 ),
2392 icon=EricMessageBox.Warning,
2393 )
2351 if res: 2394 if res:
2352 dia = HgDialog(self.tr('Rollback last transaction'), self) 2395 dia = HgDialog(self.tr("Rollback last transaction"), self)
2353 res = dia.startProcess(["rollback"]) 2396 res = dia.startProcess(["rollback"])
2354 if res: 2397 if res:
2355 dia.exec() 2398 dia.exec()
2356 2399
2357 def hgServe(self, repoPath): 2400 def hgServe(self, repoPath):
2358 """ 2401 """
2359 Public method used to serve the project. 2402 Public method used to serve the project.
2360 2403
2361 @param repoPath directory containing the repository 2404 @param repoPath directory containing the repository
2362 @type str 2405 @type str
2363 """ 2406 """
2364 from .HgServeDialog import HgServeDialog 2407 from .HgServeDialog import HgServeDialog
2408
2365 self.serveDlg = HgServeDialog(self, repoPath) 2409 self.serveDlg = HgServeDialog(self, repoPath)
2366 self.serveDlg.show() 2410 self.serveDlg.show()
2367 2411
2368 def hgImport(self): 2412 def hgImport(self):
2369 """ 2413 """
2370 Public method to import a patch file. 2414 Public method to import a patch file.
2371 2415
2372 @return flag indicating, that the import contained an add, a delete 2416 @return flag indicating, that the import contained an add, a delete
2373 or a change to the project file (boolean) 2417 or a change to the project file (boolean)
2374 """ 2418 """
2375 from .HgImportDialog import HgImportDialog 2419 from .HgImportDialog import HgImportDialog
2420
2376 dlg = HgImportDialog(self) 2421 dlg = HgImportDialog(self)
2377 if dlg.exec() == QDialog.DialogCode.Accepted: 2422 if dlg.exec() == QDialog.DialogCode.Accepted:
2378 (patchFile, noCommit, message, date, user, withSecret, stripCount, 2423 (
2379 force) = dlg.getParameters() 2424 patchFile,
2380 2425 noCommit,
2426 message,
2427 date,
2428 user,
2429 withSecret,
2430 stripCount,
2431 force,
2432 ) = dlg.getParameters()
2433
2381 args = self.initCommand("import") 2434 args = self.initCommand("import")
2382 args.append("--verbose") 2435 args.append("--verbose")
2383 if noCommit: 2436 if noCommit:
2384 args.append("--no-commit") 2437 args.append("--no-commit")
2385 else: 2438 else:
2386 if message: 2439 if message:
2387 args.append('--message') 2440 args.append("--message")
2388 args.append(message) 2441 args.append(message)
2389 if date: 2442 if date:
2390 args.append('--date') 2443 args.append("--date")
2391 args.append(date) 2444 args.append(date)
2392 if user: 2445 if user:
2393 args.append('--user') 2446 args.append("--user")
2394 args.append(user) 2447 args.append(user)
2395 if stripCount != 1: 2448 if stripCount != 1:
2396 args.append("--strip") 2449 args.append("--strip")
2397 args.append(str(stripCount)) 2450 args.append(str(stripCount))
2398 if force: 2451 if force:
2399 args.append("--force") 2452 args.append("--force")
2400 if withSecret: 2453 if withSecret:
2401 args.append("--secret") 2454 args.append("--secret")
2402 args.append(patchFile) 2455 args.append(patchFile)
2403 2456
2404 dia = HgDialog(self.tr("Import Patch"), self) 2457 dia = HgDialog(self.tr("Import Patch"), self)
2405 res = dia.startProcess(args) 2458 res = dia.startProcess(args)
2406 if res: 2459 if res:
2407 dia.exec() 2460 dia.exec()
2408 res = dia.hasAddOrDelete() 2461 res = dia.hasAddOrDelete()
2409 self.checkVCSStatus() 2462 self.checkVCSStatus()
2410 else: 2463 else:
2411 res = False 2464 res = False
2412 2465
2413 return res 2466 return res
2414 2467
2415 def hgExport(self): 2468 def hgExport(self):
2416 """ 2469 """
2417 Public method to export patches to files. 2470 Public method to export patches to files.
2418 """ 2471 """
2419 from .HgExportDialog import HgExportDialog 2472 from .HgExportDialog import HgExportDialog
2420 dlg = HgExportDialog(self.hgGetBookmarksList(), 2473
2421 self.version >= (4, 7, 0)) 2474 dlg = HgExportDialog(self.hgGetBookmarksList(), self.version >= (4, 7, 0))
2422 if dlg.exec() == QDialog.DialogCode.Accepted: 2475 if dlg.exec() == QDialog.DialogCode.Accepted:
2423 (filePattern, revisions, bookmark, switchParent, allText, 2476 (
2424 noDates, git) = dlg.getParameters() 2477 filePattern,
2425 2478 revisions,
2479 bookmark,
2480 switchParent,
2481 allText,
2482 noDates,
2483 git,
2484 ) = dlg.getParameters()
2485
2426 args = self.initCommand("export") 2486 args = self.initCommand("export")
2427 args.append("--output") 2487 args.append("--output")
2428 args.append(filePattern) 2488 args.append(filePattern)
2429 args.append("--verbose") 2489 args.append("--verbose")
2430 if switchParent: 2490 if switchParent:
2439 args.append("--bookmark") 2499 args.append("--bookmark")
2440 args.append(bookmark) 2500 args.append(bookmark)
2441 else: 2501 else:
2442 for rev in revisions: 2502 for rev in revisions:
2443 args.append(rev) 2503 args.append(rev)
2444 2504
2445 dia = HgDialog(self.tr("Export Patches"), self) 2505 dia = HgDialog(self.tr("Export Patches"), self)
2446 res = dia.startProcess(args) 2506 res = dia.startProcess(args)
2447 if res: 2507 if res:
2448 dia.exec() 2508 dia.exec()
2449 2509
2450 def hgPhase(self, data=None): 2510 def hgPhase(self, data=None):
2451 """ 2511 """
2452 Public method to change the phase of revisions. 2512 Public method to change the phase of revisions.
2453 2513
2454 @param data tuple giving phase data (list of revisions, phase, flag 2514 @param data tuple giving phase data (list of revisions, phase, flag
2455 indicating a forced operation) (list of strings, string, boolean) 2515 indicating a forced operation) (list of strings, string, boolean)
2456 @return flag indicating success (boolean) 2516 @return flag indicating success (boolean)
2457 @exception ValueError raised to indicate an invalid phase 2517 @exception ValueError raised to indicate an invalid phase
2458 """ 2518 """
2459 if data is None: 2519 if data is None:
2460 from .HgPhaseDialog import HgPhaseDialog 2520 from .HgPhaseDialog import HgPhaseDialog
2521
2461 dlg = HgPhaseDialog() 2522 dlg = HgPhaseDialog()
2462 if dlg.exec() == QDialog.DialogCode.Accepted: 2523 if dlg.exec() == QDialog.DialogCode.Accepted:
2463 data = dlg.getData() 2524 data = dlg.getData()
2464 2525
2465 if data: 2526 if data:
2466 revs, phase, force = data 2527 revs, phase, force = data
2467 2528
2468 if phase not in ("p", "d", "s"): 2529 if phase not in ("p", "d", "s"):
2469 raise ValueError("Invalid phase given.") 2530 raise ValueError("Invalid phase given.")
2470 2531
2471 args = self.initCommand("phase") 2532 args = self.initCommand("phase")
2472 if phase == "p": 2533 if phase == "p":
2473 args.append("--public") 2534 args.append("--public")
2474 elif phase == "d": 2535 elif phase == "d":
2475 args.append("--draft") 2536 args.append("--draft")
2476 else: 2537 else:
2477 args.append("--secret") 2538 args.append("--secret")
2478 2539
2479 if force: 2540 if force:
2480 args.append("--force") 2541 args.append("--force")
2481 for rev in revs: 2542 for rev in revs:
2482 args.append(rev) 2543 args.append(rev)
2483 2544
2484 dia = HgDialog(self.tr("Change Phase"), self) 2545 dia = HgDialog(self.tr("Change Phase"), self)
2485 res = dia.startProcess(args) 2546 res = dia.startProcess(args)
2486 if res: 2547 if res:
2487 dia.exec() 2548 dia.exec()
2488 res = dia.normalExitWithoutErrors() 2549 res = dia.normalExitWithoutErrors()
2489 else: 2550 else:
2490 res = False 2551 res = False
2491 2552
2492 return res 2553 return res
2493 2554
2494 def hgGraft(self, revs=None): 2555 def hgGraft(self, revs=None):
2495 """ 2556 """
2496 Public method to copy changesets from another branch. 2557 Public method to copy changesets from another branch.
2497 2558
2498 @param revs list of revisions to show in the revisions pane (list of 2559 @param revs list of revisions to show in the revisions pane (list of
2499 strings) 2560 strings)
2500 @return flag indicating that the project should be reread (boolean) 2561 @return flag indicating that the project should be reread (boolean)
2501 """ 2562 """
2502 from .HgGraftDialog import HgGraftDialog 2563 from .HgGraftDialog import HgGraftDialog
2564
2503 res = False 2565 res = False
2504 dlg = HgGraftDialog(self, revs) 2566 dlg = HgGraftDialog(self, revs)
2505 if dlg.exec() == QDialog.DialogCode.Accepted: 2567 if dlg.exec() == QDialog.DialogCode.Accepted:
2506 (revs, 2568 (
2507 (userData, currentUser, userName), 2569 revs,
2508 (dateData, currentDate, dateStr), 2570 (userData, currentUser, userName),
2509 log, dryrun, noCommit) = dlg.getData() 2571 (dateData, currentDate, dateStr),
2510 2572 log,
2573 dryrun,
2574 noCommit,
2575 ) = dlg.getData()
2576
2511 args = self.initCommand("graft") 2577 args = self.initCommand("graft")
2512 args.append("--verbose") 2578 args.append("--verbose")
2513 if userData: 2579 if userData:
2514 if currentUser: 2580 if currentUser:
2515 args.append("--currentuser") 2581 args.append("--currentuser")
2527 if dryrun: 2593 if dryrun:
2528 args.append("--dry-run") 2594 args.append("--dry-run")
2529 if noCommit: 2595 if noCommit:
2530 args.append("--no-commit") 2596 args.append("--no-commit")
2531 args.extend(revs) 2597 args.extend(revs)
2532 2598
2533 dia = HgDialog(self.tr('Copy Changesets'), self) 2599 dia = HgDialog(self.tr("Copy Changesets"), self)
2534 res = dia.startProcess(args) 2600 res = dia.startProcess(args)
2535 if res: 2601 if res:
2536 dia.exec() 2602 dia.exec()
2537 res = dia.hasAddOrDelete() 2603 res = dia.hasAddOrDelete()
2538 self.checkVCSStatus() 2604 self.checkVCSStatus()
2539 return res 2605 return res
2540 2606
2541 def __hgGraftSubCommand(self, subcommand, title): 2607 def __hgGraftSubCommand(self, subcommand, title):
2542 """ 2608 """
2543 Private method to perform a Mercurial graft subcommand. 2609 Private method to perform a Mercurial graft subcommand.
2544 2610
2545 @param subcommand subcommand flag 2611 @param subcommand subcommand flag
2546 @type str 2612 @type str
2547 @param title tirle of the dialog 2613 @param title tirle of the dialog
2548 @type str 2614 @type str
2549 @return flag indicating that the project should be reread 2615 @return flag indicating that the project should be reread
2550 @rtype bool 2616 @rtype bool
2551 """ 2617 """
2552 args = self.initCommand("graft") 2618 args = self.initCommand("graft")
2553 args.append(subcommand) 2619 args.append(subcommand)
2554 args.append("--verbose") 2620 args.append("--verbose")
2555 2621
2556 dia = HgDialog(title, self) 2622 dia = HgDialog(title, self)
2557 res = dia.startProcess(args) 2623 res = dia.startProcess(args)
2558 if res: 2624 if res:
2559 dia.exec() 2625 dia.exec()
2560 res = dia.hasAddOrDelete() 2626 res = dia.hasAddOrDelete()
2561 self.checkVCSStatus() 2627 self.checkVCSStatus()
2562 return res 2628 return res
2563 2629
2564 def hgGraftContinue(self, path): 2630 def hgGraftContinue(self, path):
2565 """ 2631 """
2566 Public method to continue copying changesets from another branch. 2632 Public method to continue copying changesets from another branch.
2567 2633
2568 @param path directory name of the project 2634 @param path directory name of the project
2569 @type str 2635 @type str
2570 @return flag indicating that the project should be reread 2636 @return flag indicating that the project should be reread
2571 @rtype bool 2637 @rtype bool
2572 """ 2638 """
2573 return self.__hgGraftSubCommand( 2639 return self.__hgGraftSubCommand(
2574 "--continue", self.tr('Copy Changesets (Continue)')) 2640 "--continue", self.tr("Copy Changesets (Continue)")
2575 2641 )
2642
2576 def hgGraftStop(self, path): 2643 def hgGraftStop(self, path):
2577 """ 2644 """
2578 Public method to stop an interrupted copying session. 2645 Public method to stop an interrupted copying session.
2579 2646
2580 @param path directory name of the project 2647 @param path directory name of the project
2581 @type str 2648 @type str
2582 @return flag indicating that the project should be reread 2649 @return flag indicating that the project should be reread
2583 @rtype bool 2650 @rtype bool
2584 """ 2651 """
2585 return self.__hgGraftSubCommand( 2652 return self.__hgGraftSubCommand("--stop", self.tr("Copy Changesets (Stop)"))
2586 "--stop", self.tr('Copy Changesets (Stop)')) 2653
2587
2588 def hgGraftAbort(self, path): 2654 def hgGraftAbort(self, path):
2589 """ 2655 """
2590 Public method to abort an interrupted copying session and perform 2656 Public method to abort an interrupted copying session and perform
2591 a rollback. 2657 a rollback.
2592 2658
2593 @param path directory name of the project 2659 @param path directory name of the project
2594 @type str 2660 @type str
2595 @return flag indicating that the project should be reread 2661 @return flag indicating that the project should be reread
2596 @rtype bool 2662 @rtype bool
2597 """ 2663 """
2598 return self.__hgGraftSubCommand( 2664 return self.__hgGraftSubCommand("--abort", self.tr("Copy Changesets (Abort)"))
2599 "--abort", self.tr('Copy Changesets (Abort)')) 2665
2600
2601 def hgArchive(self): 2666 def hgArchive(self):
2602 """ 2667 """
2603 Public method to create an unversioned archive from the repository. 2668 Public method to create an unversioned archive from the repository.
2604 """ 2669 """
2605 from .HgArchiveDialog import HgArchiveDialog 2670 from .HgArchiveDialog import HgArchiveDialog
2671
2606 dlg = HgArchiveDialog(self) 2672 dlg = HgArchiveDialog(self)
2607 if dlg.exec() == QDialog.DialogCode.Accepted: 2673 if dlg.exec() == QDialog.DialogCode.Accepted:
2608 archive, type_, prefix, subrepos = dlg.getData() 2674 archive, type_, prefix, subrepos = dlg.getData()
2609 2675
2610 args = self.initCommand("archive") 2676 args = self.initCommand("archive")
2611 if type_: 2677 if type_:
2612 args.append("--type") 2678 args.append("--type")
2613 args.append(type_) 2679 args.append(type_)
2614 if prefix: 2680 if prefix:
2615 args.append("--prefix") 2681 args.append("--prefix")
2616 args.append(prefix) 2682 args.append(prefix)
2617 if subrepos: 2683 if subrepos:
2618 args.append("--subrepos") 2684 args.append("--subrepos")
2619 args.append(archive) 2685 args.append(archive)
2620 2686
2621 dia = HgDialog(self.tr("Create Unversioned Archive"), self) 2687 dia = HgDialog(self.tr("Create Unversioned Archive"), self)
2622 res = dia.startProcess(args) 2688 res = dia.startProcess(args)
2623 if res: 2689 if res:
2624 dia.exec() 2690 dia.exec()
2625 2691
2626 def hgDeleteBackups(self): 2692 def hgDeleteBackups(self):
2627 """ 2693 """
2628 Public method to delete all backup bundles in the backup area. 2694 Public method to delete all backup bundles in the backup area.
2629 """ 2695 """
2630 backupdir = os.path.join(self.getClient().getRepository(), 2696 backupdir = os.path.join(
2631 self.adminDir, "strip-backup") 2697 self.getClient().getRepository(), self.adminDir, "strip-backup"
2698 )
2632 yes = EricMessageBox.yesNo( 2699 yes = EricMessageBox.yesNo(
2633 self.__ui, 2700 self.__ui,
2634 self.tr("Delete All Backups"), 2701 self.tr("Delete All Backups"),
2635 self.tr( 2702 self.tr(
2636 """<p>Do you really want to delete all backup bundles""" 2703 """<p>Do you really want to delete all backup bundles"""
2637 """ stored in the backup area?<br/><b>{0}</b></p>""" 2704 """ stored in the backup area?<br/><b>{0}</b></p>"""
2638 ).format(backupdir) 2705 ).format(backupdir),
2639 ) 2706 )
2640 if yes: 2707 if yes:
2641 shutil.rmtree(backupdir, True) 2708 shutil.rmtree(backupdir, True)
2642 2709
2643 ########################################################################### 2710 ###########################################################################
2644 ## Methods to deal with sub-repositories are below. 2711 ## Methods to deal with sub-repositories are below.
2645 ########################################################################### 2712 ###########################################################################
2646 2713
2647 def getHgSubPath(self): 2714 def getHgSubPath(self):
2648 """ 2715 """
2649 Public method to get the path to the .hgsub file containing the 2716 Public method to get the path to the .hgsub file containing the
2650 definitions of sub-repositories. 2717 definitions of sub-repositories.
2651 2718
2652 @return full path of the .hgsub file (string) 2719 @return full path of the .hgsub file (string)
2653 """ 2720 """
2654 ppath = self.__projectHelper.getProject().getProjectPath() 2721 ppath = self.__projectHelper.getProject().getProjectPath()
2655 return os.path.join(ppath, ".hgsub") 2722 return os.path.join(ppath, ".hgsub")
2656 2723
2657 def hasSubrepositories(self): 2724 def hasSubrepositories(self):
2658 """ 2725 """
2659 Public method to check, if the project might have sub-repositories. 2726 Public method to check, if the project might have sub-repositories.
2660 2727
2661 @return flag indicating the existence of sub-repositories (boolean) 2728 @return flag indicating the existence of sub-repositories (boolean)
2662 """ 2729 """
2663 hgsub = self.getHgSubPath() 2730 hgsub = self.getHgSubPath()
2664 return os.path.isfile(hgsub) and os.stat(hgsub).st_size > 0 2731 return os.path.isfile(hgsub) and os.stat(hgsub).st_size > 0
2665 2732
2666 def hgAddSubrepository(self): 2733 def hgAddSubrepository(self):
2667 """ 2734 """
2668 Public method to add a sub-repository. 2735 Public method to add a sub-repository.
2669 """ 2736 """
2670 from .HgAddSubrepositoryDialog import HgAddSubrepositoryDialog 2737 from .HgAddSubrepositoryDialog import HgAddSubrepositoryDialog
2738
2671 ppath = self.__projectHelper.getProject().getProjectPath() 2739 ppath = self.__projectHelper.getProject().getProjectPath()
2672 hgsub = self.getHgSubPath() 2740 hgsub = self.getHgSubPath()
2673 dlg = HgAddSubrepositoryDialog(ppath) 2741 dlg = HgAddSubrepositoryDialog(ppath)
2674 if dlg.exec() == QDialog.DialogCode.Accepted: 2742 if dlg.exec() == QDialog.DialogCode.Accepted:
2675 relPath, subrepoType, subrepoUrl = dlg.getData() 2743 relPath, subrepoType, subrepoUrl = dlg.getData()
2676 if subrepoType == "hg": 2744 if subrepoType == "hg":
2677 url = subrepoUrl 2745 url = subrepoUrl
2678 else: 2746 else:
2679 url = "[{0}]{1}".format(subrepoType, subrepoUrl) 2747 url = "[{0}]{1}".format(subrepoType, subrepoUrl)
2680 entry = "{0} = {1}\n".format(relPath, url) 2748 entry = "{0} = {1}\n".format(relPath, url)
2681 2749
2682 contents = [] 2750 contents = []
2683 if os.path.isfile(hgsub): 2751 if os.path.isfile(hgsub):
2684 # file exists; check, if such an entry exists already 2752 # file exists; check, if such an entry exists already
2685 needsAdd = False 2753 needsAdd = False
2686 try: 2754 try:
2690 EricMessageBox.critical( 2758 EricMessageBox.critical(
2691 self.__ui, 2759 self.__ui,
2692 self.tr("Add Sub-repository"), 2760 self.tr("Add Sub-repository"),
2693 self.tr( 2761 self.tr(
2694 """<p>The sub-repositories file .hgsub could not""" 2762 """<p>The sub-repositories file .hgsub could not"""
2695 """ be read.</p><p>Reason: {0}</p>""") 2763 """ be read.</p><p>Reason: {0}</p>"""
2696 .format(str(err))) 2764 ).format(str(err)),
2765 )
2697 return 2766 return
2698 2767
2699 if entry in contents: 2768 if entry in contents:
2700 EricMessageBox.critical( 2769 EricMessageBox.critical(
2701 self.__ui, 2770 self.__ui,
2702 self.tr("Add Sub-repository"), 2771 self.tr("Add Sub-repository"),
2703 self.tr( 2772 self.tr(
2704 """<p>The sub-repositories file .hgsub already""" 2773 """<p>The sub-repositories file .hgsub already"""
2705 """ contains an entry <b>{0}</b>.""" 2774 """ contains an entry <b>{0}</b>."""
2706 """ Aborting...</p>""").format(entry)) 2775 """ Aborting...</p>"""
2776 ).format(entry),
2777 )
2707 return 2778 return
2708 else: 2779 else:
2709 needsAdd = True 2780 needsAdd = True
2710 2781
2711 if contents and not contents[-1].endswith("\n"): 2782 if contents and not contents[-1].endswith("\n"):
2712 contents[-1] = contents[-1] + "\n" 2783 contents[-1] = contents[-1] + "\n"
2713 contents.append(entry) 2784 contents.append(entry)
2714 try: 2785 try:
2715 with open(hgsub, "w") as f: 2786 with open(hgsub, "w") as f:
2718 EricMessageBox.critical( 2789 EricMessageBox.critical(
2719 self.__ui, 2790 self.__ui,
2720 self.tr("Add Sub-repository"), 2791 self.tr("Add Sub-repository"),
2721 self.tr( 2792 self.tr(
2722 """<p>The sub-repositories file .hgsub could not""" 2793 """<p>The sub-repositories file .hgsub could not"""
2723 """ be written to.</p><p>Reason: {0}</p>""") 2794 """ be written to.</p><p>Reason: {0}</p>"""
2724 .format(str(err))) 2795 ).format(str(err)),
2796 )
2725 return 2797 return
2726 2798
2727 if needsAdd: 2799 if needsAdd:
2728 self.vcsAdd(hgsub) 2800 self.vcsAdd(hgsub)
2729 self.__projectHelper.getProject().appendFile(hgsub) 2801 self.__projectHelper.getProject().appendFile(hgsub)
2730 2802
2731 def hgRemoveSubrepositories(self): 2803 def hgRemoveSubrepositories(self):
2732 """ 2804 """
2733 Public method to remove sub-repositories. 2805 Public method to remove sub-repositories.
2734 """ 2806 """
2735 hgsub = self.getHgSubPath() 2807 hgsub = self.getHgSubPath()
2736 2808
2737 subrepositories = [] 2809 subrepositories = []
2738 if not os.path.isfile(hgsub): 2810 if not os.path.isfile(hgsub):
2739 EricMessageBox.critical( 2811 EricMessageBox.critical(
2740 self.__ui, 2812 self.__ui,
2741 self.tr("Remove Sub-repositories"), 2813 self.tr("Remove Sub-repositories"),
2742 self.tr("""<p>The sub-repositories file .hgsub does not""" 2814 self.tr(
2743 """ exist. Aborting...</p>""")) 2815 """<p>The sub-repositories file .hgsub does not"""
2816 """ exist. Aborting...</p>"""
2817 ),
2818 )
2744 return 2819 return
2745 2820
2746 try: 2821 try:
2747 with open(hgsub, "r") as f: 2822 with open(hgsub, "r") as f:
2748 subrepositories = [line.strip() for line in f.readlines()] 2823 subrepositories = [line.strip() for line in f.readlines()]
2749 except OSError as err: 2824 except OSError as err:
2750 EricMessageBox.critical( 2825 EricMessageBox.critical(
2751 self.__ui, 2826 self.__ui,
2752 self.tr("Remove Sub-repositories"), 2827 self.tr("Remove Sub-repositories"),
2753 self.tr("""<p>The sub-repositories file .hgsub could not""" 2828 self.tr(
2754 """ be read.</p><p>Reason: {0}</p>""") 2829 """<p>The sub-repositories file .hgsub could not"""
2755 .format(str(err))) 2830 """ be read.</p><p>Reason: {0}</p>"""
2831 ).format(str(err)),
2832 )
2756 return 2833 return
2757 2834
2758 from .HgRemoveSubrepositoriesDialog import ( 2835 from .HgRemoveSubrepositoriesDialog import HgRemoveSubrepositoriesDialog
2759 HgRemoveSubrepositoriesDialog 2836
2760 )
2761 dlg = HgRemoveSubrepositoriesDialog(subrepositories) 2837 dlg = HgRemoveSubrepositoriesDialog(subrepositories)
2762 if dlg.exec() == QDialog.DialogCode.Accepted: 2838 if dlg.exec() == QDialog.DialogCode.Accepted:
2763 subrepositories, removedSubrepos, deleteSubrepos = dlg.getData() 2839 subrepositories, removedSubrepos, deleteSubrepos = dlg.getData()
2764 contents = "\n".join(subrepositories) + "\n" 2840 contents = "\n".join(subrepositories) + "\n"
2765 try: 2841 try:
2769 EricMessageBox.critical( 2845 EricMessageBox.critical(
2770 self.__ui, 2846 self.__ui,
2771 self.tr("Remove Sub-repositories"), 2847 self.tr("Remove Sub-repositories"),
2772 self.tr( 2848 self.tr(
2773 """<p>The sub-repositories file .hgsub could not""" 2849 """<p>The sub-repositories file .hgsub could not"""
2774 """ be written to.</p><p>Reason: {0}</p>""") 2850 """ be written to.</p><p>Reason: {0}</p>"""
2775 .format(str(err))) 2851 ).format(str(err)),
2852 )
2776 return 2853 return
2777 2854
2778 if deleteSubrepos: 2855 if deleteSubrepos:
2779 ppath = self.__projectHelper.getProject().getProjectPath() 2856 ppath = self.__projectHelper.getProject().getProjectPath()
2780 for removedSubrepo in removedSubrepos: 2857 for removedSubrepo in removedSubrepos:
2781 subrepoPath = removedSubrepo.split("=", 1)[0].strip() 2858 subrepoPath = removedSubrepo.split("=", 1)[0].strip()
2782 subrepoAbsPath = os.path.join(ppath, subrepoPath) 2859 subrepoAbsPath = os.path.join(ppath, subrepoPath)
2783 shutil.rmtree(subrepoAbsPath, True) 2860 shutil.rmtree(subrepoAbsPath, True)
2784 2861
2785 ########################################################################### 2862 ###########################################################################
2786 ## Methods to handle configuration dependent stuff are below. 2863 ## Methods to handle configuration dependent stuff are below.
2787 ########################################################################### 2864 ###########################################################################
2788 2865
2789 def __checkDefaults(self): 2866 def __checkDefaults(self):
2790 """ 2867 """
2791 Private method to check, if the default and default-push URLs 2868 Private method to check, if the default and default-push URLs
2792 have been configured. 2869 have been configured.
2793 """ 2870 """
2794 args = self.initCommand("showconfig") 2871 args = self.initCommand("showconfig")
2795 args.append('paths') 2872 args.append("paths")
2796 2873
2797 output, error = self.__client.runcommand(args) 2874 output, error = self.__client.runcommand(args)
2798 2875
2799 self.__defaultConfigured = False 2876 self.__defaultConfigured = False
2800 self.__defaultPushConfigured = False 2877 self.__defaultPushConfigured = False
2801 if output: 2878 if output:
2802 for line in output.splitlines(): 2879 for line in output.splitlines():
2803 line = line.strip() 2880 line = line.strip()
2804 if ( 2881 if line.startswith("paths.default=") and not line.endswith("="):
2805 line.startswith("paths.default=") and
2806 not line.endswith("=")
2807 ):
2808 self.__defaultConfigured = True 2882 self.__defaultConfigured = True
2809 if ( 2883 if line.startswith("paths.default-push=") and not line.endswith("="):
2810 line.startswith("paths.default-push=") and
2811 not line.endswith("=")
2812 ):
2813 self.__defaultPushConfigured = True 2884 self.__defaultPushConfigured = True
2814 2885
2815 def canCommitMerge(self): 2886 def canCommitMerge(self):
2816 """ 2887 """
2817 Public method to check, if the working directory is an uncommitted 2888 Public method to check, if the working directory is an uncommitted
2818 merge. 2889 merge.
2819 2890
2820 @return flag indicating commit merge capability 2891 @return flag indicating commit merge capability
2821 @rtype bool 2892 @rtype bool
2822 """ 2893 """
2823 args = self.initCommand("identify") 2894 args = self.initCommand("identify")
2824 2895
2825 output, error = self.__client.runcommand(args) 2896 output, error = self.__client.runcommand(args)
2826 2897
2827 return output.count('+') == 2 2898 return output.count("+") == 2
2828 2899
2829 def canPull(self): 2900 def canPull(self):
2830 """ 2901 """
2831 Public method to check, if pull is possible. 2902 Public method to check, if pull is possible.
2832 2903
2833 @return flag indicating pull capability (boolean) 2904 @return flag indicating pull capability (boolean)
2834 """ 2905 """
2835 return self.__defaultConfigured 2906 return self.__defaultConfigured
2836 2907
2837 def canPush(self): 2908 def canPush(self):
2838 """ 2909 """
2839 Public method to check, if push is possible. 2910 Public method to check, if push is possible.
2840 2911
2841 @return flag indicating push capability (boolean) 2912 @return flag indicating push capability (boolean)
2842 """ 2913 """
2843 return self.__defaultPushConfigured or self.__defaultConfigured 2914 return self.__defaultPushConfigured or self.__defaultConfigured
2844 2915
2845 def __iniFileChanged(self, path): 2916 def __iniFileChanged(self, path):
2846 """ 2917 """
2847 Private slot to handle a change of the Mercurial configuration file. 2918 Private slot to handle a change of the Mercurial configuration file.
2848 2919
2849 @param path name of the changed file (string) 2920 @param path name of the changed file (string)
2850 """ 2921 """
2851 if self.__client: 2922 if self.__client:
2852 ok, err = self.__client.restartServer() 2923 ok, err = self.__client.restartServer()
2853 if not ok: 2924 if not ok:
2854 EricMessageBox.warning( 2925 EricMessageBox.warning(
2855 None, 2926 None,
2856 self.tr("Mercurial Command Server"), 2927 self.tr("Mercurial Command Server"),
2857 self.tr( 2928 self.tr(
2858 """<p>The Mercurial Command Server could not be""" 2929 """<p>The Mercurial Command Server could not be"""
2859 """ restarted.</p><p>Reason: {0}</p>""").format(err)) 2930 """ restarted.</p><p>Reason: {0}</p>"""
2860 2931 ).format(err),
2932 )
2933
2861 self.__getExtensionsInfo() 2934 self.__getExtensionsInfo()
2862 2935
2863 if self.__repoIniFile and path == self.__repoIniFile: 2936 if self.__repoIniFile and path == self.__repoIniFile:
2864 self.__checkDefaults() 2937 self.__checkDefaults()
2865 2938
2866 self.iniFileChanged.emit() 2939 self.iniFileChanged.emit()
2867 2940
2868 def __monitorRepoIniFile(self, repodir): 2941 def __monitorRepoIniFile(self, repodir):
2869 """ 2942 """
2870 Private slot to add a repository configuration file to the list of 2943 Private slot to add a repository configuration file to the list of
2871 monitored files. 2944 monitored files.
2872 2945
2873 @param repodir directory name of the repository 2946 @param repodir directory name of the repository
2874 @type str 2947 @type str
2875 """ 2948 """
2876 cfgFile = os.path.join(repodir, self.adminDir, "hgrc") 2949 cfgFile = os.path.join(repodir, self.adminDir, "hgrc")
2877 if os.path.exists(cfgFile): 2950 if os.path.exists(cfgFile):
2878 self.__iniWatcher.addPath(cfgFile) 2951 self.__iniWatcher.addPath(cfgFile)
2879 self.__repoIniFile = cfgFile 2952 self.__repoIniFile = cfgFile
2880 self.__checkDefaults() 2953 self.__checkDefaults()
2881 2954
2882 ########################################################################### 2955 ###########################################################################
2883 ## Methods to handle extensions are below. 2956 ## Methods to handle extensions are below.
2884 ########################################################################### 2957 ###########################################################################
2885 2958
2886 def __getExtensionsInfo(self): 2959 def __getExtensionsInfo(self):
2887 """ 2960 """
2888 Private method to get the active extensions from Mercurial. 2961 Private method to get the active extensions from Mercurial.
2889 """ 2962 """
2890 activeExtensions = sorted(self.__activeExtensions) 2963 activeExtensions = sorted(self.__activeExtensions)
2891 self.__activeExtensions = [] 2964 self.__activeExtensions = []
2892 2965
2893 args = self.initCommand("showconfig") 2966 args = self.initCommand("showconfig")
2894 args.append('extensions') 2967 args.append("extensions")
2895 2968
2896 output, error = self.__client.runcommand(args) 2969 output, error = self.__client.runcommand(args)
2897 2970
2898 if output: 2971 if output:
2899 for line in output.splitlines(): 2972 for line in output.splitlines():
2900 extensionName = ( 2973 extensionName = line.split("=", 1)[0].strip().split(".")[-1].strip()
2901 line.split("=", 1)[0].strip().split(".")[-1].strip()
2902 )
2903 self.__activeExtensions.append(extensionName) 2974 self.__activeExtensions.append(extensionName)
2904 if self.version < (4, 8, 0) and "closehead" in self.__activeExtensions: 2975 if self.version < (4, 8, 0) and "closehead" in self.__activeExtensions:
2905 self.__activeExtensions.remove["closehead"] 2976 self.__activeExtensions.remove["closehead"]
2906 2977
2907 if activeExtensions != sorted(self.__activeExtensions): 2978 if activeExtensions != sorted(self.__activeExtensions):
2908 self.activeExtensionsChanged.emit() 2979 self.activeExtensionsChanged.emit()
2909 2980
2910 def isExtensionActive(self, extensionName): 2981 def isExtensionActive(self, extensionName):
2911 """ 2982 """
2912 Public method to check, if an extension is active. 2983 Public method to check, if an extension is active.
2913 2984
2914 @param extensionName name of the extension to check for (string) 2985 @param extensionName name of the extension to check for (string)
2915 @return flag indicating an active extension (boolean) 2986 @return flag indicating an active extension (boolean)
2916 """ 2987 """
2917 extensionName = extensionName.strip() 2988 extensionName = extensionName.strip()
2918 isActive = extensionName in self.__activeExtensions 2989 isActive = extensionName in self.__activeExtensions
2919 2990
2920 return isActive 2991 return isActive
2921 2992
2922 def getExtensionObject(self, extensionName): 2993 def getExtensionObject(self, extensionName):
2923 """ 2994 """
2924 Public method to get a reference to an extension object. 2995 Public method to get a reference to an extension object.
2925 2996
2926 @param extensionName name of the extension (string) 2997 @param extensionName name of the extension (string)
2927 @return reference to the extension object (boolean) 2998 @return reference to the extension object (boolean)
2928 """ 2999 """
2929 return self.__extensions[extensionName] 3000 return self.__extensions[extensionName]
2930 3001
2931 ########################################################################### 3002 ###########################################################################
2932 ## Methods to get the helper objects are below. 3003 ## Methods to get the helper objects are below.
2933 ########################################################################### 3004 ###########################################################################
2934 3005
2935 def vcsGetProjectBrowserHelper(self, browser, project, 3006 def vcsGetProjectBrowserHelper(self, browser, project, isTranslationsBrowser=False):
2936 isTranslationsBrowser=False):
2937 """ 3007 """
2938 Public method to instantiate a helper object for the different 3008 Public method to instantiate a helper object for the different
2939 project browsers. 3009 project browsers.
2940 3010
2941 @param browser reference to the project browser object 3011 @param browser reference to the project browser object
2942 @param project reference to the project object 3012 @param project reference to the project object
2943 @param isTranslationsBrowser flag indicating, the helper is requested 3013 @param isTranslationsBrowser flag indicating, the helper is requested
2944 for the translations browser (this needs some special treatment) 3014 for the translations browser (this needs some special treatment)
2945 @return the project browser helper object 3015 @return the project browser helper object
2946 """ 3016 """
2947 from .ProjectBrowserHelper import HgProjectBrowserHelper 3017 from .ProjectBrowserHelper import HgProjectBrowserHelper
2948 return HgProjectBrowserHelper(self, browser, project, 3018
2949 isTranslationsBrowser) 3019 return HgProjectBrowserHelper(self, browser, project, isTranslationsBrowser)
2950 3020
2951 def vcsGetProjectHelper(self, project): 3021 def vcsGetProjectHelper(self, project):
2952 """ 3022 """
2953 Public method to instantiate a helper object for the project. 3023 Public method to instantiate a helper object for the project.
2954 3024
2955 @param project reference to the project object 3025 @param project reference to the project object
2956 @return the project helper object 3026 @return the project helper object
2957 """ 3027 """
2958 # find the root of the repo 3028 # find the root of the repo
2959 repodir = project.getProjectPath() 3029 repodir = project.getProjectPath()
2960 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 3030 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
2961 repodir = os.path.dirname(repodir) 3031 repodir = os.path.dirname(repodir)
2962 if not repodir or os.path.splitdrive(repodir)[1] == os.sep: 3032 if not repodir or os.path.splitdrive(repodir)[1] == os.sep:
2963 repodir = "" 3033 repodir = ""
2964 break 3034 break
2965 3035
2966 self.__projectHelper = self.__plugin.getProjectHelper() 3036 self.__projectHelper = self.__plugin.getProjectHelper()
2967 self.__projectHelper.setObjects(self, project) 3037 self.__projectHelper.setObjects(self, project)
2968 3038
2969 if repodir: 3039 if repodir:
2970 self.__repoDir = repodir 3040 self.__repoDir = repodir
2971 self.__createClient(repodir) 3041 self.__createClient(repodir)
2972 self.__monitorRepoIniFile(repodir) 3042 self.__monitorRepoIniFile(repodir)
2973 3043
2974 return self.__projectHelper 3044 return self.__projectHelper
2975 3045
2976 ########################################################################### 3046 ###########################################################################
2977 ## Methods to handle the Mercurial command server are below. 3047 ## Methods to handle the Mercurial command server are below.
2978 ########################################################################### 3048 ###########################################################################
2979 3049
2980 def __createClient(self, repodir=""): 3050 def __createClient(self, repodir=""):
2981 """ 3051 """
2982 Private method to create a Mercurial command server client. 3052 Private method to create a Mercurial command server client.
2983 3053
2984 @param repodir path of the local repository 3054 @param repodir path of the local repository
2985 @type str 3055 @type str
2986 """ 3056 """
2987 self.stopClient() 3057 self.stopClient()
2988 3058
2989 self.__client = HgClient(repodir, "utf-8", self) 3059 self.__client = HgClient(repodir, "utf-8", self)
2990 ok, err = self.__client.startServer() 3060 ok, err = self.__client.startServer()
2991 if not ok: 3061 if not ok:
2992 EricMessageBox.warning( 3062 EricMessageBox.warning(
2993 None, 3063 None,
2994 self.tr("Mercurial Command Server"), 3064 self.tr("Mercurial Command Server"),
2995 self.tr( 3065 self.tr(
2996 """<p>The Mercurial Command Server could not be""" 3066 """<p>The Mercurial Command Server could not be"""
2997 """ started.</p><p>Reason: {0}</p>""").format(err)) 3067 """ started.</p><p>Reason: {0}</p>"""
2998 3068 ).format(err),
3069 )
3070
2999 def getClient(self): 3071 def getClient(self):
3000 """ 3072 """
3001 Public method to get a reference to the command server interface. 3073 Public method to get a reference to the command server interface.
3002 3074
3003 @return reference to the client (HgClient) 3075 @return reference to the client (HgClient)
3004 """ 3076 """
3005 if self.__client is None: 3077 if self.__client is None:
3006 self.__createClient(self.__repoDir) 3078 self.__createClient(self.__repoDir)
3007 3079
3008 return self.__client 3080 return self.__client
3009 3081
3010 def stopClient(self): 3082 def stopClient(self):
3011 """ 3083 """
3012 Public method to stop the command server client. 3084 Public method to stop the command server client.
3013 """ 3085 """
3014 if self.__client is not None: 3086 if self.__client is not None:
3015 self.__client.stopServer() 3087 self.__client.stopServer()
3016 self.__client = None 3088 self.__client = None
3017 3089
3018 ########################################################################### 3090 ###########################################################################
3019 ## Status Monitor Thread methods 3091 ## Status Monitor Thread methods
3020 ########################################################################### 3092 ###########################################################################
3021 3093
3022 def _createStatusMonitorThread(self, interval, project): 3094 def _createStatusMonitorThread(self, interval, project):
3023 """ 3095 """
3024 Protected method to create an instance of the VCS status monitor 3096 Protected method to create an instance of the VCS status monitor
3025 thread. 3097 thread.
3026 3098
3027 @param interval check interval for the monitor thread in seconds 3099 @param interval check interval for the monitor thread in seconds
3028 (integer) 3100 (integer)
3029 @param project reference to the project object (Project) 3101 @param project reference to the project object (Project)
3030 @return reference to the monitor thread (QThread) 3102 @return reference to the monitor thread (QThread)
3031 """ 3103 """
3032 from .HgStatusMonitorThread import HgStatusMonitorThread 3104 from .HgStatusMonitorThread import HgStatusMonitorThread
3105
3033 return HgStatusMonitorThread(interval, project, self) 3106 return HgStatusMonitorThread(interval, project, self)
3034 3107
3035 ########################################################################### 3108 ###########################################################################
3036 ## Bookmarks methods 3109 ## Bookmarks methods
3037 ########################################################################### 3110 ###########################################################################
3039 def hgListBookmarks(self): 3112 def hgListBookmarks(self):
3040 """ 3113 """
3041 Public method used to list the available bookmarks. 3114 Public method used to list the available bookmarks.
3042 """ 3115 """
3043 self.bookmarksList = [] 3116 self.bookmarksList = []
3044 3117
3045 if self.bookmarksListDlg is None: 3118 if self.bookmarksListDlg is None:
3046 from .HgBookmarksListDialog import HgBookmarksListDialog 3119 from .HgBookmarksListDialog import HgBookmarksListDialog
3120
3047 self.bookmarksListDlg = HgBookmarksListDialog(self) 3121 self.bookmarksListDlg = HgBookmarksListDialog(self)
3048 self.bookmarksListDlg.show() 3122 self.bookmarksListDlg.show()
3049 self.bookmarksListDlg.raise_() 3123 self.bookmarksListDlg.raise_()
3050 self.bookmarksListDlg.start(self.bookmarksList) 3124 self.bookmarksListDlg.start(self.bookmarksList)
3051 3125
3052 def hgGetBookmarksList(self): 3126 def hgGetBookmarksList(self):
3053 """ 3127 """
3054 Public method to get the list of bookmarks. 3128 Public method to get the list of bookmarks.
3055 3129
3056 @return list of bookmarks (list of string) 3130 @return list of bookmarks (list of string)
3057 """ 3131 """
3058 args = self.initCommand("bookmarks") 3132 args = self.initCommand("bookmarks")
3059 3133
3060 client = self.getClient() 3134 client = self.getClient()
3061 output = client.runcommand(args)[0] 3135 output = client.runcommand(args)[0]
3062 3136
3063 self.bookmarksList = [] 3137 self.bookmarksList = []
3064 for line in output.splitlines(): 3138 for line in output.splitlines():
3065 li = line.strip().split() 3139 li = line.strip().split()
3066 if li[-1][0] in "1234567890": 3140 if li[-1][0] in "1234567890":
3067 # last element is a rev:changeset 3141 # last element is a rev:changeset
3068 del li[-1] 3142 del li[-1]
3069 if li[0] == "*": 3143 if li[0] == "*":
3070 del li[0] 3144 del li[0]
3071 name = " ".join(li) 3145 name = " ".join(li)
3072 self.bookmarksList.append(name) 3146 self.bookmarksList.append(name)
3073 3147
3074 return self.bookmarksList[:] 3148 return self.bookmarksList[:]
3075 3149
3076 def hgBookmarkDefine(self, revision=None, bookmark=None): 3150 def hgBookmarkDefine(self, revision=None, bookmark=None):
3077 """ 3151 """
3078 Public method to define a bookmark. 3152 Public method to define a bookmark.
3079 3153
3080 @param revision revision to set bookmark for (string) 3154 @param revision revision to set bookmark for (string)
3081 @param bookmark name of the bookmark (string) 3155 @param bookmark name of the bookmark (string)
3082 """ 3156 """
3083 if bool(revision) and bool(bookmark): 3157 if bool(revision) and bool(bookmark):
3084 ok = True 3158 ok = True
3085 else: 3159 else:
3086 from .HgBookmarkDialog import HgBookmarkDialog 3160 from .HgBookmarkDialog import HgBookmarkDialog
3087 dlg = HgBookmarkDialog(HgBookmarkDialog.DEFINE_MODE, 3161
3088 self.hgGetTagsList(), 3162 dlg = HgBookmarkDialog(
3089 self.hgGetBranchesList(), 3163 HgBookmarkDialog.DEFINE_MODE,
3090 self.hgGetBookmarksList()) 3164 self.hgGetTagsList(),
3165 self.hgGetBranchesList(),
3166 self.hgGetBookmarksList(),
3167 )
3091 if dlg.exec() == QDialog.DialogCode.Accepted: 3168 if dlg.exec() == QDialog.DialogCode.Accepted:
3092 revision, bookmark = dlg.getData() 3169 revision, bookmark = dlg.getData()
3093 ok = True 3170 ok = True
3094 else: 3171 else:
3095 ok = False 3172 ok = False
3096 3173
3097 if ok: 3174 if ok:
3098 args = self.initCommand("bookmarks") 3175 args = self.initCommand("bookmarks")
3099 if revision: 3176 if revision:
3100 args.append("--rev") 3177 args.append("--rev")
3101 args.append(revision) 3178 args.append(revision)
3102 args.append(bookmark) 3179 args.append(bookmark)
3103 3180
3104 dia = HgDialog(self.tr('Mercurial Bookmark'), self) 3181 dia = HgDialog(self.tr("Mercurial Bookmark"), self)
3105 res = dia.startProcess(args) 3182 res = dia.startProcess(args)
3106 if res: 3183 if res:
3107 dia.exec() 3184 dia.exec()
3108 3185
3109 def hgBookmarkDelete(self, bookmark=None): 3186 def hgBookmarkDelete(self, bookmark=None):
3110 """ 3187 """
3111 Public method to delete a bookmark. 3188 Public method to delete a bookmark.
3112 3189
3113 @param bookmark name of the bookmark (string) 3190 @param bookmark name of the bookmark (string)
3114 """ 3191 """
3115 if bookmark: 3192 if bookmark:
3116 ok = True 3193 ok = True
3117 else: 3194 else:
3118 bookmark, ok = QInputDialog.getItem( 3195 bookmark, ok = QInputDialog.getItem(
3119 None, 3196 None,
3120 self.tr("Delete Bookmark"), 3197 self.tr("Delete Bookmark"),
3121 self.tr("Select the bookmark to be deleted:"), 3198 self.tr("Select the bookmark to be deleted:"),
3122 [""] + sorted(self.hgGetBookmarksList()), 3199 [""] + sorted(self.hgGetBookmarksList()),
3123 0, True) 3200 0,
3201 True,
3202 )
3124 if ok and bookmark: 3203 if ok and bookmark:
3125 args = self.initCommand("bookmarks") 3204 args = self.initCommand("bookmarks")
3126 args.append("--delete") 3205 args.append("--delete")
3127 args.append(bookmark) 3206 args.append(bookmark)
3128 3207
3129 dia = HgDialog(self.tr('Delete Mercurial Bookmark'), self) 3208 dia = HgDialog(self.tr("Delete Mercurial Bookmark"), self)
3130 res = dia.startProcess(args) 3209 res = dia.startProcess(args)
3131 if res: 3210 if res:
3132 dia.exec() 3211 dia.exec()
3133 3212
3134 def hgBookmarkRename(self, renameInfo=None): 3213 def hgBookmarkRename(self, renameInfo=None):
3135 """ 3214 """
3136 Public method to rename a bookmark. 3215 Public method to rename a bookmark.
3137 3216
3138 @param renameInfo old and new names of the bookmark 3217 @param renameInfo old and new names of the bookmark
3139 @type tuple of str and str 3218 @type tuple of str and str
3140 """ 3219 """
3141 if not renameInfo: 3220 if not renameInfo:
3142 from .HgBookmarkRenameDialog import HgBookmarkRenameDialog 3221 from .HgBookmarkRenameDialog import HgBookmarkRenameDialog
3222
3143 dlg = HgBookmarkRenameDialog(self.hgGetBookmarksList()) 3223 dlg = HgBookmarkRenameDialog(self.hgGetBookmarksList())
3144 if dlg.exec() == QDialog.DialogCode.Accepted: 3224 if dlg.exec() == QDialog.DialogCode.Accepted:
3145 renameInfo = dlg.getData() 3225 renameInfo = dlg.getData()
3146 3226
3147 if renameInfo: 3227 if renameInfo:
3148 args = self.initCommand("bookmarks") 3228 args = self.initCommand("bookmarks")
3149 args.append("--rename") 3229 args.append("--rename")
3150 args.append(renameInfo[0]) 3230 args.append(renameInfo[0])
3151 args.append(renameInfo[1]) 3231 args.append(renameInfo[1])
3152 3232
3153 dia = HgDialog(self.tr('Rename Mercurial Bookmark'), self) 3233 dia = HgDialog(self.tr("Rename Mercurial Bookmark"), self)
3154 res = dia.startProcess(args) 3234 res = dia.startProcess(args)
3155 if res: 3235 if res:
3156 dia.exec() 3236 dia.exec()
3157 3237
3158 def hgBookmarkMove(self, revision=None, bookmark=None): 3238 def hgBookmarkMove(self, revision=None, bookmark=None):
3159 """ 3239 """
3160 Public method to move a bookmark. 3240 Public method to move a bookmark.
3161 3241
3162 @param revision revision to set bookmark for (string) 3242 @param revision revision to set bookmark for (string)
3163 @param bookmark name of the bookmark (string) 3243 @param bookmark name of the bookmark (string)
3164 """ 3244 """
3165 if bool(revision) and bool(bookmark): 3245 if bool(revision) and bool(bookmark):
3166 ok = True 3246 ok = True
3167 else: 3247 else:
3168 from .HgBookmarkDialog import HgBookmarkDialog 3248 from .HgBookmarkDialog import HgBookmarkDialog
3169 dlg = HgBookmarkDialog(HgBookmarkDialog.MOVE_MODE, 3249
3170 self.hgGetTagsList(), 3250 dlg = HgBookmarkDialog(
3171 self.hgGetBranchesList(), 3251 HgBookmarkDialog.MOVE_MODE,
3172 self.hgGetBookmarksList()) 3252 self.hgGetTagsList(),
3253 self.hgGetBranchesList(),
3254 self.hgGetBookmarksList(),
3255 )
3173 if dlg.exec() == QDialog.DialogCode.Accepted: 3256 if dlg.exec() == QDialog.DialogCode.Accepted:
3174 revision, bookmark = dlg.getData() 3257 revision, bookmark = dlg.getData()
3175 ok = True 3258 ok = True
3176 else: 3259 else:
3177 ok = False 3260 ok = False
3178 3261
3179 if ok: 3262 if ok:
3180 args = self.initCommand("bookmarks") 3263 args = self.initCommand("bookmarks")
3181 args.append("--force") 3264 args.append("--force")
3182 if revision: 3265 if revision:
3183 args.append("--rev") 3266 args.append("--rev")
3184 args.append(revision) 3267 args.append(revision)
3185 args.append(bookmark) 3268 args.append(bookmark)
3186 3269
3187 dia = HgDialog(self.tr('Move Mercurial Bookmark'), self) 3270 dia = HgDialog(self.tr("Move Mercurial Bookmark"), self)
3188 res = dia.startProcess(args) 3271 res = dia.startProcess(args)
3189 if res: 3272 if res:
3190 dia.exec() 3273 dia.exec()
3191 3274
3192 def hgBookmarkIncoming(self): 3275 def hgBookmarkIncoming(self):
3193 """ 3276 """
3194 Public method to show a list of incoming bookmarks. 3277 Public method to show a list of incoming bookmarks.
3195 """ 3278 """
3196 from .HgBookmarksInOutDialog import HgBookmarksInOutDialog 3279 from .HgBookmarksInOutDialog import HgBookmarksInOutDialog
3280
3197 self.bookmarksInOutDlg = HgBookmarksInOutDialog( 3281 self.bookmarksInOutDlg = HgBookmarksInOutDialog(
3198 self, HgBookmarksInOutDialog.INCOMING) 3282 self, HgBookmarksInOutDialog.INCOMING
3283 )
3199 self.bookmarksInOutDlg.show() 3284 self.bookmarksInOutDlg.show()
3200 self.bookmarksInOutDlg.start() 3285 self.bookmarksInOutDlg.start()
3201 3286
3202 def hgBookmarkOutgoing(self): 3287 def hgBookmarkOutgoing(self):
3203 """ 3288 """
3204 Public method to show a list of outgoing bookmarks. 3289 Public method to show a list of outgoing bookmarks.
3205 """ 3290 """
3206 from .HgBookmarksInOutDialog import HgBookmarksInOutDialog 3291 from .HgBookmarksInOutDialog import HgBookmarksInOutDialog
3292
3207 self.bookmarksInOutDlg = HgBookmarksInOutDialog( 3293 self.bookmarksInOutDlg = HgBookmarksInOutDialog(
3208 self, HgBookmarksInOutDialog.OUTGOING) 3294 self, HgBookmarksInOutDialog.OUTGOING
3295 )
3209 self.bookmarksInOutDlg.show() 3296 self.bookmarksInOutDlg.show()
3210 self.bookmarksInOutDlg.start() 3297 self.bookmarksInOutDlg.start()
3211 3298
3212 def __getInOutBookmarks(self, incoming): 3299 def __getInOutBookmarks(self, incoming):
3213 """ 3300 """
3214 Private method to get the list of incoming or outgoing bookmarks. 3301 Private method to get the list of incoming or outgoing bookmarks.
3215 3302
3216 @param incoming flag indicating to get incoming bookmarks (boolean) 3303 @param incoming flag indicating to get incoming bookmarks (boolean)
3217 @return list of bookmarks (list of string) 3304 @return list of bookmarks (list of string)
3218 """ 3305 """
3219 bookmarksList = [] 3306 bookmarksList = []
3220 3307
3221 args = ( 3308 args = (
3222 self.initCommand("incoming") 3309 self.initCommand("incoming") if incoming else self.initCommand("outgoing")
3223 if incoming else
3224 self.initCommand("outgoing")
3225 ) 3310 )
3226 args.append('--bookmarks') 3311 args.append("--bookmarks")
3227 3312
3228 client = self.getClient() 3313 client = self.getClient()
3229 output = client.runcommand(args)[0] 3314 output = client.runcommand(args)[0]
3230 3315
3231 for line in output.splitlines(): 3316 for line in output.splitlines():
3232 if line.startswith(" "): 3317 if line.startswith(" "):
3233 li = line.strip().split() 3318 li = line.strip().split()
3234 del li[-1] 3319 del li[-1]
3235 name = " ".join(li) 3320 name = " ".join(li)
3236 bookmarksList.append(name) 3321 bookmarksList.append(name)
3237 3322
3238 return bookmarksList 3323 return bookmarksList
3239 3324
3240 def hgBookmarkPull(self, current=False, bookmark=None): 3325 def hgBookmarkPull(self, current=False, bookmark=None):
3241 """ 3326 """
3242 Public method to pull a bookmark from a remote repository. 3327 Public method to pull a bookmark from a remote repository.
3243 3328
3244 @param current flag indicating to pull the current bookmark 3329 @param current flag indicating to pull the current bookmark
3245 @type bool 3330 @type bool
3246 @param bookmark name of the bookmark 3331 @param bookmark name of the bookmark
3247 @type str 3332 @type str
3248 """ 3333 """
3256 bookmark, ok = QInputDialog.getItem( 3341 bookmark, ok = QInputDialog.getItem(
3257 None, 3342 None,
3258 self.tr("Pull Bookmark"), 3343 self.tr("Pull Bookmark"),
3259 self.tr("Select the bookmark to be pulled:"), 3344 self.tr("Select the bookmark to be pulled:"),
3260 [""] + sorted(bookmarks), 3345 [""] + sorted(bookmarks),
3261 0, True) 3346 0,
3262 3347 True,
3348 )
3349
3263 if ok and bookmark: 3350 if ok and bookmark:
3264 args = self.initCommand("pull") 3351 args = self.initCommand("pull")
3265 args.append('--bookmark') 3352 args.append("--bookmark")
3266 args.append(bookmark) 3353 args.append(bookmark)
3267 3354
3268 dia = HgDialog(self.tr( 3355 dia = HgDialog(
3269 'Pulling bookmark from a remote Mercurial repository'), 3356 self.tr("Pulling bookmark from a remote Mercurial repository"), self
3270 self) 3357 )
3271 res = dia.startProcess(args) 3358 res = dia.startProcess(args)
3272 if res: 3359 if res:
3273 dia.exec() 3360 dia.exec()
3274 3361
3275 def hgBookmarkPush(self, current=False, bookmark=None, allBookmarks=False): 3362 def hgBookmarkPush(self, current=False, bookmark=None, allBookmarks=False):
3276 """ 3363 """
3277 Public method to push a bookmark to a remote repository. 3364 Public method to push a bookmark to a remote repository.
3278 3365
3279 @param current flag indicating to push the current bookmark 3366 @param current flag indicating to push the current bookmark
3280 @type bool 3367 @type bool
3281 @param bookmark name of the bookmark 3368 @param bookmark name of the bookmark
3282 @type str 3369 @type str
3283 @param allBookmarks flag indicating to push all bookmarks 3370 @param allBookmarks flag indicating to push all bookmarks
3293 bookmark, ok = QInputDialog.getItem( 3380 bookmark, ok = QInputDialog.getItem(
3294 None, 3381 None,
3295 self.tr("Push Bookmark"), 3382 self.tr("Push Bookmark"),
3296 self.tr("Select the bookmark to be push:"), 3383 self.tr("Select the bookmark to be push:"),
3297 [""] + sorted(bookmarks), 3384 [""] + sorted(bookmarks),
3298 0, True) 3385 0,
3299 3386 True,
3387 )
3388
3300 if ok and (bool(bookmark) or all): 3389 if ok and (bool(bookmark) or all):
3301 args = self.initCommand("push") 3390 args = self.initCommand("push")
3302 if allBookmarks: 3391 if allBookmarks:
3303 args.append('--all-bookmarks') 3392 args.append("--all-bookmarks")
3304 else: 3393 else:
3305 args.append('--bookmark') 3394 args.append("--bookmark")
3306 args.append(bookmark) 3395 args.append(bookmark)
3307 3396
3308 dia = HgDialog(self.tr( 3397 dia = HgDialog(
3309 'Pushing bookmark to a remote Mercurial repository'), 3398 self.tr("Pushing bookmark to a remote Mercurial repository"), self
3310 self) 3399 )
3311 res = dia.startProcess(args) 3400 res = dia.startProcess(args)
3312 if res: 3401 if res:
3313 dia.exec() 3402 dia.exec()

eric ide

mercurial