changeset 619:4f7ca2d192df

Merge
author Chris Cannam
date Tue, 03 Jul 2012 20:10:04 +0100
parents 54ca6a0e9aef (current diff) 4d44bad5a8ef (diff)
children 7f1adcdc6cdc
files src/mainwindow.cpp
diffstat 19 files changed, 154 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Tue Jul 03 20:09:46 2012 +0100
+++ b/.hgtags	Tue Jul 03 20:10:04 2012 +0100
@@ -20,3 +20,4 @@
 9b300409c184d47d57fba49341b2a1818b7fd0bc easyhg_v1.2
 8bcf7ce9b1d209b94f71593545fc5de7c008f5a3 easyhg_v1.2_win32_2
 abfef4acceca78078fe0c3b7fa8794f9ec77a4d3 easyhg_v1.2.1
+aade37785eca08d98afa7d12a66a181e1a2f4e2c easyhg_v1.2.2
--- a/CHANGELOG	Tue Jul 03 20:09:46 2012 +0100
+++ b/CHANGELOG	Tue Jul 03 20:10:04 2012 +0100
@@ -1,3 +1,15 @@
+
+Changes in v1.2.2 since v1.2.1:
+ * Fix failure to provide IV arg to AES CBC constructor in PyCrypto
+ * Update the history after a failed merge to show the merge
+ * Clear the history while cloning a new repo
+ * Show a sensible error when clone target can't be created
+ * Minor improvements to zooming in history widget
+ * Various other minor fixes
+
+Changes in v1.2.1 since v1.2:
+ * Fix a filesystem watcher bug (affecting OS/X only)
+
 Changes in v1.2 since v1.1:
 
  * Add a Find function to both My Work and History tabs
--- a/easyhg.py	Tue Jul 03 20:09:46 2012 +0100
+++ b/easyhg.py	Tue Jul 03 20:10:04 2012 +0100
@@ -53,12 +53,18 @@
 # "remember this password") feature without them
 #
 easyhg_authfile_imports_ok = True
+
 try:
     from Crypto.Cipher import AES
+except ImportError:
+    print "EasyHg: Failed to import Crypto.Cipher module required for authfile support (try installing PyCrypto?)"
+    easyhg_authfile_imports_ok = False
+
+try:
     import ConfigParser # Mercurial version won't write files
     import base64
 except ImportError:
-    print "EasyHg: Failed to import required modules for authfile support"
+    print "EasyHg: Failed to import modules (ConfigParser, base64) required for authfile support"
     easyhg_authfile_imports_ok = False
 
 
@@ -83,7 +89,8 @@
         self.remember = False
 
         if self.use_auth_file:
-            self.auth_cipher = AES.new(self.auth_key, AES.MODE_CBC)
+            self.auth_cipher = AES.new(self.auth_key, AES.MODE_CBC,
+                                       os.urandom(16))
             self.auth_file = os.path.expanduser(self.auth_file)
             self.load_auth_data()
 
--- a/easyhg.wxs	Tue Jul 03 20:09:46 2012 +0100
+++ b/easyhg.wxs	Tue Jul 03 20:10:04 2012 +0100
@@ -2,13 +2,13 @@
 
   <Product
       Name="EasyMercurial" 
-      Id="CDD72D35-518B-49E2-A389-B3F7C1AE289D" 
+      Id="*"
       Language="1033"
       Codepage="1252" 
-      Version="1.2.0" 
+      Version="1.2.2" 
       UpgradeCode="B82DFDA9-B9DE-49BC-93E5-0B96F9DEB04B"
       Manufacturer="Queen Mary, University of London">
-
+    
     <Package
         Id="*"
         Keywords="Installer"
@@ -20,6 +20,8 @@
         Compressed="yes" 
         SummaryCodepage="1252"/>
 
+    <MajorUpgrade DowngradeErrorMessage="A later version of EasyMercurial is already installed. Setup will now exit."/>
+
     <Media Id="1" Cabinet="easyhg.cab" EmbedCab="yes" DiskPrompt="CD-ROM #1"/>
     <Property Id="DiskPrompt" Value="EasyMercurial Installation [1]"/>
 
