changeset 238:e2f2c6e3c01b

* Attempt a different way of handling filesystem updates, that's more forgiving of fs changes caused by hg itself
author Chris Cannam
date Mon, 10 Jan 2011 13:30:19 +0000
parents c9a7e4ec2f78
children 661f5808aa0a
files easyhg.pro hgrunner.cpp hgrunner.h mainwindow.cpp mainwindow.h
diffstat 5 files changed, 80 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/easyhg.pro	Mon Jan 10 12:44:03 2011 +0000
+++ b/easyhg.pro	Mon Jan 10 13:30:19 2011 +0000
@@ -1,5 +1,5 @@
 
-CONFIG += release
+CONFIG += debug
 
 macx-* {
     QMAKE_MAC_SDK=/Developer/SDKs/MacOSX10.4u.sdk
--- a/hgrunner.cpp	Mon Jan 10 12:44:03 2011 +0000
+++ b/hgrunner.cpp	Mon Jan 10 13:30:19 2011 +0000
@@ -482,6 +482,8 @@
 
     DEBUG << "set current action to " << m_currentAction.action << endl;
     
+    emit commandStarting(action);
+
     m_proc->start(executable, params);
 }
 
--- a/hgrunner.h	Mon Jan 10 12:44:03 2011 +0000
+++ b/hgrunner.h	Mon Jan 10 13:30:19 2011 +0000
@@ -40,6 +40,7 @@
     void killCurrentActions(); // kill anything running; clear the queue
 
 signals:
+    void commandStarting(HgAction action);
     void commandCompleted(HgAction action, QString stdOut);
     void commandFailed(HgAction action, QString stdErr);
 
--- a/mainwindow.cpp	Mon Jan 10 12:44:03 2011 +0000
+++ b/mainwindow.cpp	Mon Jan 10 13:30:19 2011 +0000
@@ -32,6 +32,7 @@
 #include <QRegExp>
 #include <QShortcut>
 #include <QUrl>
+#include <QTimer>
 
 #include "mainwindow.h"
 #include "multichoicedialog.h"
@@ -46,7 +47,9 @@
 
 
 MainWindow::MainWindow(QString myDirPath) :
-    m_myDirPath(myDirPath)
+    m_myDirPath(myDirPath),
+    m_fsWatcherGeneralTimer(0),
+    m_fsWatcherRestoreTimer(0)
 {
     setWindowIcon(QIcon(":images/easyhg-icon.png"));
 
@@ -238,11 +241,6 @@
 
     lastStatOutput = "";
 
-    // annoyingly, hg stat actually modifies the working directory --
-    // it creates files called hg-checklink and hg-checkexec to test
-    // properties of the filesystem
-    if (fsWatcher) fsWatcher->blockSignals(true);
-
     runner->requestAction(HgAction(ACT_STAT, workFolderPath, params));
 }
 
@@ -1480,6 +1478,16 @@
         }
     }
 
+    // The general timer isn't really related to the fs watcher
+    // object, it just does something similar -- every now and then we
+    // do a refresh just to update the history dates etc
+
+    m_fsWatcherGeneralTimer = new QTimer(this);
+    connect(m_fsWatcherGeneralTimer, SIGNAL(timeout()),
+            this, SLOT(checkFilesystem()));
+    m_fsWatcherGeneralTimer->setInterval(30 * 60 * 1000); // half an hour
+    m_fsWatcherGeneralTimer->start();
+
     if (justCreated) {
         connect(fsWatcher, SIGNAL(directoryChanged(QString)),
                 this, SLOT(fsDirectoryChanged(QString)));
@@ -1488,6 +1496,47 @@
     }
 }
 
