src/eric7/Plugins/VcsPlugins/vcsMercurial/FastexportExtension/fastexport.py

branch
eric7
changeset 11075
282fc28b44ee
child 11076
2989645b2618
equal deleted inserted replaced
11074:97f6160548a6 11075:282fc28b44ee
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2025 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the fastexport extension interface.
8 """
9
10 import os
11
12 from PyQt6.QtCore import QProcess, pyqtSlot
13 from PyQt6.QtWidgets import QDialog
14
15 from eric7.EricWidgets import EricMessageBox
16 from eric7.EricWidgets.EricProgressDialog import EricProgressDialog
17
18 from ..HgExtension import HgExtension
19 from ..HgUtilities import getHgExecutable
20
21
22 class Fastexport(HgExtension):
23 """
24 Class implementing the fastexport extension interface.
25 """
26
27 def __init__(self, vcs, ui=None):
28 """
29 Constructor
30
31 @param vcs reference to the Mercurial vcs object
32 @type Hg
33 @param ui reference to a UI widget (defaults to None)
34 @type QWidget
35 """
36 super().__init__(vcs, ui=ui)
37
38 self.__process = None
39 self.__progress = None
40
41 def hgFastexport(self, revisions=None):
42 """
43 Public method to export the repository as a git fast-import stream.
44
45 @param revisions list of revisions to be exported
46 @type list of str
47 """
48 from .HgFastexportConfigDialog import HgFastexportConfigDialog
49
50 dlg = HgFastexportConfigDialog(revisions=revisions, parent=self.ui)
51 if dlg.exec() == QDialog.DialogCode.Accepted:
52 outputFile, revisions, authormap, importMarks, exportMarks = dlg.getData()
53
54 if os.path.exists(outputFile):
55 overwrite = EricMessageBox.yesNo(
56 self.ui,
57 self.tr("Mercurial Fastexport"),
58 self.tr(
59 "<p>The output file <b>{0}</b> exists already. Overwrite it?"
60 "</p>"
61 ).format(outputFile),
62 )
63 if not overwrite:
64 return
65
66 repoPath = self.vcs.getClient().getRepository()
67 hgExecutable = getHgExecutable()
68
69 args = self.vcs.initCommand("fastexport")
70 args.extend(["--config", "progress.assume-tty=True"])
71 args.extend(["--config", "progress.format=topic number estimate"])
72 if authormap:
73 args.extend(["--authormap", authormap])
74 if importMarks:
75 args.extend(["--import-marks", importMarks])
76 if exportMarks:
77 args.extend(["--export-marks", exportMarks])
78 for revision in revisions:
79 args.extend(["--rev", revision])
80
81 self.__progress = None
82
83 self.__process = QProcess(parent=self)
84 self.__process.setStandardOutputFile(outputFile)
85 self.__process.setWorkingDirectory(repoPath)
86 self.__process.readyReadStandardError.connect(self.__readStderr)
87 self.__process.finished.connect(self.__processFinished)
88 self.__process.start(hgExecutable, args)
89
90 @pyqtSlot()
91 def __readStderr(self):
92 """
93 Private slot to handle the readyReadStandardError signal.
94 """
95 if self.__process is not None:
96 output = str(
97 self.__process.readAllStandardError(), self.vcs.getEncoding(), "replace"
98 )
99 if output.lstrip().startswith("exporting "):
100 msg = output.splitlines()[-1]
101 topic, number, estimate = msg.split(None, 2)
102 value, maximum = number.split("/", 1)
103 if self.__progress is None:
104 self.__progress = EricProgressDialog(
105 labelText="",
106 cancelButtonText=self.tr("Cancel"),
107 minimum=0,
108 maximum=int(maximum),
109 labelFormat=self.tr("%v/%m Changesets"),
110 parent=self.ui,
111 )
112 self.__progress.setWindowTitle(self.tr("Mercurial Fastexport"))
113 self.__progress.show()
114 self.__progress.setLabelText(
115 self.tr("Exporting repository (time remaining: {0}) ...").format(
116 estimate
117 )
118 )
119 self.__progress.setValue(int(value))
120
121 if self.__progress.wasCanceled() and self.__process is not None:
122 self.__process.terminate()
123
124 else:
125 if (
126 self.__progress
127 and not self.__progress.wasCanceled()
128 and self.output.strip()
129 ):
130 EricMessageBox.warning(
131 self.ui,
132 self.tr("Mercurial Fastexport"),
133 self.tr(
134 "<p>The repository fastexport process sent an error"
135 " message.</p><p>{0}</p>"
136 ).format(output.strip()),
137 )
138
139 @pyqtSlot(int, QProcess.ExitStatus)
140 def __processFinished(self, exitCode, exitStatus):
141 """
142 Private slot to handle the process finished signal.
143
144 @param exitCode exit code of the process
145 @type int
146 @param exitStatus exit status
147 @type QProcess.ExitStatus
148 """
149 if self.__progress is not None:
150 self.__progress.hide()
151 self.__progress.deleteLater()
152 self.__progress = None
153
154 if exitStatus == QProcess.ExitStatus.NormalExit:
155 if exitCode == 0:
156 EricMessageBox.information(
157 self.ui,
158 self.tr("Mercurial Fastexport"),
159 self.tr(
160 "<p>The repository fastexport process finished"
161 " successfully.</p>"
162 ),
163 )
164 elif exitCode == 255:
165 EricMessageBox.warning(
166 self.ui,
167 self.tr("Mercurial Fastexport"),
168 self.tr("<p>The repository fastexport process was cancelled.</p>"),
169 )
170 else:
171 EricMessageBox.warning(
172 self.ui,
173 self.tr("Mercurial Fastexport"),
174 self.tr(
175 "<p>The repository fastexport process finished"
176 " with exit code <b>{0}</b>.</p>"
177 ).format(exitCode),
178 )
179 else:
180 EricMessageBox.critical(
181 self.ui,
182 self.tr("Mercurial Fastexport"),
183 self.tr("<p>The repository fastexport process crashed.</p>"),
184 )
185
186 self.__process.deleteLater()
187 self.__process = None

eric ide

mercurial