60 self.mode = "log" |
59 self.mode = "log" |
61 self.bundle = bundle |
60 self.bundle = bundle |
62 self.__hgClient = self.vcs.getClient() |
61 self.__hgClient = self.vcs.getClient() |
63 |
62 |
64 self.contents.setHtml( |
63 self.contents.setHtml( |
65 self.trUtf8('<b>Processing your request, please wait...</b>')) |
64 self.tr('<b>Processing your request, please wait...</b>')) |
66 |
65 |
67 self.process.finished.connect(self.__procFinished) |
66 self.process.finished.connect(self.__procFinished) |
68 self.process.readyReadStandardOutput.connect(self.__readStdout) |
67 self.process.readyReadStandardOutput.connect(self.__readStdout) |
69 self.process.readyReadStandardError.connect(self.__readStderr) |
68 self.process.readyReadStandardError.connect(self.__readStderr) |
70 |
69 |
71 self.contents.anchorClicked.connect(self.__sourceChanged) |
70 self.contents.anchorClicked.connect(self.__sourceChanged) |
72 |
71 |
73 self.revisions = [] # stack of remembered revisions |
72 self.revisions = [] # stack of remembered revisions |
74 self.revString = self.trUtf8('Revision') |
73 self.revString = self.tr('Revision') |
75 self.projectMode = False |
74 self.projectMode = False |
76 |
75 |
77 self.logEntries = [] # list of log entries |
76 self.logEntries = [] # list of log entries |
78 self.lastLogEntry = {} |
77 self.lastLogEntry = {} |
79 self.fileCopies = {} |
78 self.fileCopies = {} |
128 self.projectMode = (self.fname == "." and self.dname == self.repodir) |
127 self.projectMode = (self.fname == "." and self.dname == self.repodir) |
129 |
128 |
130 self.activateWindow() |
129 self.activateWindow() |
131 self.raise_() |
130 self.raise_() |
132 |
131 |
133 args = [] |
132 preargs = [] |
134 args.append(self.mode) |
133 args = self.vcs.initCommand(self.mode) |
135 self.vcs.addArguments(args, self.vcs.options['global']) |
|
136 self.vcs.addArguments(args, self.vcs.options['log']) |
|
137 if noEntries and self.mode == "log": |
134 if noEntries and self.mode == "log": |
138 args.append('--limit') |
135 args.append('--limit') |
139 args.append(str(noEntries)) |
136 args.append(str(noEntries)) |
140 if self.mode in ("incoming", "outgoing"): |
137 if self.mode in ("incoming", "outgoing"): |
141 args.append("--newest-first") |
138 args.append("--newest-first") |
158 args.append(self.bundle) |
155 args.append(self.bundle) |
159 elif not self.vcs.hasSubrepositories(): |
156 elif not self.vcs.hasSubrepositories(): |
160 project = e5App().getObject("Project") |
157 project = e5App().getObject("Project") |
161 self.vcs.bundleFile = os.path.join( |
158 self.vcs.bundleFile = os.path.join( |
162 project.getProjectManagementDir(), "hg-bundle.hg") |
159 project.getProjectManagementDir(), "hg-bundle.hg") |
163 args.append('--bundle') |
160 if os.path.exists(self.vcs.bundleFile): |
|
161 os.remove(self.vcs.bundleFile) |
|
162 preargs = args[:] |
|
163 preargs.append("--quiet") |
|
164 preargs.append('--bundle') |
|
165 preargs.append(self.vcs.bundleFile) |
164 args.append(self.vcs.bundleFile) |
166 args.append(self.vcs.bundleFile) |
165 if revisions: |
167 if revisions: |
166 for rev in revisions: |
168 for rev in revisions: |
167 args.append("--rev") |
169 args.append("--rev") |
168 args.append(rev) |
170 args.append(rev) |
171 |
173 |
172 if self.__hgClient: |
174 if self.__hgClient: |
173 self.inputGroup.setEnabled(False) |
175 self.inputGroup.setEnabled(False) |
174 self.inputGroup.hide() |
176 self.inputGroup.hide() |
175 |
177 |
176 out, err = self.__hgClient.runcommand(args) |
178 if preargs: |
177 |
179 out, err = self.__hgClient.runcommand(preargs) |
|
180 else: |
|
181 err = "" |
178 if err: |
182 if err: |
179 self.__showError(err) |
183 self.__showError(err) |
180 if out and self.isVisible(): |
184 elif self.mode != "incoming" or \ |
181 for line in out.splitlines(True): |
185 (self.vcs.bundleFile and |
182 self.__processOutputLine(line) |
186 os.path.exists(self.vcs.bundleFile)) or \ |
183 if self.__hgClient.wasCanceled(): |
187 self.bundle: |
184 break |
188 out, err = self.__hgClient.runcommand(args) |
185 |
189 if err: |
|
190 self.__showError(err) |
|
191 if out and self.isVisible(): |
|
192 for line in out.splitlines(True): |
|
193 self.__processOutputLine(line) |
|
194 if self.__hgClient.wasCanceled(): |
|
195 break |
186 self.__finish() |
196 self.__finish() |
187 else: |
197 else: |
188 self.process.kill() |
198 self.process.kill() |
189 |
199 |
190 self.process.setWorkingDirectory(self.repodir) |
200 self.process.setWorkingDirectory(self.repodir) |
191 |
201 |
192 self.process.start('hg', args) |
202 if preargs: |
193 procStarted = self.process.waitForStarted(5000) |
203 process = QProcess() |
194 if not procStarted: |
204 process.setWorkingDirectory(self.repodir) |
195 self.inputGroup.setEnabled(False) |
205 process.start('hg', args) |
196 self.inputGroup.hide() |
206 procStarted = process.waitForStarted(5000) |
197 E5MessageBox.critical( |
207 if procStarted: |
198 self, |
208 process.waitForFinished(30000) |
199 self.trUtf8('Process Generation Error'), |
209 |
200 self.trUtf8( |
210 if self.mode != "incoming" or \ |
201 'The process {0} could not be started. ' |
211 (self.vcs.bundleFile and |
202 'Ensure, that it is in the search path.' |
212 os.path.exists(self.vcs.bundleFile)) or \ |
203 ).format('hg')) |
213 self.bundle: |
|
214 self.process.start('hg', args) |
|
215 procStarted = self.process.waitForStarted(5000) |
|
216 if not procStarted: |
|
217 self.inputGroup.setEnabled(False) |
|
218 self.inputGroup.hide() |
|
219 E5MessageBox.critical( |
|
220 self, |
|
221 self.tr('Process Generation Error'), |
|
222 self.tr( |
|
223 'The process {0} could not be started. ' |
|
224 'Ensure, that it is in the search path.' |
|
225 ).format('hg')) |
|
226 else: |
|
227 self.__finish() |
204 |
228 |
205 def __getParents(self, rev): |
229 def __getParents(self, rev): |
206 """ |
230 """ |
207 Private method to get the parents of the currently viewed |
231 Private method to get the parents of the currently viewed |
208 file/directory. |
232 file/directory. |
240 process.start('hg', args) |
263 process.start('hg', args) |
241 procStarted = process.waitForStarted(5000) |
264 procStarted = process.waitForStarted(5000) |
242 if procStarted: |
265 if procStarted: |
243 finished = process.waitForFinished(30000) |
266 finished = process.waitForFinished(30000) |
244 if finished and process.exitCode() == 0: |
267 if finished and process.exitCode() == 0: |
245 output = \ |
268 output = str(process.readAllStandardOutput(), |
246 str(process.readAllStandardOutput(), |
269 self.vcs.getEncoding(), 'replace') |
247 Preferences.getSystem("IOEncoding"), |
|
248 'replace') |
|
249 else: |
270 else: |
250 if not finished: |
271 if not finished: |
251 errMsg = self.trUtf8( |
272 errMsg = self.tr( |
252 "The hg process did not finish within 30s.") |
273 "The hg process did not finish within 30s.") |
253 else: |
274 else: |
254 errMsg = self.trUtf8("Could not start the hg executable.") |
275 errMsg = self.tr("Could not start the hg executable.") |
255 |
276 |
256 if errMsg: |
277 if errMsg: |
257 E5MessageBox.critical( |
278 E5MessageBox.critical( |
258 self, |
279 self, |
259 self.trUtf8("Mercurial Error"), |
280 self.tr("Mercurial Error"), |
260 errMsg) |
281 errMsg) |
261 |
282 |
262 if output: |
283 if output: |
263 parents = [p for p in output.strip().splitlines()] |
284 parents = [p for p in output.strip().splitlines()] |
264 |
285 |
318 query.append(parent.split(":")[0]).append('_').append(rev) |
339 query.append(parent.split(":")[0]).append('_').append(rev) |
319 url.setEncodedQuery(query) |
340 url.setEncodedQuery(query) |
320 dstr += ' [<a href="{0}" name="{1}" id="{1}">{2}</a>]'.format( |
341 dstr += ' [<a href="{0}" name="{1}" id="{1}">{2}</a>]'.format( |
321 url.toString(), |
342 url.toString(), |
322 str(query, encoding="ascii"), |
343 str(query, encoding="ascii"), |
323 self.trUtf8('diff to {0}').format(parent), |
344 self.tr('diff to {0}').format(parent), |
324 ) |
345 ) |
325 dstr += '<br />\n' |
346 dstr += '<br />\n' |
326 html += dstr |
347 html += dstr |
327 |
348 |
328 if "phase" in entry: |
349 if "phase" in entry: |
329 html += self.trUtf8("Phase: {0}<br />\n")\ |
350 html += self.tr("Phase: {0}<br />\n")\ |
330 .format(entry["phase"]) |
351 .format(entry["phase"]) |
331 |
352 |
332 html += self.trUtf8("Branches: {0}<br />\n")\ |
353 html += self.tr("Branches: {0}<br />\n")\ |
333 .format(entry["branches"]) |
354 .format(entry["branches"]) |
334 |
355 |
335 html += self.trUtf8("Tags: {0}<br />\n").format(entry["tags"]) |
356 html += self.tr("Tags: {0}<br />\n").format(entry["tags"]) |
336 |
357 |
337 if "bookmarks" in entry: |
358 if "bookmarks" in entry: |
338 html += self.trUtf8("Bookmarks: {0}<br />\n")\ |
359 html += self.tr("Bookmarks: {0}<br />\n")\ |
339 .format(entry["bookmarks"]) |
360 .format(entry["bookmarks"]) |
340 |
361 |
341 html += self.trUtf8("Parents: {0}<br />\n")\ |
362 html += self.tr("Parents: {0}<br />\n")\ |
342 .format(entry["parents"]) |
363 .format(entry["parents"]) |
343 |
364 |
344 html += self.trUtf8('<i>Author: {0}</i><br />\n')\ |
365 html += self.tr('<i>Author: {0}</i><br />\n')\ |
345 .format(entry["user"]) |
366 .format(entry["user"]) |
346 |
367 |
347 date, time = entry["date"].split()[:2] |
368 date, time = entry["date"].split()[:2] |
348 html += self.trUtf8('<i>Date: {0}, {1}</i><br />\n')\ |
369 html += self.tr('<i>Date: {0}, {1}</i><br />\n')\ |
349 .format(date, time) |
370 .format(date, time) |
350 |
371 |
351 for line in entry["description"]: |
372 for line in entry["description"]: |
352 html += Utilities.html_encode(line.strip()) |
373 html += Utilities.html_encode(line.strip()) |
353 html += '<br />\n' |
374 html += '<br />\n' |
354 |
375 |
355 if entry["file_adds"]: |
376 if entry["file_adds"]: |
356 html += '<br />\n' |
377 html += '<br />\n' |
357 for f in entry["file_adds"].strip().split(", "): |
378 for f in entry["file_adds"].strip().split(", "): |
358 if f in fileCopies: |
379 if f in fileCopies: |
359 html += self.trUtf8( |
380 html += self.tr( |
360 'Added {0} (copied from {1})<br />\n')\ |
381 'Added {0} (copied from {1})<br />\n')\ |
361 .format(Utilities.html_encode(f), |
382 .format(Utilities.html_encode(f), |
362 Utilities.html_encode(fileCopies[f])) |
383 Utilities.html_encode(fileCopies[f])) |
363 else: |
384 else: |
364 html += self.trUtf8('Added {0}<br />\n')\ |
385 html += self.tr('Added {0}<br />\n')\ |
365 .format(Utilities.html_encode(f)) |
386 .format(Utilities.html_encode(f)) |
366 |
387 |
367 if entry["files_mods"]: |
388 if entry["files_mods"]: |
368 html += '<br />\n' |
389 html += '<br />\n' |
369 for f in entry["files_mods"].strip().split(", "): |
390 for f in entry["files_mods"].strip().split(", "): |
370 html += self.trUtf8('Modified {0}<br />\n')\ |
391 html += self.tr('Modified {0}<br />\n')\ |
371 .format(Utilities.html_encode(f)) |
392 .format(Utilities.html_encode(f)) |
372 |
393 |
373 if entry["file_dels"]: |
394 if entry["file_dels"]: |
374 html += '<br />\n' |
395 html += '<br />\n' |
375 for f in entry["file_dels"].strip().split(", "): |
396 for f in entry["file_dels"].strip().split(", "): |
376 html += self.trUtf8('Deleted {0}<br />\n')\ |
397 html += self.tr('Deleted {0}<br />\n')\ |
377 .format(Utilities.html_encode(f)) |
398 .format(Utilities.html_encode(f)) |
378 |
399 |
379 html += '</p>{0}<br/>\n'.format(80 * "=") |
400 html += '</p>{0}<br/>\n'.format(80 * "=") |
380 |
401 |
381 self.contents.setHtml(html) |
402 self.contents.setHtml(html) |
391 It reads the output of the process and inserts it into a buffer. |
412 It reads the output of the process and inserts it into a buffer. |
392 """ |
413 """ |
393 self.process.setReadChannel(QProcess.StandardOutput) |
414 self.process.setReadChannel(QProcess.StandardOutput) |
394 |
415 |
395 while self.process.canReadLine(): |
416 while self.process.canReadLine(): |
396 s = str(self.process.readLine(), |
417 s = str(self.process.readLine(), self.vcs.getEncoding(), 'replace') |
397 Preferences.getSystem("IOEncoding"), |
|
398 'replace') |
|
399 self.__processOutputLine(s) |
418 self.__processOutputLine(s) |
400 |
419 |
401 def __processOutputLine(self, line): |
420 def __processOutputLine(self, line): |
402 """ |
421 """ |
403 Private method to process the lines of output. |
422 Private method to process the lines of output. |
414 except ValueError: |
433 except ValueError: |
415 key = "" |
434 key = "" |
416 value = line |
435 value = line |
417 if key == "change": |
436 if key == "change": |
418 self.endInitialText = True |
437 self.endInitialText = True |
419 if key in ("change", "branches", "tags", "parents", "user", |
438 if key in ("change", "tags", "parents", "user", "date", |
420 "date", "file_copies", "file_adds", "files_mods", |
439 "file_copies", "file_adds", "files_mods", "file_dels", |
421 "file_dels", "bookmarks", "phase"): |
440 "bookmarks", "phase"): |
422 self.lastLogEntry[key] = value.strip() |
441 self.lastLogEntry[key] = value.strip() |
|
442 elif key == "branches": |
|
443 if value.strip(): |
|
444 self.lastLogEntry[key] = value.strip() |
|
445 else: |
|
446 self.lastLogEntry[key] = "default" |
423 elif key == "description": |
447 elif key == "description": |
424 self.lastLogEntry[key] = [value.strip()] |
448 self.lastLogEntry[key] = [value.strip()] |
425 else: |
449 else: |
426 if self.endInitialText: |
450 if self.endInitialText: |
427 self.lastLogEntry["description"].append(value.strip()) |
451 self.lastLogEntry["description"].append(value.strip()) |