eric7/Plugins/VcsPlugins/vcsMercurial/HgSummaryDialog.py

branch
eric7
changeset 8312
800c432b34c8
parent 8228
772103b14c18
child 8318
962bce857696
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Plugins/VcsPlugins/vcsMercurial/HgSummaryDialog.py	Sat May 15 18:45:04 2021 +0200
@@ -0,0 +1,373 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2013 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to show some summary information of the working
+directory state.
+"""
+
+from PyQt5.QtCore import pyqtSlot
+from PyQt5.QtWidgets import QDialog, QDialogButtonBox
+
+from .Ui_HgSummaryDialog import Ui_HgSummaryDialog
+
+
+class HgSummaryDialog(QDialog, Ui_HgSummaryDialog):
+    """
+    Class implementing a dialog to show some summary information of the working
+    directory state.
+    """
+    def __init__(self, vcs, parent=None):
+        """
+        Constructor
+        
+        @param vcs reference to the vcs object
+        @param parent parent widget (QWidget)
+        """
+        super().__init__(parent)
+        self.setupUi(self)
+        
+        self.refreshButton = self.buttonBox.addButton(
+            self.tr("Refresh"), QDialogButtonBox.ButtonRole.ActionRole)
+        self.refreshButton.setToolTip(
+            self.tr("Press to refresh the summary display"))
+        self.refreshButton.setEnabled(False)
+        
+        self.vcs = vcs
+        self.vcs.committed.connect(self.__committed)
+    
+    def start(self, mq=False, largefiles=False):
+        """
+        Public slot to start the hg summary command.
+        
+        @param mq flag indicating to show the queue status as well (boolean)
+        @param largefiles flag indicating to show the largefiles status as
+            well (boolean)
+        """
+        self.errorGroup.hide()
+        self.refreshButton.setEnabled(False)
+        self.summary.clear()
+        
+        self.__mq = mq
+        self.__largefiles = largefiles
+        
+        args = self.vcs.initCommand("summary")
+        if self.vcs.canPull():
+            args.append("--remote")
+        if self.__mq:
+            args.append("--mq")
+        if self.__largefiles:
+            args.append("--large")
+        
+        client = self.vcs.getClient()
+        output, error = client.runcommand(args)
+        if error:
+            self.__showError(error)
+        else:
+            self.__processOutput(output.splitlines())
+        
+        self.refreshButton.setEnabled(True)
+    
+    def on_buttonBox_clicked(self, button):
+        """
+        Private slot called by a button of the button box clicked.
+        
+        @param button button that was clicked (QAbstractButton)
+        """
+        if button == self.buttonBox.button(
+            QDialogButtonBox.StandardButton.Close
+        ):
+            self.close()
+        elif button == self.refreshButton:
+            self.on_refreshButton_clicked()
+    
+    @pyqtSlot()
+    def on_refreshButton_clicked(self):
+        """
+        Private slot to refresh the status display.
+        """
+        self.start(mq=self.__mq)
+    
+    def __committed(self):
+        """
+        Private slot called after the commit has finished.
+        """
+        if self.isVisible():
+            self.on_refreshButton_clicked()
+    
+    def __showError(self, out):
+        """
+        Private slot to show some error.
+        
+        @param out error to be shown (string)
+        """
+        self.errorGroup.show()
+        self.errors.insertPlainText(out)
+        self.errors.ensureCursorVisible()
+    
+    def __processOutput(self, output):
+        """
+        Private method to process the output into nice readable text.
+        
+        @param output output from the summary command (string)
+        """
+        infoDict = {}
+        
+        # step 1: parse the output
+        while output:
+            line = output.pop(0)
+            if ':' not in line:
+                continue
+            name, value = line.split(": ", 1)
+            value = value.strip()
+            
+            if name == "parent":
+                if " " in value:
+                    parent, tags = value.split(" ", 1)
+                else:
+                    parent = value
+                    tags = ""
+                rev, node = parent.split(":")
+                
+                remarks = []
+                if tags:
+                    if " (empty repository)" in tags:
+                        remarks.append("@EMPTY@")
+                        tags = tags.replace(" (empty repository)", "")
+                    if " (no revision checked out)" in tags:
+                        remarks.append("@NO_REVISION@")
+                        tags = tags.replace(" (no revision checked out)", "")
+                else:
+                    tags = None
+                
+                value = infoDict.get(name, [])
+                
+                if rev == "-1":
+                    value.append((int(rev), node, tags, None, remarks))
+                else:
+                    message = output.pop(0).strip()
+                    value.append((int(rev), node, tags, message, remarks))
+            elif name in ("branch", "bookmarks"):
+                pass
+            elif name == "commit":
+                stateDict = {}
+                if "(" in value:
+                    if value.startswith("("):
+                        states = ""
+                        remark = value[1:-1]
+                    else:
+                        states, remark = value.rsplit(" (", 1)
+                        remark = remark[:-1]
+                else:
+                    states = value
+                    remark = ""
+                states = states.split(", ")
+                for state in states:
+                    if state:
+                        count, category = state.split(" ")
+                        stateDict[category] = count
+                value = (stateDict, remark)
+            elif name == "update":
+                if value.endswith("(current)"):
+                    value = ("@CURRENT@", 0, 0)
+                elif value.endswith("(update)"):
+                    value = ("@UPDATE@", int(value.split(" ", 1)[0]), 0)
+                elif value.endswith("(merge)"):
+                    parts = value.split(", ")
+                    value = ("@MERGE@", int(parts[0].split(" ", 1)[0]),
+                             int(parts[1].split(" ", 1)[0]))
+                else:
+                    value = ("@UNKNOWN@", 0, 0)
+            elif name == "remote":
+                if value == "(synced)":
+                    value = (0, 0, 0, 0)
+                else:
+                    inc = incb = outg = outgb = 0
+                    for val in value.split(", "):
+                        count, category = val.split(" ", 1)
+                        if category == "outgoing":
+                            outg = int(count)
+                        elif category.endswith("incoming"):
+                            inc = int(count)
+                        elif category == "incoming bookmarks":
+                            incb = int(count)
+                        elif category == "outgoing bookmarks":
+                            outgb = int(count)
+                    value = (inc, outg, incb, outgb)
+            elif name == "mq":
+                if value == "(empty queue)":
+                    value = (0, 0)
+                else:
+                    applied = unapplied = 0
+                    for val in value.split(", "):
+                        count, category = val.split(" ", 1)
+                        if category == "applied":
+                            applied = int(count)
+                        elif category == "unapplied":
+                            unapplied = int(count)
+                    value = (applied, unapplied)
+            elif name == "largefiles":
+                if not value[0].isdigit():
+                    value = 0
+                else:
+                    value = int(value.split(None, 1)[0])
+            else:
+                # ignore unknown entries
+                continue
+            
+            infoDict[name] = value
+        
+        # step 2: build the output
+        if infoDict:
+            info = ["<table>"]
+            for pindex, (rev, node, tags, message, remarks) in enumerate(
+                infoDict["parent"], start=1
+            ):
+                changeset = "{0}:{1}".format(rev, node)
+                if len(infoDict["parent"]) > 1:
+                    info.append(self.tr(
+                        "<tr><td><b>Parent #{0}</b></td><td>{1}</td></tr>")
+                        .format(pindex, changeset))
+                else:
+                    info.append(self.tr(
+                        "<tr><td><b>Parent</b></td><td>{0}</td></tr>")
+                        .format(changeset))
+                if tags:
+                    info.append(self.tr(
+                        "<tr><td><b>Tags</b></td><td>{0}</td></tr>")
+                        .format('<br/>'.join(tags.split())))
+                if message:
+                    info.append(self.tr(
+                        "<tr><td><b>Commit Message</b></td><td>{0}</td></tr>")
+                        .format(message))
+                if remarks:
+                    rem = []
+                    if "@EMPTY@" in remarks:
+                        rem.append(self.tr("empty repository"))
+                    if "@NO_REVISION@" in remarks:
+                        rem.append(self.tr("no revision checked out"))
+                    info.append(self.tr(
+                        "<tr><td><b>Remarks</b></td><td>{0}</td></tr>")
+                        .format(", ".join(rem)))
+            if "branch" in infoDict:
+                info.append(self.tr(
+                    "<tr><td><b>Branch</b></td><td>{0}</td></tr>")
+                    .format(infoDict["branch"]))
+            if "bookmarks" in infoDict:
+                bookmarks = infoDict["bookmarks"].split()
+                for i in range(len(bookmarks)):
+                    if bookmarks[i].startswith("*"):
+                        bookmarks[i] = "<b>{0}</b>".format(bookmarks[i])
+                info.append(self.tr(
+                    "<tr><td><b>Bookmarks</b></td><td>{0}</td></tr>")
+                    .format('<br/>'.join(bookmarks)))
+            if "commit" in infoDict:
+                cinfo = []
+                for category, count in infoDict["commit"][0].items():
+                    if category == "modified":
+                        cinfo.append(self.tr("{0} modified").format(count))
+                    elif category == "added":
+                        cinfo.append(self.tr("{0} added").format(count))
+                    elif category == "removed":
+                        cinfo.append(self.tr("{0} removed").format(count))
+                    elif category == "renamed":
+                        cinfo.append(self.tr("{0} renamed").format(count))
+                    elif category == "copied":
+                        cinfo.append(self.tr("{0} copied").format(count))
+                    elif category == "deleted":
+                        cinfo.append(self.tr("{0} deleted").format(count))
+                    elif category == "unknown":
+                        cinfo.append(self.tr("{0} unknown").format(count))
+                    elif category == "ignored":
+                        cinfo.append(self.tr("{0} ignored").format(count))
+                    elif category == "unresolved":
+                        cinfo.append(
+                            self.tr("{0} unresolved").format(count))
+                    elif category == "subrepos":
+                        cinfo.append(self.tr("{0} subrepos").format(count))
+                remark = infoDict["commit"][1]
+                if remark == "merge":
+                    cinfo.append(self.tr("Merge needed"))
+                elif remark == "new branch":
+                    cinfo.append(self.tr("New Branch"))
+                elif remark == "head closed":
+                    cinfo.append(self.tr("Head is closed"))
+                elif remark == "clean":
+                    cinfo.append(self.tr("No commit required"))
+                elif remark == "new branch head":
+                    cinfo.append(self.tr("New Branch Head"))
+                info.append(self.tr(
+                    "<tr><td><b>Commit Status</b></td><td>{0}</td></tr>")
+                    .format("<br/>".join(cinfo)))
+            if "update" in infoDict:
+                if infoDict["update"][0] == "@CURRENT@":
+                    uinfo = self.tr("current")
+                elif infoDict["update"][0] == "@UPDATE@":
+                    uinfo = self.tr(
+                        "%n new changeset(s)<br/>Update required", "",
+                        infoDict["update"][1])
+                elif infoDict["update"][0] == "@MERGE@":
+                    uinfo1 = self.tr(
+                        "%n new changeset(s)", "", infoDict["update"][1])
+                    uinfo2 = self.tr(
+                        "%n branch head(s)", "", infoDict["update"][2])
+                    uinfo = self.tr(
+                        "{0}<br/>{1}<br/>Merge required",
+                        "0 is changesets, 1 is branch heads"
+                    ).format(uinfo1, uinfo2)
+                else:
+                    uinfo = self.tr("unknown status")
+                info.append(self.tr(
+                    "<tr><td><b>Update Status</b></td><td>{0}</td></tr>")
+                    .format(uinfo))
+            if "remote" in infoDict:
+                if infoDict["remote"] == (0, 0, 0, 0):
+                    rinfo = self.tr("synched")
+                else:
+                    li = []
+                    if infoDict["remote"][0]:
+                        li.append(self.tr("1 or more incoming changesets"))
+                    if infoDict["remote"][1]:
+                        li.append(self.tr("%n outgoing changeset(s)", "",
+                                  infoDict["remote"][1]))
+                    if infoDict["remote"][2]:
+                        li.append(self.tr("%n incoming bookmark(s)", "",
+                                  infoDict["remote"][2]))
+                    if infoDict["remote"][3]:
+                        li.append(self.tr("%n outgoing bookmark(s)", "",
+                                  infoDict["remote"][3]))
+                    rinfo = "<br/>".join(li)
+                info.append(self.tr(
+                    "<tr><td><b>Remote Status</b></td><td>{0}</td></tr>")
+                    .format(rinfo))
+            if "mq" in infoDict:
+                if infoDict["mq"] == (0, 0):
+                    qinfo = self.tr("empty queue")
+                else:
+                    li = []
+                    if infoDict["mq"][0]:
+                        li.append(self.tr("{0} applied")
+                                  .format(infoDict["mq"][0]))
+                    if infoDict["mq"][1]:
+                        li.append(self.tr("{0} unapplied")
+                                  .format(infoDict["mq"][1]))
+                    qinfo = "<br/>".join(li)
+                info.append(self.tr(
+                    "<tr><td><b>Queues Status</b></td><td>{0}</td></tr>")
+                    .format(qinfo))
+            if "largefiles" in infoDict:
+                if infoDict["largefiles"] == 0:
+                    lfInfo = self.tr("No files to upload")
+                else:
+                    lfInfo = self.tr("%n file(s) to upload", "",
+                                     infoDict["largefiles"])
+                info.append(self.tr(
+                    "<tr><td><b>Large Files</b></td><td>{0}</td></tr>")
+                    .format(lfInfo))
+            info.append("</table>")
+        else:
+            info = [self.tr("<p>No status information available.</p>")]
+        
+        self.summary.insertHtml("\n".join(info))

eric ide

mercurial