src/eric7/VCS/VersionControl.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
11 import contextlib 11 import contextlib
12 import json 12 import json
13 import os 13 import os
14 14
15 from PyQt6.QtCore import ( 15 from PyQt6.QtCore import (
16 QObject, QThread, QMutex, QProcess, Qt, pyqtSignal, QCoreApplication, 16 QObject,
17 QLockFile 17 QThread,
18 QMutex,
19 QProcess,
20 Qt,
21 pyqtSignal,
22 QCoreApplication,
23 QLockFile,
18 ) 24 )
19 from PyQt6.QtWidgets import QApplication 25 from PyQt6.QtWidgets import QApplication
20 26
21 from EricWidgets import EricMessageBox 27 from EricWidgets import EricMessageBox
22 from EricWidgets.EricApplication import ericApp 28 from EricWidgets.EricApplication import ericApp
26 32
27 class VersionControl(QObject): 33 class VersionControl(QObject):
28 """ 34 """
29 Class implementing an abstract base class to be subclassed by all specific 35 Class implementing an abstract base class to be subclassed by all specific
30 VCS interfaces. 36 VCS interfaces.
31 37
32 It defines the vcs interface to be implemented by subclasses 38 It defines the vcs interface to be implemented by subclasses
33 and the common methods. 39 and the common methods.
34 40
35 @signal committed() emitted after the commit action has completed 41 @signal committed() emitted after the commit action has completed
36 @signal vcsStatusMonitorData(list of str) emitted to update the VCS status 42 @signal vcsStatusMonitorData(list of str) emitted to update the VCS status
37 @signal vcsStatusMonitorAllData(dict) emitted to signal all VCS status 43 @signal vcsStatusMonitorAllData(dict) emitted to signal all VCS status
38 (key is project relative file name, value is status) 44 (key is project relative file name, value is status)
39 @signal vcsStatusMonitorStatus(str, str) emitted to signal the status of 45 @signal vcsStatusMonitorStatus(str, str) emitted to signal the status of
41 @signal vcsStatusMonitorInfo(str) emitted to signal some info of the 47 @signal vcsStatusMonitorInfo(str) emitted to signal some info of the
42 monitoring thread 48 monitoring thread
43 @signal vcsStatusChanged() emitted to indicate a change of the overall 49 @signal vcsStatusChanged() emitted to indicate a change of the overall
44 VCS status 50 VCS status
45 """ 51 """
52
46 committed = pyqtSignal() 53 committed = pyqtSignal()
47 vcsStatusMonitorData = pyqtSignal(list) 54 vcsStatusMonitorData = pyqtSignal(list)
48 vcsStatusMonitorAllData = pyqtSignal(dict) 55 vcsStatusMonitorAllData = pyqtSignal(dict)
49 vcsStatusMonitorStatus = pyqtSignal(str, str) 56 vcsStatusMonitorStatus = pyqtSignal(str, str)
50 vcsStatusMonitorInfo = pyqtSignal(str) 57 vcsStatusMonitorInfo = pyqtSignal(str)
51 vcsStatusChanged = pyqtSignal() 58 vcsStatusChanged = pyqtSignal()
52 59
53 canBeCommitted = 1 # Indicates that a file/directory is in the vcs. 60 canBeCommitted = 1 # Indicates that a file/directory is in the vcs.
54 canBeAdded = 2 # Indicates that a file/directory is not in vcs. 61 canBeAdded = 2 # Indicates that a file/directory is not in vcs.
55 62
56 commitHistoryLock = "commitHistory.lock" 63 commitHistoryLock = "commitHistory.lock"
57 commitHistoryData = "commitHistory.json" 64 commitHistoryData = "commitHistory.json"
58 65
59 def __init__(self, parent=None, name=None): 66 def __init__(self, parent=None, name=None):
60 """ 67 """
61 Constructor 68 Constructor
62 69
63 @param parent parent widget (QWidget) 70 @param parent parent widget (QWidget)
64 @param name name of this object (string) 71 @param name name of this object (string)
65 """ 72 """
66 super().__init__(parent) 73 super().__init__(parent)
67 if name: 74 if name:
68 self.setObjectName(name) 75 self.setObjectName(name)
69 self.defaultOptions = { 76 self.defaultOptions = {
70 'global': [''], 77 "global": [""],
71 'commit': [''], 78 "commit": [""],
72 'checkout': [''], 79 "checkout": [""],
73 'update': [''], 80 "update": [""],
74 'add': [''], 81 "add": [""],
75 'remove': [''], 82 "remove": [""],
76 'diff': [''], 83 "diff": [""],
77 'log': [''], 84 "log": [""],
78 'history': [''], 85 "history": [""],
79 'status': [''], 86 "status": [""],
80 'tag': [''], 87 "tag": [""],
81 'export': [''] 88 "export": [""],
82 } 89 }
83 self.interestingDataKeys = [] 90 self.interestingDataKeys = []
84 self.options = {} 91 self.options = {}
85 self.otherData = {} 92 self.otherData = {}
86 self.canDetectBinaries = True 93 self.canDetectBinaries = True
87 94
88 self.statusMonitorThread = None 95 self.statusMonitorThread = None
89 self.vcsExecutionMutex = QMutex() 96 self.vcsExecutionMutex = QMutex()
90 97
91 def vcsShutdown(self): 98 def vcsShutdown(self):
92 """ 99 """
93 Public method used to shutdown the vcs interface. 100 Public method used to shutdown the vcs interface.
94 101
95 @exception RuntimeError to indicate that this method must be 102 @exception RuntimeError to indicate that this method must be
96 implemented by a subclass 103 implemented by a subclass
97 """ 104 """
98 raise RuntimeError('Not implemented') 105 raise RuntimeError("Not implemented")
99 106
100 def vcsExists(self): 107 def vcsExists(self):
101 """ 108 """
102 Public method used to test for the presence of the vcs. 109 Public method used to test for the presence of the vcs.
103 110
104 @return tuple of flag indicating the existence and a string 111 @return tuple of flag indicating the existence and a string
105 giving an error message in case of failure 112 giving an error message in case of failure
106 @exception RuntimeError to indicate that this method must be 113 @exception RuntimeError to indicate that this method must be
107 implemented by a subclass 114 implemented by a subclass
108 """ 115 """
109 raise RuntimeError('Not implemented') 116 raise RuntimeError("Not implemented")
110 117
111 return (False, "") 118 return (False, "")
112 119
113 def vcsInit(self, vcsDir, noDialog=False): 120 def vcsInit(self, vcsDir, noDialog=False):
114 """ 121 """
115 Public method used to initialize the vcs. 122 Public method used to initialize the vcs.
116 123
117 @param vcsDir name of the VCS directory (string) 124 @param vcsDir name of the VCS directory (string)
118 @param noDialog flag indicating quiet operations (boolean) 125 @param noDialog flag indicating quiet operations (boolean)
119 @return flag indicating success (boolean) 126 @return flag indicating success (boolean)
120 @exception RuntimeError to indicate that this method must be 127 @exception RuntimeError to indicate that this method must be
121 implemented by a subclass 128 implemented by a subclass
122 """ 129 """
123 raise RuntimeError('Not implemented') 130 raise RuntimeError("Not implemented")
124 131
125 return False 132 return False
126 133
127 def vcsConvertProject(self, vcsDataDict, project, addAll=True): 134 def vcsConvertProject(self, vcsDataDict, project, addAll=True):
128 """ 135 """
129 Public method to convert an uncontrolled project to a version 136 Public method to convert an uncontrolled project to a version
130 controlled project. 137 controlled project.
131 138
132 @param vcsDataDict dictionary of data required for the conversion 139 @param vcsDataDict dictionary of data required for the conversion
133 @type dict 140 @type dict
134 @param project reference to the project object 141 @param project reference to the project object
135 @type Project 142 @type Project
136 @param addAll flag indicating to add all files to the repository 143 @param addAll flag indicating to add all files to the repository
137 @type bool 144 @type bool
138 @exception RuntimeError to indicate that this method must be 145 @exception RuntimeError to indicate that this method must be
139 implemented by a subclass 146 implemented by a subclass
140 """ 147 """
141 raise RuntimeError('Not implemented') 148 raise RuntimeError("Not implemented")
142 149
143 def vcsImport(self, vcsDataDict, projectDir, noDialog=False, addAll=True): 150 def vcsImport(self, vcsDataDict, projectDir, noDialog=False, addAll=True):
144 """ 151 """
145 Public method used to import the project into the vcs. 152 Public method used to import the project into the vcs.
146 153
147 @param vcsDataDict dictionary of data required for the import 154 @param vcsDataDict dictionary of data required for the import
148 @type dict 155 @type dict
149 @param projectDir project directory (string) 156 @param projectDir project directory (string)
150 @type str 157 @type str
151 @param noDialog flag indicating quiet operations 158 @param noDialog flag indicating quiet operations
156 and a flag indicating the version control status 163 and a flag indicating the version control status
157 @rtype tuple of (bool, bool) 164 @rtype tuple of (bool, bool)
158 @exception RuntimeError to indicate that this method must be 165 @exception RuntimeError to indicate that this method must be
159 implemented by a subclass 166 implemented by a subclass
160 """ 167 """
161 raise RuntimeError('Not implemented') 168 raise RuntimeError("Not implemented")
162 169
163 return (False, False) 170 return (False, False)
164 171
165 def vcsCheckout(self, vcsDataDict, projectDir, noDialog=False): 172 def vcsCheckout(self, vcsDataDict, projectDir, noDialog=False):
166 """ 173 """
167 Public method used to check the project out of the vcs. 174 Public method used to check the project out of the vcs.
168 175
169 @param vcsDataDict dictionary of data required for the checkout 176 @param vcsDataDict dictionary of data required for the checkout
170 @param projectDir project directory to create (string) 177 @param projectDir project directory to create (string)
171 @param noDialog flag indicating quiet operations 178 @param noDialog flag indicating quiet operations
172 @return flag indicating an execution without errors (boolean) 179 @return flag indicating an execution without errors (boolean)
173 @exception RuntimeError to indicate that this method must be 180 @exception RuntimeError to indicate that this method must be
174 implemented by a subclass 181 implemented by a subclass
175 """ 182 """
176 raise RuntimeError('Not implemented') 183 raise RuntimeError("Not implemented")
177 184
178 return False 185 return False
179 186
180 def vcsExport(self, vcsDataDict, projectDir): 187 def vcsExport(self, vcsDataDict, projectDir):
181 """ 188 """
182 Public method used to export a directory from the vcs. 189 Public method used to export a directory from the vcs.
183 190
184 @param vcsDataDict dictionary of data required for the export 191 @param vcsDataDict dictionary of data required for the export
185 @param projectDir project directory to create (string) 192 @param projectDir project directory to create (string)
186 @return flag indicating an execution without errors (boolean) 193 @return flag indicating an execution without errors (boolean)
187 @exception RuntimeError to indicate that this method must be 194 @exception RuntimeError to indicate that this method must be
188 implemented by a subclass 195 implemented by a subclass
189 """ 196 """
190 raise RuntimeError('Not implemented') 197 raise RuntimeError("Not implemented")
191 198
192 return False 199 return False
193 200
194 def vcsCommit(self, name, message, noDialog=False): 201 def vcsCommit(self, name, message, noDialog=False):
195 """ 202 """
196 Public method used to make the change of a file/directory permanent in 203 Public method used to make the change of a file/directory permanent in
197 the vcs. 204 the vcs.
198 205
199 @param name file/directory name to be committed (string) 206 @param name file/directory name to be committed (string)
200 @param message message for this operation (string) 207 @param message message for this operation (string)
201 @param noDialog flag indicating quiet operations (boolean) 208 @param noDialog flag indicating quiet operations (boolean)
202 @return flag indicating success (boolean) 209 @return flag indicating success (boolean)
203 @exception RuntimeError to indicate that this method must be 210 @exception RuntimeError to indicate that this method must be
204 implemented by a subclass 211 implemented by a subclass
205 """ 212 """
206 raise RuntimeError('Not implemented') 213 raise RuntimeError("Not implemented")
207 214
208 return False 215 return False
209 216
210 def vcsCommitMessages(self): 217 def vcsCommitMessages(self):
211 """ 218 """
212 Public method to get the list of saved commit messages. 219 Public method to get the list of saved commit messages.
213 220
214 @return list of saved commit messages 221 @return list of saved commit messages
215 @rtype list of str 222 @rtype list of str
216 @exception RuntimeError to indicate that this method must be 223 @exception RuntimeError to indicate that this method must be
217 implemented by a subclass 224 implemented by a subclass
218 """ 225 """
219 raise RuntimeError('Not implemented') 226 raise RuntimeError("Not implemented")
220 227
221 return [] 228 return []
222 229
223 def _vcsProjectCommitMessages(self): 230 def _vcsProjectCommitMessages(self):
224 """ 231 """
225 Protected method to get the list of saved commit messages. 232 Protected method to get the list of saved commit messages.
226 233
227 @return list of saved commit messages 234 @return list of saved commit messages
228 @rtype list of str 235 @rtype list of str
229 """ 236 """
230 messages = [] 237 messages = []
231 if Preferences.getVCS("PerProjectCommitHistory"): 238 if Preferences.getVCS("PerProjectCommitHistory"):
232 projectMgmtDir = ( 239 projectMgmtDir = ericApp().getObject("Project").getProjectManagementDir()
233 ericApp().getObject("Project").getProjectManagementDir()
234 )
235 with contextlib.suppress(OSError, json.JSONDecodeError): 240 with contextlib.suppress(OSError, json.JSONDecodeError):
236 with open(os.path.join(projectMgmtDir, 241 with open(
237 VersionControl.commitHistoryData), 242 os.path.join(projectMgmtDir, VersionControl.commitHistoryData), "r"
238 "r") as f: 243 ) as f:
239 jsonString = f.read() 244 jsonString = f.read()
240 messages = json.loads(jsonString) 245 messages = json.loads(jsonString)
241 246
242 return messages 247 return messages
243 248
244 def vcsAddCommitMessage(self, message): 249 def vcsAddCommitMessage(self, message):
245 """ 250 """
246 Public method to add a commit message to the list of saved messages. 251 Public method to add a commit message to the list of saved messages.
247 252
248 @param message message to be added 253 @param message message to be added
249 @type str 254 @type str
250 @exception RuntimeError to indicate that this method must be 255 @exception RuntimeError to indicate that this method must be
251 implemented by a subclass 256 implemented by a subclass
252 """ 257 """
253 raise RuntimeError('Not implemented') 258 raise RuntimeError("Not implemented")
254 259
255 def _vcsAddProjectCommitMessage(self, message): 260 def _vcsAddProjectCommitMessage(self, message):
256 """ 261 """
257 Protected method to add a commit message to the list of project 262 Protected method to add a commit message to the list of project
258 specific saved messages. 263 specific saved messages.
259 264
260 @param message message to be added 265 @param message message to be added
261 @type str 266 @type str
262 @return flag indicating success 267 @return flag indicating success
263 @rtype bool 268 @rtype bool
264 """ 269 """
265 if Preferences.getVCS("PerProjectCommitHistory"): 270 if Preferences.getVCS("PerProjectCommitHistory"):
266 projectMgmtDir = ( 271 projectMgmtDir = ericApp().getObject("Project").getProjectManagementDir()
267 ericApp().getObject("Project").getProjectManagementDir() 272 lockFile = QLockFile(
273 os.path.join(projectMgmtDir, VersionControl.commitHistoryLock)
268 ) 274 )
269 lockFile = QLockFile(
270 os.path.join(projectMgmtDir, VersionControl.commitHistoryLock))
271 if lockFile.lock(): 275 if lockFile.lock():
272 noMessages = Preferences.getVCS("CommitMessages") 276 noMessages = Preferences.getVCS("CommitMessages")
273 messages = self.vcsCommitMessages() 277 messages = self.vcsCommitMessages()
274 if message in messages: 278 if message in messages:
275 messages.remove(message) 279 messages.remove(message)
276 messages.insert(0, message) 280 messages.insert(0, message)
277 del messages[noMessages:] 281 del messages[noMessages:]
278 282
279 with contextlib.suppress(TypeError, OSError): 283 with contextlib.suppress(TypeError, OSError):
280 jsonString = json.dumps(messages, indent=2) 284 jsonString = json.dumps(messages, indent=2)
281 with open(os.path.join(projectMgmtDir, 285 with open(
282 VersionControl.commitHistoryData), 286 os.path.join(projectMgmtDir, VersionControl.commitHistoryData),
283 "w") as f: 287 "w",
288 ) as f:
284 f.write(jsonString) 289 f.write(jsonString)
285 lockFile.unlock() 290 lockFile.unlock()
286 return True 291 return True
287 292
288 return False 293 return False
289 294
290 def vcsClearCommitMessages(self): 295 def vcsClearCommitMessages(self):
291 """ 296 """
292 Public method to clear the list of saved messages. 297 Public method to clear the list of saved messages.
293 298
294 @exception RuntimeError to indicate that this method must be 299 @exception RuntimeError to indicate that this method must be
295 implemented by a subclass 300 implemented by a subclass
296 """ 301 """
297 raise RuntimeError('Not implemented') 302 raise RuntimeError("Not implemented")
298 303
299 def _vcsClearProjectCommitMessages(self): 304 def _vcsClearProjectCommitMessages(self):
300 """ 305 """
301 Protected method to clear the list of project specific saved messages. 306 Protected method to clear the list of project specific saved messages.
302 307
303 @return flag indicating success 308 @return flag indicating success
304 @rtype bool 309 @rtype bool
305 """ 310 """
306 if Preferences.getVCS("PerProjectCommitHistory"): 311 if Preferences.getVCS("PerProjectCommitHistory"):
307 projectMgmtDir = ( 312 projectMgmtDir = ericApp().getObject("Project").getProjectManagementDir()
308 ericApp().getObject("Project").getProjectManagementDir() 313 lockFile = QLockFile(
314 os.path.join(projectMgmtDir, VersionControl.commitHistoryLock)
309 ) 315 )
310 lockFile = QLockFile(
311 os.path.join(projectMgmtDir, VersionControl.commitHistoryLock))
312 if lockFile.lock(): 316 if lockFile.lock():
313 with contextlib.suppress(TypeError, OSError): 317 with contextlib.suppress(TypeError, OSError):
314 jsonString = json.dumps([], indent=2) 318 jsonString = json.dumps([], indent=2)
315 with open(os.path.join(projectMgmtDir, 319 with open(
316 VersionControl.commitHistoryData), 320 os.path.join(projectMgmtDir, VersionControl.commitHistoryData),
317 "w") as f: 321 "w",
322 ) as f:
318 f.write(jsonString) 323 f.write(jsonString)
319 lockFile.unlock() 324 lockFile.unlock()
320 return True 325 return True
321 326
322 return False 327 return False
323 328
324 def vcsUpdate(self, name, noDialog=False): 329 def vcsUpdate(self, name, noDialog=False):
325 """ 330 """
326 Public method used to update a file/directory in the vcs. 331 Public method used to update a file/directory in the vcs.
327 332
328 @param name file/directory name to be updated (string) 333 @param name file/directory name to be updated (string)
329 @param noDialog flag indicating quiet operations (boolean) 334 @param noDialog flag indicating quiet operations (boolean)
330 @return flag indicating, that the update contained an add 335 @return flag indicating, that the update contained an add
331 or delete (boolean) 336 or delete (boolean)
332 @exception RuntimeError to indicate that this method must be 337 @exception RuntimeError to indicate that this method must be
333 implemented by a subclass 338 implemented by a subclass
334 """ 339 """
335 raise RuntimeError('Not implemented') 340 raise RuntimeError("Not implemented")
336 341
337 return False 342 return False
338 343
339 def vcsAdd(self, name, isDir=False, noDialog=False): 344 def vcsAdd(self, name, isDir=False, noDialog=False):
340 """ 345 """
341 Public method used to add a file/directory in the vcs. 346 Public method used to add a file/directory in the vcs.
342 347
343 @param name file/directory name to be added (string) 348 @param name file/directory name to be added (string)
344 @param isDir flag indicating name is a directory (boolean) 349 @param isDir flag indicating name is a directory (boolean)
345 @param noDialog flag indicating quiet operations (boolean) 350 @param noDialog flag indicating quiet operations (boolean)
346 @exception RuntimeError to indicate that this method must be 351 @exception RuntimeError to indicate that this method must be
347 implemented by a subclass 352 implemented by a subclass
348 """ 353 """
349 raise RuntimeError('Not implemented') 354 raise RuntimeError("Not implemented")
350 355
351 def vcsAddBinary(self, name, isDir=False): 356 def vcsAddBinary(self, name, isDir=False):
352 """ 357 """
353 Public method used to add a file/directory in binary mode in the vcs. 358 Public method used to add a file/directory in binary mode in the vcs.
354 359
355 @param name file/directory name to be added (string) 360 @param name file/directory name to be added (string)
356 @param isDir flag indicating name is a directory (boolean) 361 @param isDir flag indicating name is a directory (boolean)
357 @exception RuntimeError to indicate that this method must be 362 @exception RuntimeError to indicate that this method must be
358 implemented by a subclass 363 implemented by a subclass
359 """ 364 """
360 raise RuntimeError('Not implemented') 365 raise RuntimeError("Not implemented")
361 366
362 def vcsAddTree(self, path): 367 def vcsAddTree(self, path):
363 """ 368 """
364 Public method to add a directory tree rooted at path in the vcs. 369 Public method to add a directory tree rooted at path in the vcs.
365 370
366 @param path root directory of the tree to be added (string) 371 @param path root directory of the tree to be added (string)
367 @exception RuntimeError to indicate that this method must be 372 @exception RuntimeError to indicate that this method must be
368 implemented by a subclass 373 implemented by a subclass
369 """ 374 """
370 raise RuntimeError('Not implemented') 375 raise RuntimeError("Not implemented")
371 376
372 def vcsRemove(self, name, project=False, noDialog=False): 377 def vcsRemove(self, name, project=False, noDialog=False):
373 """ 378 """
374 Public method used to add a file/directory in the vcs. 379 Public method used to add a file/directory in the vcs.
375 380
376 @param name file/directory name to be removed (string) 381 @param name file/directory name to be removed (string)
377 @param project flag indicating deletion of a project tree (boolean) 382 @param project flag indicating deletion of a project tree (boolean)
378 @param noDialog flag indicating quiet operations 383 @param noDialog flag indicating quiet operations
379 @return flag indicating success (boolean) 384 @return flag indicating success (boolean)
380 @exception RuntimeError to indicate that this method must be 385 @exception RuntimeError to indicate that this method must be
381 implemented by a subclass 386 implemented by a subclass
382 """ 387 """
383 raise RuntimeError('Not implemented') 388 raise RuntimeError("Not implemented")
384 389
385 return False 390 return False
386 391
387 def vcsMove(self, name, project, target=None, noDialog=False): 392 def vcsMove(self, name, project, target=None, noDialog=False):
388 """ 393 """
389 Public method used to move a file/directory. 394 Public method used to move a file/directory.
390 395
391 @param name file/directory name to be moved (string) 396 @param name file/directory name to be moved (string)
392 @param project reference to the project object 397 @param project reference to the project object
393 @param target new name of the file/directory (string) 398 @param target new name of the file/directory (string)
394 @param noDialog flag indicating quiet operations 399 @param noDialog flag indicating quiet operations
395 @return flag indicating successfull operation (boolean) 400 @return flag indicating successfull operation (boolean)
396 @exception RuntimeError to indicate that this method must be 401 @exception RuntimeError to indicate that this method must be
397 implemented by a subclass 402 implemented by a subclass
398 """ 403 """
399 raise RuntimeError('Not implemented') 404 raise RuntimeError("Not implemented")
400 405
401 return False 406 return False
402 407
403 def vcsLogBrowser(self, name, isFile=False): 408 def vcsLogBrowser(self, name, isFile=False):
404 """ 409 """
405 Public method used to view the log of a file/directory in the vcs 410 Public method used to view the log of a file/directory in the vcs
406 with a log browser dialog. 411 with a log browser dialog.
407 412
408 @param name file/directory name to show the log for (string) 413 @param name file/directory name to show the log for (string)
409 @param isFile flag indicating log for a file is to be shown 414 @param isFile flag indicating log for a file is to be shown
410 (boolean) 415 (boolean)
411 @exception RuntimeError to indicate that this method must be 416 @exception RuntimeError to indicate that this method must be
412 implemented by a subclass 417 implemented by a subclass
413 """ 418 """
414 raise RuntimeError('Not implemented') 419 raise RuntimeError("Not implemented")
415 420
416 def vcsDiff(self, name): 421 def vcsDiff(self, name):
417 """ 422 """
418 Public method used to view the diff of a file/directory in the vcs. 423 Public method used to view the diff of a file/directory in the vcs.
419 424
420 @param name file/directory name to be diffed (string) 425 @param name file/directory name to be diffed (string)
421 @exception RuntimeError to indicate that this method must be 426 @exception RuntimeError to indicate that this method must be
422 implemented by a subclass 427 implemented by a subclass
423 """ 428 """
424 raise RuntimeError('Not implemented') 429 raise RuntimeError("Not implemented")
425 430
426 def vcsSbsDiff(self, name, extended=False, revisions=None): 431 def vcsSbsDiff(self, name, extended=False, revisions=None):
427 """ 432 """
428 Public method used to view the difference of a file to the Mercurial 433 Public method used to view the difference of a file to the Mercurial
429 repository side-by-side. 434 repository side-by-side.
430 435
431 @param name file name to be diffed 436 @param name file name to be diffed
432 @type str 437 @type str
433 @param extended flag indicating the extended variant 438 @param extended flag indicating the extended variant
434 @type bool 439 @type bool
435 @param revisions tuple of two revisions 440 @param revisions tuple of two revisions
436 @type tuple of two str 441 @type tuple of two str
437 @exception RuntimeError to indicate that this method must be 442 @exception RuntimeError to indicate that this method must be
438 implemented by a subclass 443 implemented by a subclass
439 """ 444 """
440 raise RuntimeError('Not implemented') 445 raise RuntimeError("Not implemented")
441 446
442 def vcsStatus(self, name): 447 def vcsStatus(self, name):
443 """ 448 """
444 Public method used to view the status of a file/directory in the vcs. 449 Public method used to view the status of a file/directory in the vcs.
445 450
446 @param name file/directory name to show the status for (string) 451 @param name file/directory name to show the status for (string)
447 @exception RuntimeError to indicate that this method must be 452 @exception RuntimeError to indicate that this method must be
448 implemented by a subclass 453 implemented by a subclass
449 """ 454 """
450 raise RuntimeError('Not implemented') 455 raise RuntimeError("Not implemented")
451 456
452 def vcsTag(self, name): 457 def vcsTag(self, name):
453 """ 458 """
454 Public method used to set the tag of a file/directory in the vcs. 459 Public method used to set the tag of a file/directory in the vcs.
455 460
456 @param name file/directory name to be tagged (string) 461 @param name file/directory name to be tagged (string)
457 @exception RuntimeError to indicate that this method must be 462 @exception RuntimeError to indicate that this method must be
458 implemented by a subclass 463 implemented by a subclass
459 """ 464 """
460 raise RuntimeError('Not implemented') 465 raise RuntimeError("Not implemented")
461 466
462 def vcsRevert(self, name): 467 def vcsRevert(self, name):
463 """ 468 """
464 Public method used to revert changes made to a file/directory. 469 Public method used to revert changes made to a file/directory.
465 470
466 @param name file/directory name to be reverted 471 @param name file/directory name to be reverted
467 @type str 472 @type str
468 @return flag indicating, that the update contained an add 473 @return flag indicating, that the update contained an add
469 or delete 474 or delete
470 @rtype bool 475 @rtype bool
471 @exception RuntimeError to indicate that this method must be 476 @exception RuntimeError to indicate that this method must be
472 implemented by a subclass 477 implemented by a subclass
473 """ 478 """
474 raise RuntimeError('Not implemented') 479 raise RuntimeError("Not implemented")
475 480
476 return False 481 return False
477 482
478 def vcsForget(self, name): 483 def vcsForget(self, name):
479 """ 484 """
480 Public method used to remove a file from the repository. 485 Public method used to remove a file from the repository.
481 486
482 @param name file/directory name to be removed 487 @param name file/directory name to be removed
483 @type str or list of str 488 @type str or list of str
484 @exception RuntimeError to indicate that this method must be 489 @exception RuntimeError to indicate that this method must be
485 implemented by a subclass 490 implemented by a subclass
486 """ 491 """
487 raise RuntimeError('Not implemented') 492 raise RuntimeError("Not implemented")
488 493
489 def vcsSwitch(self, name): 494 def vcsSwitch(self, name):
490 """ 495 """
491 Public method used to switch a directory to a different tag/branch. 496 Public method used to switch a directory to a different tag/branch.
492 497
493 @param name directory name to be switched (string) 498 @param name directory name to be switched (string)
494 @return flag indicating, that the switch contained an add 499 @return flag indicating, that the switch contained an add
495 or delete (boolean) 500 or delete (boolean)
496 @exception RuntimeError to indicate that this method must be 501 @exception RuntimeError to indicate that this method must be
497 implemented by a subclass 502 implemented by a subclass
498 """ 503 """
499 raise RuntimeError('Not implemented') 504 raise RuntimeError("Not implemented")
500 505
501 return False 506 return False
502 507
503 def vcsMerge(self, name): 508 def vcsMerge(self, name):
504 """ 509 """
505 Public method used to merge a tag/branch into the local project. 510 Public method used to merge a tag/branch into the local project.
506 511
507 @param name file/directory name to be merged (string) 512 @param name file/directory name to be merged (string)
508 @exception RuntimeError to indicate that this method must be 513 @exception RuntimeError to indicate that this method must be
509 implemented by a subclass 514 implemented by a subclass
510 """ 515 """
511 raise RuntimeError('Not implemented') 516 raise RuntimeError("Not implemented")
512 517
513 def vcsRegisteredState(self, name): 518 def vcsRegisteredState(self, name):
514 """ 519 """
515 Public method used to get the registered state of a file in the vcs. 520 Public method used to get the registered state of a file in the vcs.
516 521
517 @param name filename to check (string) 522 @param name filename to check (string)
518 @return a combination of canBeCommited and canBeAdded or 523 @return a combination of canBeCommited and canBeAdded or
519 0 in order to signal an error 524 0 in order to signal an error
520 @exception RuntimeError to indicate that this method must be 525 @exception RuntimeError to indicate that this method must be
521 implemented by a subclass 526 implemented by a subclass
522 """ 527 """
523 raise RuntimeError('Not implemented') 528 raise RuntimeError("Not implemented")
524 529
525 return 0 530 return 0
526 531
527 def vcsAllRegisteredStates(self, names, dname): 532 def vcsAllRegisteredStates(self, names, dname):
528 """ 533 """
529 Public method used to get the registered states of a number of files 534 Public method used to get the registered states of a number of files
530 in the vcs. 535 in the vcs.
531 536
532 @param names dictionary with all filenames to be checked as keys 537 @param names dictionary with all filenames to be checked as keys
533 @param dname directory to check in (string) 538 @param dname directory to check in (string)
534 @return the received dictionary completed with a combination of 539 @return the received dictionary completed with a combination of
535 canBeCommited and canBeAdded or None in order to signal an error 540 canBeCommited and canBeAdded or None in order to signal an error
536 @exception RuntimeError to indicate that this method must be 541 @exception RuntimeError to indicate that this method must be
537 implemented by a subclass 542 implemented by a subclass
538 """ 543 """
539 raise RuntimeError('Not implemented') 544 raise RuntimeError("Not implemented")
540 545
541 return {} 546 return {}
542 547
543 def vcsName(self): 548 def vcsName(self):
544 """ 549 """
545 Public method returning the name of the vcs. 550 Public method returning the name of the vcs.
546 551
547 @return name of the vcs (string) 552 @return name of the vcs (string)
548 @exception RuntimeError to indicate that this method must be 553 @exception RuntimeError to indicate that this method must be
549 implemented by a subclass 554 implemented by a subclass
550 """ 555 """
551 raise RuntimeError('Not implemented') 556 raise RuntimeError("Not implemented")
552 557
553 return "" 558 return ""
554 559
555 def vcsCleanup(self, name): 560 def vcsCleanup(self, name):
556 """ 561 """
557 Public method used to cleanup the local copy. 562 Public method used to cleanup the local copy.
558 563
559 @param name directory name to be cleaned up (string) 564 @param name directory name to be cleaned up (string)
560 @exception RuntimeError to indicate that this method must be 565 @exception RuntimeError to indicate that this method must be
561 implemented by a subclass 566 implemented by a subclass
562 """ 567 """
563 raise RuntimeError('Not implemented') 568 raise RuntimeError("Not implemented")
564 569
565 def vcsCommandLine(self, name): 570 def vcsCommandLine(self, name):
566 """ 571 """
567 Public method used to execute arbitrary vcs commands. 572 Public method used to execute arbitrary vcs commands.
568 573
569 @param name directory name of the working directory (string) 574 @param name directory name of the working directory (string)
570 @exception RuntimeError to indicate that this method must be 575 @exception RuntimeError to indicate that this method must be
571 implemented by a subclass 576 implemented by a subclass
572 """ 577 """
573 raise RuntimeError('Not implemented') 578 raise RuntimeError("Not implemented")
574 579
575 def vcsOptionsDialog(self, project, archive, editable=False, parent=None): 580 def vcsOptionsDialog(self, project, archive, editable=False, parent=None):
576 """ 581 """
577 Public method to get a dialog to enter repository info. 582 Public method to get a dialog to enter repository info.
578 583
579 @param project reference to the project object 584 @param project reference to the project object
580 @param archive name of the project in the repository (string) 585 @param archive name of the project in the repository (string)
581 @param editable flag indicating that the project name is editable 586 @param editable flag indicating that the project name is editable
582 (boolean) 587 (boolean)
583 @param parent parent widget (QWidget) 588 @param parent parent widget (QWidget)
584 @exception RuntimeError to indicate that this method must be 589 @exception RuntimeError to indicate that this method must be
585 implemented by a subclass 590 implemented by a subclass
586 """ 591 """
587 raise RuntimeError('Not implemented') 592 raise RuntimeError("Not implemented")
588 593
589 def vcsNewProjectOptionsDialog(self, parent=None): 594 def vcsNewProjectOptionsDialog(self, parent=None):
590 """ 595 """
591 Public method to get a dialog to enter repository info for getting a 596 Public method to get a dialog to enter repository info for getting a
592 new project. 597 new project.
593 598
594 @param parent parent widget (QWidget) 599 @param parent parent widget (QWidget)
595 @exception RuntimeError to indicate that this method must be 600 @exception RuntimeError to indicate that this method must be
596 implemented by a subclass 601 implemented by a subclass
597 """ 602 """
598 raise RuntimeError('Not implemented') 603 raise RuntimeError("Not implemented")
599 604
600 def vcsRepositoryInfos(self, ppath): 605 def vcsRepositoryInfos(self, ppath):
601 """ 606 """
602 Public method to retrieve information about the repository. 607 Public method to retrieve information about the repository.
603 608
604 @param ppath local path to get the repository infos (string) 609 @param ppath local path to get the repository infos (string)
605 @return string with ready formated info for display (string) 610 @return string with ready formated info for display (string)
606 @exception RuntimeError to indicate that this method must be 611 @exception RuntimeError to indicate that this method must be
607 implemented by a subclass 612 implemented by a subclass
608 """ 613 """
609 raise RuntimeError('Not implemented') 614 raise RuntimeError("Not implemented")
610 615
611 return "" 616 return ""
612 617
613 def vcsGetProjectBrowserHelper(self, browser, project, 618 def vcsGetProjectBrowserHelper(self, browser, project, isTranslationsBrowser=False):
614 isTranslationsBrowser=False):
615 """ 619 """
616 Public method to instanciate a helper object for the different 620 Public method to instanciate a helper object for the different
617 project browsers. 621 project browsers.
618 622
619 @param browser reference to the project browser object 623 @param browser reference to the project browser object
620 @param project reference to the project object 624 @param project reference to the project object
621 @param isTranslationsBrowser flag indicating, the helper is requested 625 @param isTranslationsBrowser flag indicating, the helper is requested
622 for the translations browser (this needs some special treatment) 626 for the translations browser (this needs some special treatment)
623 @return the project browser helper object 627 @return the project browser helper object
624 @exception RuntimeError to indicate that this method must be 628 @exception RuntimeError to indicate that this method must be
625 implemented by a subclass 629 implemented by a subclass
626 """ 630 """
627 raise RuntimeError('Not implemented') 631 raise RuntimeError("Not implemented")
628 632
629 return None # __IGNORE_WARNING_M831__ 633 return None # __IGNORE_WARNING_M831__
630 634
631 def vcsGetProjectHelper(self, project): 635 def vcsGetProjectHelper(self, project):
632 """ 636 """
633 Public method to instanciate a helper object for the project. 637 Public method to instanciate a helper object for the project.
634 638
635 @param project reference to the project object 639 @param project reference to the project object
636 @return the project helper object 640 @return the project helper object
637 @exception RuntimeError to indicate that this method must be 641 @exception RuntimeError to indicate that this method must be
638 implemented by a subclass 642 implemented by a subclass
639 """ 643 """
640 raise RuntimeError('Not implemented') 644 raise RuntimeError("Not implemented")
641 645
642 return None # __IGNORE_WARNING_M831__ 646 return None # __IGNORE_WARNING_M831__
643 647
644 ##################################################################### 648 #####################################################################
645 ## methods above need to be implemented by a subclass 649 ## methods above need to be implemented by a subclass
646 ##################################################################### 650 #####################################################################
647 651
648 def clearStatusCache(self): 652 def clearStatusCache(self):
649 """ 653 """
650 Public method to clear the status cache. 654 Public method to clear the status cache.
651 """ 655 """
652 pass 656 pass
653 657
654 def vcsInitConfig(self, project): 658 def vcsInitConfig(self, project):
655 """ 659 """
656 Public method to initialize the VCS configuration. 660 Public method to initialize the VCS configuration.
657 661
658 This method could ensure, that certain files or directories are 662 This method could ensure, that certain files or directories are
659 exclude from being version controlled. 663 exclude from being version controlled.
660 664
661 @param project reference to the project (Project) 665 @param project reference to the project (Project)
662 """ 666 """
663 pass 667 pass
664 668
665 def vcsSupportCommandOptions(self): 669 def vcsSupportCommandOptions(self):
666 """ 670 """
667 Public method to signal the support of user settable command options. 671 Public method to signal the support of user settable command options.
668 672
669 @return flag indicating the support of user settable command options 673 @return flag indicating the support of user settable command options
670 (boolean) 674 (boolean)
671 """ 675 """
672 return True 676 return True
673 677
674 def vcsSetOptions(self, options): 678 def vcsSetOptions(self, options):
675 """ 679 """
676 Public method used to set the options for the vcs. 680 Public method used to set the options for the vcs.
677 681
678 @param options a dictionary of option strings with keys as 682 @param options a dictionary of option strings with keys as
679 defined by the default options 683 defined by the default options
680 """ 684 """
681 if self.vcsSupportCommandOptions(): 685 if self.vcsSupportCommandOptions():
682 for key in options: 686 for key in options:
683 with contextlib.suppress(KeyError): 687 with contextlib.suppress(KeyError):
684 self.options[key] = options[key] 688 self.options[key] = options[key]
685 689
686 def vcsGetOptions(self): 690 def vcsGetOptions(self):
687 """ 691 """
688 Public method used to retrieve the options of the vcs. 692 Public method used to retrieve the options of the vcs.
689 693
690 @return a dictionary of option strings that can be passed to 694 @return a dictionary of option strings that can be passed to
691 vcsSetOptions. 695 vcsSetOptions.
692 """ 696 """
693 if self.vcsSupportCommandOptions(): 697 if self.vcsSupportCommandOptions():
694 return self.options 698 return self.options
695 else: 699 else:
696 return self.defaultOptions 700 return self.defaultOptions
697 701
698 def vcsSetOtherData(self, data): 702 def vcsSetOtherData(self, data):
699 """ 703 """
700 Public method used to set vcs specific data. 704 Public method used to set vcs specific data.
701 705
702 @param data a dictionary of vcs specific data 706 @param data a dictionary of vcs specific data
703 """ 707 """
704 for key in data: 708 for key in data:
705 with contextlib.suppress(KeyError): 709 with contextlib.suppress(KeyError):
706 self.otherData[key] = data[key] 710 self.otherData[key] = data[key]
707 711
708 def vcsGetOtherData(self): 712 def vcsGetOtherData(self):
709 """ 713 """
710 Public method used to retrieve vcs specific data. 714 Public method used to retrieve vcs specific data.
711 715
712 @return a dictionary of vcs specific data 716 @return a dictionary of vcs specific data
713 """ 717 """
714 return self.otherData 718 return self.otherData
715 719
716 def vcsSetData(self, key, value): 720 def vcsSetData(self, key, value):
717 """ 721 """
718 Public method used to set an entry in the otherData dictionary. 722 Public method used to set an entry in the otherData dictionary.
719 723
720 @param key the key of the data (string) 724 @param key the key of the data (string)
721 @param value the value of the data 725 @param value the value of the data
722 """ 726 """
723 if key in self.interestingDataKeys: 727 if key in self.interestingDataKeys:
724 self.otherData[key] = value 728 self.otherData[key] = value
725 729
726 def vcsSetDataFromDict(self, dictionary): 730 def vcsSetDataFromDict(self, dictionary):
727 """ 731 """
728 Public method used to set entries in the otherData dictionary. 732 Public method used to set entries in the otherData dictionary.
729 733
730 @param dictionary dictionary to pick entries from 734 @param dictionary dictionary to pick entries from
731 """ 735 """
732 for key in self.interestingDataKeys: 736 for key in self.interestingDataKeys:
733 if key in dictionary: 737 if key in dictionary:
734 self.otherData[key] = dictionary[key] 738 self.otherData[key] = dictionary[key]
735 739
736 def vcsResolved(self, name): 740 def vcsResolved(self, name):
737 """ 741 """
738 Public method used to resolve conflicts of a file/directory. 742 Public method used to resolve conflicts of a file/directory.
739 743
740 @param name file/directory name to be resolved 744 @param name file/directory name to be resolved
741 @type str 745 @type str
742 """ 746 """
743 # default implementation just refreshes the status 747 # default implementation just refreshes the status
744 self.checkVCSStatus() 748 self.checkVCSStatus()
745 749
746 ##################################################################### 750 #####################################################################
747 ## below are some utility methods 751 ## below are some utility methods
748 ##################################################################### 752 #####################################################################
749 753
750 def startSynchronizedProcess(self, proc, program, arguments, 754 def startSynchronizedProcess(self, proc, program, arguments, workingDir=None):
751 workingDir=None):
752 """ 755 """
753 Public method to start a synchroneous process. 756 Public method to start a synchroneous process.
754 757
755 This method starts a process and waits 758 This method starts a process and waits
756 for its end while still serving the Qt event loop. 759 for its end while still serving the Qt event loop.
757 760
758 @param proc process to start (QProcess) 761 @param proc process to start (QProcess)
759 @param program path of the executable to start (string) 762 @param program path of the executable to start (string)
760 @param arguments list of arguments for the process (list of strings) 763 @param arguments list of arguments for the process (list of strings)
761 @param workingDir working directory for the process (string) 764 @param workingDir working directory for the process (string)
762 @return flag indicating normal exit (boolean) 765 @return flag indicating normal exit (boolean)
763 """ 766 """
764 if proc is None: 767 if proc is None:
765 return False 768 return False
766 769
767 if workingDir: 770 if workingDir:
768 proc.setWorkingDirectory(workingDir) 771 proc.setWorkingDirectory(workingDir)
769 proc.start(program, arguments) 772 proc.start(program, arguments)
770 procStarted = proc.waitForStarted(5000) 773 procStarted = proc.waitForStarted(5000)
771 if not procStarted: 774 if not procStarted:
772 EricMessageBox.critical( 775 EricMessageBox.critical(
773 None, 776 None,
774 QCoreApplication.translate( 777 QCoreApplication.translate(
775 "VersionControl", 'Process Generation Error'), 778 "VersionControl", "Process Generation Error"
779 ),
776 QCoreApplication.translate( 780 QCoreApplication.translate(
777 "VersionControl", 781 "VersionControl",
778 'The process {0} could not be started. ' 782 "The process {0} could not be started. "
779 'Ensure, that it is in the search path.' 783 "Ensure, that it is in the search path.",
780 ).format(program)) 784 ).format(program),
785 )
781 return False 786 return False
782 else: 787 else:
783 while proc.state() == QProcess.ProcessState.Running: 788 while proc.state() == QProcess.ProcessState.Running:
784 QThread.msleep(300) 789 QThread.msleep(300)
785 QApplication.processEvents() 790 QApplication.processEvents()
786 return ( 791 return (proc.exitStatus() == QProcess.ExitStatus.NormalExit) and (
787 (proc.exitStatus() == QProcess.ExitStatus.NormalExit) and 792 proc.exitCode() == 0
788 (proc.exitCode() == 0)
789 ) 793 )
790 794
791 def splitPath(self, name): 795 def splitPath(self, name):
792 """ 796 """
793 Public method splitting name into a directory part and a file part. 797 Public method splitting name into a directory part and a file part.
794 798
795 @param name path name (string) 799 @param name path name (string)
796 @return a tuple of 2 strings (dirname, filename). 800 @return a tuple of 2 strings (dirname, filename).
797 """ 801 """
798 if os.path.isdir(name): 802 if os.path.isdir(name):
799 dn = os.path.abspath(name) 803 dn = os.path.abspath(name)
800 fn = "." 804 fn = "."
801 else: 805 else:
802 dn, fn = os.path.split(name) 806 dn, fn = os.path.split(name)
803 return (dn, fn) 807 return (dn, fn)
804 808
805 def splitPathList(self, names): 809 def splitPathList(self, names):
806 """ 810 """
807 Public method splitting the list of names into a common directory part 811 Public method splitting the list of names into a common directory part
808 and a file list. 812 and a file list.
809 813
810 @param names list of paths (list of strings) 814 @param names list of paths (list of strings)
811 @return a tuple of string and list of strings (dirname, filenamelist) 815 @return a tuple of string and list of strings (dirname, filenamelist)
812 """ 816 """
813 dname = os.path.commonprefix(names) 817 dname = os.path.commonprefix(names)
814 if dname: 818 if dname:
815 if not dname.endswith(os.sep): 819 if not dname.endswith(os.sep):
816 dname = os.path.dirname(dname) + os.sep 820 dname = os.path.dirname(dname) + os.sep
817 fnames = [n.replace(dname, '') for n in names] 821 fnames = [n.replace(dname, "") for n in names]
818 dname = os.path.dirname(dname) 822 dname = os.path.dirname(dname)
819 return (dname, fnames) 823 return (dname, fnames)
820 else: 824 else:
821 return ("/", names) 825 return ("/", names)
822 826
823 def addArguments(self, args, argslist): 827 def addArguments(self, args, argslist):
824 """ 828 """
825 Public method to add an argument list to the already present 829 Public method to add an argument list to the already present
826 arguments. 830 arguments.
827 831
828 @param args current arguments list (list of strings) 832 @param args current arguments list (list of strings)
829 @param argslist list of arguments (list of strings) 833 @param argslist list of arguments (list of strings)
830 """ 834 """
831 for arg in argslist: 835 for arg in argslist:
832 if arg != '': 836 if arg != "":
833 args.append(arg) 837 args.append(arg)
834 838
835 ########################################################################### 839 ###########################################################################
836 ## VCS status monitor thread related methods 840 ## VCS status monitor thread related methods
837 ########################################################################### 841 ###########################################################################
838 842
839 def __statusMonitorStatus(self, status, statusMsg): 843 def __statusMonitorStatus(self, status, statusMsg):
840 """ 844 """
841 Private slot to receive the status monitor status. 845 Private slot to receive the status monitor status.
842 846
843 It simply re-emits the received status. 847 It simply re-emits the received status.
844 848
845 @param status status of the monitoring thread 849 @param status status of the monitoring thread
846 @type str (one of ok, nok or off) 850 @type str (one of ok, nok or off)
847 @param statusMsg explanotory text for the signaled status 851 @param statusMsg explanotory text for the signaled status
848 @type str 852 @type str
849 """ 853 """
851 QCoreApplication.processEvents() 855 QCoreApplication.processEvents()
852 856
853 def __statusMonitorData(self, statusList): 857 def __statusMonitorData(self, statusList):
854 """ 858 """
855 Private method to receive the status monitor data update. 859 Private method to receive the status monitor data update.
856 860
857 It simply re-emits the received status list. 861 It simply re-emits the received status list.
858 862
859 @param statusList list of status records 863 @param statusList list of status records
860 @type list of str 864 @type list of str
861 """ 865 """
862 self.vcsStatusMonitorData.emit(statusList) 866 self.vcsStatusMonitorData.emit(statusList)
863 QCoreApplication.processEvents() 867 QCoreApplication.processEvents()
864 868
865 def __statusMonitorAllData(self, statusDict): 869 def __statusMonitorAllData(self, statusDict):
866 """ 870 """
867 Private method to receive all status monitor data. 871 Private method to receive all status monitor data.
868 872
869 It simply re-emits the received status list. 873 It simply re-emits the received status list.
870 874
871 @param statusDict dictionary of status records 875 @param statusDict dictionary of status records
872 @type dict 876 @type dict
873 """ 877 """
874 self.vcsStatusMonitorAllData.emit(statusDict) 878 self.vcsStatusMonitorAllData.emit(statusDict)
875 QCoreApplication.processEvents() 879 QCoreApplication.processEvents()
876 880
877 def __statusMonitorInfo(self, info): 881 def __statusMonitorInfo(self, info):
878 """ 882 """
879 Private slot to receive the status monitor info message. 883 Private slot to receive the status monitor info message.
880 884
881 It simply re-emits the received info message. 885 It simply re-emits the received info message.
882 886
883 @param info received info message 887 @param info received info message
884 @type str 888 @type str
885 """ 889 """
886 self.vcsStatusMonitorInfo.emit(info) 890 self.vcsStatusMonitorInfo.emit(info)
887 QCoreApplication.processEvents() 891 QCoreApplication.processEvents()
888 892
889 def startStatusMonitor(self, project): 893 def startStatusMonitor(self, project):
890 """ 894 """
891 Public method to start the VCS status monitor thread. 895 Public method to start the VCS status monitor thread.
892 896
893 @param project reference to the project object 897 @param project reference to the project object
894 @return reference to the monitor thread (QThread) 898 @return reference to the monitor thread (QThread)
895 """ 899 """
896 vcsStatusMonitorInterval = ( 900 vcsStatusMonitorInterval = (
897 project.pudata["VCSSTATUSMONITORINTERVAL"] 901 project.pudata["VCSSTATUSMONITORINTERVAL"]
898 if project.pudata["VCSSTATUSMONITORINTERVAL"] else 902 if project.pudata["VCSSTATUSMONITORINTERVAL"]
899 Preferences.getVCS("StatusMonitorInterval") 903 else Preferences.getVCS("StatusMonitorInterval")
900 ) 904 )
901 if vcsStatusMonitorInterval > 0: 905 if vcsStatusMonitorInterval > 0:
902 self.statusMonitorThread = self._createStatusMonitorThread( 906 self.statusMonitorThread = self._createStatusMonitorThread(
903 vcsStatusMonitorInterval, project) 907 vcsStatusMonitorInterval, project
908 )
904 if self.statusMonitorThread is not None: 909 if self.statusMonitorThread is not None:
905 self.statusMonitorThread.vcsStatusMonitorData.connect( 910 self.statusMonitorThread.vcsStatusMonitorData.connect(
906 self.__statusMonitorData, 911 self.__statusMonitorData, Qt.ConnectionType.QueuedConnection
907 Qt.ConnectionType.QueuedConnection) 912 )
908 self.statusMonitorThread.vcsStatusMonitorAllData.connect( 913 self.statusMonitorThread.vcsStatusMonitorAllData.connect(
909 self.__statusMonitorAllData, 914 self.__statusMonitorAllData, Qt.ConnectionType.QueuedConnection
910 Qt.ConnectionType.QueuedConnection) 915 )
911 self.statusMonitorThread.vcsStatusMonitorStatus.connect( 916 self.statusMonitorThread.vcsStatusMonitorStatus.connect(
912 self.__statusMonitorStatus, 917 self.__statusMonitorStatus, Qt.ConnectionType.QueuedConnection
913 Qt.ConnectionType.QueuedConnection) 918 )
914 self.statusMonitorThread.vcsStatusMonitorInfo.connect( 919 self.statusMonitorThread.vcsStatusMonitorInfo.connect(
915 self.__statusMonitorInfo, 920 self.__statusMonitorInfo, Qt.ConnectionType.QueuedConnection
916 Qt.ConnectionType.QueuedConnection) 921 )
917 self.statusMonitorThread.setAutoUpdate( 922 self.statusMonitorThread.setAutoUpdate(Preferences.getVCS("AutoUpdate"))
918 Preferences.getVCS("AutoUpdate"))
919 self.statusMonitorThread.start() 923 self.statusMonitorThread.start()
920 else: 924 else:
921 self.statusMonitorThread = None 925 self.statusMonitorThread = None
922 return self.statusMonitorThread 926 return self.statusMonitorThread
923 927
924 def stopStatusMonitor(self): 928 def stopStatusMonitor(self):
925 """ 929 """
926 Public method to stop the VCS status monitor thread. 930 Public method to stop the VCS status monitor thread.
927 """ 931 """
928 if self.statusMonitorThread is not None: 932 if self.statusMonitorThread is not None:
929 self.__statusMonitorData(["--RESET--"]) 933 self.__statusMonitorData(["--RESET--"])
930 self.statusMonitorThread.vcsStatusMonitorData.disconnect( 934 self.statusMonitorThread.vcsStatusMonitorData.disconnect(
931 self.__statusMonitorData) 935 self.__statusMonitorData
936 )
932 self.statusMonitorThread.vcsStatusMonitorAllData.disconnect( 937 self.statusMonitorThread.vcsStatusMonitorAllData.disconnect(
933 self.__statusMonitorAllData) 938 self.__statusMonitorAllData
939 )
934 self.statusMonitorThread.vcsStatusMonitorStatus.disconnect( 940 self.statusMonitorThread.vcsStatusMonitorStatus.disconnect(
935 self.__statusMonitorStatus) 941 self.__statusMonitorStatus
942 )
936 self.statusMonitorThread.vcsStatusMonitorInfo.disconnect( 943 self.statusMonitorThread.vcsStatusMonitorInfo.disconnect(
937 self.__statusMonitorInfo) 944 self.__statusMonitorInfo
945 )
938 self.statusMonitorThread.stop() 946 self.statusMonitorThread.stop()
939 self.statusMonitorThread.wait(10000) 947 self.statusMonitorThread.wait(10000)
940 if not self.statusMonitorThread.isFinished(): 948 if not self.statusMonitorThread.isFinished():
941 self.statusMonitorThread.terminate() 949 self.statusMonitorThread.terminate()
942 self.statusMonitorThread.wait(10000) 950 self.statusMonitorThread.wait(10000)
943 self.statusMonitorThread = None 951 self.statusMonitorThread = None
944 self.__statusMonitorStatus( 952 self.__statusMonitorStatus(
945 "off", 953 "off",
946 QCoreApplication.translate( 954 QCoreApplication.translate(
947 "VersionControl", 955 "VersionControl", "Repository status checking is switched off"
948 "Repository status checking is switched off")) 956 ),
957 )
949 self.__statusMonitorInfo("") 958 self.__statusMonitorInfo("")
950 959
951 def setStatusMonitorInterval(self, interval, project): 960 def setStatusMonitorInterval(self, interval, project):
952 """ 961 """
953 Public method to change the monitor interval. 962 Public method to change the monitor interval.
954 963
955 @param interval new interval in seconds (integer) 964 @param interval new interval in seconds (integer)
956 @param project reference to the project object 965 @param project reference to the project object
957 """ 966 """
958 if self.statusMonitorThread is not None: 967 if self.statusMonitorThread is not None:
959 if interval == 0: 968 if interval == 0:
960 self.stopStatusMonitor() 969 self.stopStatusMonitor()
961 else: 970 else:
962 self.statusMonitorThread.setInterval(interval) 971 self.statusMonitorThread.setInterval(interval)
963 else: 972 else:
964 self.startStatusMonitor(project) 973 self.startStatusMonitor(project)
965 974
966 def getStatusMonitorInterval(self): 975 def getStatusMonitorInterval(self):
967 """ 976 """
968 Public method to get the monitor interval. 977 Public method to get the monitor interval.
969 978
970 @return interval in seconds (integer) 979 @return interval in seconds (integer)
971 """ 980 """
972 if self.statusMonitorThread is not None: 981 if self.statusMonitorThread is not None:
973 return self.statusMonitorThread.getInterval() 982 return self.statusMonitorThread.getInterval()
974 else: 983 else:
975 return 0 984 return 0
976 985
977 def setStatusMonitorAutoUpdate(self, auto): 986 def setStatusMonitorAutoUpdate(self, auto):
978 """ 987 """
979 Public method to enable the auto update function. 988 Public method to enable the auto update function.
980 989
981 @param auto status of the auto update function (boolean) 990 @param auto status of the auto update function (boolean)
982 """ 991 """
983 if self.statusMonitorThread is not None: 992 if self.statusMonitorThread is not None:
984 self.statusMonitorThread.setAutoUpdate(auto) 993 self.statusMonitorThread.setAutoUpdate(auto)
985 994
986 def getStatusMonitorAutoUpdate(self): 995 def getStatusMonitorAutoUpdate(self):
987 """ 996 """
988 Public method to retrieve the status of the auto update function. 997 Public method to retrieve the status of the auto update function.
989 998
990 @return status of the auto update function (boolean) 999 @return status of the auto update function (boolean)
991 """ 1000 """
992 if self.statusMonitorThread is not None: 1001 if self.statusMonitorThread is not None:
993 return self.statusMonitorThread.getAutoUpdate() 1002 return self.statusMonitorThread.getAutoUpdate()
994 else: 1003 else:
995 return False 1004 return False
996 1005
997 def checkVCSStatus(self): 1006 def checkVCSStatus(self):
998 """ 1007 """
999 Public method to wake up the VCS status monitor thread. 1008 Public method to wake up the VCS status monitor thread.
1000 """ 1009 """
1001 self.vcsStatusChanged.emit() 1010 self.vcsStatusChanged.emit()
1002 1011
1003 if self.statusMonitorThread is not None: 1012 if self.statusMonitorThread is not None:
1004 self.statusMonitorThread.checkStatus() 1013 self.statusMonitorThread.checkStatus()
1005 1014
1006 def clearStatusMonitorCachedState(self, name): 1015 def clearStatusMonitorCachedState(self, name):
1007 """ 1016 """
1008 Public method to clear the cached VCS state of a file/directory. 1017 Public method to clear the cached VCS state of a file/directory.
1009 1018
1010 @param name name of the entry to be cleared (string) 1019 @param name name of the entry to be cleared (string)
1011 """ 1020 """
1012 if self.statusMonitorThread is not None: 1021 if self.statusMonitorThread is not None:
1013 self.statusMonitorThread.clearCachedState(name) 1022 self.statusMonitorThread.clearCachedState(name)
1014 1023
1015 def _createStatusMonitorThread(self, interval, project): 1024 def _createStatusMonitorThread(self, interval, project):
1016 """ 1025 """
1017 Protected method to create an instance of the VCS status monitor 1026 Protected method to create an instance of the VCS status monitor
1018 thread. 1027 thread.
1019 1028
1020 Note: This method should be overwritten in subclasses in order to 1029 Note: This method should be overwritten in subclasses in order to
1021 support VCS status monitoring. 1030 support VCS status monitoring.
1022 1031
1023 @param interval check interval for the monitor thread in seconds 1032 @param interval check interval for the monitor thread in seconds
1024 (integer) 1033 (integer)
1025 @param project reference to the project object 1034 @param project reference to the project object
1026 @return reference to the monitor thread (QThread) 1035 @return reference to the monitor thread (QThread)
1027 """ 1036 """
1028 return None # __IGNORE_WARNING_M831__ 1037 return None # __IGNORE_WARNING_M831__

eric ide

mercurial