+void MainWindow::suspendFileSystemWatcher()
+{
+    DEBUG << "MainWindow::suspendFileSystemWatcher" << endl;
+    if (fsWatcher) {
+        m_fsWatcherRestoreTimer->stop();
+        m_fsWatcherGeneralTimer->stop();
+        fsWatcher->blockSignals(true);
+    }
+}
+
+void MainWindow::restoreFileSystemWatcher()
+{
+    DEBUG << "MainWindow::restoreFileSystemWatcher" << endl;
+    if (m_fsWatcherRestoreTimer) delete m_fsWatcherRestoreTimer;
+        
+    // The restore timer is used to leave a polite interval between
+    // being asked to restore the watcher and actually doing so.  It's
+    // a single shot timer each time it's used, but we don't use
+    // QTimer::singleShot because we want to stop the previous one if
+    // it's running (via deleting it)
+
+    m_fsWatcherRestoreTimer = new QTimer(this);
+    connect(m_fsWatcherRestoreTimer, SIGNAL(timeout()),
+            this, SLOT(actuallyRestoreFileSystemWatcher()));
+    m_fsWatcherRestoreTimer->setInterval(1000);
+    m_fsWatcherRestoreTimer->setSingleShot(true);
+    m_fsWatcherRestoreTimer->start();
+}
+
+void MainWindow::actuallyRestoreFileSystemWatcher()
+{
+    DEBUG << "MainWindow::actuallyRestoreFileSystemWatcher" << endl;
+    if (fsWatcher) fsWatcher->blockSignals(false);
+}
+
+void MainWindow::checkFilesystem()
+{
+    DEBUG << "MainWindow::checkFilesystem" << endl;
+    hgStat();
+}
+
 void MainWindow::fsDirectoryChanged(QString d)
 {
     DEBUG << "MainWindow::fsDirectoryChanged " << d << endl;
@@ -1611,9 +1660,21 @@
     }
 }
 
+void MainWindow::commandStarting(HgAction action)
+{
+    // Annoyingly, hg stat actually modifies the working directory --
+    // it creates files called hg-checklink and hg-checkexec to test
+    // properties of the filesystem.  For safety's sake, suspend the
+    // fs watcher while running commands, and restore it shortly after
+    // a command has finished.
+
+    suspendFileSystemWatcher();
+}
+
 void MainWindow::commandFailed(HgAction action, QString output)
 {
     DEBUG << "MainWindow::commandFailed" << endl;
+    restoreFileSystemWatcher();
 
     QString setstr;
 #ifdef Q_OS_MAC
@@ -1671,7 +1732,6 @@
             return;
         }
     case ACT_STAT:
-        if (fsWatcher) fsWatcher->blockSignals(false);
         break; // go on and report
     default:
         break;
@@ -1699,6 +1759,7 @@
 
 void MainWindow::commandCompleted(HgAction completedAction, QString output)
 {
+    restoreFileSystemWatcher();
     HGACTIONS action = completedAction.action;
 
     if (action == ACT_NONE) return;
@@ -1739,7 +1800,6 @@
     case ACT_STAT:
         lastStatOutput = output;
         updateFileSystemWatcher();
-        if (fsWatcher) fsWatcher->blockSignals(false);
         break;
 
     case ACT_RESOLVE_LIST:
--- a/mainwindow.h	Mon Jan 10 12:44:03 2011 +0000
+++ b/mainwindow.h	Mon Jan 10 13:30:19 2011 +0000
@@ -31,6 +31,7 @@
 QT_BEGIN_NAMESPACE
 class QAction;
 class QMenu;
+class QTimer;
 QT_END_NAMESPACE
 
 class MainWindow : public QMainWindow
@@ -60,6 +61,7 @@
 public slots:
     void open(QString local);
     void hgRefresh();
+    void commandStarting(HgAction);
     void commandCompleted(HgAction action, QString stdOut);
     void commandFailed(HgAction action, QString stdErr);
     void enableDisableActions();
@@ -104,6 +106,8 @@
 
     void fsDirectoryChanged(QString);
     void fsFileChanged(QString);
+    void checkFilesystem();
+    void actuallyRestoreFileSystemWatcher();
 
 private:
     void hgQueryBranch();
@@ -154,6 +158,8 @@
     void clearState();
 
     void updateFileSystemWatcher();
+    void suspendFileSystemWatcher();
+    void restoreFileSystemWatcher();
 
     bool firstStart;
 
@@ -210,6 +216,8 @@
     QString findEditorBinaryName();
 
     QFileSystemWatcher *fsWatcher;
+    QTimer *m_fsWatcherGeneralTimer;
+    QTimer *m_fsWatcherRestoreTimer;
 
     QString lastStatOutput;
     QStringList lastRevertedFiles;