Continued implementing an interface to the Mercurial command server.

Wed, 31 Aug 2011 18:44:04 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 31 Aug 2011 18:44:04 +0200
changeset 1255
e1d8a8a4d40c
parent 1254
c077fa008aae
child 1256
885706dbb69f

Continued implementing an interface to the Mercurial command server.
Modified part 2 of the queues extension and the status monitor thread.

Plugins/VcsPlugins/vcsMercurial/HgStatusMonitorThread.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListDialog.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListGuardsDialog.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesQueueManagementDialog.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsMercurial/QueuesExtension/queues.py file | annotate | diff | comparison | revisions
VCS/StatusMonitorThread.py file | annotate | diff | comparison | revisions
--- a/Plugins/VcsPlugins/vcsMercurial/HgStatusMonitorThread.py	Tue Aug 30 19:39:52 2011 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/HgStatusMonitorThread.py	Wed Aug 31 18:44:04 2011 +0200
@@ -10,6 +10,7 @@
 from PyQt4.QtCore import QProcess
 
 from VCS.StatusMonitorThread import VcsStatusMonitorThread
+from .HgClient import HgClient
 
 import Preferences
 
@@ -30,6 +31,9 @@
         VcsStatusMonitorThread.__init__(self, interval, project, vcs, parent)
         
         self.__ioEncoding = Preferences.getSystem("IOEncoding")
+        
+        self.__client = None
+        self.__useCommandLine = False
     
     def _performMonitor(self):
         """
@@ -54,66 +58,103 @@
         """
         self.shouldUpdate = False
         
-        process = QProcess()
+        if self.__client is None and not self.__useCommandLine:
+            if self.vcs.versionStr >= "1.9":
+                client = HgClient(self.projectDir, "utf-8")
+                ok, err = client.startServer()
+                if ok:
+                   self.__client = client
+                else:
+                    self.__useCommandLine = True
+            else:
+                self.__useCommandLine = True
+        
+        # step 1: get overall status
         args = []
         args.append('status')
         args.append('--noninteractive')
         args.append('--all')
-        process.setWorkingDirectory(self.projectDir)
-        process.start('hg', args)
-        procStarted = process.waitForStarted()
-        if procStarted:
-            finished = process.waitForFinished(300000)
-            if finished and process.exitCode() == 0:
-                output = \
-                    str(process.readAllStandardOutput(), self.__ioEncoding, 'replace')
-                states = {}
-                for line in output.splitlines():
-                    if not line.startswith("  "):
-                        flag, name = line.split(" ", 1)
-                        if flag in "AMR":
-                            if flag == "R":
-                                status = "O"
-                            else:
-                                status = flag
-                            states[name] = status
-                
-                args = []
-                args.append('resolve')
-                args.append('--list')
-                process.setWorkingDirectory(self.projectDir)
-                process.start('hg', args)
-                procStarted = process.waitForStarted()
-                if procStarted:
-                    finished = process.waitForFinished(300000)
-                    if finished and process.exitCode() == 0:
-                        output = str(
-                            process.readAllStandardOutput(), self.__ioEncoding, 'replace')
-                        for line in output.splitlines():
-                            flag, name = line.split(" ", 1)
-                            if flag == "U":
-                                states[name] = "Z"  # conflict
-                
-                for name in states:
-                    try:
-                        if self.reportedStates[name] != states[name]:
-                            self.statusList.append("{0} {1}".format(states[name], name))
-                    except KeyError:
-                        self.statusList.append("{0} {1}".format(states[name], name))
-                for name in self.reportedStates.keys():
-                    if name not in states:
-                        self.statusList.append("  {0}".format(name))
-                self.reportedStates = states
-                return True, \
-                       self.trUtf8("Mercurial status checked successfully")
+        
+        output = ""
+        error = ""
+        if self.__client:
+            output, error = self.__client.runcommand(args)
+        else:
+            process = QProcess()
+            process.setWorkingDirectory(self.projectDir)
+            process.start('hg', args)
+            procStarted = process.waitForStarted()
+            if procStarted:
+                finished = process.waitForFinished(300000)
+                if finished and process.exitCode() == 0:
+                    output = \
+                        str(process.readAllStandardOutput(), self.__ioEncoding, 'replace')
+                else:
+                    process.kill()
+                    process.waitForFinished()
+                    error = \
+                        str(process.readAllStandardError(), self.__ioEncoding, 'replace')
             else:
                 process.kill()
                 process.waitForFinished()
