18 |
18 |
19 |
19 |
20 class GitDiffGenerator(QObject): |
20 class GitDiffGenerator(QObject): |
21 """ |
21 """ |
22 Class implementing the generation of output of the git diff command. |
22 Class implementing the generation of output of the git diff command. |
23 |
23 |
24 @signal finished() emitted when all processes have finished |
24 @signal finished() emitted when all processes have finished |
25 """ |
25 """ |
|
26 |
26 finished = pyqtSignal() |
27 finished = pyqtSignal() |
27 |
28 |
28 def __init__(self, vcs, parent=None): |
29 def __init__(self, vcs, parent=None): |
29 """ |
30 """ |
30 Constructor |
31 Constructor |
31 |
32 |
32 @param vcs reference to the vcs object |
33 @param vcs reference to the vcs object |
33 @param parent parent widget (QWidget) |
34 @param parent parent widget (QWidget) |
34 """ |
35 """ |
35 super().__init__(parent) |
36 super().__init__(parent) |
36 |
37 |
37 self.vcs = vcs |
38 self.vcs = vcs |
38 |
39 |
39 self.__process = EricOverrideCursorProcess() |
40 self.__process = EricOverrideCursorProcess() |
40 self.__process.finished.connect(self.__procFinished) |
41 self.__process.finished.connect(self.__procFinished) |
41 self.__process.readyReadStandardOutput.connect( |
42 self.__process.readyReadStandardOutput.connect( |
42 lambda: self.__readStdout(self.__process)) |
43 lambda: self.__readStdout(self.__process) |
|
44 ) |
43 self.__process.readyReadStandardError.connect( |
45 self.__process.readyReadStandardError.connect( |
44 lambda: self.__readStderr(self.__process)) |
46 lambda: self.__readStderr(self.__process) |
45 |
47 ) |
|
48 |
46 self.__process2 = EricOverrideCursorProcess() |
49 self.__process2 = EricOverrideCursorProcess() |
47 self.__process2.finished.connect(self.__procFinished) |
50 self.__process2.finished.connect(self.__procFinished) |
48 self.__process2.readyReadStandardOutput.connect( |
51 self.__process2.readyReadStandardOutput.connect( |
49 lambda: self.__readStdout(self.__process2)) |
52 lambda: self.__readStdout(self.__process2) |
|
53 ) |
50 self.__process2.readyReadStandardError.connect( |
54 self.__process2.readyReadStandardError.connect( |
51 lambda: self.__readStderr(self.__process2)) |
55 lambda: self.__readStderr(self.__process2) |
52 |
56 ) |
|
57 |
53 def stopProcesses(self): |
58 def stopProcesses(self): |
54 """ |
59 """ |
55 Public slot to stop the diff processes. |
60 Public slot to stop the diff processes. |
56 """ |
61 """ |
57 for process in [self.__process, self.__process2]: |
62 for process in [self.__process, self.__process2]: |
58 if ( |
63 if ( |
59 process is not None and |
64 process is not None |
60 process.state() != QProcess.ProcessState.NotRunning |
65 and process.state() != QProcess.ProcessState.NotRunning |
61 ): |
66 ): |
62 process.terminate() |
67 process.terminate() |
63 QTimer.singleShot(2000, process.kill) |
68 QTimer.singleShot(2000, process.kill) |
64 process.waitForFinished(3000) |
69 process.waitForFinished(3000) |
65 |
70 |
66 def start(self, fn, versions=None, diffMode="work2repo", stashName=""): |
71 def start(self, fn, versions=None, diffMode="work2repo", stashName=""): |
67 """ |
72 """ |
68 Public slot to start the git diff command. |
73 Public slot to start the git diff command. |
69 |
74 |
70 @param fn filename to be diffed (string) |
75 @param fn filename to be diffed (string) |
71 @param versions list of versions to be diffed (list of up to 2 strings |
76 @param versions list of versions to be diffed (list of up to 2 strings |
72 or None) |
77 or None) |
73 @param diffMode indication for the type of diff to be performed ( |
78 @param diffMode indication for the type of diff to be performed ( |
74 'work2repo' compares the working tree with the HEAD commit, |
79 'work2repo' compares the working tree with the HEAD commit, |
130 args = self.vcs.initCommand("stash") |
139 args = self.vcs.initCommand("stash") |
131 args.append("show") |
140 args.append("show") |
132 args.append("--patch") |
141 args.append("--patch") |
133 if stashName: |
142 if stashName: |
134 args.append(stashName) |
143 args.append(stashName) |
135 |
144 |
136 # find the root of the repo |
145 # find the root of the repo |
137 repodir = dname |
146 repodir = dname |
138 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)): |
147 while not os.path.isdir(os.path.join(repodir, self.vcs.adminDir)): |
139 repodir = os.path.dirname(repodir) |
148 repodir = os.path.dirname(repodir) |
140 if os.path.splitdrive(repodir)[1] == os.sep: |
149 if os.path.splitdrive(repodir)[1] == os.sep: |
141 return False |
150 return False |
142 |
151 |
143 self.__process.kill() |
152 self.__process.kill() |
144 self.__process.setWorkingDirectory(repodir) |
153 self.__process.setWorkingDirectory(repodir) |
145 self.__process.start('git', args) |
154 self.__process.start("git", args) |
146 procStarted = self.__process.waitForStarted(5000) |
155 procStarted = self.__process.waitForStarted(5000) |
147 if not procStarted: |
156 if not procStarted: |
148 return False |
157 return False |
149 |
158 |
150 if diffMode == "work2stage2repo": |
159 if diffMode == "work2stage2repo": |
151 self.__process2.kill() |
160 self.__process2.kill() |
152 self.__process2.setWorkingDirectory(repodir) |
161 self.__process2.setWorkingDirectory(repodir) |
153 self.__process2.start('git', args2) |
162 self.__process2.start("git", args2) |
154 procStarted = self.__process2.waitForStarted(5000) |
163 procStarted = self.__process2.waitForStarted(5000) |
155 if not procStarted: |
164 if not procStarted: |
156 return False |
165 return False |
157 |
166 |
158 return True |
167 return True |
159 |
168 |
160 def __procFinished(self, exitCode, exitStatus): |
169 def __procFinished(self, exitCode, exitStatus): |
161 """ |
170 """ |
162 Private slot connected to the finished signal. |
171 Private slot connected to the finished signal. |
163 |
172 |
164 @param exitCode exit code of the process (integer) |
173 @param exitCode exit code of the process (integer) |
165 @param exitStatus exit status of the process (QProcess.ExitStatus) |
174 @param exitStatus exit status of the process (QProcess.ExitStatus) |
166 """ |
175 """ |
167 if ( |
176 if ( |
168 self.__process.state() == QProcess.ProcessState.NotRunning and |
177 self.__process.state() == QProcess.ProcessState.NotRunning |
169 self.__process2.state() == QProcess.ProcessState.NotRunning |
178 and self.__process2.state() == QProcess.ProcessState.NotRunning |
170 ): |
179 ): |
171 self.finished.emit() |
180 self.finished.emit() |
172 |
181 |
173 def getResult(self): |
182 def getResult(self): |
174 """ |
183 """ |
175 Public method to return the result data. |
184 Public method to return the result data. |
176 |
185 |
177 @return tuple of lists of string containing lines of the diff, the diff |
186 @return tuple of lists of string containing lines of the diff, the diff |
178 between stage and repo for 'work2stage2repo' mode (empty |
187 between stage and repo for 'work2stage2repo' mode (empty |
179 otherwise), the list of errors and a list of tuples of filenames |
188 otherwise), the list of errors and a list of tuples of filenames |
180 and the line into the diff output. |
189 and the line into the diff output. |
181 """ |
190 """ |
182 return (self.__output1, self.__output2, self.__errors, |
191 return (self.__output1, self.__output2, self.__errors, self.__fileSeparators) |
183 self.__fileSeparators) |
192 |
184 |
|
185 def __processFileLine(self, line, isTopDiff): |
193 def __processFileLine(self, line, isTopDiff): |
186 """ |
194 """ |
187 Private slot to process a line giving the old/new file. |
195 Private slot to process a line giving the old/new file. |
188 |
196 |
189 @param line line to be processed (string) |
197 @param line line to be processed (string) |
190 @param isTopDiff flag indicating to show the output in the top |
198 @param isTopDiff flag indicating to show the output in the top |
191 output widget (boolean) |
199 output widget (boolean) |
192 """ |
200 """ |
193 prefix, filenames = line.split(" a/", 1) |
201 prefix, filenames = line.split(" a/", 1) |
194 oldFile, newFile = filenames.split(" b/", 1) |
202 oldFile, newFile = filenames.split(" b/", 1) |
195 if isTopDiff: |
203 if isTopDiff: |
196 self.__fileSeparators.append((oldFile.strip(), newFile.strip(), |
204 self.__fileSeparators.append( |
197 len(self.__output1), -2)) |
205 (oldFile.strip(), newFile.strip(), len(self.__output1), -2) |
|
206 ) |
198 else: |
207 else: |
199 self.__fileSeparators.append((oldFile.strip(), newFile.strip(), |
208 self.__fileSeparators.append( |
200 -2, len(self.__output2))) |
209 (oldFile.strip(), newFile.strip(), -2, len(self.__output2)) |
201 |
210 ) |
|
211 |
202 def __processLine(self, line, isTopDiff): |
212 def __processLine(self, line, isTopDiff): |
203 """ |
213 """ |
204 Private method to process one line of output. |
214 Private method to process one line of output. |
205 |
215 |
206 @param line output line to process (string) |
216 @param line output line to process (string) |
207 @param isTopDiff flag indicating to show the output in the top |
217 @param isTopDiff flag indicating to show the output in the top |
208 output widget (boolean) |
218 output widget (boolean) |
209 """ |
219 """ |
210 if line.startswith("diff --git"): |
220 if line.startswith("diff --git"): |
211 self.__processFileLine(line, isTopDiff) |
221 self.__processFileLine(line, isTopDiff) |
212 |
222 |
213 if isTopDiff: |
223 if isTopDiff: |
214 self.__output1.append(line) |
224 self.__output1.append(line) |
215 else: |
225 else: |
216 self.__output2.append(line) |
226 self.__output2.append(line) |
217 |
227 |
218 def __readStdout(self, process): |
228 def __readStdout(self, process): |
219 """ |
229 """ |
220 Private slot to handle the readyReadStandardOutput signal. |
230 Private slot to handle the readyReadStandardOutput signal. |
221 |
231 |
222 It reads the output of the process, formats it and inserts it into |
232 It reads the output of the process, formats it and inserts it into |
223 the contents pane. |
233 the contents pane. |
224 |
234 |
225 @param process reference to the process providing output |
235 @param process reference to the process providing output |
226 @type QProcess |
236 @type QProcess |
227 """ |
237 """ |
228 process.setReadChannel(QProcess.ProcessChannel.StandardOutput) |
238 process.setReadChannel(QProcess.ProcessChannel.StandardOutput) |
229 |
239 |
230 isTopDiff = process == self.__process |
240 isTopDiff = process == self.__process |
231 |
241 |
232 while process.canReadLine(): |
242 while process.canReadLine(): |
233 line = str(process.readLine(), self.__ioEncoding, |
243 line = str(process.readLine(), self.__ioEncoding, "replace") |
234 'replace') |
|
235 self.__processLine(line, isTopDiff) |
244 self.__processLine(line, isTopDiff) |
236 |
245 |
237 def __readStderr(self, process): |
246 def __readStderr(self, process): |
238 """ |
247 """ |
239 Private slot to handle the readyReadStandardError signal. |
248 Private slot to handle the readyReadStandardError signal. |
240 |
249 |
241 It reads the error output of the process and inserts it into the |
250 It reads the error output of the process and inserts it into the |
242 error pane. |
251 error pane. |
243 |
252 |
244 @param process reference to the process providing error output |
253 @param process reference to the process providing error output |
245 @type QProcess |
254 @type QProcess |
246 """ |
255 """ |
247 s = str(process.readAllStandardError(), self.__ioEncoding, |
256 s = str(process.readAllStandardError(), self.__ioEncoding, "replace") |
248 'replace') |
|
249 self.__errors.append(s) |
257 self.__errors.append(s) |