|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2006 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the VCS status monitor thread class for Subversion. |
|
8 """ |
|
9 |
|
10 import re |
|
11 |
|
12 from PyQt6.QtCore import QProcess |
|
13 |
|
14 from VCS.StatusMonitorThread import VcsStatusMonitorThread |
|
15 |
|
16 import Preferences |
|
17 |
|
18 |
|
19 class SvnStatusMonitorThread(VcsStatusMonitorThread): |
|
20 """ |
|
21 Class implementing the VCS status monitor thread class for Subversion. |
|
22 """ |
|
23 def __init__(self, interval, project, vcs, parent=None): |
|
24 """ |
|
25 Constructor |
|
26 |
|
27 @param interval new interval in seconds (integer) |
|
28 @param project reference to the project object (Project) |
|
29 @param vcs reference to the version control object |
|
30 @param parent reference to the parent object (QObject) |
|
31 """ |
|
32 VcsStatusMonitorThread.__init__(self, interval, project, vcs, parent) |
|
33 |
|
34 self.__ioEncoding = Preferences.getSystem("IOEncoding") |
|
35 |
|
36 self.rx_status1 = re.compile('(.{8,9})\\s+([0-9-]+)\\s+(.+)\\s*') |
|
37 self.rx_status2 = re.compile( |
|
38 '(.{8,9})\\s+([0-9-]+)\\s+([0-9?]+)\\s+(\\S+)\\s+(.+)\\s*') |
|
39 |
|
40 def _performMonitor(self): |
|
41 """ |
|
42 Protected method implementing the monitoring action. |
|
43 |
|
44 This method populates the statusList member variable |
|
45 with a list of strings giving the status in the first column and the |
|
46 path relative to the project directory starting with the third column. |
|
47 The allowed status flags are: |
|
48 <ul> |
|
49 <li>"A" path was added but not yet committed</li> |
|
50 <li>"M" path has local changes</li> |
|
51 <li>"O" path was removed</li> |
|
52 <li>"R" path was deleted and then re-added</li> |
|
53 <li>"U" path needs an update</li> |
|
54 <li>"Z" path contains a conflict</li> |
|
55 <li>"?" path is not tracked</li> |
|
56 <li>"!" path is missing</li> |
|
57 <li>" " path is back at normal</li> |
|
58 </ul> |
|
59 |
|
60 @return tuple of flag indicating successful operation (boolean) and |
|
61 a status message in case of non successful operation (string) |
|
62 """ |
|
63 self.shouldUpdate = False |
|
64 |
|
65 process = QProcess() |
|
66 args = [] |
|
67 args.append('status') |
|
68 if not Preferences.getVCS("MonitorLocalStatus"): |
|
69 args.append('--show-updates') |
|
70 args.append('--non-interactive') |
|
71 args.append('.') |
|
72 process.setWorkingDirectory(self.projectDir) |
|
73 process.start('svn', args) |
|
74 procStarted = process.waitForStarted(5000) |
|
75 if procStarted: |
|
76 finished = process.waitForFinished(300000) |
|
77 if finished and process.exitCode() == 0: |
|
78 output = str(process.readAllStandardOutput(), |
|
79 self.__ioEncoding, 'replace') |
|
80 states = {} |
|
81 for line in output.splitlines(): |
|
82 match = ( |
|
83 self.rx_status1.fullmatch(line) or |
|
84 self.rx_status2.fullmatch(line) |
|
85 ) |
|
86 if match is None: |
|
87 continue |
|
88 elif match.re is self.rx_status1: |
|
89 flags = match.group(1) |
|
90 path = match.group(3).strip() |
|
91 elif match.re is self.rx_status2: |
|
92 flags = match.group(1) |
|
93 path = match.group(5).strip() |
|
94 if ( |
|
95 flags[0] in "ACDMR?!" or |
|
96 (flags[0] == " " and flags[-1] == "*") or |
|
97 flags[1] in "CM" |
|
98 ): |
|
99 if flags[-1] == "*": |
|
100 status = "U" |
|
101 else: |
|
102 status = flags[0] |
|
103 if status == "C" or flags[1] == "C": |
|
104 status = "Z" # give it highest priority |
|
105 elif status == "D": |
|
106 status = "O" |
|
107 if status == "U": |
|
108 self.shouldUpdate = True |
|
109 if status == " " and flags[1] == "M": |
|
110 status = "M" |
|
111 name = path |
|
112 states[name] = status |
|
113 try: |
|
114 if self.reportedStates[name] != status: |
|
115 self.statusList.append( |
|
116 "{0} {1}".format(status, name)) |
|
117 except KeyError: |
|
118 self.statusList.append( |
|
119 "{0} {1}".format(status, name)) |
|
120 for name in list(self.reportedStates.keys()): |
|
121 if name not in states: |
|
122 self.statusList.append(" {0}".format(name)) |
|
123 self.reportedStates = states |
|
124 return True, self.tr( |
|
125 "Subversion status checked successfully (using svn)") |
|
126 else: |
|
127 process.kill() |
|
128 process.waitForFinished() |
|
129 return ( |
|
130 False, |
|
131 str(process.readAllStandardError(), |
|
132 Preferences.getSystem("IOEncoding"), |
|
133 'replace') |
|
134 ) |
|
135 else: |
|
136 process.kill() |
|
137 process.waitForFinished() |
|
138 return False, self.tr( |
|
139 "Could not start the Subversion process.") |