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

branch
eric7
changeset 11075
282fc28b44ee
child 11076
2989645b2618
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/Plugins/VcsPlugins/vcsMercurial/FastexportExtension/fastexport.py	Tue Dec 03 14:21:36 2024 +0100
@@ -0,0 +1,187 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2025 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the fastexport extension interface.
+"""
+
+import os
+
+from PyQt6.QtCore import QProcess, pyqtSlot
+from PyQt6.QtWidgets import QDialog
+
+from eric7.EricWidgets import EricMessageBox
+from eric7.EricWidgets.EricProgressDialog import EricProgressDialog
+
+from ..HgExtension import HgExtension
+from ..HgUtilities import getHgExecutable
+
+
+class Fastexport(HgExtension):
+    """
+    Class implementing the fastexport extension interface.
+    """
+
+    def __init__(self, vcs, ui=None):
+        """
+        Constructor
+
+        @param vcs reference to the Mercurial vcs object
+        @type Hg
+        @param ui reference to a UI widget (defaults to None)
+        @type QWidget
+        """
+        super().__init__(vcs, ui=ui)
+
+        self.__process = None
+        self.__progress = None
+
+    def hgFastexport(self, revisions=None):
+        """
+        Public method to export the repository as a git fast-import stream.
+
+        @param revisions list of revisions to be exported
+        @type list of str
+        """
+        from .HgFastexportConfigDialog import HgFastexportConfigDialog
+
+        dlg = HgFastexportConfigDialog(revisions=revisions, parent=self.ui)
+        if dlg.exec() == QDialog.DialogCode.Accepted:
+            outputFile, revisions, authormap, importMarks, exportMarks = dlg.getData()
+
+            if os.path.exists(outputFile):
+                overwrite = EricMessageBox.yesNo(
+                    self.ui,
+                    self.tr("Mercurial Fastexport"),
+                    self.tr(
+                        "<p>The output file <b>{0}</b> exists already. Overwrite it?"
+                        "</p>"
+                    ).format(outputFile),
+                )
+                if not overwrite:
+                    return
+
+            repoPath = self.vcs.getClient().getRepository()
+            hgExecutable = getHgExecutable()
+
+            args = self.vcs.initCommand("fastexport")
+            args.extend(["--config", "progress.assume-tty=True"])
+            args.extend(["--config", "progress.format=topic number estimate"])
+            if authormap:
+                args.extend(["--authormap", authormap])
+            if importMarks:
+                args.extend(["--import-marks", importMarks])
+            if exportMarks:
+                args.extend(["--export-marks", exportMarks])
+            for revision in revisions:
+                args.extend(["--rev", revision])
+
+            self.__progress = None
+
+            self.__process = QProcess(parent=self)
+            self.__process.setStandardOutputFile(outputFile)
+            self.__process.setWorkingDirectory(repoPath)
+            self.__process.readyReadStandardError.connect(self.__readStderr)
+            self.__process.finished.connect(self.__processFinished)
+            self.__process.start(hgExecutable, args)
+
+    @pyqtSlot()
+    def __readStderr(self):
+        """
+        Private slot to handle the readyReadStandardError signal.
+        """
+        if self.__process is not None:
+            output = str(
+                self.__process.readAllStandardError(), self.vcs.getEncoding(), "replace"
+            )
+            if output.lstrip().startswith("exporting "):
+                msg = output.splitlines()[-1]
+                topic, number, estimate = msg.split(None, 2)
+                value, maximum = number.split("/", 1)
+                if self.__progress is None:
+                    self.__progress = EricProgressDialog(
+                        labelText="",
+                        cancelButtonText=self.tr("Cancel"),
+                        minimum=0,
+                        maximum=int(maximum),
+                        labelFormat=self.tr("%v/%m Changesets"),
+                        parent=self.ui,
+                    )
+                    self.__progress.setWindowTitle(self.tr("Mercurial Fastexport"))
+                    self.__progress.show()
+                self.__progress.setLabelText(
+                    self.tr("Exporting repository (time remaining: {0}) ...").format(
+                        estimate
+                    )
+                )
+                self.__progress.setValue(int(value))
+
+                if self.__progress.wasCanceled() and self.__process is not None:
+                    self.__process.terminate()
+
+            else:
+                if (
+                    self.__progress
+                    and not self.__progress.wasCanceled()
+                    and self.output.strip()
+                ):
+                    EricMessageBox.warning(
+                        self.ui,
+                        self.tr("Mercurial Fastexport"),
+                        self.tr(
+                            "<p>The repository fastexport process sent an error"
+                            " message.</p><p>{0}</p>"
+                        ).format(output.strip()),
+                    )
+
+    @pyqtSlot(int, QProcess.ExitStatus)
+    def __processFinished(self, exitCode, exitStatus):
+        """
+        Private slot to handle the process finished signal.
+
+        @param exitCode exit code of the process
+        @type int
+        @param exitStatus exit status
+        @type QProcess.ExitStatus
+        """
+        if self.__progress is not None:
+            self.__progress.hide()
+            self.__progress.deleteLater()
+            self.__progress = None
+
+        if exitStatus == QProcess.ExitStatus.NormalExit:
+            if exitCode == 0:
+                EricMessageBox.information(
+                    self.ui,
+                    self.tr("Mercurial Fastexport"),
+                    self.tr(
+                        "<p>The repository fastexport process finished"
+                        " successfully.</p>"
+                    ),
+                )
+            elif exitCode == 255:
+                EricMessageBox.warning(
+                    self.ui,
+                    self.tr("Mercurial Fastexport"),
+                    self.tr("<p>The repository fastexport process was cancelled.</p>"),
+                )
+            else:
+                EricMessageBox.warning(
+                    self.ui,
+                    self.tr("Mercurial Fastexport"),
+                    self.tr(
+                        "<p>The repository fastexport process finished"
+                        " with exit code <b>{0}</b>.</p>"
+                    ).format(exitCode),
+                )
+        else:
+            EricMessageBox.critical(
+                self.ui,
+                self.tr("Mercurial Fastexport"),
+                self.tr("<p>The repository fastexport process crashed.</p>"),
+            )
+
+        self.__process.deleteLater()
+        self.__process = None

eric ide

mercurial