changeset 605:ab92f695f776

Expand environmental parameters and executable name in action when it is received rather than when it's executed. This ensures we can correctly compare actions and fixes #141 "Unexpected error if you double-click on a toolbar button"
author Chris Cannam
date Tue, 03 Jul 2012 11:22:10 +0100
parents 98f57888d893
children 372b191247da
files easyhg.pro src/hgaction.h src/hgrunner.cpp src/hgrunner.h
diffstat 4 files changed, 58 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/easyhg.pro	Tue Jul 03 10:43:05 2012 +0100
+++ b/easyhg.pro	Tue Jul 03 11:22:10 2012 +0100
@@ -1,5 +1,5 @@
 
-CONFIG += release
+CONFIG += debug
 
 TEMPLATE = app
 TARGET = EasyMercurial
--- a/src/hgaction.h	Tue Jul 03 10:43:05 2012 +0100
+++ b/src/hgaction.h	Tue Jul 03 11:22:10 2012 +0100
@@ -70,7 +70,7 @@
     QString executable; // empty for normal Hg, but gets filled in by hgrunner
     void *extraData;
 
-    HgAction() : action(ACT_NONE) { }
+    HgAction() : action(ACT_NONE), extraData(0) { }
 
     HgAction(HGACTIONS _action, QString _wd, QStringList _params) :
         action(_action), workingDir(_wd), params(_params), extraData(0) { }
@@ -79,9 +79,10 @@
         action(_action), workingDir(_wd), params(_params), extraData(_d) { }
 
     bool operator==(const HgAction &a) {
-        return (a.action == action && a.workingDir == workingDir &&
-                a.params == params && a.executable == executable &&
-                a.extraData == extraData);
+        bool equal = (a.action == action && a.workingDir == workingDir &&
+                      a.params == params && a.executable == executable &&
+                      a.extraData == extraData);
+        return equal;
     }
 
     bool shouldBeFast() const {
--- a/src/hgrunner.cpp	Tue Jul 03 10:43:05 2012 +0100
+++ b/src/hgrunner.cpp	Tue Jul 03 11:22:10 2012 +0100
@@ -151,8 +151,11 @@
 
 void HgRunner::requestAction(HgAction action)
 {
-    DEBUG << "requestAction " << action.action << endl;
+    DEBUG << "requestAction " << action.action << ": " << m_queue.size() << " thing(s) in queue, current action is " << m_currentAction.action << endl;
     bool pushIt = true;
+
+    action = expandEnvironment(action);
+
     if (m_queue.empty()) {
         if (action == m_currentAction) {
             // this request is identical to the thing we're executing
@@ -168,10 +171,50 @@
             pushIt = false;
         }
     }
-    if (pushIt) m_queue.push_back(action);
+    if (pushIt) {
+        m_queue.push_back(action);
+    }
     checkQueue();
 }
 
+HgAction HgRunner::expandEnvironment(HgAction action)
+{
+    // Adjust the executable and params for action to match our actual
+    // environment. We do this when the action is received, rather
+    // than when we execute it, so that we can compare
+    // (post-expansion) commands to see e.g. whether the one just
+    // received is the same as the one we're currently executing
+
+    QString executable = action.executable;
+    QStringList params = action.params;
+
+    if (executable == "") {
+        // This is a Hg command
+        executable = getHgBinaryName();
+        if (executable == "") executable = "hg";
+
+        QString ssh = getSshBinaryName();
+        if (ssh != "") {
+            params.push_front(QString("ui.ssh=\"%1\"").arg(ssh));
+            params.push_front("--config");
+        }
+
+        if (action.mayBeInteractive()) {
+            params.push_front("ui.interactive=true");
+            params.push_front("--config");
+            QSettings settings;
+            if (settings.value("useextension", true).toBool()) {
+                params = addExtensionOptions(params);
+            }
+        }            
+    }
+
+    action.executable = executable;
+    action.params = params;
+
+    return action;
+}
+
 QString HgRunner::getHgBinaryName()
 {
     QSettings settings;
@@ -349,6 +392,8 @@
 
     HgAction completedAction = m_currentAction;
 
+    DEBUG << "HgRunner::finished: completed " << completedAction.action << endl;
+
     m_isRunning = false;
     m_currentAction = HgAction();
 
@@ -503,40 +548,12 @@
 
 void HgRunner::startCommand(HgAction action)
 {
-    QString executable = action.executable;
-    bool interactive = false;
-    QStringList params = action.params;
-
     if (action.workingDir.isEmpty()) {
         // We require a working directory, never just operate in pwd
         emit commandFailed(action, "EasyMercurial: No working directory supplied, will not run Mercurial command without one", "");
         return;
     }
 
-    if (executable == "") {
-        // This is a Hg command
-        executable = getHgBinaryName();
-        if (executable == "") executable = "hg";
-
-        QString ssh = getSshBinaryName();
-        if (ssh != "") {
-            params.push_front(QString("ui.ssh=\"%1\"").arg(ssh));
-            params.push_front("--config");
-        }
-
-        if (action.mayBeInteractive()) {
-            params.push_front("ui.interactive=true");
-            params.push_front("--config");
-            QSettings settings;
-            if (settings.value("useextension", true).toBool()) {
-                params = addExtensionOptions(params);
-            }
-            interactive = true;
-        }            
-
-        //!!! want an option to use the mercurial_keyring extension as well
-    }
-
     m_isRunning = true;
     m_progress->setRange(0, 0);
     if (!action.shouldBeFast()) {
@@ -583,7 +600,7 @@
 
     m_proc->setWorkingDirectory(action.workingDir);
 
-    if (interactive) {
+    if (action.mayBeInteractive()) {
         openTerminal();
         if (m_ptySlaveFilename != "") {
             DEBUG << "HgRunner: connecting to pseudoterminal" << endl;
@@ -593,22 +610,18 @@
         }
     }
 
-    QString cmdline = executable;
-    foreach (QString param, params) cmdline += " " + param;
+    QString cmdline = action.executable;
+    foreach (QString param, action.params) cmdline += " " + param;
     DEBUG << "HgRunner: starting: " << cmdline << " with cwd "
           << action.workingDir << endl;
 
     m_currentAction = action;
 
-    // fill these out with what we actually ran
-    m_currentAction.executable = executable;
-    m_currentAction.params = params;
-
     DEBUG << "set current action to " << m_currentAction.action << endl;
     
     emit commandStarting(action);
 
-    m_proc->start(executable, params);
+    m_proc->start(action.executable, action.params);
 }
 
 void HgRunner::closeProcInput()
--- a/src/hgrunner.h	Tue Jul 03 10:43:05 2012 +0100
+++ b/src/hgrunner.h	Tue Jul 03 11:22:10 2012 +0100
@@ -90,6 +90,7 @@
     QProgressBar *m_progress;
     QPushButton *m_cancel;
 
+    HgAction expandEnvironment(HgAction);
     QStringList addExtensionOptions(QStringList);
 
     int m_ptyMasterFd;