--- a/src/filestatuswidget.cpp	Tue Jul 03 20:09:46 2012 +0100
+++ b/src/filestatuswidget.cpp	Tue Jul 03 20:10:04 2012 +0100
@@ -441,6 +441,16 @@
 }
 
 void
+FileStatusWidget::clearWidgets()
+{
+    foreach (FileStates::State s, m_stateListMap.keys()) {
+        QListWidget *w = m_stateListMap[s];
+        w->clear();
+        w->parentWidget()->hide();
+    }
+}
+
+void
 FileStatusWidget::updateWidgets()
 {
     QDateTime lastInteractionTime;
--- a/src/filestatuswidget.h	Tue Jul 03 20:09:46 2012 +0100
+++ b/src/filestatuswidget.h	Tue Jul 03 20:10:04 2012 +0100
@@ -78,6 +78,7 @@
 public slots:
     void clearSelections();
     void updateWidgets();
+    void clearWidgets(); // e.g. while cloning a new repo slowly
 
     void setSearchText(QString text);
 
--- a/src/fswatcher.cpp	Tue Jul 03 20:09:46 2012 +0100
+++ b/src/fswatcher.cpp	Tue Jul 03 20:10:04 2012 +0100
@@ -28,7 +28,7 @@
 
 #include <deque>
 
-#define DEBUG_FSWATCHER 1
+//#define DEBUG_FSWATCHER 1
 
 /*
  * Watching the filesystem is trickier than it seems at first glance.
--- a/src/hgaction.h	Tue Jul 03 20:09:46 2012 +0100
+++ b/src/hgaction.h	Tue Jul 03 20:10:04 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 20:09:46 2012 +0100
+++ b/src/hgrunner.cpp	Tue Jul 03 20:10:04 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 20:09:46 2012 +0100
+++ b/src/hgrunner.h	Tue Jul 03 20:10:04 2012 +0100
@@ -90,6 +90,7 @@
     QProgressBar *m_progress;
     QPushButton *m_cancel;
 
+    HgAction expandEnvironment(HgAction);
     QStringList addExtensionOptions(QStringList);
 
     int m_ptyMasterFd;
--- a/src/hgtabwidget.cpp	Tue Jul 03 20:09:46 2012 +0100
+++ b/src/hgtabwidget.cpp	Tue Jul 03 20:10:04 2012 +0100
@@ -144,6 +144,12 @@
     m_historyWidget->setClosedHeadIds(closed);
 }
 
+void HgTabWidget::clearAll()
+{
+    m_fileStatusWidget->clearWidgets();
+    m_historyWidget->clear();
+}
+
 void HgTabWidget::updateFileStates()
 {
     m_fileStatusWidget->updateWidgets();
--- a/src/hgtabwidget.h	Tue Jul 03 20:09:46 2012 +0100
+++ b/src/hgtabwidget.h	Tue Jul 03 20:10:04 2012 +0100
@@ -52,6 +52,7 @@
 
     void setHaveMerge(bool);
 
+    void clearAll();
     void updateFileStates();
     void updateHistory();
 
--- a/src/historywidget.cpp	Tue Jul 03 20:09:46 2012 +0100
+++ b/src/historywidget.cpp	Tue Jul 03 20:10:04 2012 +0100
@@ -205,6 +205,13 @@
     }
 }
 
+void HistoryWidget::clear()
+{
+    QGraphicsScene *oldScene = m_panned->scene();
+    m_panned->setScene(0);
+    delete oldScene;
+}
+
 void HistoryWidget::layoutAll()
 {
     m_refreshNeeded = false;
--- a/src/historywidget.h	Tue Jul 03 20:09:46 2012 +0100
+++ b/src/historywidget.h	Tue Jul 03 20:10:04 2012 +0100
@@ -47,8 +47,6 @@
 
     bool haveNewItems() const { return !m_newIds.empty(); }
 
-    void update();
-
 signals:
     void commit();
     void revert();
@@ -72,7 +70,9 @@
 
 public slots:
     void setSearchText(QString);
-    
+    void update();
+    void clear();
+
 private:
     Changesets m_changesets;
     QStringList m_currentIds;
--- a/src/mainwindow.cpp	Tue Jul 03 20:09:46 2012 +0100
+++ b/src/mainwindow.cpp	Tue Jul 03 20:10:04 2012 +0100
@@ -766,9 +766,12 @@
 
     f.open(QFile::ReadOnly);
     bool glob = false;
+    bool cr = false; // whether the last line examined ended with a CR
     while (!f.atEnd()) {
         QByteArray ba = f.readLine();
-        QString s = QString::fromLocal8Bit(ba).trimmed();
+        QString s = QString::fromLocal8Bit(ba);
+        cr = (s.endsWith('\n') || s.endsWith('\r'));
+        s = s.trimmed();
         if (s.startsWith("syntax:")) {
             if (s.endsWith("glob")) {
                 glob = true;
@@ -782,6 +785,10 @@
     f.open(QFile::Append);
     QTextStream out(&f);
 
+    if (!cr) {
+        out << endl;
+    }
+
     if (!glob) {
         out << "syntax: glob" << endl;
     }
@@ -1208,7 +1215,10 @@
         if (!QDir().mkpath(m_workFolderPath)) {
             DEBUG << "hgCloneFromRemote: Failed to create target path "
                   << m_workFolderPath << endl;
-            //!!! report error
+            QMessageBox::critical
+                (this, tr("Could not create target folder"),
+                 tr("<qt><b>Could not create target folder</b><br><br>The local target folder \"%1\" does not exist<br>and could not be created.</qt>").arg(xmlEncode(m_workFolderPath)));
+            m_workFolderPath = "";
             return;
         }
     }
@@ -1217,6 +1227,7 @@
     
     updateWorkFolderAndRepoNames();
     m_hgTabs->updateWorkFolderFileList("");
+    m_hgTabs->clearAll();
 
     m_runner->requestAction(HgAction(ACT_CLONEFROMREMOTE, m_workFolderPath, params));
 }
@@ -1485,9 +1496,9 @@
 
     QString explanation;
     if (initial) {
-        explanation = tr("Provide a URL to use for push and pull actions from the current local repository.<br>This will be the default for subsequent pushes and pulls.<br>You can change it using &ldquo;Set Remote Location&rdquo; on the File menu.");
+        explanation = tr("Provide a remote URL to use when pushing from, or pulling to, the local<br>repository <code>%1</code>.<br>This will be the default for subsequent pushes and pulls.<br>You can change it using &ldquo;Set Remote Location&rdquo; on the File menu.").arg(m_workFolderPath);
     } else {
-        explanation = tr("Provide a new URL to use for push and pull actions from the current local repository.");
+        explanation = tr("Provide a new remote URL to use when pushing from, or pulling to, the local<br>repository <code>%1</code>.").arg(m_workFolderPath);
     }
 
     d->addChoice("remote",
@@ -2133,6 +2144,7 @@
              tr("Some files were not merged successfully.<p>You can Merge again to repeat the interactive merge; use Revert to abandon the merge entirely; or edit the files that are in conflict in an editor and, when you are happy with them, choose Mark Resolved in each file's right-button menu."),
              stdErr);
         m_mergeCommitComment = "";
+        hgQueryPaths();
         return;
     case ACT_STAT:
         break; // go on to default report
@@ -2882,7 +2894,7 @@
     }
     foreach (QString r, recent) {
         QAction *a = m_recentMenu->addAction(r);
-        connect(a, SIGNAL(activated()), this, SLOT(recentMenuActivated()));
+        connect(a, SIGNAL(triggered()), this, SLOT(recentMenuActivated()));
     }
 }
 
@@ -2890,11 +2902,11 @@
 {
     //File actions
     m_openAct = new QAction(QIcon(":/images/fileopen.png"), tr("&Open..."), this);
-    m_openAct->setStatusTip(tr("Open an existing repository or working folder"));
+    m_openAct->setStatusTip(tr("Open a remote repository or an existing local folder"));
     m_openAct->setShortcut(tr("Ctrl+O"));
 
-    m_changeRemoteRepoAct = new QAction(tr("Set Remote &Location..."), this);
-    m_changeRemoteRepoAct->setStatusTip(tr("Set or change the default remote repository for pull and push actions"));
+    m_changeRemoteRepoAct = new QAction(tr("Set Push and Pull &Location..."), this);
+    m_changeRemoteRepoAct->setStatusTip(tr("Set or change the default URL for pull and push actions from this repository"));
 
     m_settingsAct = new QAction(QIcon(":/images/settings.png"), tr("&Settings..."), this);
     m_settingsAct->setStatusTip(tr("View and change application settings"));
@@ -3014,10 +3026,9 @@
 
     QMenu *remoteMenu;
     remoteMenu = menuBar()->addMenu(tr("&Remote"));
-    remoteMenu->addAction(m_changeRemoteRepoAct);
-    remoteMenu->addSeparator();
     remoteMenu->addAction(m_hgIncomingAct);
     remoteMenu->addSeparator();
+    remoteMenu->addAction(m_changeRemoteRepoAct);
     remoteMenu->addAction(m_hgPullAct);
     remoteMenu->addAction(m_hgPushAct);
 
--- a/src/multichoicedialog.cpp	Tue Jul 03 20:09:46 2012 +0100
+++ b/src/multichoicedialog.cpp	Tue Jul 03 20:10:04 2012 +0100
@@ -275,6 +275,17 @@
     }
 }
 
+bool
+MultiChoiceDialog::urlComboNotUrl() const
+{
+    QString url = m_urlCombo->currentText();
+    if (QRegExp("^\\w+://").indexIn(url) < 0) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
 void
 MultiChoiceDialog::choiceChanged()
 {
@@ -347,14 +358,18 @@
         m_urlLabel->show();
         m_urlCombo->show();
         m_urlCombo->addItems(rf->getRecent());
-        if (m_defaultEmpty[id]) m_urlCombo->lineEdit()->setText("");
+        if (m_defaultEmpty[id] || urlComboNotUrl()) {
+            m_urlCombo->lineEdit()->setText("");
+        }
         break;
 
     case UrlToDirectoryArg:
         m_urlLabel->show();
         m_urlCombo->show();
         m_urlCombo->addItems(rf->getRecent());
-        if (m_defaultEmpty[id]) m_urlCombo->lineEdit()->setText("");
+        if (m_defaultEmpty[id] || urlComboNotUrl()) {
+            m_urlCombo->lineEdit()->setText("");
+        }
         m_fileLabel->setText(tr("&Folder:"));
         m_fileLabel->show();
         m_fileCombo->show();
--- a/src/multichoicedialog.h	Tue Jul 03 20:09:46 2012 +0100
+++ b/src/multichoicedialog.h	Tue Jul 03 20:10:04 2012 +0100
@@ -88,6 +88,7 @@
     QAbstractButton *m_okButton;
 
     QString getDefaultPath() const;
+    bool urlComboNotUrl() const;
 };
 
 #endif // MULTICHOICEDIALOG_H
--- a/src/settingsdialog.cpp	Tue Jul 03 20:09:46 2012 +0100
+++ b/src/settingsdialog.cpp	Tue Jul 03 20:10:04 2012 +0100
@@ -268,7 +268,7 @@
     QSettings settings;
     settings.beginGroup("Locations");
     QString hg = settings.value("hgbinary", "").toString();
-    if (hg == "") {
+    if (hg == "" || !QFile(hg).exists()) {
         hg = findInPath("hg", m_installPath, true);
     }
     if (hg != "") {
--- a/src/version.h	Tue Jul 03 20:09:46 2012 +0100
+++ b/src/version.h	Tue Jul 03 20:10:04 2012 +0100
@@ -1,1 +1,1 @@
-#define EASYHG_VERSION "1.2.1"
+#define EASYHG_VERSION "1.2.2"