-                return False, \
-                       str(process.readAllStandardError(),
-                            Preferences.getSystem("IOEncoding"),
-                            'replace')
+                error = self.trUtf8("Could not start the Mercurial process.")
+        
+        if error:
+            return False, error
+        
+        states = {}
+        for line in output.splitlines():
+            if not line.startswith("  "):
+                flag, name = line.split(" ", 1)
+                if flag in "AMR":
+                    if flag == "R":
+                        status = "O"
+                    else:
+                        status = flag
+                    states[name] = status
+        
+        # step 2: get conflicting changes
+        args = []
+        args.append('resolve')
+        args.append('--list')
+        
+        output = ""
+        error = ""
+        if self.__client:
+            output, error = self.__client.runcommand(args)
         else:
-            process.kill()
-            process.waitForFinished()
-            return False, self.trUtf8("Could not start the Mercurial process.")
+            process.setWorkingDirectory(self.projectDir)
+            process.start('hg', args)
+            procStarted = process.waitForStarted()
+            if procStarted:
+                finished = process.waitForFinished(300000)
+                if finished and process.exitCode() == 0:
+                    output = str(
+                        process.readAllStandardOutput(), self.__ioEncoding, 'replace')
+        
+        for line in output.splitlines():
+            flag, name = line.split(" ", 1)
+            if flag == "U":
+                states[name] = "Z"  # conflict
+        
+        # step 3: collect the status to be reported back
+        for name in states:
+            try:
+                if self.reportedStates[name] != states[name]:
+                    self.statusList.append("{0} {1}".format(states[name], name))
+            except KeyError:
+                self.statusList.append("{0} {1}".format(states[name], name))
+        for name in self.reportedStates.keys():
+            if name not in states:
+                self.statusList.append("  {0}".format(name))
+        self.reportedStates = states
+        
+        return True, \
+               self.trUtf8("Mercurial status checked successfully")
+    
+    def _shutdown(self):
+        """
+        Protected method performing shutdown actions.
+        """
+        if self.__client:
+            self.__client.stopServer()
--- a/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListDialog.py	Tue Aug 30 19:39:52 2011 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListDialog.py	Wed Aug 31 18:44:04 2011 +0200
@@ -39,6 +39,7 @@
         
         self.process = QProcess()
         self.vcs = vcs
+        self.__hgClient = vcs.getClient()
         
         self.patchesList.header().setSortIndicator(0, Qt.AscendingOrder)
         
@@ -110,23 +111,40 @@
         if missing:
             args.append('--missing')
         
-        self.process.kill()
-        self.process.setWorkingDirectory(self.__repodir)
-        
-        self.process.start('hg', args)
-        procStarted = self.process.waitForStarted()
-        if not procStarted:
+        if self.__hgClient:
             self.inputGroup.setEnabled(False)
             self.inputGroup.hide()
-            E5MessageBox.critical(self,
-                self.trUtf8('Process Generation Error'),
-                self.trUtf8(
-                    'The process {0} could not be started. '
-                    'Ensure, that it is in the search path.'
-                ).format('hg'))
+            
+            out, err = self.__hgClient.runcommand(args)
+            if err:
+                self.__showError(err)
+            if out:
+                for line in out.splitlines():
+                    self.__processOutputLine(line)
+            if self.__mode == "qseries":
+                self.__getSeries(True)
+            elif self.__mode == "missing":
+                self.__getTop()
+            else:
+                self.__finish()
         else:
