src/eric7/Plugins/VcsPlugins/vcsSubversion/subversion.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
28 28
29 29
30 class Subversion(VersionControl): 30 class Subversion(VersionControl):
31 """ 31 """
32 Class implementing the version control systems interface to Subversion. 32 Class implementing the version control systems interface to Subversion.
33 33
34 @signal committed() emitted after the commit action has completed 34 @signal committed() emitted after the commit action has completed
35 """ 35 """
36
36 committed = pyqtSignal() 37 committed = pyqtSignal()
37 38
38 def __init__(self, plugin, parent=None, name=None): 39 def __init__(self, plugin, parent=None, name=None):
39 """ 40 """
40 Constructor 41 Constructor
41 42
42 @param plugin reference to the plugin object 43 @param plugin reference to the plugin object
43 @param parent parent widget (QWidget) 44 @param parent parent widget (QWidget)
44 @param name name of this object (string) 45 @param name name of this object (string)
45 """ 46 """
46 VersionControl.__init__(self, parent, name) 47 VersionControl.__init__(self, parent, name)
47 self.defaultOptions = { 48 self.defaultOptions = {
48 'global': [''], 49 "global": [""],
49 'commit': [''], 50 "commit": [""],
50 'checkout': [''], 51 "checkout": [""],
51 'update': [''], 52 "update": [""],
52 'add': [''], 53 "add": [""],
53 'remove': [''], 54 "remove": [""],
54 'diff': [''], 55 "diff": [""],
55 'log': [''], 56 "log": [""],
56 'history': [''], 57 "history": [""],
57 'status': [''], 58 "status": [""],
58 'tag': [''], 59 "tag": [""],
59 'export': [''] 60 "export": [""],
60 } 61 }
61 self.interestingDataKeys = [ 62 self.interestingDataKeys = [
62 "standardLayout", 63 "standardLayout",
63 ] 64 ]
64 65
65 self.__plugin = plugin 66 self.__plugin = plugin
66 self.__ui = parent 67 self.__ui = parent
67 68
68 self.options = self.defaultOptions 69 self.options = self.defaultOptions
69 self.otherData["standardLayout"] = True 70 self.otherData["standardLayout"] = True
70 self.tagsList = [] 71 self.tagsList = []
71 self.branchesList = [] 72 self.branchesList = []
72 self.allTagsBranchesList = [] 73 self.allTagsBranchesList = []
73 self.mergeList = [[], [], []] 74 self.mergeList = [[], [], []]
74 self.showedTags = False 75 self.showedTags = False
75 self.showedBranches = False 76 self.showedBranches = False
76 77
77 self.tagTypeList = [ 78 self.tagTypeList = [
78 'tags', 79 "tags",
79 'branches', 80 "branches",
80 ] 81 ]
81 82
82 self.commandHistory = [] 83 self.commandHistory = []
83 self.wdHistory = [] 84 self.wdHistory = []
84 85
85 if "SVN_ASP_DOT_NET_HACK" in os.environ: 86 if "SVN_ASP_DOT_NET_HACK" in os.environ:
86 self.adminDir = '_svn' 87 self.adminDir = "_svn"
87 else: 88 else:
88 self.adminDir = '.svn' 89 self.adminDir = ".svn"
89 90
90 self.log = None 91 self.log = None
91 self.diff = None 92 self.diff = None
92 self.sbsDiff = None 93 self.sbsDiff = None
93 self.status = None 94 self.status = None
94 self.propList = None 95 self.propList = None
95 self.tagbranchList = None 96 self.tagbranchList = None
96 self.blame = None 97 self.blame = None
97 self.repoBrowser = None 98 self.repoBrowser = None
98 self.logBrowser = None 99 self.logBrowser = None
99 100
100 # regular expression object for evaluation of the status output 101 # regular expression object for evaluation of the status output
101 self.rx_status1 = re.compile( 102 self.rx_status1 = re.compile(
102 '(.{8})\\s+([0-9-]+)\\s+([0-9?]+)\\s+(\\S+)\\s+(.+)') 103 "(.{8})\\s+([0-9-]+)\\s+([0-9?]+)\\s+(\\S+)\\s+(.+)"
103 self.rx_status2 = re.compile('(.{8})\\s+(.+)\\s*') 104 )
105 self.rx_status2 = re.compile("(.{8})\\s+(.+)\\s*")
104 self.statusCache = {} 106 self.statusCache = {}
105 107
106 self.__commitData = {} 108 self.__commitData = {}
107 self.__commitDialog = None 109 self.__commitDialog = None
108 110
109 self.__wcng = True 111 self.__wcng = True
110 # assume new generation working copy metadata format 112 # assume new generation working copy metadata format
111 113
112 def getPlugin(self): 114 def getPlugin(self):
113 """ 115 """
114 Public method to get a reference to the plugin object. 116 Public method to get a reference to the plugin object.
115 117
116 @return reference to the plugin object (VcsSubversionPlugin) 118 @return reference to the plugin object (VcsSubversionPlugin)
117 """ 119 """
118 return self.__plugin 120 return self.__plugin
119 121
120 def vcsShutdown(self): 122 def vcsShutdown(self):
121 """ 123 """
122 Public method used to shutdown the Subversion interface. 124 Public method used to shutdown the Subversion interface.
123 """ 125 """
124 if self.log is not None: 126 if self.log is not None:
137 self.blame.close() 139 self.blame.close()
138 if self.repoBrowser is not None: 140 if self.repoBrowser is not None:
139 self.repoBrowser.close() 141 self.repoBrowser.close()
140 if self.logBrowser is not None: 142 if self.logBrowser is not None:
141 self.logBrowser.close() 143 self.logBrowser.close()
142 144
143 def vcsExists(self): 145 def vcsExists(self):
144 """ 146 """
145 Public method used to test for the presence of the svn executable. 147 Public method used to test for the presence of the svn executable.
146 148
147 @return flag indicating the existance (boolean) and an error message 149 @return flag indicating the existance (boolean) and an error message
148 (string) 150 (string)
149 """ 151 """
150 self.versionStr = '' 152 self.versionStr = ""
151 errMsg = "" 153 errMsg = ""
152 ioEncoding = Preferences.getSystem("IOEncoding") 154 ioEncoding = Preferences.getSystem("IOEncoding")
153 155
154 process = QProcess() 156 process = QProcess()
155 process.start('svn', ['--version']) 157 process.start("svn", ["--version"])
156 procStarted = process.waitForStarted(5000) 158 procStarted = process.waitForStarted(5000)
157 if procStarted: 159 if procStarted:
158 finished = process.waitForFinished(30000) 160 finished = process.waitForFinished(30000)
159 if finished and process.exitCode() == 0: 161 if finished and process.exitCode() == 0:
160 output = str(process.readAllStandardOutput(), 162 output = str(process.readAllStandardOutput(), ioEncoding, "replace")
161 ioEncoding,
162 'replace')
163 self.versionStr = output.split()[2] 163 self.versionStr = output.split()[2]
164 v = list(re.match(r'.*?(\d+)\.(\d+)\.?(\d+)?', self.versionStr) 164 v = list(
165 .groups()) 165 re.match(r".*?(\d+)\.(\d+)\.?(\d+)?", self.versionStr).groups()
166 )
166 for i in range(3): 167 for i in range(3):
167 try: 168 try:
168 v[i] = int(v[i]) 169 v[i] = int(v[i])
169 except TypeError: 170 except TypeError:
170 v[i] = 0 171 v[i] = 0
176 if finished: 177 if finished:
177 errMsg = self.tr( 178 errMsg = self.tr(
178 "The svn process finished with the exit code {0}" 179 "The svn process finished with the exit code {0}"
179 ).format(process.exitCode()) 180 ).format(process.exitCode())
180 else: 181 else:
181 errMsg = self.tr( 182 errMsg = self.tr("The svn process did not finish within 30s.")
182 "The svn process did not finish within 30s.")
183 else: 183 else:
184 errMsg = self.tr("Could not start the svn executable.") 184 errMsg = self.tr("Could not start the svn executable.")
185 185
186 return False, errMsg 186 return False, errMsg
187 187
188 def vcsInit(self, vcsDir, noDialog=False): 188 def vcsInit(self, vcsDir, noDialog=False):
189 """ 189 """
190 Public method used to initialize the subversion repository. 190 Public method used to initialize the subversion repository.
191 191
192 The subversion repository has to be initialized from outside eric 192 The subversion repository has to be initialized from outside eric
193 because the respective command always works locally. Therefore we 193 because the respective command always works locally. Therefore we
194 always return TRUE without doing anything. 194 always return TRUE without doing anything.
195 195
196 @param vcsDir name of the VCS directory (string) 196 @param vcsDir name of the VCS directory (string)
197 @param noDialog flag indicating quiet operations (boolean) 197 @param noDialog flag indicating quiet operations (boolean)
198 @return always TRUE 198 @return always TRUE
199 """ 199 """
200 return True 200 return True
201 201
202 def vcsConvertProject(self, vcsDataDict, project, addAll=True): 202 def vcsConvertProject(self, vcsDataDict, project, addAll=True):
203 """ 203 """
204 Public method to convert an uncontrolled project to a version 204 Public method to convert an uncontrolled project to a version
205 controlled project. 205 controlled project.
206 206
207 @param vcsDataDict dictionary of data required for the conversion 207 @param vcsDataDict dictionary of data required for the conversion
208 @type dict 208 @type dict
209 @param project reference to the project object 209 @param project reference to the project object
210 @type Project 210 @type Project
211 @param addAll flag indicating to add all files to the repository 211 @param addAll flag indicating to add all files to the repository
217 self.__ui, 217 self.__ui,
218 self.tr("Create project in repository"), 218 self.tr("Create project in repository"),
219 self.tr( 219 self.tr(
220 """The project could not be created in the repository.""" 220 """The project could not be created in the repository."""
221 """ Maybe the given repository doesn't exist or the""" 221 """ Maybe the given repository doesn't exist or the"""
222 """ repository server is down.""")) 222 """ repository server is down."""
223 ),
224 )
223 else: 225 else:
224 cwdIsPpath = False 226 cwdIsPpath = False
225 if os.getcwd() == project.ppath: 227 if os.getcwd() == project.ppath:
226 os.chdir(os.path.dirname(project.ppath)) 228 os.chdir(os.path.dirname(project.ppath))
227 cwdIsPpath = True 229 cwdIsPpath = True
241 self.__ui, 243 self.__ui,
242 self.tr("New project"), 244 self.tr("New project"),
243 self.tr( 245 self.tr(
244 """The project could not be checked out of the""" 246 """The project could not be checked out of the"""
245 """ repository.<br />""" 247 """ repository.<br />"""
246 """Restoring the original contents.""")) 248 """Restoring the original contents."""
249 ),
250 )
247 if os.getcwd() == project.ppath: 251 if os.getcwd() == project.ppath:
248 os.chdir(os.path.dirname(project.ppath)) 252 os.chdir(os.path.dirname(project.ppath))
249 cwdIsPpath = True 253 cwdIsPpath = True
250 else: 254 else:
251 cwdIsPpath = False 255 cwdIsPpath = False
252 shutil.rmtree(project.ppath, True) 256 shutil.rmtree(project.ppath, True)
253 os.rename(tmpProjectDir, project.ppath) 257 os.rename(tmpProjectDir, project.ppath)
254 project.pdata["VCS"] = 'None' 258 project.pdata["VCS"] = "None"
255 project.vcs = None 259 project.vcs = None
256 project.setDirty(True) 260 project.setDirty(True)
257 project.saveProject() 261 project.saveProject()
258 project.closeProject() 262 project.closeProject()
259 return 263 return
260 shutil.rmtree(tmpProjectDir, True) 264 shutil.rmtree(tmpProjectDir, True)
261 project.closeProject(noSave=True) 265 project.closeProject(noSave=True)
262 project.openProject(pfn) 266 project.openProject(pfn)
263 267
264 def vcsImport(self, vcsDataDict, projectDir, noDialog=False, addAll=True): 268 def vcsImport(self, vcsDataDict, projectDir, noDialog=False, addAll=True):
265 """ 269 """
266 Public method used to import the project into the Subversion 270 Public method used to import the project into the Subversion
267 repository. 271 repository.
268 272
269 @param vcsDataDict dictionary of data required for the import 273 @param vcsDataDict dictionary of data required for the import
270 @type dict 274 @type dict
271 @param projectDir project directory (string) 275 @param projectDir project directory (string)
272 @type str 276 @type str
273 @param noDialog flag indicating quiet operations 277 @param noDialog flag indicating quiet operations
279 @rtype tuple of (bool, bool) 283 @rtype tuple of (bool, bool)
280 """ 284 """
281 noDialog = False 285 noDialog = False
282 msg = vcsDataDict["message"] 286 msg = vcsDataDict["message"]
283 if not msg: 287 if not msg:
284 msg = '***' 288 msg = "***"
285 289
286 vcsDir = self.svnNormalizeURL(vcsDataDict["url"]) 290 vcsDir = self.svnNormalizeURL(vcsDataDict["url"])
287 if vcsDir.startswith('/'): 291 if vcsDir.startswith("/"):
288 vcsDir = 'file://{0}'.format(vcsDir) 292 vcsDir = "file://{0}".format(vcsDir)
289 elif vcsDir[1] in ['|', ':']: 293 elif vcsDir[1] in ["|", ":"]:
290 vcsDir = 'file:///{0}'.format(vcsDir) 294 vcsDir = "file:///{0}".format(vcsDir)
291 295
292 project = vcsDir[vcsDir.rfind('/') + 1:] 296 project = vcsDir[vcsDir.rfind("/") + 1 :]
293 297
294 # create the dir structure to be imported into the repository 298 # create the dir structure to be imported into the repository
295 tmpDir = '{0}_tmp'.format(projectDir) 299 tmpDir = "{0}_tmp".format(projectDir)
296 try: 300 try:
297 os.makedirs(tmpDir) 301 os.makedirs(tmpDir)
298 if self.otherData["standardLayout"]: 302 if self.otherData["standardLayout"]:
299 os.mkdir(os.path.join(tmpDir, project)) 303 os.mkdir(os.path.join(tmpDir, project))
300 os.mkdir(os.path.join(tmpDir, project, 'branches')) 304 os.mkdir(os.path.join(tmpDir, project, "branches"))
301 os.mkdir(os.path.join(tmpDir, project, 'tags')) 305 os.mkdir(os.path.join(tmpDir, project, "tags"))
302 shutil.copytree( 306 shutil.copytree(projectDir, os.path.join(tmpDir, project, "trunk"))
303 projectDir, os.path.join(tmpDir, project, 'trunk'))
304 else: 307 else:
305 shutil.copytree(projectDir, os.path.join(tmpDir, project)) 308 shutil.copytree(projectDir, os.path.join(tmpDir, project))
306 except OSError: 309 except OSError:
307 if os.path.isdir(tmpDir): 310 if os.path.isdir(tmpDir):
308 shutil.rmtree(tmpDir, True) 311 shutil.rmtree(tmpDir, True)
309 return False, False 312 return False, False
310 313
311 args = [] 314 args = []
312 args.append('import') 315 args.append("import")
313 self.addArguments(args, self.options['global']) 316 self.addArguments(args, self.options["global"])
314 args.append('-m') 317 args.append("-m")
315 args.append(msg) 318 args.append(msg)
316 args.append(self.__svnURL(vcsDir)) 319 args.append(self.__svnURL(vcsDir))
317 320
318 if noDialog: 321 if noDialog:
319 status = self.startSynchronizedProcess( 322 status = self.startSynchronizedProcess(
320 QProcess(), "svn", args, os.path.join(tmpDir, project)) 323 QProcess(), "svn", args, os.path.join(tmpDir, project)
321 else: 324 )
322 dia = SvnDialog( 325 else:
323 self.tr('Importing project into Subversion repository')) 326 dia = SvnDialog(self.tr("Importing project into Subversion repository"))
324 res = dia.startProcess(args, os.path.join(tmpDir, project)) 327 res = dia.startProcess(args, os.path.join(tmpDir, project))
325 if res: 328 if res:
326 dia.exec() 329 dia.exec()
327 status = dia.normalExit() 330 status = dia.normalExit()
328 331
329 shutil.rmtree(tmpDir, True) 332 shutil.rmtree(tmpDir, True)
330 return status, False 333 return status, False
331 334
332 def vcsCheckout(self, vcsDataDict, projectDir, noDialog=False): 335 def vcsCheckout(self, vcsDataDict, projectDir, noDialog=False):
333 """ 336 """
334 Public method used to check the project out of the Subversion 337 Public method used to check the project out of the Subversion
335 repository. 338 repository.
336 339
337 @param vcsDataDict dictionary of data required for the checkout 340 @param vcsDataDict dictionary of data required for the checkout
338 @param projectDir project directory to create (string) 341 @param projectDir project directory to create (string)
339 @param noDialog flag indicating quiet operations 342 @param noDialog flag indicating quiet operations
340 @return flag indicating an execution without errors (boolean) 343 @return flag indicating an execution without errors (boolean)
341 """ 344 """
343 try: 346 try:
344 tag = vcsDataDict["tag"] 347 tag = vcsDataDict["tag"]
345 except KeyError: 348 except KeyError:
346 tag = None 349 tag = None
347 vcsDir = self.svnNormalizeURL(vcsDataDict["url"]) 350 vcsDir = self.svnNormalizeURL(vcsDataDict["url"])
348 if vcsDir.startswith('/'): 351 if vcsDir.startswith("/"):
349 vcsDir = 'file://{0}'.format(vcsDir) 352 vcsDir = "file://{0}".format(vcsDir)
350 elif vcsDir[1] in ['|', ':']: 353 elif vcsDir[1] in ["|", ":"]:
351 vcsDir = 'file:///{0}'.format(vcsDir) 354 vcsDir = "file:///{0}".format(vcsDir)
352 355
353 if self.otherData["standardLayout"]: 356 if self.otherData["standardLayout"]:
354 if tag is None or tag == '': 357 if tag is None or tag == "":
355 svnUrl = '{0}/trunk'.format(vcsDir) 358 svnUrl = "{0}/trunk".format(vcsDir)
356 else: 359 else:
357 if ( 360 if not tag.startswith("tags") and not tag.startswith("branches"):
358 not tag.startswith('tags') and
359 not tag.startswith('branches')
360 ):
361 tagType, ok = QInputDialog.getItem( 361 tagType, ok = QInputDialog.getItem(
362 None, 362 None,
363 self.tr("Subversion Checkout"), 363 self.tr("Subversion Checkout"),
364 self.tr( 364 self.tr(
365 "The tag must be a normal tag (tags) or" 365 "The tag must be a normal tag (tags) or"
366 " a branch tag (branches)." 366 " a branch tag (branches)."
367 " Please select from the list."), 367 " Please select from the list."
368 ),
368 self.tagTypeList, 369 self.tagTypeList,
369 0, False) 370 0,
371 False,
372 )
370 if not ok: 373 if not ok:
371 return False 374 return False
372 tag = '{0}/{1}'.format(tagType, tag) 375 tag = "{0}/{1}".format(tagType, tag)
373 svnUrl = '{0}/{1}'.format(vcsDir, tag) 376 svnUrl = "{0}/{1}".format(vcsDir, tag)
374 else: 377 else:
375 svnUrl = vcsDir 378 svnUrl = vcsDir
376 379
377 args = [] 380 args = []
378 args.append('checkout') 381 args.append("checkout")
379 self.addArguments(args, self.options['global']) 382 self.addArguments(args, self.options["global"])
380 self.addArguments(args, self.options['checkout']) 383 self.addArguments(args, self.options["checkout"])
381 args.append(self.__svnURL(svnUrl)) 384 args.append(self.__svnURL(svnUrl))
382 args.append(projectDir) 385 args.append(projectDir)
383 386
384 if noDialog: 387 if noDialog:
385 return self.startSynchronizedProcess(QProcess(), 'svn', args) 388 return self.startSynchronizedProcess(QProcess(), "svn", args)
386 else: 389 else:
387 dia = SvnDialog( 390 dia = SvnDialog(self.tr("Checking project out of Subversion repository"))
388 self.tr('Checking project out of Subversion repository'))
389 res = dia.startProcess(args) 391 res = dia.startProcess(args)
390 if res: 392 if res:
391 dia.exec() 393 dia.exec()
392 return dia.normalExit() 394 return dia.normalExit()
393 395
394 def vcsExport(self, vcsDataDict, projectDir): 396 def vcsExport(self, vcsDataDict, projectDir):
395 """ 397 """
396 Public method used to export a directory from the Subversion 398 Public method used to export a directory from the Subversion
397 repository. 399 repository.
398 400
399 @param vcsDataDict dictionary of data required for the checkout 401 @param vcsDataDict dictionary of data required for the checkout
400 @param projectDir project directory to create (string) 402 @param projectDir project directory to create (string)
401 @return flag indicating an execution without errors (boolean) 403 @return flag indicating an execution without errors (boolean)
402 """ 404 """
403 try: 405 try:
404 tag = vcsDataDict["tag"] 406 tag = vcsDataDict["tag"]
405 except KeyError: 407 except KeyError:
406 tag = None 408 tag = None
407 vcsDir = self.svnNormalizeURL(vcsDataDict["url"]) 409 vcsDir = self.svnNormalizeURL(vcsDataDict["url"])
408 if vcsDir.startswith('/') or vcsDir[1] == '|': 410 if vcsDir.startswith("/") or vcsDir[1] == "|":
409 vcsDir = 'file://{0}'.format(vcsDir) 411 vcsDir = "file://{0}".format(vcsDir)
410 412
411 if self.otherData["standardLayout"]: 413 if self.otherData["standardLayout"]:
412 if tag is None or tag == '': 414 if tag is None or tag == "":
413 svnUrl = '{0}/trunk'.format(vcsDir) 415 svnUrl = "{0}/trunk".format(vcsDir)
414 else: 416 else:
415 if ( 417 if not tag.startswith("tags") and not tag.startswith("branches"):
416 not tag.startswith('tags') and
417 not tag.startswith('branches')
418 ):
419 tagType, ok = QInputDialog.getItem( 418 tagType, ok = QInputDialog.getItem(
420 None, 419 None,
421 self.tr("Subversion Export"), 420 self.tr("Subversion Export"),
422 self.tr( 421 self.tr(
423 "The tag must be a normal tag (tags) or" 422 "The tag must be a normal tag (tags) or"
424 " a branch tag (branches)." 423 " a branch tag (branches)."
425 " Please select from the list."), 424 " Please select from the list."
425 ),
426 self.tagTypeList, 426 self.tagTypeList,
427 0, False) 427 0,
428 False,
429 )
428 if not ok: 430 if not ok:
429 return False 431 return False
430 tag = '{0}/{1}'.format(tagType, tag) 432 tag = "{0}/{1}".format(tagType, tag)
431 svnUrl = '{0}/{1}'.format(vcsDir, tag) 433 svnUrl = "{0}/{1}".format(vcsDir, tag)
432 else: 434 else:
433 svnUrl = vcsDir 435 svnUrl = vcsDir
434 436
435 args = [] 437 args = []
436 args.append('export') 438 args.append("export")
437 self.addArguments(args, self.options['global']) 439 self.addArguments(args, self.options["global"])
438 args.append("--force") 440 args.append("--force")
439 args.append(self.__svnURL(svnUrl)) 441 args.append(self.__svnURL(svnUrl))
440 args.append(projectDir) 442 args.append(projectDir)
441 443
442 dia = SvnDialog( 444 dia = SvnDialog(self.tr("Exporting project from Subversion repository"))
443 self.tr('Exporting project from Subversion repository'))
444 res = dia.startProcess(args) 445 res = dia.startProcess(args)
445 if res: 446 if res:
446 dia.exec() 447 dia.exec()
447 return dia.normalExit() 448 return dia.normalExit()
448 449
449 def vcsCommit(self, name, message, noDialog=False): 450 def vcsCommit(self, name, message, noDialog=False):
450 """ 451 """
451 Public method used to make the change of a file/directory permanent 452 Public method used to make the change of a file/directory permanent
452 in the Subversion repository. 453 in the Subversion repository.
453 454
454 @param name file/directory name to be committed (string or list of 455 @param name file/directory name to be committed (string or list of
455 strings) 456 strings)
456 @param message message for this operation (string) 457 @param message message for this operation (string)
457 @param noDialog flag indicating quiet operations 458 @param noDialog flag indicating quiet operations
458 """ 459 """
459 msg = message 460 msg = message
460 461
461 if not noDialog and not msg: 462 if not noDialog and not msg:
462 # call CommitDialog and get message from there 463 # call CommitDialog and get message from there
463 if self.__commitDialog is None: 464 if self.__commitDialog is None:
464 from .SvnCommitDialog import SvnCommitDialog 465 from .SvnCommitDialog import SvnCommitDialog
466
465 self.__commitDialog = SvnCommitDialog(self, self.__ui) 467 self.__commitDialog = SvnCommitDialog(self, self.__ui)
466 self.__commitDialog.accepted.connect(self.__vcsCommit_Step2) 468 self.__commitDialog.accepted.connect(self.__vcsCommit_Step2)
467 self.__commitDialog.show() 469 self.__commitDialog.show()
468 self.__commitDialog.raise_() 470 self.__commitDialog.raise_()
469 self.__commitDialog.activateWindow() 471 self.__commitDialog.activateWindow()
470 472
471 self.__commitData["name"] = name 473 self.__commitData["name"] = name
472 self.__commitData["msg"] = msg 474 self.__commitData["msg"] = msg
473 self.__commitData["noDialog"] = noDialog 475 self.__commitData["noDialog"] = noDialog
474 476
475 if noDialog: 477 if noDialog:
476 self.__vcsCommit_Step2() 478 self.__vcsCommit_Step2()
477 479
478 def __vcsCommit_Step2(self): 480 def __vcsCommit_Step2(self):
479 """ 481 """
480 Private slot performing the second step of the commit action. 482 Private slot performing the second step of the commit action.
481 """ 483 """
482 name = self.__commitData["name"] 484 name = self.__commitData["name"]
483 msg = self.__commitData["msg"] 485 msg = self.__commitData["msg"]
484 noDialog = self.__commitData["noDialog"] 486 noDialog = self.__commitData["noDialog"]
485 487
486 if not noDialog: 488 if not noDialog:
487 # check, if there are unsaved changes, that should be committed 489 # check, if there are unsaved changes, that should be committed
488 if isinstance(name, list): 490 if isinstance(name, list):
489 nameList = name 491 nameList = name
490 else: 492 else:
494 # check for commit of the project 496 # check for commit of the project
495 if os.path.isdir(nam): 497 if os.path.isdir(nam):
496 project = ericApp().getObject("Project") 498 project = ericApp().getObject("Project")
497 if nam == project.getProjectPath(): 499 if nam == project.getProjectPath():
498 ok &= ( 500 ok &= (
499 project.checkAllScriptsDirty( 501 project.checkAllScriptsDirty(reportSyntaxErrors=True)
500 reportSyntaxErrors=True) and 502 and project.checkDirty()
501 project.checkDirty()
502 ) 503 )
503 continue 504 continue
504 elif os.path.isfile(nam): 505 elif os.path.isfile(nam):
505 editor = ericApp().getObject("ViewManager").getOpenEditor( 506 editor = ericApp().getObject("ViewManager").getOpenEditor(nam)
506 nam)
507 if editor: 507 if editor:
508 ok &= editor.checkDirty() 508 ok &= editor.checkDirty()
509 if not ok: 509 if not ok:
510 break 510 break
511 511
512 if not ok: 512 if not ok:
513 res = EricMessageBox.yesNo( 513 res = EricMessageBox.yesNo(
514 self.__ui, 514 self.__ui,
515 self.tr("Commit Changes"), 515 self.tr("Commit Changes"),
516 self.tr( 516 self.tr(
517 """The commit affects files, that have unsaved""" 517 """The commit affects files, that have unsaved"""
518 """ changes. Shall the commit be continued?"""), 518 """ changes. Shall the commit be continued?"""
519 icon=EricMessageBox.Warning) 519 ),
520 icon=EricMessageBox.Warning,
521 )
520 if not res: 522 if not res:
521 return 523 return
522 524
523 if self.__commitDialog is not None: 525 if self.__commitDialog is not None:
524 msg = self.__commitDialog.logMessage() 526 msg = self.__commitDialog.logMessage()
525 if self.__commitDialog.hasChangelists(): 527 if self.__commitDialog.hasChangelists():
526 changelists, keepChangelists = ( 528 changelists, keepChangelists = self.__commitDialog.changelistsData()
527 self.__commitDialog.changelistsData()
528 )
529 else: 529 else:
530 changelists, keepChangelists = [], False 530 changelists, keepChangelists = [], False
531 self.__commitDialog.deleteLater() 531 self.__commitDialog.deleteLater()
532 self.__commitDialog = None 532 self.__commitDialog = None
533 else: 533 else:
534 changelists, keepChangelists = [], False 534 changelists, keepChangelists = [], False
535 535
536 if not msg: 536 if not msg:
537 msg = '***' 537 msg = "***"
538 538
539 args = [] 539 args = []
540 args.append('commit') 540 args.append("commit")
541 self.addArguments(args, self.options['global']) 541 self.addArguments(args, self.options["global"])
542 self.addArguments(args, self.options['commit']) 542 self.addArguments(args, self.options["commit"])
543 if keepChangelists: 543 if keepChangelists:
544 args.append("--keep-changelists") 544 args.append("--keep-changelists")
545 for changelist in changelists: 545 for changelist in changelists:
546 args.append("--changelist") 546 args.append("--changelist")
547 args.append(changelist) 547 args.append(changelist)
551 dname, fnames = self.splitPathList(name) 551 dname, fnames = self.splitPathList(name)
552 self.addArguments(args, fnames) 552 self.addArguments(args, fnames)
553 else: 553 else:
554 dname, fname = self.splitPath(name) 554 dname, fname = self.splitPath(name)
555 args.append(fname) 555 args.append(fname)
556 556
557 if ( 557 if self.svnGetReposName(dname).startswith("http") or self.svnGetReposName(
558 self.svnGetReposName(dname).startswith('http') or 558 dname
559 self.svnGetReposName(dname).startswith('svn') 559 ).startswith("svn"):
560 ):
561 noDialog = False 560 noDialog = False
562 561
563 if noDialog: 562 if noDialog:
564 self.startSynchronizedProcess(QProcess(), "svn", args, dname) 563 self.startSynchronizedProcess(QProcess(), "svn", args, dname)
565 else: 564 else:
566 dia = SvnDialog( 565 dia = SvnDialog(self.tr("Commiting changes to Subversion repository"))
567 self.tr('Commiting changes to Subversion repository'))
568 res = dia.startProcess(args, dname) 566 res = dia.startProcess(args, dname)
569 if res: 567 if res:
570 dia.exec() 568 dia.exec()
571 self.committed.emit() 569 self.committed.emit()
572 self.checkVCSStatus() 570 self.checkVCSStatus()
573 571
574 def vcsCommitMessages(self): 572 def vcsCommitMessages(self):
575 """ 573 """
576 Public method to get the list of saved commit messages. 574 Public method to get the list of saved commit messages.
577 575
578 @return list of saved commit messages 576 @return list of saved commit messages
579 @rtype list of str 577 @rtype list of str
580 """ 578 """
581 # try per project commit history first 579 # try per project commit history first
582 messages = self._vcsProjectCommitMessages() 580 messages = self._vcsProjectCommitMessages()
583 if not messages: 581 if not messages:
584 # empty list returned, try the vcs specific one 582 # empty list returned, try the vcs specific one
585 messages = self.getPlugin().getPreferences("Commits") 583 messages = self.getPlugin().getPreferences("Commits")
586 584
587 return messages 585 return messages
588 586
589 def vcsAddCommitMessage(self, message): 587 def vcsAddCommitMessage(self, message):
590 """ 588 """
591 Public method to add a commit message to the list of saved messages. 589 Public method to add a commit message to the list of saved messages.
592 590
593 @param message message to be added 591 @param message message to be added
594 @type str 592 @type str
595 """ 593 """
596 if not self._vcsAddProjectCommitMessage(message): 594 if not self._vcsAddProjectCommitMessage(message):
597 commitMessages = self.vcsCommitMessages() 595 commitMessages = self.vcsCommitMessages()
599 commitMessages.remove(message) 597 commitMessages.remove(message)
600 commitMessages.insert(0, message) 598 commitMessages.insert(0, message)
601 no = Preferences.getVCS("CommitMessages") 599 no = Preferences.getVCS("CommitMessages")
602 del commitMessages[no:] 600 del commitMessages[no:]
603 self.getPlugin().setPreferences("Commits", commitMessages) 601 self.getPlugin().setPreferences("Commits", commitMessages)
604 602
605 def vcsClearCommitMessages(self): 603 def vcsClearCommitMessages(self):
606 """ 604 """
607 Public method to clear the list of saved messages. 605 Public method to clear the list of saved messages.
608 """ 606 """
609 if not self._vcsClearProjectCommitMessages(): 607 if not self._vcsClearProjectCommitMessages():
610 self.getPlugin().setPreferences('Commits', []) 608 self.getPlugin().setPreferences("Commits", [])
611 609
612 def vcsUpdate(self, name, noDialog=False): 610 def vcsUpdate(self, name, noDialog=False):
613 """ 611 """
614 Public method used to update a file/directory with the Subversion 612 Public method used to update a file/directory with the Subversion
615 repository. 613 repository.
616 614
617 @param name file/directory name to be updated (string or list of 615 @param name file/directory name to be updated (string or list of
618 strings) 616 strings)
619 @param noDialog flag indicating quiet operations (boolean) 617 @param noDialog flag indicating quiet operations (boolean)
620 @return flag indicating, that the update contained an add 618 @return flag indicating, that the update contained an add
621 or delete (boolean) 619 or delete (boolean)
622 """ 620 """
623 args = [] 621 args = []
624 args.append('update') 622 args.append("update")
625 self.addArguments(args, self.options['global']) 623 self.addArguments(args, self.options["global"])
626 self.addArguments(args, self.options['update']) 624 self.addArguments(args, self.options["update"])
627 if self.version >= (1, 5, 0): 625 if self.version >= (1, 5, 0):
628 args.append('--accept') 626 args.append("--accept")
629 args.append('postpone') 627 args.append("postpone")
630 if isinstance(name, list): 628 if isinstance(name, list):
631 dname, fnames = self.splitPathList(name) 629 dname, fnames = self.splitPathList(name)
632 self.addArguments(args, fnames) 630 self.addArguments(args, fnames)
633 else: 631 else:
634 dname, fname = self.splitPath(name) 632 dname, fname = self.splitPath(name)
635 args.append(fname) 633 args.append(fname)
636 634
637 if noDialog: 635 if noDialog:
638 self.startSynchronizedProcess(QProcess(), "svn", args, dname) 636 self.startSynchronizedProcess(QProcess(), "svn", args, dname)
639 res = False 637 res = False
640 else: 638 else:
641 dia = SvnDialog( 639 dia = SvnDialog(self.tr("Synchronizing with the Subversion repository"))
642 self.tr('Synchronizing with the Subversion repository'))
643 res = dia.startProcess(args, dname, True) 640 res = dia.startProcess(args, dname, True)
644 if res: 641 if res:
645 dia.exec() 642 dia.exec()
646 res = dia.hasAddOrDelete() 643 res = dia.hasAddOrDelete()
647 self.checkVCSStatus() 644 self.checkVCSStatus()
648 return res 645 return res
649 646
650 def vcsAdd(self, name, isDir=False, noDialog=False): 647 def vcsAdd(self, name, isDir=False, noDialog=False):
651 """ 648 """
652 Public method used to add a file/directory to the Subversion 649 Public method used to add a file/directory to the Subversion
653 repository. 650 repository.
654 651
655 @param name file/directory name to be added (string) 652 @param name file/directory name to be added (string)
656 @param isDir flag indicating name is a directory (boolean) 653 @param isDir flag indicating name is a directory (boolean)
657 @param noDialog flag indicating quiet operations 654 @param noDialog flag indicating quiet operations
658 """ 655 """
659 args = [] 656 args = []
660 args.append('add') 657 args.append("add")
661 self.addArguments(args, self.options['global']) 658 self.addArguments(args, self.options["global"])
662 self.addArguments(args, self.options['add']) 659 self.addArguments(args, self.options["add"])
663 args.append('--non-recursive') 660 args.append("--non-recursive")
664 if noDialog and '--force' not in args: 661 if noDialog and "--force" not in args:
665 args.append('--force') 662 args.append("--force")
666 663
667 if isinstance(name, list): 664 if isinstance(name, list):
668 if isDir: 665 if isDir:
669 dname, fname = os.path.split(name[0]) 666 dname, fname = os.path.split(name[0])
670 else: 667 else:
671 dname, fnames = self.splitPathList(name) 668 dname, fnames = self.splitPathList(name)
680 repodir = dname 677 repodir = dname
681 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 678 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
682 repodir = os.path.dirname(repodir) 679 repodir = os.path.dirname(repodir)
683 if os.path.splitdrive(repodir)[1] == os.sep: 680 if os.path.splitdrive(repodir)[1] == os.sep:
684 return # oops, project is not version controlled 681 return # oops, project is not version controlled
685 while ( 682 while os.path.normcase(dname) != os.path.normcase(repodir) and (
686 os.path.normcase(dname) != os.path.normcase(repodir) and 683 os.path.normcase(dname) not in self.statusCache
687 (os.path.normcase(dname) not in self.statusCache or 684 or self.statusCache[os.path.normcase(dname)] == self.canBeAdded
688 self.statusCache[os.path.normcase(dname)] ==
689 self.canBeAdded)
690 ): 685 ):
691 # add directories recursively, if they aren't in the 686 # add directories recursively, if they aren't in the
692 # repository already 687 # repository already
693 tree.insert(-1, dname) 688 tree.insert(-1, dname)
694 dname = os.path.dirname(dname) 689 dname = os.path.dirname(dname)
699 # repository already 694 # repository already
700 tree.insert(-1, dname) 695 tree.insert(-1, dname)
701 dname = os.path.dirname(dname) 696 dname = os.path.dirname(dname)
702 wdir = dname 697 wdir = dname
703 self.addArguments(args, tree) 698 self.addArguments(args, tree)
704 699
705 if isinstance(name, list): 700 if isinstance(name, list):
706 tree2 = [] 701 tree2 = []
707 for n in name: 702 for n in name:
708 d = os.path.dirname(n) 703 d = os.path.dirname(n)
709 if self.__wcng: 704 if self.__wcng:
710 repodir = d 705 repodir = d
711 while not os.path.isdir( 706 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
712 os.path.join(repodir, self.adminDir)):
713 repodir = os.path.dirname(repodir) 707 repodir = os.path.dirname(repodir)
714 if os.path.splitdrive(repodir)[1] == os.sep: 708 if os.path.splitdrive(repodir)[1] == os.sep:
715 return # oops, project is not version controlled 709 return # oops, project is not version controlled
716 while ( 710 while (
717 os.path.normcase(d) != os.path.normcase(repodir) and 711 os.path.normcase(d) != os.path.normcase(repodir)
718 (d not in tree2 + tree) and 712 and (d not in tree2 + tree)
719 (os.path.normcase(d) not in self.statusCache or 713 and (
720 self.statusCache[os.path.normcase(d)] == 714 os.path.normcase(d) not in self.statusCache
721 self.canBeAdded) 715 or self.statusCache[os.path.normcase(d)] == self.canBeAdded
716 )
722 ): 717 ):
723 tree2.append(d) 718 tree2.append(d)
724 d = os.path.dirname(d) 719 d = os.path.dirname(d)
725 else: 720 else:
726 while not os.path.exists(os.path.join(d, self.adminDir)): 721 while not os.path.exists(os.path.join(d, self.adminDir)):
731 tree2.reverse() 726 tree2.reverse()
732 self.addArguments(args, tree2) 727 self.addArguments(args, tree2)
733 self.addArguments(args, name) 728 self.addArguments(args, name)
734 else: 729 else:
735 args.append(name) 730 args.append(name)
736 731
737 if noDialog: 732 if noDialog:
738 self.startSynchronizedProcess(QProcess(), "svn", args, wdir) 733 self.startSynchronizedProcess(QProcess(), "svn", args, wdir)
739 else: 734 else:
740 dia = SvnDialog( 735 dia = SvnDialog(
741 self.tr('Adding files/directories to the Subversion' 736 self.tr("Adding files/directories to the Subversion" " repository")
742 ' repository')) 737 )
743 res = dia.startProcess(args, wdir) 738 res = dia.startProcess(args, wdir)
744 if res: 739 if res:
745 dia.exec() 740 dia.exec()
746 741
747 def vcsAddBinary(self, name, isDir=False): 742 def vcsAddBinary(self, name, isDir=False):
748 """ 743 """
749 Public method used to add a file/directory in binary mode to the 744 Public method used to add a file/directory in binary mode to the
750 Subversion repository. 745 Subversion repository.
751 746
752 @param name file/directory name to be added (string) 747 @param name file/directory name to be added (string)
753 @param isDir flag indicating name is a directory (boolean) 748 @param isDir flag indicating name is a directory (boolean)
754 """ 749 """
755 self.vcsAdd(name, isDir) 750 self.vcsAdd(name, isDir)
756 751
757 def vcsAddTree(self, path): 752 def vcsAddTree(self, path):
758 """ 753 """
759 Public method to add a directory tree rooted at path to the Subversion 754 Public method to add a directory tree rooted at path to the Subversion
760 repository. 755 repository.
761 756
762 @param path root directory of the tree to be added (string or list of 757 @param path root directory of the tree to be added (string or list of
763 strings)) 758 strings))
764 """ 759 """
765 args = [] 760 args = []
766 args.append('add') 761 args.append("add")
767 self.addArguments(args, self.options['global']) 762 self.addArguments(args, self.options["global"])
768 self.addArguments(args, self.options['add']) 763 self.addArguments(args, self.options["add"])
769 764
770 tree = [] 765 tree = []
771 if isinstance(path, list): 766 if isinstance(path, list):
772 dname, fnames = self.splitPathList(path) 767 dname, fnames = self.splitPathList(path)
773 for n in path: 768 for n in path:
774 d = os.path.dirname(n) 769 d = os.path.dirname(n)
775 if self.__wcng: 770 if self.__wcng:
776 repodir = d 771 repodir = d
777 while not os.path.isdir( 772 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
778 os.path.join(repodir, self.adminDir)):
779 repodir = os.path.dirname(repodir) 773 repodir = os.path.dirname(repodir)
780 if os.path.splitdrive(repodir)[1] == os.sep: 774 if os.path.splitdrive(repodir)[1] == os.sep:
781 return # oops, project is not version controlled 775 return # oops, project is not version controlled
782 while ( 776 while (
783 os.path.normcase(d) != os.path.normcase(repodir) and 777 os.path.normcase(d) != os.path.normcase(repodir)
784 (d not in tree) and 778 and (d not in tree)
785 (os.path.normcase(d) not in self.statusCache or 779 and (
786 self.statusCache[os.path.normcase(d)] == 780 os.path.normcase(d) not in self.statusCache
787 self.canBeAdded) 781 or self.statusCache[os.path.normcase(d)] == self.canBeAdded
782 )
788 ): 783 ):
789 tree.append(d) 784 tree.append(d)
790 d = os.path.dirname(d) 785 d = os.path.dirname(d)
791 else: 786 else:
792 while not os.path.exists(os.path.join(d, self.adminDir)): 787 while not os.path.exists(os.path.join(d, self.adminDir)):
803 repodir = dname 798 repodir = dname
804 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 799 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
805 repodir = os.path.dirname(repodir) 800 repodir = os.path.dirname(repodir)
806 if os.path.splitdrive(repodir)[1] == os.sep: 801 if os.path.splitdrive(repodir)[1] == os.sep:
807 return # oops, project is not version controlled 802 return # oops, project is not version controlled
808 while ( 803 while os.path.normcase(dname) != os.path.normcase(repodir) and (
809 os.path.normcase(dname) != os.path.normcase(repodir) and 804 os.path.normcase(dname) not in self.statusCache
810 (os.path.normcase(dname) not in self.statusCache or 805 or self.statusCache[os.path.normcase(dname)] == self.canBeAdded
811 self.statusCache[os.path.normcase(dname)] ==
812 self.canBeAdded)
813 ): 806 ):
814 # add directories recursively, if they aren't in the 807 # add directories recursively, if they aren't in the
815 # repository already 808 # repository already
816 tree.insert(-1, dname) 809 tree.insert(-1, dname)
817 dname = os.path.dirname(dname) 810 dname = os.path.dirname(dname)
821 # if they aren't in the repository already 814 # if they aren't in the repository already
822 tree.insert(-1, dname) 815 tree.insert(-1, dname)
823 dname = os.path.dirname(dname) 816 dname = os.path.dirname(dname)
824 if tree: 817 if tree:
825 self.vcsAdd(tree, True) 818 self.vcsAdd(tree, True)
826 819
827 if isinstance(path, list): 820 if isinstance(path, list):
828 self.addArguments(args, path) 821 self.addArguments(args, path)
829 else: 822 else:
830 args.append(path) 823 args.append(path)
831 824
832 dia = SvnDialog( 825 dia = SvnDialog(self.tr("Adding directory trees to the Subversion repository"))
833 self.tr('Adding directory trees to the Subversion repository'))
834 res = dia.startProcess(args, dname) 826 res = dia.startProcess(args, dname)
835 if res: 827 if res:
836 dia.exec() 828 dia.exec()
837 829
838 def vcsRemove(self, name, project=False, noDialog=False): 830 def vcsRemove(self, name, project=False, noDialog=False):
839 """ 831 """
840 Public method used to remove a file/directory from the Subversion 832 Public method used to remove a file/directory from the Subversion
841 repository. 833 repository.
842 834
843 The default operation is to remove the local copy as well. 835 The default operation is to remove the local copy as well.
844 836
845 @param name file/directory name to be removed (string or list of 837 @param name file/directory name to be removed (string or list of
846 strings)) 838 strings))
847 @param project flag indicating deletion of a project tree (boolean) 839 @param project flag indicating deletion of a project tree (boolean)
848 (not needed) 840 (not needed)
849 @param noDialog flag indicating quiet operations 841 @param noDialog flag indicating quiet operations
850 @return flag indicating successfull operation (boolean) 842 @return flag indicating successfull operation (boolean)
851 """ 843 """
852 args = [] 844 args = []
853 args.append('delete') 845 args.append("delete")
854 self.addArguments(args, self.options['global']) 846 self.addArguments(args, self.options["global"])
855 self.addArguments(args, self.options['remove']) 847 self.addArguments(args, self.options["remove"])
856 if noDialog and '--force' not in args: 848 if noDialog and "--force" not in args:
857 args.append('--force') 849 args.append("--force")
858 850
859 if isinstance(name, list): 851 if isinstance(name, list):
860 self.addArguments(args, name) 852 self.addArguments(args, name)
861 else: 853 else:
862 args.append(name) 854 args.append(name)
863 855
864 if noDialog: 856 if noDialog:
865 res = self.startSynchronizedProcess(QProcess(), "svn", args) 857 res = self.startSynchronizedProcess(QProcess(), "svn", args)
866 else: 858 else:
867 dia = SvnDialog( 859 dia = SvnDialog(
868 self.tr('Removing files/directories from the Subversion' 860 self.tr("Removing files/directories from the Subversion" " repository")
869 ' repository')) 861 )
870 res = dia.startProcess(args) 862 res = dia.startProcess(args)
871 if res: 863 if res:
872 dia.exec() 864 dia.exec()
873 res = dia.normalExit() 865 res = dia.normalExit()
874 866
875 return res 867 return res
876 868
877 def vcsMove(self, name, project, target=None, noDialog=False): 869 def vcsMove(self, name, project, target=None, noDialog=False):
878 """ 870 """
879 Public method used to move a file/directory. 871 Public method used to move a file/directory.
880 872
881 @param name file/directory name to be moved (string) 873 @param name file/directory name to be moved (string)
882 @param project reference to the project object 874 @param project reference to the project object
883 @param target new name of the file/directory (string) 875 @param target new name of the file/directory (string)
884 @param noDialog flag indicating quiet operations 876 @param noDialog flag indicating quiet operations
885 @return flag indicating successfull operation (boolean) 877 @return flag indicating successfull operation (boolean)
886 """ 878 """
887 rx_prot = re.compile('(file:|svn:|svn+ssh:|http:|https:).+') 879 rx_prot = re.compile("(file:|svn:|svn+ssh:|http:|https:).+")
888 opts = self.options['global'][:] 880 opts = self.options["global"][:]
889 force = '--force' in opts 881 force = "--force" in opts
890 if force: 882 if force:
891 del opts[opts.index('--force')] 883 del opts[opts.index("--force")]
892 884
893 res = False 885 res = False
894 if noDialog: 886 if noDialog:
895 if target is None: 887 if target is None:
896 return False 888 return False
897 force = True 889 force = True
898 accepted = True 890 accepted = True
899 else: 891 else:
900 from .SvnCopyDialog import SvnCopyDialog 892 from .SvnCopyDialog import SvnCopyDialog
893
901 dlg = SvnCopyDialog(name, None, True, force) 894 dlg = SvnCopyDialog(name, None, True, force)
902 accepted = (dlg.exec() == QDialog.DialogCode.Accepted) 895 accepted = dlg.exec() == QDialog.DialogCode.Accepted
903 if accepted: 896 if accepted:
904 target, force = dlg.getData() 897 target, force = dlg.getData()
905 if not target: 898 if not target:
906 return False 899 return False
907 900
908 isDir = (os.path.isdir(name) if rx_prot.fullmatch(target) is None 901 isDir = os.path.isdir(name) if rx_prot.fullmatch(target) is None else False
909 else False) 902
910
911 if accepted: 903 if accepted:
912 args = [] 904 args = []
913 args.append('move') 905 args.append("move")
914 self.addArguments(args, opts) 906 self.addArguments(args, opts)
915 if force: 907 if force:
916 args.append('--force') 908 args.append("--force")
917 if rx_prot.fullmatch(target) is not None: 909 if rx_prot.fullmatch(target) is not None:
918 args.append('--message') 910 args.append("--message")
919 args.append('Moving {0} to {1}'.format(name, target)) 911 args.append("Moving {0} to {1}".format(name, target))
920 target = self.__svnURL(target) 912 target = self.__svnURL(target)
921 args.append(name) 913 args.append(name)
922 args.append(target) 914 args.append(target)
923 915
924 if noDialog: 916 if noDialog:
925 res = self.startSynchronizedProcess(QProcess(), "svn", args) 917 res = self.startSynchronizedProcess(QProcess(), "svn", args)
926 else: 918 else:
927 dia = SvnDialog(self.tr('Moving {0}') 919 dia = SvnDialog(self.tr("Moving {0}").format(name))
928 .format(name))
929 res = dia.startProcess(args) 920 res = dia.startProcess(args)
930 if res: 921 if res:
931 dia.exec() 922 dia.exec()
932 res = dia.normalExit() 923 res = dia.normalExit()
933 if res and rx_prot.fullmatch(target) is None: 924 if res and rx_prot.fullmatch(target) is None:
940 if isDir: 931 if isDir:
941 project.removeDirectory(name) 932 project.removeDirectory(name)
942 else: 933 else:
943 project.removeFile(name) 934 project.removeFile(name)
944 return res 935 return res
945 936
946 def vcsDiff(self, name): 937 def vcsDiff(self, name):
947 """ 938 """
948 Public method used to view the difference of a file/directory to the 939 Public method used to view the difference of a file/directory to the
949 Subversion repository. 940 Subversion repository.
950 941
951 If name is a directory and is the project directory, all project files 942 If name is a directory and is the project directory, all project files
952 are saved first. If name is a file (or list of files), which is/are 943 are saved first. If name is a file (or list of files), which is/are
953 being edited and has unsaved modification, they can be saved or the 944 being edited and has unsaved modification, they can be saved or the
954 operation may be aborted. 945 operation may be aborted.
955 946
956 @param name file/directory name to be diffed (string) 947 @param name file/directory name to be diffed (string)
957 """ 948 """
958 names = name[:] if isinstance(name, list) else [name] 949 names = name[:] if isinstance(name, list) else [name]
959 for nam in names: 950 for nam in names:
960 if os.path.isfile(nam): 951 if os.path.isfile(nam):
965 project = ericApp().getObject("Project") 956 project = ericApp().getObject("Project")
966 if nam == project.ppath and not project.saveAllScripts(): 957 if nam == project.ppath and not project.saveAllScripts():
967 return 958 return
968 if self.diff is None: 959 if self.diff is None:
969 from .SvnDiffDialog import SvnDiffDialog 960 from .SvnDiffDialog import SvnDiffDialog
961
970 self.diff = SvnDiffDialog(self) 962 self.diff = SvnDiffDialog(self)
971 self.diff.show() 963 self.diff.show()
972 self.diff.raise_() 964 self.diff.raise_()
973 QApplication.processEvents() 965 QApplication.processEvents()
974 self.diff.start(name, refreshable=True) 966 self.diff.start(name, refreshable=True)
975 967
976 def vcsStatus(self, name): 968 def vcsStatus(self, name):
977 """ 969 """
978 Public method used to view the status of files/directories in the 970 Public method used to view the status of files/directories in the
979 Subversion repository. 971 Subversion repository.
980 972
981 @param name file/directory name(s) to show the status of 973 @param name file/directory name(s) to show the status of
982 (string or list of strings) 974 (string or list of strings)
983 """ 975 """
984 if self.status is None: 976 if self.status is None:
985 from .SvnStatusDialog import SvnStatusDialog 977 from .SvnStatusDialog import SvnStatusDialog
978
986 self.status = SvnStatusDialog(self) 979 self.status = SvnStatusDialog(self)
987 self.status.show() 980 self.status.show()
988 self.status.raise_() 981 self.status.raise_()
989 self.status.start(name) 982 self.status.start(name)
990 983
991 def vcsTag(self, name): 984 def vcsTag(self, name):
992 """ 985 """
993 Public method used to set the tag of a file/directory in the 986 Public method used to set the tag of a file/directory in the
994 Subversion repository. 987 Subversion repository.
995 988
996 @param name file/directory name to be tagged (string) 989 @param name file/directory name to be tagged (string)
997 """ 990 """
998 dname, fname = self.splitPath(name) 991 dname, fname = self.splitPath(name)
999 992
1000 reposURL = self.svnGetReposName(dname) 993 reposURL = self.svnGetReposName(dname)
1001 if reposURL is None: 994 if reposURL is None:
1002 EricMessageBox.critical( 995 EricMessageBox.critical(
1003 self.__ui, 996 self.__ui,
1004 self.tr("Subversion Error"), 997 self.tr("Subversion Error"),
1005 self.tr( 998 self.tr(
1006 """The URL of the project repository could not be""" 999 """The URL of the project repository could not be"""
1007 """ retrieved from the working copy. The tag operation""" 1000 """ retrieved from the working copy. The tag operation"""
1008 """ will be aborted""")) 1001 """ will be aborted"""
1002 ),
1003 )
1009 return 1004 return
1010 1005
1011 url = ( 1006 url = (
1012 None 1007 None if self.otherData["standardLayout"] else self.svnNormalizeURL(reposURL)
1013 if self.otherData["standardLayout"] else
1014 self.svnNormalizeURL(reposURL)
1015 ) 1008 )
1016 from .SvnTagDialog import SvnTagDialog 1009 from .SvnTagDialog import SvnTagDialog
1017 dlg = SvnTagDialog(self.allTagsBranchesList, url, 1010
1018 self.otherData["standardLayout"]) 1011 dlg = SvnTagDialog(
1012 self.allTagsBranchesList, url, self.otherData["standardLayout"]
1013 )
1019 if dlg.exec() == QDialog.DialogCode.Accepted: 1014 if dlg.exec() == QDialog.DialogCode.Accepted:
1020 tag, tagOp = dlg.getParameters() 1015 tag, tagOp = dlg.getParameters()
1021 if tag in self.allTagsBranchesList: 1016 if tag in self.allTagsBranchesList:
1022 self.allTagsBranchesList.remove(tag) 1017 self.allTagsBranchesList.remove(tag)
1023 self.allTagsBranchesList.insert(0, tag) 1018 self.allTagsBranchesList.insert(0, tag)
1024 else: 1019 else:
1025 return 1020 return
1026 1021
1027 if self.otherData["standardLayout"]: 1022 if self.otherData["standardLayout"]:
1028 rx_base = re.compile('(.+)/(trunk|tags|branches).*') 1023 rx_base = re.compile("(.+)/(trunk|tags|branches).*")
1029 match = rx_base.fullmatch(reposURL) 1024 match = rx_base.fullmatch(reposURL)
1030 if match is None: 1025 if match is None:
1031 EricMessageBox.critical( 1026 EricMessageBox.critical(
1032 self.__ui, 1027 self.__ui,
1033 self.tr("Subversion Error"), 1028 self.tr("Subversion Error"),
1034 self.tr( 1029 self.tr(
1035 """The URL of the project repository has an""" 1030 """The URL of the project repository has an"""
1036 """ invalid format. The tag operation will""" 1031 """ invalid format. The tag operation will"""
1037 """ be aborted""")) 1032 """ be aborted"""
1033 ),
1034 )
1038 return 1035 return
1039 1036
1040 reposRoot = match.group(1) 1037 reposRoot = match.group(1)
1041 if tagOp in [1, 4]: 1038 if tagOp in [1, 4]:
1042 url = '{0}/tags/{1}'.format(reposRoot, quote(tag)) 1039 url = "{0}/tags/{1}".format(reposRoot, quote(tag))
1043 elif tagOp in [2, 8]: 1040 elif tagOp in [2, 8]:
1044 url = '{0}/branches/{1}'.format(reposRoot, quote(tag)) 1041 url = "{0}/branches/{1}".format(reposRoot, quote(tag))
1045 else: 1042 else:
1046 url = self.__svnURL(tag) 1043 url = self.__svnURL(tag)
1047 1044
1048 args = [] 1045 args = []
1049 if tagOp in [1, 2]: 1046 if tagOp in [1, 2]:
1050 args.append('copy') 1047 args.append("copy")
1051 self.addArguments(args, self.options['global']) 1048 self.addArguments(args, self.options["global"])
1052 self.addArguments(args, self.options['tag']) 1049 self.addArguments(args, self.options["tag"])
1053 args.append('--message') 1050 args.append("--message")
1054 args.append('Created tag <{0}>'.format(tag)) 1051 args.append("Created tag <{0}>".format(tag))
1055 args.append(reposURL) 1052 args.append(reposURL)
1056 args.append(url) 1053 args.append(url)
1057 else: 1054 else:
1058 args.append('delete') 1055 args.append("delete")
1059 self.addArguments(args, self.options['global']) 1056 self.addArguments(args, self.options["global"])
1060 self.addArguments(args, self.options['tag']) 1057 self.addArguments(args, self.options["tag"])
1061 args.append('--message') 1058 args.append("--message")
1062 args.append('Deleted tag <{0}>'.format(tag)) 1059 args.append("Deleted tag <{0}>".format(tag))
1063 args.append(url) 1060 args.append(url)
1064 1061
1065 dia = SvnDialog(self.tr('Tagging {0} in the Subversion repository') 1062 dia = SvnDialog(
1066 .format(name)) 1063 self.tr("Tagging {0} in the Subversion repository").format(name)
1064 )
1067 res = dia.startProcess(args) 1065 res = dia.startProcess(args)
1068 if res: 1066 if res:
1069 dia.exec() 1067 dia.exec()
1070 1068
1071 def vcsRevert(self, name): 1069 def vcsRevert(self, name):
1072 """ 1070 """
1073 Public method used to revert changes made to a file/directory. 1071 Public method used to revert changes made to a file/directory.
1074 1072
1075 @param name file/directory name to be reverted 1073 @param name file/directory name to be reverted
1076 @type str 1074 @type str
1077 @return flag indicating, that the update contained an add 1075 @return flag indicating, that the update contained an add
1078 or delete 1076 or delete
1079 @rtype bool 1077 @rtype bool
1080 """ 1078 """
1081 args = [] 1079 args = []
1082 args.append('revert') 1080 args.append("revert")
1083 self.addArguments(args, self.options['global']) 1081 self.addArguments(args, self.options["global"])
1084 if isinstance(name, list): 1082 if isinstance(name, list):
1085 self.addArguments(args, name) 1083 self.addArguments(args, name)
1086 names = name[:] 1084 names = name[:]
1087 else: 1085 else:
1088 if os.path.isdir(name): 1086 if os.path.isdir(name):
1089 args.append('--recursive') 1087 args.append("--recursive")
1090 args.append(name) 1088 args.append(name)
1091 names = [name] 1089 names = [name]
1092 1090
1093 project = ericApp().getObject("Project") 1091 project = ericApp().getObject("Project")
1094 names = [project.getRelativePath(nam) for nam in names] 1092 names = [project.getRelativePath(nam) for nam in names]
1095 if names[0]: 1093 if names[0]:
1096 from UI.DeleteFilesConfirmationDialog import ( 1094 from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog
1097 DeleteFilesConfirmationDialog 1095
1098 )
1099 dlg = DeleteFilesConfirmationDialog( 1096 dlg = DeleteFilesConfirmationDialog(
1100 self.parent(), 1097 self.parent(),
1101 self.tr("Revert changes"), 1098 self.tr("Revert changes"),
1102 self.tr("Do you really want to revert all changes to" 1099 self.tr(
1103 " these files or directories?"), 1100 "Do you really want to revert all changes to"
1104 names) 1101 " these files or directories?"
1102 ),
1103 names,
1104 )
1105 yes = dlg.exec() == QDialog.DialogCode.Accepted 1105 yes = dlg.exec() == QDialog.DialogCode.Accepted
1106 else: 1106 else:
1107 yes = EricMessageBox.yesNo( 1107 yes = EricMessageBox.yesNo(
1108 None, 1108 None,
1109 self.tr("Revert changes"), 1109 self.tr("Revert changes"),
1110 self.tr("""Do you really want to revert all changes of""" 1110 self.tr(
1111 """ the project?""")) 1111 """Do you really want to revert all changes of"""
1112 """ the project?"""
1113 ),
1114 )
1112 if yes: 1115 if yes:
1113 dia = SvnDialog(self.tr('Reverting changes')) 1116 dia = SvnDialog(self.tr("Reverting changes"))
1114 res = dia.startProcess(args) 1117 res = dia.startProcess(args)
1115 if res: 1118 if res:
1116 dia.exec() 1119 dia.exec()
1117 self.checkVCSStatus() 1120 self.checkVCSStatus()
1118 1121
1119 return False 1122 return False
1120 1123
1121 def vcsForget(self, name): 1124 def vcsForget(self, name):
1122 """ 1125 """
1123 Public method used to remove a file from the repository. 1126 Public method used to remove a file from the repository.
1124 1127
1125 Note: svn does not support this operation. The method is implemented 1128 Note: svn does not support this operation. The method is implemented
1126 as a NoOp. 1129 as a NoOp.
1127 1130
1128 @param name file/directory name to be removed 1131 @param name file/directory name to be removed
1129 @type str or list of str 1132 @type str or list of str
1130 """ 1133 """
1131 pass 1134 pass
1132 1135
1133 def vcsSwitch(self, name): 1136 def vcsSwitch(self, name):
1134 """ 1137 """
1135 Public method used to switch a directory to a different tag/branch. 1138 Public method used to switch a directory to a different tag/branch.
1136 1139
1137 @param name directory name to be switched (string) 1140 @param name directory name to be switched (string)
1138 @return flag indicating added or changed files (boolean) 1141 @return flag indicating added or changed files (boolean)
1139 """ 1142 """
1140 dname, fname = self.splitPath(name) 1143 dname, fname = self.splitPath(name)
1141 1144
1142 reposURL = self.svnGetReposName(dname) 1145 reposURL = self.svnGetReposName(dname)
1143 if reposURL is None: 1146 if reposURL is None:
1144 EricMessageBox.critical( 1147 EricMessageBox.critical(
1145 self.__ui, 1148 self.__ui,
1146 self.tr("Subversion Error"), 1149 self.tr("Subversion Error"),
1147 self.tr( 1150 self.tr(
1148 """The URL of the project repository could not be""" 1151 """The URL of the project repository could not be"""
1149 """ retrieved from the working copy. The switch""" 1152 """ retrieved from the working copy. The switch"""
1150 """ operation will be aborted""")) 1153 """ operation will be aborted"""
1154 ),
1155 )
1151 return False 1156 return False
1152 1157
1153 url = ( 1158 url = (
1154 None 1159 None if self.otherData["standardLayout"] else self.svnNormalizeURL(reposURL)
1155 if self.otherData["standardLayout"] else
1156 self.svnNormalizeURL(reposURL)
1157 ) 1160 )
1158 from .SvnSwitchDialog import SvnSwitchDialog 1161 from .SvnSwitchDialog import SvnSwitchDialog
1159 dlg = SvnSwitchDialog(self.allTagsBranchesList, url, 1162
1160 self.otherData["standardLayout"]) 1163 dlg = SvnSwitchDialog(
1164 self.allTagsBranchesList, url, self.otherData["standardLayout"]
1165 )
1161 if dlg.exec() == QDialog.DialogCode.Accepted: 1166 if dlg.exec() == QDialog.DialogCode.Accepted:
1162 tag, tagType = dlg.getParameters() 1167 tag, tagType = dlg.getParameters()
1163 if tag in self.allTagsBranchesList: 1168 if tag in self.allTagsBranchesList:
1164 self.allTagsBranchesList.remove(tag) 1169 self.allTagsBranchesList.remove(tag)
1165 self.allTagsBranchesList.insert(0, tag) 1170 self.allTagsBranchesList.insert(0, tag)
1166 else: 1171 else:
1167 return False 1172 return False
1168 1173
1169 if self.otherData["standardLayout"]: 1174 if self.otherData["standardLayout"]:
1170 rx_base = re.compile('(.+)/(trunk|tags|branches).*') 1175 rx_base = re.compile("(.+)/(trunk|tags|branches).*")
1171 match = rx_base.fullmatch(reposURL) 1176 match = rx_base.fullmatch(reposURL)
1172 if match is None: 1177 if match is None:
1173 EricMessageBox.critical( 1178 EricMessageBox.critical(
1174 self.__ui, 1179 self.__ui,
1175 self.tr("Subversion Error"), 1180 self.tr("Subversion Error"),
1176 self.tr( 1181 self.tr(
1177 """The URL of the project repository has an""" 1182 """The URL of the project repository has an"""
1178 """ invalid format. The switch operation will""" 1183 """ invalid format. The switch operation will"""
1179 """ be aborted""")) 1184 """ be aborted"""
1185 ),
1186 )
1180 return False 1187 return False
1181 1188
1182 reposRoot = match.group(1) 1189 reposRoot = match.group(1)
1183 tn = tag 1190 tn = tag
1184 if tagType == 1: 1191 if tagType == 1:
1185 url = '{0}/tags/{1}'.format(reposRoot, quote(tag)) 1192 url = "{0}/tags/{1}".format(reposRoot, quote(tag))
1186 elif tagType == 2: 1193 elif tagType == 2:
1187 url = '{0}/branches/{1}'.format(reposRoot, quote(tag)) 1194 url = "{0}/branches/{1}".format(reposRoot, quote(tag))
1188 elif tagType == 4: 1195 elif tagType == 4:
1189 url = '{0}/trunk'.format(reposRoot) 1196 url = "{0}/trunk".format(reposRoot)
1190 tn = 'HEAD' 1197 tn = "HEAD"
1191 else: 1198 else:
1192 url = self.__svnURL(tag) 1199 url = self.__svnURL(tag)
1193 tn = url 1200 tn = url
1194 1201
1195 args = [] 1202 args = []
1196 args.append('switch') 1203 args.append("switch")
1197 if self.version >= (1, 5, 0): 1204 if self.version >= (1, 5, 0):
1198 args.append('--accept') 1205 args.append("--accept")
1199 args.append('postpone') 1206 args.append("postpone")
1200 args.append(url) 1207 args.append(url)
1201 args.append(name) 1208 args.append(name)
1202 1209
1203 dia = SvnDialog(self.tr('Switching to {0}') 1210 dia = SvnDialog(self.tr("Switching to {0}").format(tn))
1204 .format(tn))
1205 res = dia.startProcess(args, setLanguage=True) 1211 res = dia.startProcess(args, setLanguage=True)
1206 if res: 1212 if res:
1207 dia.exec() 1213 dia.exec()
1208 res = dia.hasAddOrDelete() 1214 res = dia.hasAddOrDelete()
1209 self.checkVCSStatus() 1215 self.checkVCSStatus()
1210 return res 1216 return res
1211 1217
1212 def vcsMerge(self, name): 1218 def vcsMerge(self, name):
1213 """ 1219 """
1214 Public method used to merge a URL/revision into the local project. 1220 Public method used to merge a URL/revision into the local project.
1215 1221
1216 @param name file/directory name to be merged (string) 1222 @param name file/directory name to be merged (string)
1217 """ 1223 """
1218 dname, fname = self.splitPath(name) 1224 dname, fname = self.splitPath(name)
1219 1225
1220 opts = self.options['global'][:] 1226 opts = self.options["global"][:]
1221 force = '--force' in opts 1227 force = "--force" in opts
1222 if force: 1228 if force:
1223 del opts[opts.index('--force')] 1229 del opts[opts.index("--force")]
1224 1230
1225 from .SvnMergeDialog import SvnMergeDialog 1231 from .SvnMergeDialog import SvnMergeDialog
1232
1226 dlg = SvnMergeDialog( 1233 dlg = SvnMergeDialog(
1227 self.mergeList[0], self.mergeList[1], self.mergeList[2], force) 1234 self.mergeList[0], self.mergeList[1], self.mergeList[2], force
1235 )
1228 if dlg.exec() == QDialog.DialogCode.Accepted: 1236 if dlg.exec() == QDialog.DialogCode.Accepted:
1229 urlrev1, urlrev2, target, force = dlg.getParameters() 1237 urlrev1, urlrev2, target, force = dlg.getParameters()
1230 else: 1238 else:
1231 return 1239 return
1232 1240
1233 # remember URL or revision 1241 # remember URL or revision
1234 if urlrev1 in self.mergeList[0]: 1242 if urlrev1 in self.mergeList[0]:
1235 self.mergeList[0].remove(urlrev1) 1243 self.mergeList[0].remove(urlrev1)
1236 self.mergeList[0].insert(0, urlrev1) 1244 self.mergeList[0].insert(0, urlrev1)
1237 if urlrev2 in self.mergeList[1]: 1245 if urlrev2 in self.mergeList[1]:
1238 self.mergeList[1].remove(urlrev2) 1246 self.mergeList[1].remove(urlrev2)
1239 self.mergeList[1].insert(0, urlrev2) 1247 self.mergeList[1].insert(0, urlrev2)
1240 1248
1241 rx_rev = re.compile('\\d+|HEAD') 1249 rx_rev = re.compile("\\d+|HEAD")
1242 1250
1243 args = [] 1251 args = []
1244 args.append('merge') 1252 args.append("merge")
1245 self.addArguments(args, opts) 1253 self.addArguments(args, opts)
1246 if self.version >= (1, 5, 0): 1254 if self.version >= (1, 5, 0):
1247 args.append('--accept') 1255 args.append("--accept")
1248 args.append('postpone') 1256 args.append("postpone")
1249 if force: 1257 if force:
1250 args.append('--force') 1258 args.append("--force")
1251 if rx_rev.fullmatch(urlrev1) is not None: 1259 if rx_rev.fullmatch(urlrev1) is not None:
1252 args.append('-r') 1260 args.append("-r")
1253 args.append('{0}:{1}'.format(urlrev1, urlrev2)) 1261 args.append("{0}:{1}".format(urlrev1, urlrev2))
1254 if not target: 1262 if not target:
1255 args.append(name) 1263 args.append(name)
1256 else: 1264 else:
1257 args.append(target) 1265 args.append(target)
1258 1266
1259 # remember target 1267 # remember target
1260 if target in self.mergeList[2]: 1268 if target in self.mergeList[2]:
1261 self.mergeList[2].remove(target) 1269 self.mergeList[2].remove(target)
1262 self.mergeList[2].insert(0, target) 1270 self.mergeList[2].insert(0, target)
1263 else: 1271 else:
1264 args.append(self.__svnURL(urlrev1)) 1272 args.append(self.__svnURL(urlrev1))
1265 args.append(self.__svnURL(urlrev2)) 1273 args.append(self.__svnURL(urlrev2))
1266 args.append(fname) 1274 args.append(fname)
1267 1275
1268 dia = SvnDialog(self.tr('Merging {0}').format(name)) 1276 dia = SvnDialog(self.tr("Merging {0}").format(name))
1269 res = dia.startProcess(args, dname) 1277 res = dia.startProcess(args, dname)
1270 if res: 1278 if res:
1271 dia.exec() 1279 dia.exec()
1272 1280
1273 def vcsRegisteredState(self, name): 1281 def vcsRegisteredState(self, name):
1274 """ 1282 """
1275 Public method used to get the registered state of a file in the vcs. 1283 Public method used to get the registered state of a file in the vcs.
1276 1284
1277 @param name filename to check (string) 1285 @param name filename to check (string)
1278 @return a combination of canBeCommited and canBeAdded 1286 @return a combination of canBeCommited and canBeAdded
1279 """ 1287 """
1280 if self.__wcng: 1288 if self.__wcng:
1281 return self.__vcsRegisteredState_wcng(name) 1289 return self.__vcsRegisteredState_wcng(name)
1282 else: 1290 else:
1283 return self.__vcsRegisteredState_wc(name) 1291 return self.__vcsRegisteredState_wc(name)
1284 1292
1285 def __vcsRegisteredState_wcng(self, name): 1293 def __vcsRegisteredState_wcng(self, name):
1286 """ 1294 """
1287 Private method used to get the registered state of a file in the vcs. 1295 Private method used to get the registered state of a file in the vcs.
1288 1296
1289 This is the variant for subversion installations using the new 1297 This is the variant for subversion installations using the new
1290 working copy meta-data format. 1298 working copy meta-data format.
1291 1299
1292 @param name filename to check (string) 1300 @param name filename to check (string)
1293 @return a combination of canBeCommited and canBeAdded 1301 @return a combination of canBeCommited and canBeAdded
1294 """ 1302 """
1295 if name.endswith(os.sep): 1303 if name.endswith(os.sep):
1296 name = name[:-1] 1304 name = name[:-1]
1297 name = os.path.normcase(name) 1305 name = os.path.normcase(name)
1298 dname, fname = self.splitPath(name) 1306 dname, fname = self.splitPath(name)
1299 1307
1300 if fname == '.' and os.path.isdir(os.path.join(dname, self.adminDir)): 1308 if fname == "." and os.path.isdir(os.path.join(dname, self.adminDir)):
1301 return self.canBeCommitted 1309 return self.canBeCommitted
1302 1310
1303 if name in self.statusCache: 1311 if name in self.statusCache:
1304 return self.statusCache[name] 1312 return self.statusCache[name]
1305 1313
1306 name = os.path.normcase(name) 1314 name = os.path.normcase(name)
1307 states = {name: 0} 1315 states = {name: 0}
1308 states = self.vcsAllRegisteredStates(states, dname, False) 1316 states = self.vcsAllRegisteredStates(states, dname, False)
1309 if states[name] == self.canBeCommitted: 1317 if states[name] == self.canBeCommitted:
1310 return self.canBeCommitted 1318 return self.canBeCommitted
1311 else: 1319 else:
1312 return self.canBeAdded 1320 return self.canBeAdded
1313 1321
1314 def __vcsRegisteredState_wc(self, name): 1322 def __vcsRegisteredState_wc(self, name):
1315 """ 1323 """
1316 Private method used to get the registered state of a file in the VCS. 1324 Private method used to get the registered state of a file in the VCS.
1317 1325
1318 This is the variant for subversion installations using the old working 1326 This is the variant for subversion installations using the old working
1319 copy meta-data format. 1327 copy meta-data format.
1320 1328
1321 @param name filename to check (string) 1329 @param name filename to check (string)
1322 @return a combination of canBeCommited and canBeAdded 1330 @return a combination of canBeCommited and canBeAdded
1323 """ 1331 """
1324 dname, fname = self.splitPath(name) 1332 dname, fname = self.splitPath(name)
1325 1333
1326 if fname == '.': 1334 if fname == ".":
1327 if os.path.isdir(os.path.join(dname, self.adminDir)): 1335 if os.path.isdir(os.path.join(dname, self.adminDir)):
1328 return self.canBeCommitted 1336 return self.canBeCommitted
1329 else: 1337 else:
1330 return self.canBeAdded 1338 return self.canBeAdded
1331 1339
1332 name = os.path.normcase(name) 1340 name = os.path.normcase(name)
1333 states = {name: 0} 1341 states = {name: 0}
1334 states = self.vcsAllRegisteredStates(states, dname, False) 1342 states = self.vcsAllRegisteredStates(states, dname, False)
1335 if states[name] == self.canBeCommitted: 1343 if states[name] == self.canBeCommitted:
1336 return self.canBeCommitted 1344 return self.canBeCommitted
1337 else: 1345 else:
1338 return self.canBeAdded 1346 return self.canBeAdded
1339 1347
1340 def vcsAllRegisteredStates(self, names, dname, shortcut=True): 1348 def vcsAllRegisteredStates(self, names, dname, shortcut=True):
1341 """ 1349 """
1342 Public method used to get the registered states of a number of files 1350 Public method used to get the registered states of a number of files
1343 in the VCS. 1351 in the VCS.
1344 1352
1345 <b>Note:</b> If a shortcut is to be taken, the code will only check, 1353 <b>Note:</b> If a shortcut is to be taken, the code will only check,
1346 if the named directory has been scanned already. If so, it is assumed, 1354 if the named directory has been scanned already. If so, it is assumed,
1347 that the states for all files have been populated by the previous run. 1355 that the states for all files have been populated by the previous run.
1348 1356
1349 @param names dictionary with all filenames to be checked as keys 1357 @param names dictionary with all filenames to be checked as keys
1350 @param dname directory to check in (string) 1358 @param dname directory to check in (string)
1351 @param shortcut flag indicating a shortcut should be taken (boolean) 1359 @param shortcut flag indicating a shortcut should be taken (boolean)
1352 @return the received dictionary completed with a combination of 1360 @return the received dictionary completed with a combination of
1353 canBeCommited and canBeAdded or None in order to signal an error 1361 canBeCommited and canBeAdded or None in order to signal an error
1354 """ 1362 """
1355 if self.__wcng: 1363 if self.__wcng:
1356 return self.__vcsAllRegisteredStates_wcng(names, dname, shortcut) 1364 return self.__vcsAllRegisteredStates_wcng(names, dname, shortcut)
1357 else: 1365 else:
1358 return self.__vcsAllRegisteredStates_wc(names, dname, shortcut) 1366 return self.__vcsAllRegisteredStates_wc(names, dname, shortcut)
1359 1367
1360 def __vcsAllRegisteredStates_wcng(self, names, dname, shortcut=True): 1368 def __vcsAllRegisteredStates_wcng(self, names, dname, shortcut=True):
1361 """ 1369 """
1362 Private method used to get the registered states of a number of files 1370 Private method used to get the registered states of a number of files
1363 in the VCS. 1371 in the VCS.
1364 1372
1365 This is the variant for subversion installations using the new working 1373 This is the variant for subversion installations using the new working
1366 copy meta-data format. 1374 copy meta-data format.
1367 1375
1368 <b>Note:</b> If a shortcut is to be taken, the code will only check, 1376 <b>Note:</b> If a shortcut is to be taken, the code will only check,
1369 if the named directory has been scanned already. If so, it is assumed, 1377 if the named directory has been scanned already. If so, it is assumed,
1370 that the states for all files has been populated by the previous run. 1378 that the states for all files has been populated by the previous run.
1371 1379
1372 @param names dictionary with all filenames to be checked as keys 1380 @param names dictionary with all filenames to be checked as keys
1373 @param dname directory to check in (string) 1381 @param dname directory to check in (string)
1374 @param shortcut flag indicating a shortcut should be taken (boolean) 1382 @param shortcut flag indicating a shortcut should be taken (boolean)
1375 @return the received dictionary completed with a combination of 1383 @return the received dictionary completed with a combination of
1376 canBeCommited and canBeAdded or None in order to signal an error 1384 canBeCommited and canBeAdded or None in order to signal an error
1377 """ 1385 """
1378 if dname.endswith(os.sep): 1386 if dname.endswith(os.sep):
1379 dname = dname[:-1] 1387 dname = dname[:-1]
1380 dname = os.path.normcase(dname) 1388 dname = os.path.normcase(dname)
1381 1389
1382 found = False 1390 found = False
1383 for name in self.statusCache: 1391 for name in self.statusCache:
1384 if name in names: 1392 if name in names:
1385 found = True 1393 found = True
1386 names[name] = self.statusCache[name] 1394 names[name] = self.statusCache[name]
1387 1395
1388 if not found: 1396 if not found:
1389 # find the root of the repo 1397 # find the root of the repo
1390 repodir = dname 1398 repodir = dname
1391 while not os.path.isdir(os.path.join(repodir, self.adminDir)): 1399 while not os.path.isdir(os.path.join(repodir, self.adminDir)):
1392 repodir = os.path.dirname(repodir) 1400 repodir = os.path.dirname(repodir)
1393 if os.path.splitdrive(repodir)[1] == os.sep: 1401 if os.path.splitdrive(repodir)[1] == os.sep:
1394 return names 1402 return names
1395 1403
1396 ioEncoding = str(Preferences.getSystem("IOEncoding")) 1404 ioEncoding = str(Preferences.getSystem("IOEncoding"))
1397 process = QProcess() 1405 process = QProcess()
1398 args = [] 1406 args = []
1399 args.append('status') 1407 args.append("status")
1400 args.append('--verbose') 1408 args.append("--verbose")
1401 args.append('--non-interactive') 1409 args.append("--non-interactive")
1402 args.append(dname) 1410 args.append(dname)
1403 process.start('svn', args) 1411 process.start("svn", args)
1404 procStarted = process.waitForStarted(5000) 1412 procStarted = process.waitForStarted(5000)
1405 if procStarted: 1413 if procStarted:
1406 finished = process.waitForFinished(30000) 1414 finished = process.waitForFinished(30000)
1407 if finished and process.exitCode() == 0: 1415 if finished and process.exitCode() == 0:
1408 output = str(process.readAllStandardOutput(), ioEncoding, 1416 output = str(process.readAllStandardOutput(), ioEncoding, "replace")
1409 'replace')
1410 for line in output.splitlines(): 1417 for line in output.splitlines():
1411 match = self.rx_status1.fullmatch(line) 1418 match = self.rx_status1.fullmatch(line)
1412 if match is not None: 1419 if match is not None:
1413 flags = match.group(1) 1420 flags = match.group(1)
1414 path = match.group(5).strip() 1421 path = match.group(5).strip()
1424 if name in names: 1431 if name in names:
1425 names[name] = self.canBeCommitted 1432 names[name] = self.canBeCommitted
1426 self.statusCache[name] = self.canBeCommitted 1433 self.statusCache[name] = self.canBeCommitted
1427 else: 1434 else:
1428 self.statusCache[name] = self.canBeAdded 1435 self.statusCache[name] = self.canBeAdded
1429 1436
1430 return names 1437 return names
1431 1438
1432 def __vcsAllRegisteredStates_wc(self, names, dname, shortcut=True): 1439 def __vcsAllRegisteredStates_wc(self, names, dname, shortcut=True):
1433 """ 1440 """
1434 Private method used to get the registered states of a number of files 1441 Private method used to get the registered states of a number of files
1435 in the VCS. 1442 in the VCS.
1436 1443
1437 This is the variant for subversion installations using the old working 1444 This is the variant for subversion installations using the old working
1438 copy meta-data format. 1445 copy meta-data format.
1439 1446
1440 <b>Note:</b> If a shortcut is to be taken, the code will only check, 1447 <b>Note:</b> If a shortcut is to be taken, the code will only check,
1441 if the named directory has been scanned already. If so, it is assumed, 1448 if the named directory has been scanned already. If so, it is assumed,
1442 that the states for all files has been populated by the previous run. 1449 that the states for all files has been populated by the previous run.
1443 1450
1444 @param names dictionary with all filenames to be checked as keys 1451 @param names dictionary with all filenames to be checked as keys
1445 @param dname directory to check in (string) 1452 @param dname directory to check in (string)
1446 @param shortcut flag indicating a shortcut should be taken (boolean) 1453 @param shortcut flag indicating a shortcut should be taken (boolean)
1447 @return the received dictionary completed with a combination of 1454 @return the received dictionary completed with a combination of
1448 canBeCommited and canBeAdded or None in order to signal an error 1455 canBeCommited and canBeAdded or None in order to signal an error
1449 """ 1456 """
1450 if not os.path.isdir(os.path.join(dname, self.adminDir)): 1457 if not os.path.isdir(os.path.join(dname, self.adminDir)):
1451 # not under version control -> do nothing 1458 # not under version control -> do nothing
1452 return names 1459 return names
1453 1460
1454 found = False 1461 found = False
1455 for name in list(self.statusCache.keys()): 1462 for name in list(self.statusCache.keys()):
1456 if os.path.dirname(name) == dname: 1463 if os.path.dirname(name) == dname:
1457 if shortcut: 1464 if shortcut:
1458 found = True 1465 found = True
1459 break 1466 break
1460 if name in names: 1467 if name in names:
1461 found = True 1468 found = True
1462 names[name] = self.statusCache[name] 1469 names[name] = self.statusCache[name]
1463 1470
1464 if not found: 1471 if not found:
1465 ioEncoding = Preferences.getSystem("IOEncoding") 1472 ioEncoding = Preferences.getSystem("IOEncoding")
1466 process = QProcess() 1473 process = QProcess()
1467 args = [] 1474 args = []
1468 args.append('status') 1475 args.append("status")
1469 args.append('--verbose') 1476 args.append("--verbose")
1470 args.append('--non-interactive') 1477 args.append("--non-interactive")
1471 args.append(dname) 1478 args.append(dname)
1472 process.start('svn', args) 1479 process.start("svn", args)
1473 procStarted = process.waitForStarted(5000) 1480 procStarted = process.waitForStarted(5000)
1474 if procStarted: 1481 if procStarted:
1475 finished = process.waitForFinished(30000) 1482 finished = process.waitForFinished(30000)
1476 if finished and process.exitCode() == 0: 1483 if finished and process.exitCode() == 0:
1477 output = str(process.readAllStandardOutput(), ioEncoding, 1484 output = str(process.readAllStandardOutput(), ioEncoding, "replace")
1478 'replace')
1479 for line in output.splitlines(): 1485 for line in output.splitlines():
1480 match = self.rx_status1.fullmatch(line) 1486 match = self.rx_status1.fullmatch(line)
1481 if match is not None: 1487 if match is not None:
1482 flags = match.group(1) 1488 flags = match.group(1)
1483 path = match.group(5).strip() 1489 path = match.group(5).strip()
1493 if name in names: 1499 if name in names:
1494 names[name] = self.canBeCommitted 1500 names[name] = self.canBeCommitted
1495 self.statusCache[name] = self.canBeCommitted 1501 self.statusCache[name] = self.canBeCommitted
1496 else: 1502 else:
1497 self.statusCache[name] = self.canBeAdded 1503 self.statusCache[name] = self.canBeAdded
1498 1504
1499 return names 1505 return names
1500 1506
1501 def clearStatusCache(self): 1507 def clearStatusCache(self):
1502 """ 1508 """
1503 Public method to clear the status cache. 1509 Public method to clear the status cache.
1504 """ 1510 """
1505 self.statusCache = {} 1511 self.statusCache = {}
1506 1512
1507 def vcsInitConfig(self, project): 1513 def vcsInitConfig(self, project):
1508 """ 1514 """
1509 Public method to initialize the VCS configuration. 1515 Public method to initialize the VCS configuration.
1510 1516
1511 This method ensures, that an ignore file exists. 1517 This method ensures, that an ignore file exists.
1512 1518
1513 @param project reference to the project (Project) 1519 @param project reference to the project (Project)
1514 """ 1520 """
1515 configPath = getConfigPath() 1521 configPath = getConfigPath()
1516 if os.path.exists(configPath): 1522 if os.path.exists(configPath):
1517 amendConfig() 1523 amendConfig()
1518 else: 1524 else:
1519 createDefaultConfig() 1525 createDefaultConfig()
1520 1526
1521 def vcsName(self): 1527 def vcsName(self):
1522 """ 1528 """
1523 Public method returning the name of the vcs. 1529 Public method returning the name of the vcs.
1524 1530
1525 @return always 'Subversion' (string) 1531 @return always 'Subversion' (string)
1526 """ 1532 """
1527 return "Subversion" 1533 return "Subversion"
1528 1534
1529 def vcsCleanup(self, name): 1535 def vcsCleanup(self, name):
1530 """ 1536 """
1531 Public method used to cleanup the working copy. 1537 Public method used to cleanup the working copy.
1532 1538
1533 @param name directory name to be cleaned up (string) 1539 @param name directory name to be cleaned up (string)
1534 """ 1540 """
1535 args = [] 1541 args = []
1536 args.append('cleanup') 1542 args.append("cleanup")
1537 self.addArguments(args, self.options['global']) 1543 self.addArguments(args, self.options["global"])
1538 args.append(name) 1544 args.append(name)
1539 1545
1540 dia = SvnDialog(self.tr('Cleaning up {0}') 1546 dia = SvnDialog(self.tr("Cleaning up {0}").format(name))
1541 .format(name))
1542 res = dia.startProcess(args) 1547 res = dia.startProcess(args)
1543 if res: 1548 if res:
1544 dia.exec() 1549 dia.exec()
1545 1550
1546 def vcsCommandLine(self, name): 1551 def vcsCommandLine(self, name):
1547 """ 1552 """
1548 Public method used to execute arbitrary subversion commands. 1553 Public method used to execute arbitrary subversion commands.
1549 1554
1550 @param name directory name of the working directory (string) 1555 @param name directory name of the working directory (string)
1551 """ 1556 """
1552 from .SvnCommandDialog import SvnCommandDialog 1557 from .SvnCommandDialog import SvnCommandDialog
1558
1553 dlg = SvnCommandDialog(self.commandHistory, self.wdHistory, name) 1559 dlg = SvnCommandDialog(self.commandHistory, self.wdHistory, name)
1554 if dlg.exec() == QDialog.DialogCode.Accepted: 1560 if dlg.exec() == QDialog.DialogCode.Accepted:
1555 command, wd = dlg.getData() 1561 command, wd = dlg.getData()
1556 commandList = Utilities.parseOptionString(command) 1562 commandList = Utilities.parseOptionString(command)
1557 1563
1558 # This moves any previous occurrence of these arguments to the head 1564 # This moves any previous occurrence of these arguments to the head
1559 # of the list. 1565 # of the list.
1560 if command in self.commandHistory: 1566 if command in self.commandHistory:
1561 self.commandHistory.remove(command) 1567 self.commandHistory.remove(command)
1562 self.commandHistory.insert(0, command) 1568 self.commandHistory.insert(0, command)
1563 if wd in self.wdHistory: 1569 if wd in self.wdHistory:
1564 self.wdHistory.remove(wd) 1570 self.wdHistory.remove(wd)
1565 self.wdHistory.insert(0, wd) 1571 self.wdHistory.insert(0, wd)
1566 1572
1567 args = [] 1573 args = []
1568 self.addArguments(args, commandList) 1574 self.addArguments(args, commandList)
1569 1575
1570 dia = SvnDialog(self.tr('Subversion command')) 1576 dia = SvnDialog(self.tr("Subversion command"))
1571 res = dia.startProcess(args, wd) 1577 res = dia.startProcess(args, wd)
1572 if res: 1578 if res:
1573 dia.exec() 1579 dia.exec()
1574 1580
1575 def vcsOptionsDialog(self, project, archive, editable=False, parent=None): 1581 def vcsOptionsDialog(self, project, archive, editable=False, parent=None):
1576 """ 1582 """
1577 Public method to get a dialog to enter repository info. 1583 Public method to get a dialog to enter repository info.
1578 1584
1579 @param project reference to the project object 1585 @param project reference to the project object
1580 @param archive name of the project in the repository (string) 1586 @param archive name of the project in the repository (string)
1581 @param editable flag indicating that the project name is editable 1587 @param editable flag indicating that the project name is editable
1582 (boolean) 1588 (boolean)
1583 @param parent parent widget (QWidget) 1589 @param parent parent widget (QWidget)
1584 @return reference to the instantiated options dialog (SvnOptionsDialog) 1590 @return reference to the instantiated options dialog (SvnOptionsDialog)
1585 """ 1591 """
1586 from .SvnOptionsDialog import SvnOptionsDialog 1592 from .SvnOptionsDialog import SvnOptionsDialog
1593
1587 return SvnOptionsDialog(self, project, parent) 1594 return SvnOptionsDialog(self, project, parent)
1588 1595
1589 def vcsNewProjectOptionsDialog(self, parent=None): 1596 def vcsNewProjectOptionsDialog(self, parent=None):
1590 """ 1597 """
1591 Public method to get a dialog to enter repository info for getting 1598 Public method to get a dialog to enter repository info for getting
1592 a new project. 1599 a new project.
1593 1600
1594 @param parent parent widget (QWidget) 1601 @param parent parent widget (QWidget)
1595 @return reference to the instantiated options dialog 1602 @return reference to the instantiated options dialog
1596 (SvnNewProjectOptionsDialog) 1603 (SvnNewProjectOptionsDialog)
1597 """ 1604 """
1598 from .SvnNewProjectOptionsDialog import SvnNewProjectOptionsDialog 1605 from .SvnNewProjectOptionsDialog import SvnNewProjectOptionsDialog
1606
1599 return SvnNewProjectOptionsDialog(self, parent) 1607 return SvnNewProjectOptionsDialog(self, parent)
1600 1608
1601 def vcsRepositoryInfos(self, ppath): 1609 def vcsRepositoryInfos(self, ppath):
1602 """ 1610 """
1603 Public method to retrieve information about the repository. 1611 Public method to retrieve information about the repository.
1604 1612
1605 @param ppath local path to get the repository infos (string) 1613 @param ppath local path to get the repository infos (string)
1606 @return string with ready formated info for display (string) 1614 @return string with ready formated info for display (string)
1607 """ 1615 """
1608 info = { 1616 info = {
1609 'committed-rev': '', 1617 "committed-rev": "",
1610 'committed-date': '', 1618 "committed-date": "",
1611 'committed-time': '', 1619 "committed-time": "",
1612 'url': '', 1620 "url": "",
1613 'last-author': '', 1621 "last-author": "",
1614 'revision': '' 1622 "revision": "",
1615 } 1623 }
1616 1624
1617 ioEncoding = Preferences.getSystem("IOEncoding") 1625 ioEncoding = Preferences.getSystem("IOEncoding")
1618 1626
1619 process = QProcess() 1627 process = QProcess()
1620 args = [] 1628 args = []
1621 args.append('info') 1629 args.append("info")
1622 args.append('--non-interactive') 1630 args.append("--non-interactive")
1623 args.append('--xml') 1631 args.append("--xml")
1624 args.append(ppath) 1632 args.append(ppath)
1625 process.start('svn', args) 1633 process.start("svn", args)
1626 procStarted = process.waitForStarted(5000) 1634 procStarted = process.waitForStarted(5000)
1627 if procStarted: 1635 if procStarted:
1628 finished = process.waitForFinished(30000) 1636 finished = process.waitForFinished(30000)
1629 if finished and process.exitCode() == 0: 1637 if finished and process.exitCode() == 0:
1630 output = str(process.readAllStandardOutput(), ioEncoding, 1638 output = str(process.readAllStandardOutput(), ioEncoding, "replace")
1631 'replace')
1632 entryFound = False 1639 entryFound = False
1633 commitFound = False 1640 commitFound = False
1634 for line in output.splitlines(): 1641 for line in output.splitlines():
1635 line = line.strip() 1642 line = line.strip()
1636 if line.startswith('<entry'): 1643 if line.startswith("<entry"):
1637 entryFound = True 1644 entryFound = True
1638 elif line.startswith('<commit'): 1645 elif line.startswith("<commit"):
1639 commitFound = True 1646 commitFound = True
1640 elif line.startswith('</commit>'): 1647 elif line.startswith("</commit>"):
1641 commitFound = False 1648 commitFound = False
1642 elif line.startswith("revision="): 1649 elif line.startswith("revision="):
1643 rev = line[line.find('"') + 1:line.rfind('"')] 1650 rev = line[line.find('"') + 1 : line.rfind('"')]
1644 if entryFound: 1651 if entryFound:
1645 info['revision'] = rev 1652 info["revision"] = rev
1646 entryFound = False 1653 entryFound = False
1647 elif commitFound: 1654 elif commitFound:
1648 info['committed-rev'] = rev 1655 info["committed-rev"] = rev
1649 elif line.startswith('<url>'): 1656 elif line.startswith("<url>"):
1650 info['url'] = ( 1657 info["url"] = line.replace("<url>", "").replace("</url>", "")
1651 line.replace('<url>', '').replace('</url>', '') 1658 elif line.startswith("<author>"):
1659 info["last-author"] = line.replace("<author>", "").replace(
1660 "</author>", ""
1652 ) 1661 )
1653 elif line.startswith('<author>'): 1662 elif line.startswith("<date>"):
1654 info['last-author'] = ( 1663 value = line.replace("<date>", "").replace("</date>", "")
1655 line.replace('<author>', '') 1664 date, time = value.split("T")
1656 .replace('</author>', '') 1665 info["committed-date"] = date
1666 info["committed-time"] = "{0}{1}".format(
1667 time.split(".")[0], time[-1]
1657 ) 1668 )
1658 elif line.startswith('<date>'): 1669
1659 value = (
1660 line.replace('<date>', '').replace('</date>', '')
1661 )
1662 date, time = value.split('T')
1663 info['committed-date'] = date
1664 info['committed-time'] = "{0}{1}".format(
1665 time.split('.')[0], time[-1])
1666
1667 return QCoreApplication.translate( 1670 return QCoreApplication.translate(
1668 'subversion', 1671 "subversion",
1669 """<h3>Repository information</h3>""" 1672 """<h3>Repository information</h3>"""
1670 """<table>""" 1673 """<table>"""
1671 """<tr><td><b>Subversion V.</b></td><td>{0}</td></tr>""" 1674 """<tr><td><b>Subversion V.</b></td><td>{0}</td></tr>"""
1672 """<tr><td><b>URL</b></td><td>{1}</td></tr>""" 1675 """<tr><td><b>URL</b></td><td>{1}</td></tr>"""
1673 """<tr><td><b>Current revision</b></td><td>{2}</td></tr>""" 1676 """<tr><td><b>Current revision</b></td><td>{2}</td></tr>"""
1674 """<tr><td><b>Committed revision</b></td><td>{3}</td></tr>""" 1677 """<tr><td><b>Committed revision</b></td><td>{3}</td></tr>"""
1675 """<tr><td><b>Committed date</b></td><td>{4}</td></tr>""" 1678 """<tr><td><b>Committed date</b></td><td>{4}</td></tr>"""
1676 """<tr><td><b>Comitted time</b></td><td>{5}</td></tr>""" 1679 """<tr><td><b>Comitted time</b></td><td>{5}</td></tr>"""
1677 """<tr><td><b>Last author</b></td><td>{6}</td></tr>""" 1680 """<tr><td><b>Last author</b></td><td>{6}</td></tr>"""
1678 """</table>""" 1681 """</table>""",
1679 ).format(self.versionStr, 1682 ).format(
1680 info['url'], 1683 self.versionStr,
1681 info['revision'], 1684 info["url"],
1682 info['committed-rev'], 1685 info["revision"],
1683 info['committed-date'], 1686 info["committed-rev"],
1684 info['committed-time'], 1687 info["committed-date"],
1685 info['last-author']) 1688 info["committed-time"],
1686 1689 info["last-author"],
1690 )
1691
1687 ########################################################################### 1692 ###########################################################################
1688 ## Public Subversion specific methods are below. 1693 ## Public Subversion specific methods are below.
1689 ########################################################################### 1694 ###########################################################################
1690 1695
1691 def svnGetReposName(self, path): 1696 def svnGetReposName(self, path):
1692 """ 1697 """
1693 Public method used to retrieve the URL of the subversion repository 1698 Public method used to retrieve the URL of the subversion repository
1694 path. 1699 path.
1695 1700
1696 @param path local path to get the svn repository path for (string) 1701 @param path local path to get the svn repository path for (string)
1697 @return string with the repository path URL 1702 @return string with the repository path URL
1698 """ 1703 """
1699 ioEncoding = Preferences.getSystem("IOEncoding") 1704 ioEncoding = Preferences.getSystem("IOEncoding")
1700 1705
1701 process = QProcess() 1706 process = QProcess()
1702 args = [] 1707 args = []
1703 args.append('info') 1708 args.append("info")
1704 args.append('--xml') 1709 args.append("--xml")
1705 args.append('--non-interactive') 1710 args.append("--non-interactive")
1706 args.append(path) 1711 args.append(path)
1707 process.start('svn', args) 1712 process.start("svn", args)
1708 procStarted = process.waitForStarted(5000) 1713 procStarted = process.waitForStarted(5000)
1709 if procStarted: 1714 if procStarted:
1710 finished = process.waitForFinished(30000) 1715 finished = process.waitForFinished(30000)
1711 if finished and process.exitCode() == 0: 1716 if finished and process.exitCode() == 0:
1712 output = str(process.readAllStandardOutput(), ioEncoding, 1717 output = str(process.readAllStandardOutput(), ioEncoding, "replace")
1713 'replace')
1714 for line in output.splitlines(): 1718 for line in output.splitlines():
1715 line = line.strip() 1719 line = line.strip()
1716 if line.startswith('<url>'): 1720 if line.startswith("<url>"):
1717 reposURL = ( 1721 reposURL = line.replace("<url>", "").replace("</url>", "")
1718 line.replace('<url>', '').replace('</url>', '')
1719 )
1720 return reposURL 1722 return reposURL
1721 1723
1722 return "" 1724 return ""
1723 1725
1724 def vcsResolved(self, name): 1726 def vcsResolved(self, name):
1725 """ 1727 """
1726 Public method used to resolve conflicts of a file/directory. 1728 Public method used to resolve conflicts of a file/directory.
1727 1729
1728 @param name file/directory name to be resolved (string) 1730 @param name file/directory name to be resolved (string)
1729 """ 1731 """
1730 args = [] 1732 args = []
1731 if self.version >= (1, 5, 0): 1733 if self.version >= (1, 5, 0):
1732 args.append('resolve') 1734 args.append("resolve")
1733 args.append('--accept') 1735 args.append("--accept")
1734 args.append('working') 1736 args.append("working")
1735 else: 1737 else:
1736 args.append('resolved') 1738 args.append("resolved")
1737 self.addArguments(args, self.options['global']) 1739 self.addArguments(args, self.options["global"])
1738 if isinstance(name, list): 1740 if isinstance(name, list):
1739 self.addArguments(args, name) 1741 self.addArguments(args, name)
1740 else: 1742 else:
1741 if os.path.isdir(name): 1743 if os.path.isdir(name):
1742 args.append('--recursive') 1744 args.append("--recursive")
1743 args.append(name) 1745 args.append(name)
1744 1746
1745 dia = SvnDialog(self.tr('Resolving conficts')) 1747 dia = SvnDialog(self.tr("Resolving conficts"))
1746 res = dia.startProcess(args) 1748 res = dia.startProcess(args)
1747 if res: 1749 if res:
1748 dia.exec() 1750 dia.exec()
1749 self.checkVCSStatus() 1751 self.checkVCSStatus()
1750 1752
1751 def svnCopy(self, name, project): 1753 def svnCopy(self, name, project):
1752 """ 1754 """
1753 Public method used to copy a file/directory. 1755 Public method used to copy a file/directory.
1754 1756
1755 @param name file/directory name to be copied (string) 1757 @param name file/directory name to be copied (string)
1756 @param project reference to the project object 1758 @param project reference to the project object
1757 @return flag indicating successfull operation (boolean) 1759 @return flag indicating successfull operation (boolean)
1758 """ 1760 """
1759 from .SvnCopyDialog import SvnCopyDialog 1761 from .SvnCopyDialog import SvnCopyDialog
1760 rx_prot = re.compile('(file:|svn:|svn+ssh:|http:|https:).+') 1762
1763 rx_prot = re.compile("(file:|svn:|svn+ssh:|http:|https:).+")
1761 dlg = SvnCopyDialog(name) 1764 dlg = SvnCopyDialog(name)
1762 res = False 1765 res = False
1763 if dlg.exec() == QDialog.DialogCode.Accepted: 1766 if dlg.exec() == QDialog.DialogCode.Accepted:
1764 target, force = dlg.getData() 1767 target, force = dlg.getData()
1765 1768
1766 args = [] 1769 args = []
1767 args.append('copy') 1770 args.append("copy")
1768 self.addArguments(args, self.options['global']) 1771 self.addArguments(args, self.options["global"])
1769 match = rx_prot.fullmatch(target) 1772 match = rx_prot.fullmatch(target)
1770 if match is not None: 1773 if match is not None:
1771 args.append('--message') 1774 args.append("--message")
1772 args.append('Copying {0} to {1}'.format(name, target)) 1775 args.append("Copying {0} to {1}".format(name, target))
1773 target = self.__svnURL(target) 1776 target = self.__svnURL(target)
1774 args.append(name) 1777 args.append(name)
1775 args.append(target) 1778 args.append(target)
1776 1779
1777 dia = SvnDialog(self.tr('Copying {0}') 1780 dia = SvnDialog(self.tr("Copying {0}").format(name))
1778 .format(name))
1779 res = dia.startProcess(args) 1781 res = dia.startProcess(args)
1780 if res: 1782 if res:
1781 dia.exec() 1783 dia.exec()
1782 res = dia.normalExit() 1784 res = dia.normalExit()
1783 if ( 1785 if (
1784 res and 1786 res
1785 match is None and 1787 and match is None
1786 target.startswith(project.getProjectPath()) 1788 and target.startswith(project.getProjectPath())
1787 ): 1789 ):
1788 if os.path.isdir(name): 1790 if os.path.isdir(name):
1789 project.copyDirectory(name, target) 1791 project.copyDirectory(name, target)
1790 else: 1792 else:
1791 project.appendFile(target) 1793 project.appendFile(target)
1792 return res 1794 return res
1793 1795
1794 def svnListProps(self, name, recursive=False): 1796 def svnListProps(self, name, recursive=False):
1795 """ 1797 """
1796 Public method used to list the properties of a file/directory. 1798 Public method used to list the properties of a file/directory.
1797 1799
1798 @param name file/directory name (string or list of strings) 1800 @param name file/directory name (string or list of strings)
1799 @param recursive flag indicating a recursive list is requested 1801 @param recursive flag indicating a recursive list is requested
1800 """ 1802 """
1801 if self.propList is None: 1803 if self.propList is None:
1802 from .SvnPropListDialog import SvnPropListDialog 1804 from .SvnPropListDialog import SvnPropListDialog
1805
1803 self.propList = SvnPropListDialog(self) 1806 self.propList = SvnPropListDialog(self)
1804 self.propList.show() 1807 self.propList.show()
1805 self.propList.raise_() 1808 self.propList.raise_()
1806 self.propList.start(name, recursive) 1809 self.propList.start(name, recursive)
1807 1810
1808 def svnSetProp(self, name, recursive=False): 1811 def svnSetProp(self, name, recursive=False):
1809 """ 1812 """
1810 Public method used to add a property to a file/directory. 1813 Public method used to add a property to a file/directory.
1811 1814
1812 @param name file/directory name (string or list of strings) 1815 @param name file/directory name (string or list of strings)
1813 @param recursive flag indicating a recursive list is requested 1816 @param recursive flag indicating a recursive list is requested
1814 """ 1817 """
1815 from .SvnPropSetDialog import SvnPropSetDialog 1818 from .SvnPropSetDialog import SvnPropSetDialog
1819
1816 dlg = SvnPropSetDialog() 1820 dlg = SvnPropSetDialog()
1817 if dlg.exec() == QDialog.DialogCode.Accepted: 1821 if dlg.exec() == QDialog.DialogCode.Accepted:
1818 propName, fileFlag, propValue = dlg.getData() 1822 propName, fileFlag, propValue = dlg.getData()
1819 if not propName: 1823 if not propName:
1820 EricMessageBox.critical( 1824 EricMessageBox.critical(
1821 self.__ui, 1825 self.__ui,
1822 self.tr("Subversion Set Property"), 1826 self.tr("Subversion Set Property"),
1823 self.tr("""You have to supply a property name.""" 1827 self.tr("""You have to supply a property name.""" """ Aborting."""),
1824 """ Aborting.""")) 1828 )
1825 return 1829 return
1826 1830
1827 args = [] 1831 args = []
1828 args.append('propset') 1832 args.append("propset")
1829 self.addArguments(args, self.options['global']) 1833 self.addArguments(args, self.options["global"])
1830 if recursive: 1834 if recursive:
1831 args.append('--recursive') 1835 args.append("--recursive")
1832 args.append(propName) 1836 args.append(propName)
1833 if fileFlag: 1837 if fileFlag:
1834 args.append('--file') 1838 args.append("--file")
1835 args.append(propValue) 1839 args.append(propValue)
1836 if isinstance(name, list): 1840 if isinstance(name, list):
1837 dname, fnames = self.splitPathList(name) 1841 dname, fnames = self.splitPathList(name)
1838 self.addArguments(args, fnames) 1842 self.addArguments(args, fnames)
1839 else: 1843 else:
1840 dname, fname = self.splitPath(name) 1844 dname, fname = self.splitPath(name)
1841 args.append(fname) 1845 args.append(fname)
1842 1846
1843 dia = SvnDialog(self.tr('Subversion Set Property')) 1847 dia = SvnDialog(self.tr("Subversion Set Property"))
1844 res = dia.startProcess(args, dname) 1848 res = dia.startProcess(args, dname)
1845 if res: 1849 if res:
1846 dia.exec() 1850 dia.exec()
1847 1851
1848 def svnDelProp(self, name, recursive=False): 1852 def svnDelProp(self, name, recursive=False):
1849 """ 1853 """
1850 Public method used to delete a property of a file/directory. 1854 Public method used to delete a property of a file/directory.
1851 1855
1852 @param name file/directory name (string or list of strings) 1856 @param name file/directory name (string or list of strings)
1853 @param recursive flag indicating a recursive list is requested 1857 @param recursive flag indicating a recursive list is requested
1854 """ 1858 """
1855 propName, ok = QInputDialog.getText( 1859 propName, ok = QInputDialog.getText(
1856 None, 1860 None,
1857 self.tr("Subversion Delete Property"), 1861 self.tr("Subversion Delete Property"),
1858 self.tr("Enter property name"), 1862 self.tr("Enter property name"),
1859 QLineEdit.EchoMode.Normal) 1863 QLineEdit.EchoMode.Normal,
1860 1864 )
1865
1861 if not ok: 1866 if not ok:
1862 return 1867 return
1863 1868
1864 if not propName: 1869 if not propName:
1865 EricMessageBox.critical( 1870 EricMessageBox.critical(
1866 self.__ui, 1871 self.__ui,
1867 self.tr("Subversion Delete Property"), 1872 self.tr("Subversion Delete Property"),
1868 self.tr("""You have to supply a property name.""" 1873 self.tr("""You have to supply a property name.""" """ Aborting."""),
1869 """ Aborting.""")) 1874 )
1870 return 1875 return
1871 1876
1872 args = [] 1877 args = []
1873 args.append('propdel') 1878 args.append("propdel")
1874 self.addArguments(args, self.options['global']) 1879 self.addArguments(args, self.options["global"])
1875 if recursive: 1880 if recursive:
1876 args.append('--recursive') 1881 args.append("--recursive")
1877 args.append(propName) 1882 args.append(propName)
1878 if isinstance(name, list): 1883 if isinstance(name, list):
1879 dname, fnames = self.splitPathList(name) 1884 dname, fnames = self.splitPathList(name)
1880 self.addArguments(args, fnames) 1885 self.addArguments(args, fnames)
1881 else: 1886 else:
1882 dname, fname = self.splitPath(name) 1887 dname, fname = self.splitPath(name)
1883 args.append(fname) 1888 args.append(fname)
1884 1889
1885 dia = SvnDialog(self.tr('Subversion Delete Property')) 1890 dia = SvnDialog(self.tr("Subversion Delete Property"))
1886 res = dia.startProcess(args, dname) 1891 res = dia.startProcess(args, dname)
1887 if res: 1892 if res:
1888 dia.exec() 1893 dia.exec()
1889 1894
1890 def svnListTagBranch(self, path, tags=True): 1895 def svnListTagBranch(self, path, tags=True):
1891 """ 1896 """
1892 Public method used to list the available tags or branches. 1897 Public method used to list the available tags or branches.
1893 1898
1894 @param path directory name of the project (string) 1899 @param path directory name of the project (string)
1895 @param tags flag indicating listing of branches or tags 1900 @param tags flag indicating listing of branches or tags
1896 (False = branches, True = tags) 1901 (False = branches, True = tags)
1897 """ 1902 """
1898 if self.tagbranchList is None: 1903 if self.tagbranchList is None:
1899 from .SvnTagBranchListDialog import SvnTagBranchListDialog 1904 from .SvnTagBranchListDialog import SvnTagBranchListDialog
1905
1900 self.tagbranchList = SvnTagBranchListDialog(self) 1906 self.tagbranchList = SvnTagBranchListDialog(self)
1901 self.tagbranchList.show() 1907 self.tagbranchList.show()
1902 self.tagbranchList.raise_() 1908 self.tagbranchList.raise_()
1903 if tags: 1909 if tags:
1904 if not self.showedTags: 1910 if not self.showedTags:
1905 self.showedTags = True 1911 self.showedTags = True
1906 allTagsBranchesList = self.allTagsBranchesList 1912 allTagsBranchesList = self.allTagsBranchesList
1907 else: 1913 else:
1908 self.tagsList = [] 1914 self.tagsList = []
1909 allTagsBranchesList = None 1915 allTagsBranchesList = None
1910 self.tagbranchList.start(path, tags, 1916 self.tagbranchList.start(path, tags, self.tagsList, allTagsBranchesList)
1911 self.tagsList, allTagsBranchesList)
1912 elif not tags: 1917 elif not tags:
1913 if not self.showedBranches: 1918 if not self.showedBranches:
1914 self.showedBranches = True 1919 self.showedBranches = True
1915 allTagsBranchesList = self.allTagsBranchesList 1920 allTagsBranchesList = self.allTagsBranchesList
1916 else: 1921 else:
1917 self.branchesList = [] 1922 self.branchesList = []
1918 allTagsBranchesList = None 1923 allTagsBranchesList = None
1919 self.tagbranchList.start( 1924 self.tagbranchList.start(
1920 path, tags, self.branchesList, self.allTagsBranchesList) 1925 path, tags, self.branchesList, self.allTagsBranchesList
1921 1926 )
1927
1922 def svnBlame(self, name): 1928 def svnBlame(self, name):
1923 """ 1929 """
1924 Public method to show the output of the svn blame command. 1930 Public method to show the output of the svn blame command.
1925 1931
1926 @param name file name to show the blame for (string) 1932 @param name file name to show the blame for (string)
1927 """ 1933 """
1928 if self.blame is None: 1934 if self.blame is None:
1929 from .SvnBlameDialog import SvnBlameDialog 1935 from .SvnBlameDialog import SvnBlameDialog
1936
1930 self.blame = SvnBlameDialog(self) 1937 self.blame = SvnBlameDialog(self)
1931 self.blame.show() 1938 self.blame.show()
1932 self.blame.raise_() 1939 self.blame.raise_()
1933 self.blame.start(name) 1940 self.blame.start(name)
1934 1941
1935 def svnExtendedDiff(self, name): 1942 def svnExtendedDiff(self, name):
1936 """ 1943 """
1937 Public method used to view the difference of a file/directory to the 1944 Public method used to view the difference of a file/directory to the
1938 Subversion repository. 1945 Subversion repository.
1939 1946
1940 If name is a directory and is the project directory, all project files 1947 If name is a directory and is the project directory, all project files
1941 are saved first. If name is a file (or list of files), which is/are 1948 are saved first. If name is a file (or list of files), which is/are
1942 being edited and has unsaved modification, they can be saved or the 1949 being edited and has unsaved modification, they can be saved or the
1943 operation may be aborted. 1950 operation may be aborted.
1944 1951
1945 This method gives the chance to enter the revisions to be compared. 1952 This method gives the chance to enter the revisions to be compared.
1946 1953
1947 @param name file/directory name to be diffed (string) 1954 @param name file/directory name to be diffed (string)
1948 """ 1955 """
1949 names = name[:] if isinstance(name, list) else [name] 1956 names = name[:] if isinstance(name, list) else [name]
1950 for nam in names: 1957 for nam in names:
1951 if os.path.isfile(nam): 1958 if os.path.isfile(nam):
1955 else: 1962 else:
1956 project = ericApp().getObject("Project") 1963 project = ericApp().getObject("Project")
1957 if nam == project.ppath and not project.saveAllScripts(): 1964 if nam == project.ppath and not project.saveAllScripts():
1958 return 1965 return
1959 from .SvnRevisionSelectionDialog import SvnRevisionSelectionDialog 1966 from .SvnRevisionSelectionDialog import SvnRevisionSelectionDialog
1967
1960 dlg = SvnRevisionSelectionDialog() 1968 dlg = SvnRevisionSelectionDialog()
1961 if dlg.exec() == QDialog.DialogCode.Accepted: 1969 if dlg.exec() == QDialog.DialogCode.Accepted:
1962 revisions = dlg.getRevisions() 1970 revisions = dlg.getRevisions()
1963 from .SvnDiffDialog import SvnDiffDialog 1971 from .SvnDiffDialog import SvnDiffDialog
1972
1964 self.diff = SvnDiffDialog(self) 1973 self.diff = SvnDiffDialog(self)
1965 self.diff.show() 1974 self.diff.show()
1966 self.diff.start(name, revisions) 1975 self.diff.start(name, revisions)
1967 1976
1968 def svnUrlDiff(self, name): 1977 def svnUrlDiff(self, name):
1969 """ 1978 """
1970 Public method used to view the difference of a file/directory of two 1979 Public method used to view the difference of a file/directory of two
1971 repository URLs. 1980 repository URLs.
1972 1981
1973 If name is a directory and is the project directory, all project files 1982 If name is a directory and is the project directory, all project files
1974 are saved first. If name is a file (or list of files), which is/are 1983 are saved first. If name is a file (or list of files), which is/are
1975 being edited and has unsaved modification, they can be saved or the 1984 being edited and has unsaved modification, they can be saved or the
1976 operation may be aborted. 1985 operation may be aborted.
1977 1986
1978 This method gives the chance to enter the revisions to be compared. 1987 This method gives the chance to enter the revisions to be compared.
1979 1988
1980 @param name file/directory name to be diffed (string) 1989 @param name file/directory name to be diffed (string)
1981 """ 1990 """
1982 names = name[:] if isinstance(name, list) else [name] 1991 names = name[:] if isinstance(name, list) else [name]
1983 for nam in names: 1992 for nam in names:
1984 if os.path.isfile(nam): 1993 if os.path.isfile(nam):
1987 return 1996 return
1988 else: 1997 else:
1989 project = ericApp().getObject("Project") 1998 project = ericApp().getObject("Project")
1990 if nam == project.ppath and not project.saveAllScripts(): 1999 if nam == project.ppath and not project.saveAllScripts():
1991 return 2000 return
1992 2001
1993 dname = self.splitPath(names[0])[0] 2002 dname = self.splitPath(names[0])[0]
1994 2003
1995 from .SvnUrlSelectionDialog import SvnUrlSelectionDialog 2004 from .SvnUrlSelectionDialog import SvnUrlSelectionDialog
1996 dlg = SvnUrlSelectionDialog(self, self.tagsList, self.branchesList, 2005
1997 dname) 2006 dlg = SvnUrlSelectionDialog(self, self.tagsList, self.branchesList, dname)
1998 if dlg.exec() == QDialog.DialogCode.Accepted: 2007 if dlg.exec() == QDialog.DialogCode.Accepted:
1999 urls, summary = dlg.getURLs() 2008 urls, summary = dlg.getURLs()
2000 from .SvnDiffDialog import SvnDiffDialog 2009 from .SvnDiffDialog import SvnDiffDialog
2010
2001 self.diff = SvnDiffDialog(self) 2011 self.diff = SvnDiffDialog(self)
2002 self.diff.show() 2012 self.diff.show()
2003 QApplication.processEvents() 2013 QApplication.processEvents()
2004 self.diff.start(name, urls=urls, summary=summary) 2014 self.diff.start(name, urls=urls, summary=summary)
2005 2015
2006 def __svnGetFileForRevision(self, name, rev=""): 2016 def __svnGetFileForRevision(self, name, rev=""):
2007 """ 2017 """
2008 Private method to get a file for a specific revision from the 2018 Private method to get a file for a specific revision from the
2009 repository. 2019 repository.
2010 2020
2011 @param name file name to get from the repository (string) 2021 @param name file name to get from the repository (string)
2012 @param rev revision to retrieve (integer or string) 2022 @param rev revision to retrieve (integer or string)
2013 @return contents of the file (string) and an error message (string) 2023 @return contents of the file (string) and an error message (string)
2014 """ 2024 """
2015 args = [] 2025 args = []
2016 args.append("cat") 2026 args.append("cat")
2017 if rev: 2027 if rev:
2018 args.append("--revision") 2028 args.append("--revision")
2019 args.append(str(rev)) 2029 args.append(str(rev))
2020 args.append(name) 2030 args.append(name)
2021 2031
2022 output = "" 2032 output = ""
2023 error = "" 2033 error = ""
2024 2034
2025 process = QProcess() 2035 process = QProcess()
2026 process.start('svn', args) 2036 process.start("svn", args)
2027 procStarted = process.waitForStarted(5000) 2037 procStarted = process.waitForStarted(5000)
2028 if procStarted: 2038 if procStarted:
2029 finished = process.waitForFinished(30000) 2039 finished = process.waitForFinished(30000)
2030 if finished: 2040 if finished:
2031 if process.exitCode() == 0: 2041 if process.exitCode() == 0:
2032 output = str( 2042 output = str(
2033 process.readAllStandardOutput(), 2043 process.readAllStandardOutput(),
2034 Preferences.getSystem("IOEncoding"), 'replace') 2044 Preferences.getSystem("IOEncoding"),
2045 "replace",
2046 )
2035 else: 2047 else:
2036 error = str( 2048 error = str(
2037 process.readAllStandardError(), 2049 process.readAllStandardError(),
2038 Preferences.getSystem("IOEncoding"), 'replace') 2050 Preferences.getSystem("IOEncoding"),
2051 "replace",
2052 )
2039 else: 2053 else:
2040 error = self.tr( 2054 error = self.tr("The svn process did not finish within 30s.")
2041 "The svn process did not finish within 30s.")
2042 else: 2055 else:
2043 error = self.tr( 2056 error = self.tr(
2044 'The process {0} could not be started. ' 2057 "The process {0} could not be started. "
2045 'Ensure, that it is in the search path.').format('svn') 2058 "Ensure, that it is in the search path."
2046 2059 ).format("svn")
2060
2047 return output, error 2061 return output, error
2048 2062
2049 def vcsSbsDiff(self, name, extended=False, revisions=None): 2063 def vcsSbsDiff(self, name, extended=False, revisions=None):
2050 """ 2064 """
2051 Public method used to view the difference of a file to the Mercurial 2065 Public method used to view the difference of a file to the Mercurial
2052 repository side-by-side. 2066 repository side-by-side.
2053 2067
2054 @param name file name to be diffed (string) 2068 @param name file name to be diffed (string)
2055 @param extended flag indicating the extended variant (boolean) 2069 @param extended flag indicating the extended variant (boolean)
2056 @param revisions tuple of two revisions (tuple of strings) 2070 @param revisions tuple of two revisions (tuple of strings)
2057 @exception ValueError raised to indicate an illegal name parameter type 2071 @exception ValueError raised to indicate an illegal name parameter type
2058 """ 2072 """
2059 if isinstance(name, list): 2073 if isinstance(name, list):
2060 raise ValueError("Wrong parameter type") 2074 raise ValueError("Wrong parameter type")
2061 2075
2062 if extended: 2076 if extended:
2063 from .SvnRevisionSelectionDialog import SvnRevisionSelectionDialog 2077 from .SvnRevisionSelectionDialog import SvnRevisionSelectionDialog
2078
2064 dlg = SvnRevisionSelectionDialog() 2079 dlg = SvnRevisionSelectionDialog()
2065 if dlg.exec() == QDialog.DialogCode.Accepted: 2080 if dlg.exec() == QDialog.DialogCode.Accepted:
2066 rev1, rev2 = dlg.getRevisions() 2081 rev1, rev2 = dlg.getRevisions()
2067 if rev1 == "WORKING": 2082 if rev1 == "WORKING":
2068 rev1 = "" 2083 rev1 = ""
2072 return 2087 return
2073 elif revisions: 2088 elif revisions:
2074 rev1, rev2 = revisions[0], revisions[1] 2089 rev1, rev2 = revisions[0], revisions[1]
2075 else: 2090 else:
2076 rev1, rev2 = "", "" 2091 rev1, rev2 = "", ""
2077 2092
2078 output1, error = self.__svnGetFileForRevision(name, rev=rev1) 2093 output1, error = self.__svnGetFileForRevision(name, rev=rev1)
2079 if error: 2094 if error:
2080 EricMessageBox.critical( 2095 EricMessageBox.critical(
2081 self.__ui, 2096 self.__ui, self.tr("Subversion Side-by-Side Difference"), error
2082 self.tr("Subversion Side-by-Side Difference"), 2097 )
2083 error)
2084 return 2098 return
2085 name1 = "{0} (rev. {1})".format(name, rev1 and rev1 or ".") 2099 name1 = "{0} (rev. {1})".format(name, rev1 and rev1 or ".")
2086 2100
2087 if rev2: 2101 if rev2:
2088 output2, error = self.__svnGetFileForRevision(name, rev=rev2) 2102 output2, error = self.__svnGetFileForRevision(name, rev=rev2)
2089 if error: 2103 if error:
2090 EricMessageBox.critical( 2104 EricMessageBox.critical(
2091 self.__ui, 2105 self.__ui, self.tr("Subversion Side-by-Side Difference"), error
2092 self.tr("Subversion Side-by-Side Difference"), 2106 )
2093 error)
2094 return 2107 return
2095 name2 = "{0} (rev. {1})".format(name, rev2) 2108 name2 = "{0} (rev. {1})".format(name, rev2)
2096 else: 2109 else:
2097 try: 2110 try:
2098 with open(name, "r", encoding="utf-8") as f1: 2111 with open(name, "r", encoding="utf-8") as f1:
2100 name2 = name 2113 name2 = name
2101 except OSError: 2114 except OSError:
2102 EricMessageBox.critical( 2115 EricMessageBox.critical(
2103 self.__ui, 2116 self.__ui,
2104 self.tr("Subversion Side-by-Side Difference"), 2117 self.tr("Subversion Side-by-Side Difference"),
2105 self.tr( 2118 self.tr("""<p>The file <b>{0}</b> could not be read.</p>""").format(
2106 """<p>The file <b>{0}</b> could not be read.</p>""") 2119 name
2107 .format(name)) 2120 ),
2121 )
2108 return 2122 return
2109 2123
2110 if self.sbsDiff is None: 2124 if self.sbsDiff is None:
2111 from UI.CompareDialog import CompareDialog 2125 from UI.CompareDialog import CompareDialog
2126
2112 self.sbsDiff = CompareDialog() 2127 self.sbsDiff = CompareDialog()
2113 self.sbsDiff.show() 2128 self.sbsDiff.show()
2114 self.sbsDiff.raise_() 2129 self.sbsDiff.raise_()
2115 self.sbsDiff.compare(output1, output2, name1, name2) 2130 self.sbsDiff.compare(output1, output2, name1, name2)
2116 2131
2117 def vcsLogBrowser(self, name, isFile=False): 2132 def vcsLogBrowser(self, name, isFile=False):
2118 """ 2133 """
2119 Public method used to browse the log of a file/directory from the 2134 Public method used to browse the log of a file/directory from the
2120 Subversion repository. 2135 Subversion repository.
2121 2136
2122 @param name file/directory name to show the log of (string) 2137 @param name file/directory name to show the log of (string)
2123 @param isFile flag indicating log for a file is to be shown (boolean) 2138 @param isFile flag indicating log for a file is to be shown (boolean)
2124 """ 2139 """
2125 if self.logBrowser is None: 2140 if self.logBrowser is None:
2126 from .SvnLogBrowserDialog import SvnLogBrowserDialog 2141 from .SvnLogBrowserDialog import SvnLogBrowserDialog
2142
2127 self.logBrowser = SvnLogBrowserDialog(self) 2143 self.logBrowser = SvnLogBrowserDialog(self)
2128 self.logBrowser.show() 2144 self.logBrowser.show()
2129 self.logBrowser.raise_() 2145 self.logBrowser.raise_()
2130 self.logBrowser.start(name, isFile=isFile) 2146 self.logBrowser.start(name, isFile=isFile)
2131 2147
2132 def svnLock(self, name, stealIt=False, parent=None): 2148 def svnLock(self, name, stealIt=False, parent=None):
2133 """ 2149 """
2134 Public method used to lock a file in the Subversion repository. 2150 Public method used to lock a file in the Subversion repository.
2135 2151
2136 @param name file/directory name to be locked (string or list of 2152 @param name file/directory name to be locked (string or list of
2137 strings) 2153 strings)
2138 @param stealIt flag indicating a forced operation (boolean) 2154 @param stealIt flag indicating a forced operation (boolean)
2139 @param parent reference to the parent object of the subversion dialog 2155 @param parent reference to the parent object of the subversion dialog
2140 (QWidget) 2156 (QWidget)
2141 """ 2157 """
2142 args = [] 2158 args = []
2143 args.append('lock') 2159 args.append("lock")
2144 self.addArguments(args, self.options['global']) 2160 self.addArguments(args, self.options["global"])
2145 if stealIt: 2161 if stealIt:
2146 args.append('--force') 2162 args.append("--force")
2147 if isinstance(name, list): 2163 if isinstance(name, list):
2148 dname, fnames = self.splitPathList(name) 2164 dname, fnames = self.splitPathList(name)
2149 self.addArguments(args, fnames) 2165 self.addArguments(args, fnames)
2150 else: 2166 else:
2151 dname, fname = self.splitPath(name) 2167 dname, fname = self.splitPath(name)
2152 args.append(fname) 2168 args.append(fname)
2153 2169
2154 dia = SvnDialog( 2170 dia = SvnDialog(self.tr("Locking in the Subversion repository"), parent)
2155 self.tr('Locking in the Subversion repository'), parent)
2156 res = dia.startProcess(args, dname) 2171 res = dia.startProcess(args, dname)
2157 if res: 2172 if res:
2158 dia.exec() 2173 dia.exec()
2159 2174
2160 def svnUnlock(self, name, breakIt=False, parent=None): 2175 def svnUnlock(self, name, breakIt=False, parent=None):
2161 """ 2176 """
2162 Public method used to unlock a file in the Subversion repository. 2177 Public method used to unlock a file in the Subversion repository.
2163 2178
2164 @param name file/directory name to be unlocked (string or list of 2179 @param name file/directory name to be unlocked (string or list of
2165 strings) 2180 strings)
2166 @param breakIt flag indicating a forced operation (boolean) 2181 @param breakIt flag indicating a forced operation (boolean)
2167 @param parent reference to the parent object of the subversion dialog 2182 @param parent reference to the parent object of the subversion dialog
2168 (QWidget) 2183 (QWidget)
2169 """ 2184 """
2170 args = [] 2185 args = []
2171 args.append('unlock') 2186 args.append("unlock")
2172 self.addArguments(args, self.options['global']) 2187 self.addArguments(args, self.options["global"])
2173 if breakIt: 2188 if breakIt:
2174 args.append('--force') 2189 args.append("--force")
2175 if isinstance(name, list): 2190 if isinstance(name, list):
2176 dname, fnames = self.splitPathList(name) 2191 dname, fnames = self.splitPathList(name)
2177 self.addArguments(args, fnames) 2192 self.addArguments(args, fnames)
2178 else: 2193 else:
2179 dname, fname = self.splitPath(name) 2194 dname, fname = self.splitPath(name)
2180 args.append(fname) 2195 args.append(fname)
2181 2196
2182 dia = SvnDialog( 2197 dia = SvnDialog(self.tr("Unlocking in the Subversion repository"), parent)
2183 self.tr('Unlocking in the Subversion repository'), parent)
2184 res = dia.startProcess(args, dname) 2198 res = dia.startProcess(args, dname)
2185 if res: 2199 if res:
2186 dia.exec() 2200 dia.exec()
2187 2201
2188 def svnRelocate(self, projectPath): 2202 def svnRelocate(self, projectPath):
2189 """ 2203 """
2190 Public method to relocate the working copy to a new repository URL. 2204 Public method to relocate the working copy to a new repository URL.
2191 2205
2192 @param projectPath path name of the project (string) 2206 @param projectPath path name of the project (string)
2193 """ 2207 """
2194 from .SvnRelocateDialog import SvnRelocateDialog 2208 from .SvnRelocateDialog import SvnRelocateDialog
2209
2195 currUrl = self.svnGetReposName(projectPath) 2210 currUrl = self.svnGetReposName(projectPath)
2196 dlg = SvnRelocateDialog(currUrl) 2211 dlg = SvnRelocateDialog(currUrl)
2197 if dlg.exec() == QDialog.DialogCode.Accepted: 2212 if dlg.exec() == QDialog.DialogCode.Accepted:
2198 newUrl, inside = dlg.getData() 2213 newUrl, inside = dlg.getData()
2199 args = [] 2214 args = []
2200 args.append('switch') 2215 args.append("switch")
2201 if not inside: 2216 if not inside:
2202 args.append('--relocate') 2217 args.append("--relocate")
2203 args.append(currUrl) 2218 args.append(currUrl)
2204 args.append(newUrl) 2219 args.append(newUrl)
2205 args.append(projectPath) 2220 args.append(projectPath)
2206 2221
2207 dia = SvnDialog(self.tr('Relocating')) 2222 dia = SvnDialog(self.tr("Relocating"))
2208 res = dia.startProcess(args) 2223 res = dia.startProcess(args)
2209 if res: 2224 if res:
2210 dia.exec() 2225 dia.exec()
2211 2226
2212 def svnRepoBrowser(self, projectPath=None): 2227 def svnRepoBrowser(self, projectPath=None):
2213 """ 2228 """
2214 Public method to open the repository browser. 2229 Public method to open the repository browser.
2215 2230
2216 @param projectPath path name of the project (string) 2231 @param projectPath path name of the project (string)
2217 """ 2232 """
2218 url = self.svnGetReposName(projectPath) if projectPath else None 2233 url = self.svnGetReposName(projectPath) if projectPath else None
2219 2234
2220 if url is None: 2235 if url is None:
2221 url, ok = QInputDialog.getText( 2236 url, ok = QInputDialog.getText(
2222 None, 2237 None,
2223 self.tr("Repository Browser"), 2238 self.tr("Repository Browser"),
2224 self.tr("Enter the repository URL."), 2239 self.tr("Enter the repository URL."),
2225 QLineEdit.EchoMode.Normal) 2240 QLineEdit.EchoMode.Normal,
2241 )
2226 if not ok or not url: 2242 if not ok or not url:
2227 return 2243 return
2228 2244
2229 if self.repoBrowser is None: 2245 if self.repoBrowser is None:
2230 from .SvnRepoBrowserDialog import SvnRepoBrowserDialog 2246 from .SvnRepoBrowserDialog import SvnRepoBrowserDialog
2247
2231 self.repoBrowser = SvnRepoBrowserDialog(self) 2248 self.repoBrowser = SvnRepoBrowserDialog(self)
2232 self.repoBrowser.show() 2249 self.repoBrowser.show()
2233 self.repoBrowser.raise_() 2250 self.repoBrowser.raise_()
2234 self.repoBrowser.start(url) 2251 self.repoBrowser.start(url)
2235 2252
2236 def svnRemoveFromChangelist(self, names): 2253 def svnRemoveFromChangelist(self, names):
2237 """ 2254 """
2238 Public method to remove a file or directory from its changelist. 2255 Public method to remove a file or directory from its changelist.
2239 2256
2240 Note: Directories will be removed recursively. 2257 Note: Directories will be removed recursively.
2241 2258
2242 @param names name or list of names of file or directory to remove 2259 @param names name or list of names of file or directory to remove
2243 (string) 2260 (string)
2244 """ 2261 """
2245 args = [] 2262 args = []
2246 args.append('changelist') 2263 args.append("changelist")
2247 self.addArguments(args, self.options['global']) 2264 self.addArguments(args, self.options["global"])
2248 args.append('--remove') 2265 args.append("--remove")
2249 args.append('--recursive') 2266 args.append("--recursive")
2250 if isinstance(names, list): 2267 if isinstance(names, list):
2251 dname, fnames = self.splitPathList(names) 2268 dname, fnames = self.splitPathList(names)
2252 self.addArguments(args, fnames) 2269 self.addArguments(args, fnames)
2253 else: 2270 else:
2254 dname, fname = self.splitPath(names) 2271 dname, fname = self.splitPath(names)
2255 args.append(fname) 2272 args.append(fname)
2256 2273
2257 dia = SvnDialog(self.tr('Remove from changelist')) 2274 dia = SvnDialog(self.tr("Remove from changelist"))
2258 res = dia.startProcess(args, dname) 2275 res = dia.startProcess(args, dname)
2259 if res: 2276 if res:
2260 dia.exec() 2277 dia.exec()
2261 2278
2262 def svnAddToChangelist(self, names): 2279 def svnAddToChangelist(self, names):
2263 """ 2280 """
2264 Public method to add a file or directory to a changelist. 2281 Public method to add a file or directory to a changelist.
2265 2282
2266 Note: Directories will be added recursively. 2283 Note: Directories will be added recursively.
2267 2284
2268 @param names name or list of names of file or directory to add 2285 @param names name or list of names of file or directory to add
2269 (string) 2286 (string)
2270 """ 2287 """
2271 clname, ok = QInputDialog.getItem( 2288 clname, ok = QInputDialog.getItem(
2272 None, 2289 None,
2273 self.tr("Add to changelist"), 2290 self.tr("Add to changelist"),
2274 self.tr("Enter name of the changelist:"), 2291 self.tr("Enter name of the changelist:"),
2275 sorted(self.svnGetChangelists()), 2292 sorted(self.svnGetChangelists()),
2276 0, True) 2293 0,
2294 True,
2295 )
2277 if not ok or not clname: 2296 if not ok or not clname:
2278 return 2297 return
2279 2298
2280 args = [] 2299 args = []
2281 args.append('changelist') 2300 args.append("changelist")
2282 self.addArguments(args, self.options['global']) 2301 self.addArguments(args, self.options["global"])
2283 args.append('--recursive') 2302 args.append("--recursive")
2284 args.append(clname) 2303 args.append(clname)
2285 if isinstance(names, list): 2304 if isinstance(names, list):
2286 dname, fnames = self.splitPathList(names) 2305 dname, fnames = self.splitPathList(names)
2287 self.addArguments(args, fnames) 2306 self.addArguments(args, fnames)
2288 else: 2307 else:
2289 dname, fname = self.splitPath(names) 2308 dname, fname = self.splitPath(names)
2290 args.append(fname) 2309 args.append(fname)
2291 2310
2292 dia = SvnDialog(self.tr('Remove from changelist')) 2311 dia = SvnDialog(self.tr("Remove from changelist"))
2293 res = dia.startProcess(args, dname) 2312 res = dia.startProcess(args, dname)
2294 if res: 2313 if res:
2295 dia.exec() 2314 dia.exec()
2296 2315
2297 def svnShowChangelists(self, path): 2316 def svnShowChangelists(self, path):
2298 """ 2317 """
2299 Public method used to inspect the change lists defined for the project. 2318 Public method used to inspect the change lists defined for the project.
2300 2319
2301 @param path directory name to show change lists for (string) 2320 @param path directory name to show change lists for (string)
2302 """ 2321 """
2303 from .SvnChangeListsDialog import SvnChangeListsDialog 2322 from .SvnChangeListsDialog import SvnChangeListsDialog
2323
2304 self.changeLists = SvnChangeListsDialog(self) 2324 self.changeLists = SvnChangeListsDialog(self)
2305 self.changeLists.show() 2325 self.changeLists.show()
2306 QApplication.processEvents() 2326 QApplication.processEvents()
2307 self.changeLists.start(path) 2327 self.changeLists.start(path)
2308 2328
2309 def svnGetChangelists(self): 2329 def svnGetChangelists(self):
2310 """ 2330 """
2311 Public method to get a list of all defined change lists. 2331 Public method to get a list of all defined change lists.
2312 2332
2313 @return list of defined change list names (list of strings) 2333 @return list of defined change list names (list of strings)
2314 """ 2334 """
2315 changelists = [] 2335 changelists = []
2316 rx_changelist = re.compile('--- \\S+ .([\\w\\s]+).:\\s*') 2336 rx_changelist = re.compile("--- \\S+ .([\\w\\s]+).:\\s*")
2317 # three dashes, Changelist (translated), quote, 2337 # three dashes, Changelist (translated), quote,
2318 # changelist name, quote, : 2338 # changelist name, quote, :
2319 2339
2320 args = [] 2340 args = []
2321 args.append("status") 2341 args.append("status")
2322 args.append("--non-interactive") 2342 args.append("--non-interactive")
2323 args.append(".") 2343 args.append(".")
2324 2344
2325 ppath = ericApp().getObject("Project").getProjectPath() 2345 ppath = ericApp().getObject("Project").getProjectPath()
2326 process = QProcess() 2346 process = QProcess()
2327 process.setWorkingDirectory(ppath) 2347 process.setWorkingDirectory(ppath)
2328 process.start('svn', args) 2348 process.start("svn", args)
2329 procStarted = process.waitForStarted(5000) 2349 procStarted = process.waitForStarted(5000)
2330 if procStarted: 2350 if procStarted:
2331 finished = process.waitForFinished(30000) 2351 finished = process.waitForFinished(30000)
2332 if finished and process.exitCode() == 0: 2352 if finished and process.exitCode() == 0:
2333 output = str(process.readAllStandardOutput(), 2353 output = str(
2334 Preferences.getSystem("IOEncoding"), 2354 process.readAllStandardOutput(),
2335 'replace') 2355 Preferences.getSystem("IOEncoding"),
2356 "replace",
2357 )
2336 if output: 2358 if output:
2337 for line in output.splitlines(): 2359 for line in output.splitlines():
2338 match = rx_changelist.fullmatch(line) 2360 match = rx_changelist.fullmatch(line)
2339 if match is not None: 2361 if match is not None:
2340 changelist = match.group(1) 2362 changelist = match.group(1)
2341 if changelist not in changelists: 2363 if changelist not in changelists:
2342 changelists.append(changelist) 2364 changelists.append(changelist)
2343 2365
2344 return changelists 2366 return changelists
2345 2367
2346 def svnUpgrade(self, path): 2368 def svnUpgrade(self, path):
2347 """ 2369 """
2348 Public method to upgrade the working copy format. 2370 Public method to upgrade the working copy format.
2349 2371
2350 @param path directory name to show change lists for (string) 2372 @param path directory name to show change lists for (string)
2351 """ 2373 """
2352 args = [] 2374 args = []
2353 args.append("upgrade") 2375 args.append("upgrade")
2354 args.append(".") 2376 args.append(".")
2355 2377
2356 dia = SvnDialog(self.tr('Upgrade')) 2378 dia = SvnDialog(self.tr("Upgrade"))
2357 res = dia.startProcess(args, path) 2379 res = dia.startProcess(args, path)
2358 if res: 2380 if res:
2359 dia.exec() 2381 dia.exec()
2360 2382
2361 ########################################################################### 2383 ###########################################################################
2362 ## Private Subversion specific methods are below. 2384 ## Private Subversion specific methods are below.
2363 ########################################################################### 2385 ###########################################################################
2364 2386
2365 def __svnURL(self, url): 2387 def __svnURL(self, url):
2366 """ 2388 """
2367 Private method to format a url for subversion. 2389 Private method to format a url for subversion.
2368 2390
2369 @param url unformatted url string (string) 2391 @param url unformatted url string (string)
2370 @return properly formated url for subversion (string) 2392 @return properly formated url for subversion (string)
2371 """ 2393 """
2372 url = self.svnNormalizeURL(url) 2394 url = self.svnNormalizeURL(url)
2373 url = url.split(':', 2) 2395 url = url.split(":", 2)
2374 if len(url) == 3: 2396 if len(url) == 3:
2375 scheme = url[0] 2397 scheme = url[0]
2376 host = url[1] 2398 host = url[1]
2377 port, path = url[2].split("/", 1) 2399 port, path = url[2].split("/", 1)
2378 return "{0}:{1}:{2}/{3}".format(scheme, host, port, quote(path)) 2400 return "{0}:{1}:{2}/{3}".format(scheme, host, port, quote(path))
2389 return "{0}://{1}/{2}".format(scheme, host, quote(path)) 2411 return "{0}://{1}/{2}".format(scheme, host, quote(path))
2390 2412
2391 def svnNormalizeURL(self, url): 2413 def svnNormalizeURL(self, url):
2392 """ 2414 """
2393 Public method to normalize a url for subversion. 2415 Public method to normalize a url for subversion.
2394 2416
2395 @param url url string (string) 2417 @param url url string (string)
2396 @return properly normalized url for subversion (string) 2418 @return properly normalized url for subversion (string)
2397 """ 2419 """
2398 protocol, url = url.split("://", 1) 2420 protocol, url = url.split("://", 1)
2399 if url.startswith("\\\\"): 2421 if url.startswith("\\\\"):
2400 url = url[2:] 2422 url = url[2:]
2401 if protocol == "file": 2423 if protocol == "file":
2402 url = os.path.normcase(url) 2424 url = os.path.normcase(url)
2403 url = url.replace('\\', '/') 2425 url = url.replace("\\", "/")
2404 if url.endswith('/'): 2426 if url.endswith("/"):
2405 url = url[:-1] 2427 url = url[:-1]
2406 if not url.startswith("/") and url[1] in [":", "|"]: 2428 if not url.startswith("/") and url[1] in [":", "|"]:
2407 url = "/{0}".format(url) 2429 url = "/{0}".format(url)
2408 return "{0}://{1}".format(protocol, url) 2430 return "{0}://{1}".format(protocol, url)
2409 2431
2410 ########################################################################### 2432 ###########################################################################
2411 ## Methods to get the helper objects are below. 2433 ## Methods to get the helper objects are below.
2412 ########################################################################### 2434 ###########################################################################
2413 2435
2414 def vcsGetProjectBrowserHelper(self, browser, project, 2436 def vcsGetProjectBrowserHelper(self, browser, project, isTranslationsBrowser=False):
2415 isTranslationsBrowser=False):
2416 """ 2437 """
2417 Public method to instanciate a helper object for the different 2438 Public method to instanciate a helper object for the different
2418 project browsers. 2439 project browsers.
2419 2440
2420 @param browser reference to the project browser object 2441 @param browser reference to the project browser object
2421 @param project reference to the project object 2442 @param project reference to the project object
2422 @param isTranslationsBrowser flag indicating, the helper is requested 2443 @param isTranslationsBrowser flag indicating, the helper is requested
2423 for the translations browser (this needs some special treatment) 2444 for the translations browser (this needs some special treatment)
2424 @return the project browser helper object 2445 @return the project browser helper object
2425 """ 2446 """
2426 from .ProjectBrowserHelper import SvnProjectBrowserHelper 2447 from .ProjectBrowserHelper import SvnProjectBrowserHelper
2427 return SvnProjectBrowserHelper(self, browser, project, 2448
2428 isTranslationsBrowser) 2449 return SvnProjectBrowserHelper(self, browser, project, isTranslationsBrowser)
2429 2450
2430 def vcsGetProjectHelper(self, project): 2451 def vcsGetProjectHelper(self, project):
2431 """ 2452 """
2432 Public method to instanciate a helper object for the project. 2453 Public method to instanciate a helper object for the project.
2433 2454
2434 @param project reference to the project object 2455 @param project reference to the project object
2435 @return the project helper object 2456 @return the project helper object
2436 """ 2457 """
2437 helper = self.__plugin.getProjectHelper() 2458 helper = self.__plugin.getProjectHelper()
2438 helper.setObjects(self, project) 2459 helper.setObjects(self, project)
2439 self.__wcng = ( 2460 self.__wcng = (
2440 os.path.exists( 2461 os.path.exists(os.path.join(project.getProjectPath(), ".svn", "format"))
2441 os.path.join(project.getProjectPath(), ".svn", "format")) or 2462 or os.path.exists(os.path.join(project.getProjectPath(), "_svn", "format"))
2442 os.path.exists( 2463 or os.path.exists(os.path.join(project.getProjectPath(), ".svn", "wc.db"))
2443 os.path.join(project.getProjectPath(), "_svn", "format")) or 2464 or os.path.exists(os.path.join(project.getProjectPath(), "_svn", "wc.db"))
2444 os.path.exists(
2445 os.path.join(project.getProjectPath(), ".svn", "wc.db")) or
2446 os.path.exists(
2447 os.path.join(project.getProjectPath(), "_svn", "wc.db"))
2448 ) 2465 )
2449 return helper 2466 return helper
2450 2467
2451 ########################################################################### 2468 ###########################################################################
2452 ## Status Monitor Thread methods 2469 ## Status Monitor Thread methods
2454 2471
2455 def _createStatusMonitorThread(self, interval, project): 2472 def _createStatusMonitorThread(self, interval, project):
2456 """ 2473 """
2457 Protected method to create an instance of the VCS status monitor 2474 Protected method to create an instance of the VCS status monitor
2458 thread. 2475 thread.
2459 2476
2460 @param interval check interval for the monitor thread in seconds 2477 @param interval check interval for the monitor thread in seconds
2461 (integer) 2478 (integer)
2462 @param project reference to the project object 2479 @param project reference to the project object
2463 @return reference to the monitor thread (QThread) 2480 @return reference to the monitor thread (QThread)
2464 """ 2481 """
2465 from .SvnStatusMonitorThread import SvnStatusMonitorThread 2482 from .SvnStatusMonitorThread import SvnStatusMonitorThread
2483
2466 return SvnStatusMonitorThread(interval, project, self) 2484 return SvnStatusMonitorThread(interval, project, self)

eric ide

mercurial