eric6/Plugins/VcsPlugins/vcsMercurial/HgStatusMonitorThread.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 6970
cf9c2dc3f3cc
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2010 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the VCS status monitor thread class for Mercurial.
8 """
9
10 from __future__ import unicode_literals
11 try:
12 str = unicode
13 except NameError:
14 pass
15
16 from PyQt5.QtCore import QProcess
17
18 from VCS.StatusMonitorThread import VcsStatusMonitorThread
19
20
21 class HgStatusMonitorThread(VcsStatusMonitorThread):
22 """
23 Class implementing the VCS status monitor thread class for Mercurial.
24 """
25 def __init__(self, interval, project, vcs, parent=None):
26 """
27 Constructor
28
29 @param interval new interval in seconds (integer)
30 @param project reference to the project object (Project)
31 @param vcs reference to the version control object
32 @param parent reference to the parent object (QObject)
33 """
34 VcsStatusMonitorThread.__init__(self, interval, project, vcs, parent)
35
36 self.__client = None
37 self.__useCommandLine = False
38
39 def _performMonitor(self):
40 """
41 Protected method implementing the monitoring action.
42
43 This method populates the statusList member variable
44 with a list of strings giving the status in the first column and the
45 path relative to the project directory starting with the third column.
46 The allowed status flags are:
47 <ul>
48 <li>"A" path was added but not yet comitted</li>
49 <li>"M" path has local changes</li>
50 <li>"O" path was removed</li>
51 <li>"R" path was deleted and then re-added</li>
52 <li>"U" path needs an update</li>
53 <li>"Z" path contains a conflict</li>
54 <li>" " path is back at normal</li>
55 </ul>
56
57 @return tuple of flag indicating successful operation (boolean) and
58 a status message in case of non successful operation (string)
59 """
60 self.shouldUpdate = False
61
62 self.__initClient()
63
64 # step 1: get overall status
65 args = self.vcs.initCommand("status")
66 args.append('--noninteractive')
67 args.append('--all')
68
69 output = ""
70 error = ""
71 if self.__client:
72 output, error = self.__client.runcommand(args)
73 else:
74 process = QProcess()
75 process.setWorkingDirectory(self.projectDir)
76 process.start('hg', args)
77 procStarted = process.waitForStarted(5000)
78 if procStarted:
79 finished = process.waitForFinished(300000)
80 if finished and process.exitCode() == 0:
81 output = str(process.readAllStandardOutput(),
82 self.vcs.getEncoding(), 'replace')
83 else:
84 process.kill()
85 process.waitForFinished()
86 error = str(process.readAllStandardError(),
87 self.vcs.getEncoding(), 'replace')
88 else:
89 process.kill()
90 process.waitForFinished()
91 error = self.tr("Could not start the Mercurial process.")
92
93 if error:
94 return False, error
95
96 states = {}
97 for line in output.splitlines():
98 if not line.startswith(" "):
99 flag, name = line.split(" ", 1)
100 if flag in "AMR":
101 if flag == "R":
102 status = "O"
103 else:
104 status = flag
105 states[name] = status
106
107 # step 2: get conflicting changes
108 args = self.vcs.initCommand("resolve")
109 args.append('--list')
110
111 output = ""
112 error = ""
113 if self.__client:
114 output, error = self.__client.runcommand(args)
115 else:
116 process.setWorkingDirectory(self.projectDir)
117 process.start('hg', args)
118 procStarted = process.waitForStarted(5000)
119 if procStarted:
120 finished = process.waitForFinished(300000)
121 if finished and process.exitCode() == 0:
122 output = str(process.readAllStandardOutput(),
123 self.vcs.getEncoding(), 'replace')
124
125 for line in output.splitlines():
126 flag, name = line.split(" ", 1)
127 if flag == "U":
128 states[name] = "Z" # conflict
129
130 # step 3: collect the status to be reported back
131 for name in states:
132 try:
133 if self.reportedStates[name] != states[name]:
134 self.statusList.append(
135 "{0} {1}".format(states[name], name))
136 except KeyError:
137 self.statusList.append("{0} {1}".format(states[name], name))
138 for name in self.reportedStates.keys():
139 if name not in states:
140 self.statusList.append(" {0}".format(name))
141 self.reportedStates = states
142
143 return True, \
144 self.tr("Mercurial status checked successfully")
145
146 def _getInfo(self):
147 """
148 Protected method implementing the real info action.
149
150 This method should be overridden and create a short info message to be
151 shown in the main window status bar right next to the status indicator.
152
153 @return short info message
154 @rtype str
155 """
156 self.__initClient()
157
158 args = self.vcs.initCommand("identify")
159 args.append('--num')
160 args.append('--id')
161 args.append('--branch')
162
163 output = ""
164 error = ""
165 if self.__client:
166 output, error = self.__client.runcommand(args)
167 else:
168 process = QProcess()
169 process.setWorkingDirectory(self.projectDir)
170 process.start('hg', args)
171 procStarted = process.waitForStarted(5000)
172 if procStarted:
173 finished = process.waitForFinished(300000)
174 if finished and process.exitCode() == 0:
175 output = str(process.readAllStandardOutput(),
176 self.vcs.getEncoding(), 'replace')
177 else:
178 process.kill()
179 process.waitForFinished()
180 error = str(process.readAllStandardError(),
181 self.vcs.getEncoding(), 'replace')
182 else:
183 process.kill()
184 process.waitForFinished()
185 error = self.tr("Could not start the Mercurial process.")
186
187 if error:
188 # ignore errors
189 return ""
190
191 globalRev, localRev, branch = output.splitlines()[0].split()
192 if globalRev.endswith("+"):
193 globalRev = globalRev[:-1]
194 if localRev.endswith("+"):
195 localRev = localRev[:-1]
196
197 return self.tr("{0} / {1}:{2}", "branch, local id, global id").format(
198 branch, localRev, globalRev)
199
200 def _shutdown(self):
201 """
202 Protected method performing shutdown actions.
203 """
204 if self.__client:
205 self.__client.stopServer()
206
207 def __initClient(self):
208 """
209 Private method to initialize the Mercurial client.
210 """
211 if self.__client is None and not self.__useCommandLine:
212 from .HgClient import HgClient
213 client = HgClient(self.projectDir, "utf-8", self.vcs)
214 ok, err = client.startServer()
215 if ok:
216 self.__client = client
217 else:
218 self.__useCommandLine = True

eric ide

mercurial