-            self.inputGroup.setEnabled(True)
-            self.inputGroup.show()
+            self.process.kill()
+            self.process.setWorkingDirectory(self.__repodir)
+            
+            self.process.start('hg', args)
+            procStarted = self.process.waitForStarted()
+            if not procStarted:
+                self.inputGroup.setEnabled(False)
+                self.inputGroup.hide()
+                E5MessageBox.critical(self,
+                    self.trUtf8('Process Generation Error'),
+                    self.trUtf8(
+                        'The process {0} could not be started. '
+                        'Ensure, that it is in the search path.'
+                    ).format('hg'))
+            else:
+                self.inputGroup.setEnabled(True)
+                self.inputGroup.show()
     
     def __getTop(self):
         """
@@ -137,23 +155,35 @@
         args = []
         args.append('qtop')
         
-        self.process.kill()
-        self.process.setWorkingDirectory(self.__repodir)
-        
-        self.process.start('hg', args)
-        procStarted = self.process.waitForStarted()
-        if not procStarted:
+        if self.__hgClient:
             self.inputGroup.setEnabled(False)
             self.inputGroup.hide()
-            E5MessageBox.critical(self,
-                self.trUtf8('Process Generation Error'),
-                self.trUtf8(
-                    'The process {0} could not be started. '
-                    'Ensure, that it is in the search path.'
-                ).format('hg'))
+            
+            out, err = self.__hgClient.runcommand(args)
+            if err:
+                self.__showError(err)
+            if out:
+                for line in out.splitlines():
+                    self.__processOutputLine(line)
+            self.__finish()
         else:
-            self.inputGroup.setEnabled(True)
-            self.inputGroup.show()
+            self.process.kill()
+            self.process.setWorkingDirectory(self.__repodir)
+            
+            self.process.start('hg', args)
+            procStarted = self.process.waitForStarted()
+            if not procStarted:
+                self.inputGroup.setEnabled(False)
+                self.inputGroup.hide()
+                E5MessageBox.critical(self,
+                    self.trUtf8('Process Generation Error'),
+                    self.trUtf8(
+                        'The process {0} could not be started. '
+                        'Ensure, that it is in the search path.'
+                    ).format('hg'))
+            else:
+                self.inputGroup.setEnabled(True)
+                self.inputGroup.show()
     
     def __finish(self):
         """
@@ -191,7 +221,11 @@
         if button == self.buttonBox.button(QDialogButtonBox.Close):
             self.close()
         elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
-            self.__finish()
+            self.__mode = ""
+            if self.__hgClient:
+                self.__hgClient.cancel()
+            else:
+                self.__finish()
     
     def __procFinished(self, exitCode, exitStatus):
         """
@@ -292,23 +326,31 @@
             s = str(self.process.readLine(),
                     Preferences.getSystem("IOEncoding"),
                     'replace').strip()
-            if self.__mode == "qtop":
-                self.__markTopItem(s)
+            self.__processOutputLine(s)
+    
+    def __processOutputLine(self, line):
+        """
+        Private method to process the lines of output.
+        
+        @param line output line to be processed (string)
+        """
+        if self.__mode == "qtop":
+            self.__markTopItem(line)
+        else:
+            l = line.split(": ", 1)
+            if len(l) == 1:
+                data, summary = l[0][:-1], ""
             else:
-                l = s.split(": ", 1)
-                if len(l) == 1:
-                    data, summary = l[0][:-1], ""
-                else:
-                    data, summary = l[0], l[1]
-                l = data.split(None, 2)
-                if len(l) == 2:
-                    # missing entry
-                    index, status, name = -1, l[0], l[1]
-                elif len(l) == 3:
-                    index, status, name = l[:3]
-                else:
-                    continue
-                self.__generateItem(index, status, name, summary)
+                data, summary = l[0], l[1]
+            l = data.split(None, 2)
+            if len(l) == 2:
+                # missing entry
+                index, status, name = -1, l[0], l[1]
+            elif len(l) == 3:
+                index, status, name = l[:3]
+            else:
+                return
+            self.__generateItem(index, status, name, summary)
     
     def __readStderr(self):
         """
