# HG changeset patch # User Chris Cannam # Date 1294666219 0 # Node ID e2f2c6e3c01b4ce42e6d90e13e6ffb7860f41f15 # Parent c9a7e4ec2f7824343118658fd55be1e34bfbf10e * Attempt a different way of handling filesystem updates, that's more forgiving of fs changes caused by hg itself diff -r c9a7e4ec2f78 -r e2f2c6e3c01b easyhg.pro --- 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 diff -r c9a7e4ec2f78 -r e2f2c6e3c01b hgrunner.cpp --- 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); } diff -r c9a7e4ec2f78 -r e2f2c6e3c01b hgrunner.h --- 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); diff -r c9a7e4ec2f78 -r e2f2c6e3c01b mainwindow.cpp --- 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 #include #include +#include #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: diff -r c9a7e4ec2f78 -r e2f2c6e3c01b mainwindow.h --- 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;