@@ -318,12 +360,20 @@
         error pane.
         """
         if self.process is not None:
-            self.errorGroup.show()
             s = str(self.process.readAllStandardError(),
                     Preferences.getSystem("IOEncoding"),
                     'replace')
-            self.errors.insertPlainText(s)
-            self.errors.ensureCursorVisible()
+            self.__showError(s)
+    
+    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 on_passwordCheckBox_toggled(self, isOn):
         """
--- a/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListGuardsDialog.py	Tue Aug 30 19:39:52 2011 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListGuardsDialog.py	Wed Aug 31 18:44:04 2011 +0200
@@ -35,6 +35,7 @@
         
         self.process = QProcess()
         self.vcs = vcs
+        self.__hgClient = vcs.getClient()
         
         self.patchSelector.addItems([""] + patchesList)
     
@@ -80,35 +81,41 @@
         self.guardsList.clear()
         self.patchNameLabel.setText("")
         
-        ioEncoding = Preferences.getSystem("IOEncoding")
-        process = QProcess()
         args = []
         args.append("qguard")
         if patch:
             args.append(patch)
         
-        process.setWorkingDirectory(self.__repodir)
-        process.start('hg', args)
-        procStarted = process.waitForStarted()
-        if procStarted:
-            finished = process.waitForFinished(30000)
-            if finished and process.exitCode() == 0:
-                output = \
-                    str(process.readAllStandardOutput(), ioEncoding, 'replace').strip()
-                if output:
-                    patchName, guards = output.split(":", 1)
-                    self.patchNameLabel.setText(patchName)
-                    guardsList = guards.strip().split()
-                    for guard in guardsList:
-                        if guard.startswith("+"):
-                            icon = UI.PixmapCache.getIcon("plus.png")
-                            guard = guard[1:]
-                        elif guard.startswith("-"):
-                            icon = UI.PixmapCache.getIcon("minus.png")
-                            guard = guard[1:]
-                        else:
-                            icon = None
-                            guard = self.trUtf8("Unguarded")
-                        itm = QListWidgetItem(guard, self.guardsList)
-                        if icon:
-                            itm.setIcon(icon)
+        output = ""
+        if self.__hgClient:
+            output = self.__hgClient.runcommand(args)[0].strip()
+        else:
+            ioEncoding = Preferences.getSystem("IOEncoding")
+            process = QProcess()
+            process.setWorkingDirectory(self.__repodir)
+            process.start('hg', args)
+            procStarted = process.waitForStarted()
+            if procStarted:
+                finished = process.waitForFinished(30000)
+                if finished and process.exitCode() == 0:
+                    output = \
+                        str(process.readAllStandardOutput(),
+                            ioEncoding, 'replace').strip()
+        
+        if output:
+            patchName, guards = output.split(":", 1)
+            self.patchNameLabel.setText(patchName)
+            guardsList = guards.strip().split()
+            for guard in guardsList:
+                if guard.startswith("+"):
+                    icon = UI.PixmapCache.getIcon("plus.png")
+                    guard = guard[1:]
+                elif guard.startswith("-"):
+                    icon = UI.PixmapCache.getIcon("minus.png")
+                    guard = guard[1:]
+                else:
+                    icon = None
+                    guard = self.trUtf8("Unguarded")
+                itm = QListWidgetItem(guard, self.guardsList)
+                if icon:
+                    itm.setIcon(icon)
--- a/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesQueueManagementDialog.py	Tue Aug 30 19:39:52 2011 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesQueueManagementDialog.py	Wed Aug 31 18:44:04 2011 +0200
@@ -24,7 +24,7 @@
     NAME_INPUT = 1
     QUEUE_INPUT = 2
     
-    def __init__(self, mode, title, suppressActive, repodir, parent=None):
+    def __init__(self, mode, title, suppressActive, repodir, vcs, parent=None):
         """
         Constructor
         
@@ -35,6 +35,7 @@
         @param suppressActive flag indicating to not show the name of the active
             queue (boolean)
         @param repodir name of the repository directory (string)
+        @param vcs reference to the vcs object
         @param parent reference to the parent widget (QWidget)
         """
         super().__init__(parent)
@@ -48,6 +49,7 @@
         self.__mode = mode
         self.__repodir = repodir
         self.__suppressActive = suppressActive
+        self.__hgClient = vcs.getClient()
         
         self.inputFrame.setHidden(mode != HgQueuesQueueManagementDialog.NAME_INPUT)
         self.selectLabel.setHidden(mode != HgQueuesQueueManagementDialog.QUEUE_INPUT)
@@ -81,26 +83,31 @@
         queuesList = []
         activeQueue = ""
         
-        ioEncoding = Preferences.getSystem("IOEncoding")
-        process = QProcess()
         args = []
         args.append("qqueue")
         args.append("--list")
         
-        process.setWorkingDirectory(self.__repodir)
-        process.start('hg', args)
-        procStarted = process.waitForStarted()
-        if procStarted:
-            finished = process.waitForFinished(30000)
-            if finished and process.exitCode() == 0:
-                output = \
-                    str(process.readAllStandardOutput(), ioEncoding, 'replace')
-                for queue in output.splitlines():
-                    queue = queue.strip()
-                    if queue.endswith(")"):
-                        queue = queue.rsplit(None, 1)[0]
-                        activeQueue = queue
-                    queuesList.append(queue)
+        output = ""
+        if self.__hgClient:
+            output = self.__hgClient.runcommand(args)[0]
+        else:
+            ioEncoding = Preferences.getSystem("IOEncoding")
+            process = QProcess()
+            process.setWorkingDirectory(self.__repodir)
+            process.start('hg', args)
+            procStarted = process.waitForStarted()
+            if procStarted:
+                finished = process.waitForFinished(30000)
+                if finished and process.exitCode() == 0:
+                    output = \
+                        str(process.readAllStandardOutput(), ioEncoding, 'replace')
+        
+        for queue in output.splitlines():
+            queue = queue.strip()
+            if queue.endswith(")"):
+                queue = queue.rsplit(None, 1)[0]
+                activeQueue = queue
+            queuesList.append(queue)
         
         if self.__suppressActive:
             if activeQueue in queuesList:
--- a/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/queues.py	Tue Aug 30 19:39:52 2011 +0200
+++ b/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/queues.py	Wed Aug 31 18:44:04 2011 +0200
@@ -754,7 +754,7 @@
         else:
             title = self.trUtf8("Rename Active Queue")
         dlg = HgQueuesQueueManagementDialog(HgQueuesQueueManagementDialog.NAME_INPUT,
-            title, False, repodir)
+            title, False, repodir, self.vcs)
         if dlg.exec_() == QDialog.Accepted:
             queueName = dlg.getData()
             if queueName:
@@ -825,7 +825,7 @@
             raise ValueError("illegal value for operation")
         
         dlg = HgQueuesQueueManagementDialog(HgQueuesQueueManagementDialog.QUEUE_INPUT,
-            title, True, repodir)
+            title, True, repodir, self.vcs)
         if dlg.exec_() == QDialog.Accepted:
             queueName = dlg.getData()
             if queueName:
@@ -887,5 +887,5 @@
         self.queuesListQueuesDialog = HgQueuesQueueManagementDialog(
             HgQueuesQueueManagementDialog.NO_INPUT,
             self.trUtf8("Available Queues"),
-            False, repodir)
+            False, repodir, self.vcs)
         self.queuesListQueuesDialog.show()
--- a/VCS/StatusMonitorThread.py	Tue Aug 30 19:39:52 2011 +0200
+++ b/VCS/StatusMonitorThread.py	Wed Aug 31 18:44:04 2011 +0200
@@ -94,6 +94,7 @@
                 self.monitorCondition.wait(self.monitorMutex, self.interval * 1000)
             self.monitorMutex.unlock()
         
+        self._shutdown()
         self.exit()
     
     def setInterval(self, interval):
@@ -185,3 +186,11 @@
             a status message in case of non successful operation (string)
         """
         raise RuntimeError('Not implemented')
+    
+    def _shutdown(self):
+        """
+        Protected method performing shutdown actions.
+        
+        The default implementation does nothing.
+        """
+        pass

eric ide

mercurial