# # # patch "src/main.cpp" # from [d11b766c3378383843a5535c651e5d2581bf32cf] # to [5bcf3a85423911375242a9f34e2bd59b8ab132ff] # # patch "src/model/Ancestors.cpp" # from [ff279efc1a19d894af6db12104e7462b12cce760] # to [be26e96549d5f55721c5513d9f16e53ecf2e06e6] # # patch "src/model/Ancestors.h" # from [ae731fc84d04770fda2c286a3f717d9c2f2759ba] # to [d668133dc6751725cdea0a976466e8b8c89f3e3b] # # patch "src/model/AutomateCommand.cpp" # from [40bb1958db68f50c26d603304d6f7df9d4daa990] # to [961b064e1e5ceb07843f9fe0b1f88d985f21de08] # # patch "src/model/AutomateCommand.h" # from [2c38aad8a34201def446804676086e08296a70d0] # to [2e6f883dd2fc93eb56ec23d37a285a104303909b] # # patch "src/model/Branches.cpp" # from [f6fb7124bbf93aafb16a8b3ce3fe161c2e06f8ea] # to [7434636b987b9c42b7383d73b08327eb4210aead] # # patch "src/model/Branches.h" # from [910bd8ab66af7a0a6ad019479d867d569494178e] # to [c0cdd035892b0e3496cfd51b84dff2b278e59d8d] # # patch "src/model/Certs.cpp" # from [285dd2004b058cc9a7082ca34d0cd21fdc8d9765] # to [2573a7506dc963e2bd969e796986cf273661bcdc] # # patch "src/model/Certs.h" # from [187ae7a01ea9ccfe8467875bfe906f4a9f174790] # to [d7ec4361924586c6dd6ed83f9259e35fb5b2017e] # # patch "src/model/ContentDiff.cpp" # from [b9b75d298806aace824aae2e1e54239785b21218] # to [7d5168924ebf7cc688089dbb71e5464608e991ae] # # patch "src/model/ContentDiff.h" # from [1f974e237ab07595838d0cc47680ef11242a1474] # to [6d7f15f9d1f56bac5e7cc8189a1b6dc40993a022] # # patch "src/model/GetAttributes.cpp" # from [684f7ffa4ef7662c6f978613c7be040ad5cf3081] # to [6646ac15f25d25b19ba253f872d63c240e759331] # # patch "src/model/GetAttributes.h" # from [f34a9cc218e83e5dfeed11b7c9929e8b49c2a9cc] # to [4f7ca1ecaf78f12632e3d4a8fa65d670e09020a1] # # patch "src/model/GetContentChanged.cpp" # from [32abedcae92407071a71b07a4e2e104a6ac7edee] # to [f07066aea6bb76e5c9ff7a28ad51836a3685dced] # # patch "src/model/GetContentChanged.h" # from [be46c46e9e3222c6acb9a2d63b7ec274b98b9aa3] # to [2e459c7beea84cd2cc13c1fed6776eb8101ee361] # # patch "src/model/GetDatabaseVariables.cpp" # from [b9ad21e33c9994caf29bdadcb74103c4bb3973de] # to [a64d26ea00b105a85ca5883eabd5f280ddf4dbb0] # # patch "src/model/GetDatabaseVariables.h" # from [12358ebfe7da2c6b5bf4d2c28264af387f2f3abc] # to [d5c88700402f4dd78230f3ef8a737571950a4d57] # # patch "src/model/GetFile.cpp" # from [735189cbe8ffb4e7cffd1a40e07fef37a0068ea4] # to [2f57e09ce0224ab42b9d907cd5ace3bd35ebe999] # # patch "src/model/GetFile.h" # from [73a82bb540ba6ca45cd9c6fcdc4f165a6ded958b] # to [079d6a0490ed823f4d9169bfb8a35f107cdc07e2] # # patch "src/model/GetRevision.cpp" # from [0306aaaaa58093f4c4765f8a966fce0873120bbf] # to [7561bccabe38f3202931a7ac485c0d907395f892] # # patch "src/model/GetRevision.h" # from [8f8b5b334bc0fdaadad441f82ed65024617ea8b1] # to [29813b88948834794c0947f3fe35e6467a3b4dc3] # # patch "src/model/Inventory.cpp" # from [5c2141e6a83a9f0ed4a7e32f60aff0bc2bb983f8] # to [dbd52e14bb66a0aa0e2737f70af4da384f4a0ef3] # # patch "src/model/Inventory.h" # from [c9663f40bd61cac606d5f3015c76fd78e8914fa6] # to [268e93aa6b0b830a5bcc947353018fba8508ded3] # # patch "src/model/Keys.cpp" # from [9283be02e0195529d98eca218d0736b5666836a4] # to [02497764e76e5dca25c68abdc2a106b84c28a86b] # # patch "src/model/Keys.h" # from [c8a97fb1a99d0e451cd939434b4332443e403d95] # to [3131df73288c46a0f22f82d5490e5a184666d9a1] # # patch "src/model/Manifest.cpp" # from [6c9e78ed14e8b0889bc1d84bafafe82c46f1ed3c] # to [e50bdb95dde92c0bf991c0ce2b4eec714854bf4e] # # patch "src/model/Manifest.h" # from [9231a0ed7276006ab96952b04dbb83997a6a48e6] # to [87f96415291d30c53cfe236812da7c0f7e8e9840] # # patch "src/model/Select.cpp" # from [a82a300f0787e9ae330c0c8ca96083da99d82476] # to [e77b9594f21232a0e6c7396a3fccf4c78f874dfe] # # patch "src/model/Select.h" # from [520e6de98e71ac10e9e72ac5341f725302096816] # to [b8dc238d172c17c51ae3bf80a9cd2b2ad394939d] # # patch "src/model/Tags.cpp" # from [31c3f32539c54fb7bc7d676d18ad0581356f844c] # to [a7caf48663871fe5e12a75451dafd8c6f95d7f0a] # # patch "src/model/Tags.h" # from [f2fba601247219ecee7aae5c7ddff42aacfb872f] # to [81fec9954f65235ce921988b55da5039cdd9b9c2] # # patch "src/model/Toposort.cpp" # from [c5f0896d43e6e9763571e201281ee49db94ad22e] # to [bff816b44fd93172dd2388c8f67ba9cfda1cd300] # # patch "src/model/Toposort.h" # from [85ef196576a29c5d66202858fbe131e4a53e9332] # to [c077c6787ee68374b47d19961df83adf71258ea5] # # patch "src/monotone/FileExporter.cpp" # from [8d23af2f0072da14f8c79d2d71b3db6701693729] # to [4cea02c79f62a4d0b83a192b453be081e3c9c7e6] # # patch "src/monotone/MonotoneManager.cpp" # from [6b9181533c8b8c3b7729b49b63bdbb2052f798f1] # to [bf41ba111c4aa62c3232eab437a90c9e2ce90610] # # patch "src/monotone/MonotoneManager.h" # from [f611b78a5ed1ddfa0e1df4b71f4df6f7ca4cf552] # to [d3bef0429a337b707bbba48dd882c6e1049fcc9b] # # patch "src/monotone/MonotoneThread.cpp" # from [de00a3b90083487af0c8e0617a85cbf7d836d862] # to [53d99bd42b9b62caf3d720ced1ac673b900c28f8] # # patch "src/monotone/MonotoneThread.h" # from [eeff1fd68782cbe6f82820ff217aecd70d7d24a9] # to [d7d6864ee1f51c6d24d161afebfec7110badd985] # # patch "src/monotone/MonotoneUtil.cpp" # from [bfebdb733f088ed3707d9ffaf755575ce3a48d18] # to [61c5dbbd2cac122916b4905ef577b68740a283a0] # # patch "src/monotone/MonotoneUtil.h" # from [6650b2c4ebddee165d9c7e3acb7d8fd2743e9d1c] # to [ec6bcdda19209c8633eef251ef19972db8027cb8] # # patch "src/monotone/WorkspaceCommitter.cpp" # from [3efc567b8ef22e48f152f8b728a3b168ea0f3d0d] # to [94b1e92f38a51f424c06c3ce4cf4ac0195c22fa5] # # patch "src/util/Platform.cpp" # from [6c034a340f5fb9adf6a7e46e4210b89b3da14e56] # to [60434a883a279fb6ec5992d47271388bc46a0e4e] # # patch "src/view/dialogs/FileDiff.cpp" # from [6e8ff5dbbb84e9fba38d899f7ed619169bd03cd3] # to [44fc4a74f158ae9a6d8a5e855521dc7b8527977b] # # patch "src/view/dialogs/GenerateKeypair.cpp" # from [9b53712e884c27fabeb6b076c31d32de7266c7a6] # to [ed77400baeffdea21382a03f2dd29d33dd33085c] # # patch "src/view/dialogs/Netsync.cpp" # from [3d62c51dffa72aadfe2e4b791fc7d823cbfa331e] # to [14449784c6e3a36a9fb4a7c362b0ba669e9564ca] # # patch "src/view/dialogs/Netsync.h" # from [33cb539497a787d27d32cb594a901ffd8584f4f7] # to [e3ad8ceb0e995647c2ffd2b6494703076be331b3] # # patch "src/view/dialogs/RevisionManifest.cpp" # from [bf15341a35fbdd082baaa951b3f7b91b6594bff4] # to [c7b0722f1a40388a22c2ca0d71e412ead65e9395] # # patch "src/vocab.h" # from [47f7cac5d9cfea1f8308980d3de9268b1e97a674] # to [358c7aa5fe4b611e8339e6af5bead601fc24691f] # ============================================================ --- src/main.cpp d11b766c3378383843a5535c651e5d2581bf32cf +++ src/main.cpp 5bcf3a85423911375242a9f34e2bd59b8ab132ff @@ -55,7 +55,7 @@ int main(int argc, char** argv) qInstallMsgHandler(guitoneMsgHandler); qRegisterMetaType("TickerMap"); - qRegisterMetaType("MonotoneTask"); + qRegisterMetaType("MonotoneTaskPtr"); qRegisterMetaType("QProcess::ProcessError"); QString locale = QLocale::system().name(); ============================================================ --- src/model/Ancestors.cpp ff279efc1a19d894af6db12104e7462b12cce760 +++ src/model/Ancestors.cpp be26e96549d5f55721c5513d9f16e53ecf2e06e6 @@ -42,21 +42,21 @@ void Ancestors::readAncestors(const QStr // reset the view reset(); - MonotoneTask task(QStringList() << "ancestors" << parents); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "ancestors" << parents)); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } -void Ancestors::processTaskResult(const MonotoneTask & task) +void Ancestors::processTaskResult(const MonotoneTaskPtr & task) { - if (task.getReturnCode() == 2) + if (task->getReturnCode() == 2) { - emit invalidAncestor(task.getDecodedOutput()); + emit invalidAncestor(task->getDecodedOutput()); } - if (task.getReturnCode() != 0) + if (task->getReturnCode() != 0) { C(QString("Command returned with a non-zero return code (%1)") - .arg(task.getDecodedOutput())); + .arg(task->getDecodedOutput())); return; } @@ -65,7 +65,7 @@ void Ancestors::processTaskResult(const selRevisions->clear(); delete selRevisions; selRevisions = new RevisionList( - task.getDecodedOutput().split('\n', QString::SkipEmptyParts) + task->getDecodedOutput().split('\n', QString::SkipEmptyParts) ); // reset the view reset(); ============================================================ --- src/model/Ancestors.h ae731fc84d04770fda2c286a3f717d9c2f2759ba +++ src/model/Ancestors.h d668133dc6751725cdea0a976466e8b8c89f3e3b @@ -49,7 +49,7 @@ private: void invalidAncestor(QString); private: - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); RevisionList * selRevisions; bool sorted; DatabaseFile databaseFile; ============================================================ --- src/model/AutomateCommand.cpp 40bb1958db68f50c26d603304d6f7df9d4daa990 +++ src/model/AutomateCommand.cpp 961b064e1e5ceb07843f9fe0b1f88d985f21de08 @@ -42,7 +42,7 @@ AutomateCommand::~AutomateCommand() } } -void AutomateCommand::enqueueTask(MonotoneThread * thread, const MonotoneTask & task) +void AutomateCommand::enqueueTask(const MonotoneThreadPtr & thread, const MonotoneTaskPtr & task) { QMutexLocker locker(&lock); @@ -51,17 +51,17 @@ void AutomateCommand::enqueueTask(Monoto if (!connectedThreads.contains(threadNumber)) { QObject::connect( - thread, SIGNAL(taskAborted(const MonotoneTask &)), - cmdHelper, SLOT(taskAborted(const MonotoneTask &)) + thread.data(), SIGNAL(taskAborted(const MonotoneTaskPtr &)), + cmdHelper, SLOT(taskAborted(const MonotoneTaskPtr &)) ); QObject::connect( - thread, SIGNAL(taskFinished(const MonotoneTask &)), - cmdHelper, SLOT(taskFinished(const MonotoneTask &)) + thread.data(), SIGNAL(taskFinished(const MonotoneTaskPtr &)), + cmdHelper, SLOT(taskFinished(const MonotoneTaskPtr &)) ); QObject::connect( - thread, SIGNAL(tickersChanged(const TickerMap &)), + thread.data(), SIGNAL(tickersChanged(const TickerMap &)), cmdHelper, SLOT(tickersChanged(const TickerMap &)) ); @@ -79,15 +79,15 @@ void AutomateCommand::enqueueTask(Monoto } -void AutomateCommand::enqueueWorkspaceTask(const WorkspacePath & ws, const MonotoneTask & task) +void AutomateCommand::enqueueWorkspaceTask(const WorkspacePath & ws, const MonotoneTaskPtr & task) { - MonotoneThread * thread = APP->manager()->getThreadForWorkspace(ws); + MonotoneThreadPtr thread = APP->manager()->getThreadForWorkspace(ws); enqueueTask(thread, task); } -void AutomateCommand::enqueueDatabaseTask(const DatabaseFile & db, const MonotoneTask & task) +void AutomateCommand::enqueueDatabaseTask(const DatabaseFile & db, const MonotoneTaskPtr & task) { - MonotoneThread * thread = APP->manager()->getThreadForDatabase(db); + MonotoneThreadPtr thread = APP->manager()->getThreadForDatabase(db); enqueueTask(thread, task); } @@ -95,11 +95,8 @@ void AutomateCommand::abortThreads() { QMutexLocker locker(&lock); - QMapIterator > it(queuedCommands); - - while (it.hasNext()) + foreach (int threadNumber, connectedThreads) { - it.next(); // FIXME: this plainly aborts all threads for which we have // commands enqueued, but other models may have added their own // commands in the same thread queue and are therefor also aborted! @@ -107,9 +104,12 @@ void AutomateCommand::abortThreads() // We should find a clean and nice way to only abort the currently // running task and to restart the mtn process proceeding with the // left items in the task queue... - APP->manager()->getThreadByNumber(it.key())->abort(); - queuedCommands.remove(it.key()); + MonotoneThreadPtr thread = APP->manager()->getThreadByNumber(threadNumber); + thread->abort(); + thread->wait(); } + + connectedThreads.clear(); } void AutomateCommand::tickerUpdate(const TickerMap & tickers) @@ -117,29 +117,29 @@ void AutomateCommand::tickerUpdate(const Q_UNUSED(tickers); } -AutomateCommandHelper::AutomateCommandHelper(AutomateCommand * cmd) - : command(cmd) -{} - -void AutomateCommandHelper::taskAborted(const MonotoneTask & task) +void AutomateCommand::processTaskAbortion(const MonotoneTaskPtr & task) { // the task was aborted explicitely, no need to be verbose here - if (task.isAborted()) return; + if (task->isAborted()) return; // do sth more reasonable here in a subclass, // i.e. try to query the data again C(QString("Task %1 (%2) aborted (%3): %4") - .arg(task.getCommandNumber()) - .arg(QString::fromUtf8(task.getEncodedInput())) - .arg(task.getReturnCode()) - .arg(task.getDecodedOutput()) + .arg(task->getCommandNumber()) + .arg(QString::fromUtf8(task->getEncodedInput())) + .arg(task->getReturnCode()) + .arg(task->getDecodedOutput()) ); } -void AutomateCommandHelper::taskFinished(const MonotoneTask & task) +AutomateCommandHelper::AutomateCommandHelper(AutomateCommand * cmd) + : command(cmd) +{} + +void AutomateCommandHelper::taskAborted(const MonotoneTaskPtr & task) { - int threadNumber = task.getThreadNumber(); - int cmdNumber = task.getCommandNumber(); + int threadNumber = task->getThreadNumber(); + int cmdNumber = task->getCommandNumber(); bool threadFound = command->queuedCommands.contains(threadNumber); int commandIdx = !threadFound ? -1 : @@ -149,6 +149,27 @@ void AutomateCommandHelper::taskFinished return; command->queuedCommands[threadNumber].removeAt(commandIdx); + if (command->queuedCommands[threadNumber].size() == 0) + { + command->queuedCommands.remove(threadNumber); + } + + command->processTaskAbortion(task); +} + +void AutomateCommandHelper::taskFinished(const MonotoneTaskPtr & task) +{ + int threadNumber = task->getThreadNumber(); + int cmdNumber = task->getCommandNumber(); + + bool threadFound = command->queuedCommands.contains(threadNumber); + int commandIdx = !threadFound ? -1 : + command->queuedCommands[threadNumber].indexOf(cmdNumber); + + if (commandIdx == -1) + return; + + command->queuedCommands[threadNumber].removeAt(commandIdx); command->processTaskResult(task); } ============================================================ --- src/model/AutomateCommand.h 2c38aad8a34201def446804676086e08296a70d0 +++ src/model/AutomateCommand.h 2e6f883dd2fc93eb56ec23d37a285a104303909b @@ -35,14 +35,15 @@ protected: friend class AutomateCommandHelper; protected: - virtual void processTaskResult(const MonotoneTask &) = 0; + virtual void processTaskResult(const MonotoneTaskPtr &) = 0; + virtual void processTaskAbortion(const MonotoneTaskPtr &); virtual void tickerUpdate(const TickerMap &); - void enqueueWorkspaceTask(const WorkspacePath &, const MonotoneTask &); - void enqueueDatabaseTask(const DatabaseFile &, const MonotoneTask &); + void enqueueWorkspaceTask(const WorkspacePath &, const MonotoneTaskPtr &); + void enqueueDatabaseTask(const DatabaseFile &, const MonotoneTaskPtr &); void abortThreads(); private: - void enqueueTask(MonotoneThread * thread, const MonotoneTask &); + void enqueueTask(const MonotoneThreadPtr &, const MonotoneTaskPtr &); QMutex lock; QList connectedThreads; @@ -60,8 +61,8 @@ protected slots: AutomateCommandHelper(AutomateCommand *); protected slots: - virtual void taskAborted(const MonotoneTask &); - void taskFinished(const MonotoneTask &); + virtual void taskAborted(const MonotoneTaskPtr &); + void taskFinished(const MonotoneTaskPtr &); void tickersChanged(const TickerMap &); private: ============================================================ --- src/model/Branches.cpp f6fb7124bbf93aafb16a8b3ce3fe161c2e06f8ea +++ src/model/Branches.cpp 7434636b987b9c42b7383d73b08327eb4210aead @@ -36,16 +36,16 @@ void Branches::readBranches() branches.clear(); reset(); - MonotoneTask task(QStringList() << "branches"); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "branches")); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } -void Branches::processTaskResult(const MonotoneTask & task) +void Branches::processTaskResult(const MonotoneTaskPtr & task) { - if (task.getReturnCode() != 0) + if (task->getReturnCode() != 0) { C(QString("Command returned with a non-zero return code (%1)") - .arg(task.getDecodedOutput())); + .arg(task->getDecodedOutput())); return; } @@ -73,11 +73,11 @@ void Branches::processTaskResult(const M branches.appendRow(root); builder = new TreeBuilder(root, this); - builder->addList(task.getDecodedOutput()); + builder->addList(task->getDecodedOutput()); } else { - QStringList branchList = task.getDecodedOutput() + QStringList branchList = task->getDecodedOutput() .split("\n", QString::SkipEmptyParts); foreach (const QString & branch, branchList) { ============================================================ --- src/model/Branches.h 910bd8ab66af7a0a6ad019479d867d569494178e +++ src/model/Branches.h c0cdd035892b0e3496cfd51b84dff2b278e59d8d @@ -47,7 +47,7 @@ private: void branchesRead(void); private: - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); QStandardItem * getBranchItem(int row, int column, const QModelIndex & index) const; QStandardItem * branchFromIndex(const QModelIndex & index) const; ============================================================ --- src/model/Certs.cpp 285dd2004b058cc9a7082ca34d0cd21fdc8d9765 +++ src/model/Certs.cpp 2573a7506dc963e2bd969e796986cf273661bcdc @@ -35,20 +35,20 @@ void Certs::readCerts(const QString & re if (rev.size() == 0) return; - MonotoneTask task(QStringList() << "certs" << rev); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "certs" << rev)); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } -void Certs::processTaskResult(const MonotoneTask & task) +void Certs::processTaskResult(const MonotoneTaskPtr & task) { - if (task.getReturnCode() != 0) + if (task->getReturnCode() != 0) { C(QString("Command returned with a non-zero return code (%1)") - .arg(task.getDecodedOutput())); + .arg(task->getDecodedOutput())); return; } - BasicIOParser parser(task.getDecodedOutput()); + BasicIOParser parser(task->getDecodedOutput()); I(parser.parse()); StanzaList list = parser.getStanzas(); ============================================================ --- src/model/Certs.h 187ae7a01ea9ccfe8467875bfe906f4a9f174790 +++ src/model/Certs.h d7ec4361924586c6dd6ed83f9259e35fb5b2017e @@ -51,7 +51,7 @@ private: CertList certs; private: - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); DatabaseFile databaseFile; }; ============================================================ --- src/model/ContentDiff.cpp b9b75d298806aace824aae2e1e54239785b21218 +++ src/model/ContentDiff.cpp 7d5168924ebf7cc688089dbb71e5464608e991ae @@ -71,7 +71,7 @@ void ContentDiff::readDatabaseDiff(const opts << "r" << r; } - MonotoneTask task(cmd, opts); + MonotoneTaskPtr task(new MonotoneTask(cmd, opts)); AutomateCommand::enqueueDatabaseTask(db, task); } @@ -113,13 +113,13 @@ void ContentDiff::readWorkspaceDiff(cons opts << "r" << r; } - MonotoneTask task(cmd, opts); + MonotoneTaskPtr task(new MonotoneTask(cmd, opts)); AutomateCommand::enqueueWorkspaceTask(ws, task); } void ContentDiff::switchOutputEncoding(const QString & enc) { - if (!lastTask.isFinished()) + if (!lastTask->isFinished()) { D("task not yet finished, skip encoding switch"); return; @@ -128,24 +128,24 @@ void ContentDiff::switchOutputEncoding(c encoding = enc; cleanup(); - loadOutputIntoModel(lastTask.getOutput(), enc); + loadOutputIntoModel(lastTask->getOutput(), enc); emit encodingChanged(enc); } -void ContentDiff::processTaskResult(const MonotoneTask & task) +void ContentDiff::processTaskResult(const MonotoneTaskPtr & task) { - if (task.getReturnCode() != 0) + if (task->getReturnCode() != 0) { C(QString("Command returned with a non-zero return code (%1)") - .arg(task.getDecodedOutput())); + .arg(task->getDecodedOutput())); return; } cleanup(); lastTask = task; - loadOutputIntoModel(task.getOutput(), encoding); + loadOutputIntoModel(task->getOutput(), encoding); emit diffRead(); } ============================================================ --- src/model/ContentDiff.h 1f974e237ab07595838d0cc47680ef11242a1474 +++ src/model/ContentDiff.h 6d7f15f9d1f56bac5e7cc8189a1b6dc40993a022 @@ -100,11 +100,30 @@ public: int rowCount(const QModelIndex &) const; int columnCount(const QModelIndex &) const; - inline Diff * getDiff(QString fileName) const { return diffParser->getDiff(fileName); } - inline FileDiffs getAllDiffs() const { return diffParser->getAllDiffs(); } - inline QString getBase() const { return lastTask.getOptions().size() > 1 ? QString(lastTask.getOptions().at(1)) : ""; } - inline QString getTarget() const { return lastTask.getOptions().size() > 3 ? QString(lastTask.getOptions().at(3)) : ""; } + inline Diff * getDiff(QString fileName) const + { + return diffParser->getDiff(fileName); + } + inline FileDiffs getAllDiffs() const + { + return diffParser->getAllDiffs(); + } + + inline QString getBase() const + { + return lastTask->getOptions().size() > 1 ? + QString(lastTask->getOptions().at(1)) : + ""; + } + + inline QString getTarget() const + { + return lastTask->getOptions().size() > 3 ? + QString(lastTask->getOptions().at(3)) : + ""; + } + public slots: void readDatabaseDiff(const DatabaseFile &, const QString &, const QString &, const QString &, const QString & encoding = QString()); void readWorkspaceDiff(const WorkspacePath &, const QString &, const QString &, const QString &, const QString & encoding = QString()); @@ -115,13 +134,13 @@ private: void encodingChanged(const QString &); private: - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); void loadOutputIntoModel(const QByteArray &, const QString &); void cleanup(); DiffParser * diffParser; ListLines lines; - MonotoneTask lastTask; + MonotoneTaskPtr lastTask; QString encoding; }; ============================================================ --- src/model/GetAttributes.cpp 684f7ffa4ef7662c6f978613c7be040ad5cf3081 +++ src/model/GetAttributes.cpp 6646ac15f25d25b19ba253f872d63c240e759331 @@ -58,20 +58,20 @@ void GetAttributes::readAttributes(const else if (!path.isEmpty()) itemPath = path; - MonotoneTask task(QStringList() << "get_attributes" << itemPath); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "get_attributes" << itemPath)); AutomateCommand::enqueueWorkspaceTask(workspacePath, task); } -void GetAttributes::processTaskResult(const MonotoneTask & task) +void GetAttributes::processTaskResult(const MonotoneTaskPtr & task) { - if (task.getReturnCode() != 0) + if (task->getReturnCode() != 0) { C(QString("Command returned with a non-zero return code (%1)") - .arg(task.getDecodedOutput())); + .arg(task->getDecodedOutput())); return; } - BasicIOParser parser(task.getDecodedOutput()); + BasicIOParser parser(task->getDecodedOutput()); I(parser.parse()); StanzaList list = parser.getStanzas(); @@ -264,29 +264,35 @@ bool GetAttributes::setAttribute(const Q bool GetAttributes::setAttribute(const QString & key, const QString & value) { - MonotoneTask out = MonotoneUtil::runSynchronousWorkspaceTask( - workspacePath, - MonotoneTask(QStringList() << "set_attribute" << itemPath << key << value) - ); - return out.getReturnCode() == 0; + MonotoneTaskPtr task(new MonotoneTask( + QStringList() << "set_attribute" << itemPath << key << value + )); + + MonotoneUtil::runSynchronousWorkspaceTask(workspacePath, task); + + return task->getReturnCode() == 0; } bool GetAttributes::dropAttribute(const QString & key) { - MonotoneTask out = MonotoneUtil::runSynchronousWorkspaceTask( - workspacePath, - MonotoneTask(QStringList() << "drop_attribute" << itemPath << key) - ); - return out.getReturnCode() == 0; + MonotoneTaskPtr task(new MonotoneTask( + QStringList() << "drop_attribute" << itemPath << key + )); + + MonotoneUtil::runSynchronousWorkspaceTask(workspacePath, task); + + return task->getReturnCode() == 0; } bool GetAttributes::dropAllAttributes() { - MonotoneTask out = MonotoneUtil::runSynchronousWorkspaceTask( - workspacePath, - MonotoneTask(QStringList() << "drop_attribute" << itemPath) - ); - return out.getReturnCode() == 0; + MonotoneTaskPtr task(new MonotoneTask( + QStringList() << "drop_attribute" << itemPath + )); + + MonotoneUtil::runSynchronousWorkspaceTask(workspacePath, task); + + return task->getReturnCode() == 0; } bool GetAttributes::hasDroppableAttributes() const ============================================================ --- src/model/GetAttributes.h f34a9cc218e83e5dfeed11b7c9929e8b49c2a9cc +++ src/model/GetAttributes.h 4f7ca1ecaf78f12632e3d4a8fa65d670e09020a1 @@ -61,7 +61,7 @@ private: void attributesRead(); private: - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); QList attributes; WorkspacePath workspacePath; QString itemPath; ============================================================ --- src/model/GetContentChanged.cpp 32abedcae92407071a71b07a4e2e104a6ac7edee +++ src/model/GetContentChanged.cpp f07066aea6bb76e5c9ff7a28ad51836a3685dced @@ -82,35 +82,35 @@ void GetContentChanged::queryContentChan void GetContentChanged::queryContentChanged(const QString & rev, const QString & path) { if (stopReadingChanges) return; - MonotoneTask task(QStringList() << "get_content_changed" << rev << path); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "get_content_changed" << rev << path)); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } void GetContentChanged::queryParents(const QString & rev) { if (stopReadingChanges) return; - MonotoneTask task(QStringList() << "parents" << rev); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "parents" << rev)); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } void GetContentChanged::queryCorrespondingPath(const QString & rev, const QString & path, const QString & par) { if (stopReadingChanges) return; - MonotoneTask task(QStringList() << "get_corresponding_path" << rev << path << par); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "get_corresponding_path" << rev << path << par)); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } -void GetContentChanged::processTaskResult(const MonotoneTask & task) +void GetContentChanged::processTaskResult(const MonotoneTaskPtr & task) { - if (task.getReturnCode() != 0) + if (task->getReturnCode() != 0) { C(QString("Command returned with a non-zero return code (%1)") - .arg(task.getDecodedOutput())); + .arg(task->getDecodedOutput())); return; } - QString current = task.getArguments().at(0); - QString output = task.getDecodedOutput(); + QString current = task->getArguments().at(0); + QString output = task->getDecodedOutput(); if (current == "parents") { ============================================================ --- src/model/GetContentChanged.h be46c46e9e3222c6acb9a2d63b7ec274b98b9aa3 +++ src/model/GetContentChanged.h 2e459c7beea84cd2cc13c1fed6776eb8101ee361 @@ -58,7 +58,7 @@ private: void queryParents(const QString &); void queryCorrespondingPath(const QString &, const QString &, const QString &); - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); RevisionList revisions; ============================================================ --- src/model/GetDatabaseVariables.cpp b9ad21e33c9994caf29bdadcb74103c4bb3973de +++ src/model/GetDatabaseVariables.cpp a64d26ea00b105a85ca5883eabd5f280ddf4dbb0 @@ -34,14 +34,14 @@ void GetDatabaseVariables::readVariables void GetDatabaseVariables::readVariables() { I(!databaseFile.isEmpty()); - MonotoneTask task(QStringList() << "get_db_variables"); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "get_db_variables")); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } -void GetDatabaseVariables::processTaskResult(const MonotoneTask & task) +void GetDatabaseVariables::processTaskResult(const MonotoneTaskPtr & task) { - QString output = task.getOutput(); - if (task.getReturnCode() != 0) + QString output = task->getOutput(); + if (task->getReturnCode() != 0) { if (output.indexOf("No variables found") != -1) { @@ -51,7 +51,7 @@ void GetDatabaseVariables::processTaskRe } C(QString("Command returned with a non-zero return code (%1)") - .arg(task.getDecodedOutput())); + .arg(task->getDecodedOutput())); return; } @@ -214,19 +214,23 @@ bool GetDatabaseVariables::setVariable(c bool GetDatabaseVariables::setVariable(const QString & domain, const QString & key, const QString & value) { - MonotoneTask out = MonotoneUtil::runSynchronousDatabaseTask( - databaseFile, - MonotoneTask(QStringList() << "set_db_variable" << domain << key << value) - ); - return out.getReturnCode() == 0; + MonotoneTaskPtr task(new MonotoneTask( + QStringList() << "set_db_variable" << domain << key << value + )); + + MonotoneUtil::runSynchronousDatabaseTask(databaseFile, task); + + return task->getReturnCode() == 0; } bool GetDatabaseVariables::dropVariable(const QString & domain, const QString & key) { - MonotoneTask out = MonotoneUtil::runSynchronousDatabaseTask( - databaseFile, - MonotoneTask(QStringList() << "drop_db_variables" << domain << key) - ); - return out.getReturnCode() == 0; + MonotoneTaskPtr task(new MonotoneTask( + QStringList() << "drop_db_variables" << domain << key + )); + + MonotoneUtil::runSynchronousDatabaseTask(databaseFile, task); + + return task->getReturnCode() == 0; } ============================================================ --- src/model/GetDatabaseVariables.h 12358ebfe7da2c6b5bf4d2c28264af387f2f3abc +++ src/model/GetDatabaseVariables.h d5c88700402f4dd78230f3ef8a737571950a4d57 @@ -50,7 +50,7 @@ private: void variablesRead(); private: - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); DatabaseFile databaseFile; // technically we could rewrite the QList> as QMap<...>, // but this structure would be harder to serve the model methods ============================================================ --- src/model/GetFile.cpp 735189cbe8ffb4e7cffd1a40e07fef37a0068ea4 +++ src/model/GetFile.cpp 2f57e09ce0224ab42b9d907cd5ace3bd35ebe999 @@ -54,40 +54,40 @@ void GetFile::readFile(const DatabaseFil const QStringList & opts, const QString & encoding) { reset(); - MonotoneTask task(cmd, opts); + MonotoneTaskPtr task(new MonotoneTask(cmd, opts)); if (!encoding.isEmpty()) { - task.setOutputEncoding(encoding); + task->setOutputEncoding(encoding); } AutomateCommand::enqueueDatabaseTask(db, task); } -void GetFile::processTaskResult(const MonotoneTask & task) +void GetFile::processTaskResult(const MonotoneTaskPtr & task) { - if (task.getReturnCode() != 0) + if (task->getReturnCode() != 0) { C(QString("Command returned with a non-zero return code (%1)") - .arg(task.getDecodedOutput())); + .arg(task->getDecodedOutput())); return; } lastTask = task; - loadOutputIntoModel(task.getDecodedOutput()); + loadOutputIntoModel(task->getDecodedOutput()); emit fileRead(); } void GetFile::switchOutputEncoding(const QString & codec) { - if (!lastTask.isFinished()) + if (!lastTask->isFinished()) { D("task not yet finished, skip encoding switch"); return; } - loadOutputIntoModel(lastTask.getDecodedOutput(codec)); + loadOutputIntoModel(lastTask->getDecodedOutput(codec)); emit encodingChanged(codec); } ============================================================ --- src/model/GetFile.h 73a82bb540ba6ca45cd9c6fcdc4f165a6ded958b +++ src/model/GetFile.h 079d6a0490ed823f4d9169bfb8a35f107cdc07e2 @@ -69,11 +69,11 @@ private: private: void readFile(const DatabaseFile &, const QStringList &, const QStringList &, const QString & encoding = QString()); - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); void loadOutputIntoModel(const QString &); Content fileContents; - MonotoneTask lastTask; + MonotoneTaskPtr lastTask; }; #endif ============================================================ --- src/model/GetRevision.cpp 0306aaaaa58093f4c4765f8a966fce0873120bbf +++ src/model/GetRevision.cpp 7561bccabe38f3202931a7ac485c0d907395f892 @@ -34,7 +34,7 @@ void GetRevision::readDatabaseRevision(c void GetRevision::readDatabaseRevision(const DatabaseFile & db, const QString & rev) { revision.clear(); - MonotoneTask task( QStringList() << "get_revision" << rev); + MonotoneTaskPtr task(new MonotoneTask( QStringList() << "get_revision" << rev)); AutomateCommand::enqueueDatabaseTask(db, task); } @@ -49,19 +49,19 @@ void GetRevision::readWorkspaceRevision( args << paths; } - MonotoneTask task(args); + MonotoneTaskPtr task(new MonotoneTask(args)); AutomateCommand::enqueueWorkspaceTask(ws, task); } -void GetRevision::processTaskResult(const MonotoneTask & task) +void GetRevision::processTaskResult(const MonotoneTaskPtr & task) { - if (task.getReturnCode() != 0) + if (task->getReturnCode() != 0) { - emit readFailed(MonotoneUtil::stripMtnPrefix(task.getDecodedOutput())); + emit readFailed(MonotoneUtil::stripMtnPrefix(task->getDecodedOutput())); return; } - BasicIOParser parser(task.getDecodedOutput()); + BasicIOParser parser(task->getDecodedOutput()); I(parser.parse()); StanzaList list = parser.getStanzas(); ============================================================ --- src/model/GetRevision.h 8f8b5b334bc0fdaadad441f82ed65024617ea8b1 +++ src/model/GetRevision.h 29813b88948834794c0947f3fe35e6467a3b4dc3 @@ -176,7 +176,7 @@ private: void readFailed(const QString &); private: - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); Revision revision; QString currentParentRevision; ============================================================ --- src/model/Inventory.cpp 5c2141e6a83a9f0ed4a7e32f60aff0bc2bb983f8 +++ src/model/Inventory.cpp dbd52e14bb66a0aa0e2737f70af4da384f4a0ef3 @@ -63,7 +63,7 @@ void Inventory::read(const QString & pat opts << "no-corresponding-renames" << QString(); } - MonotoneTask task(cmd, opts); + MonotoneTaskPtr task(new MonotoneTask(cmd, opts)); AutomateCommand::enqueueWorkspaceTask(workspacePath, task); } @@ -77,35 +77,35 @@ void Inventory::read(const QString & pat request with the baseDir right here, delete the node and continue with the next one */ -void Inventory::processTaskResult(const MonotoneTask & task) +void Inventory::processTaskResult(const MonotoneTaskPtr & task) { QString queriedPath = ""; - if (task.getArguments().size() > 1) + if (task->getArguments().size() > 1) { - queriedPath = task.getArguments().at(1); + queriedPath = task->getArguments().at(1); } int queriedDepth = -1; - if (task.getOptions().size() > 1) + if (task->getOptions().size() > 1) { - queriedDepth = task.getOptions().at(1).toInt(); + queriedDepth = task->getOptions().at(1).toInt(); if (!queriedPath.isEmpty()) { queriedDepth += queriedPath.split("/", QString::SkipEmptyParts).size(); } } - QString output = task.getDecodedOutput(); + QString output = task->getDecodedOutput(); // internal errors - if (task.getReturnCode() == 1) + if (task->getReturnCode() == 1) { C(QString("Command returned with an error: %1").arg(output)); return; } // user errors - if (task.getReturnCode() == 2) + if (task->getReturnCode() == 2) { // if the path we've silently queried became unknown (i.e. was removed), // remove it from the model. Note however that automate inventory does ============================================================ --- src/model/Inventory.h c9663f40bd61cac606d5f3015c76fd78e8914fa6 +++ src/model/Inventory.h 268e93aa6b0b830a5bcc947353018fba8508ded3 @@ -42,7 +42,7 @@ private: void read(const QString & path = QString(), bool fullQuery = false); private: - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); void insertRowsRecursive(ModelItem *, const QMap > &); void removeRowsRecursive(ModelItem *, int, int); ============================================================ --- src/model/Keys.cpp 9283be02e0195529d98eca218d0736b5666836a4 +++ src/model/Keys.cpp 02497764e76e5dca25c68abdc2a106b84c28a86b @@ -33,23 +33,23 @@ void Keys::readKeys() void Keys::readKeys() { - MonotoneTask task(QStringList() << "keys"); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "keys")); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } -void Keys::processTaskResult(const MonotoneTask & task) +void Keys::processTaskResult(const MonotoneTaskPtr & task) { - if (task.getReturnCode() != 0) + if (task->getReturnCode() != 0) { C(QString("Command returned with a non-zero return code (%1)") - .arg(task.getDecodedOutput())); + .arg(task->getDecodedOutput())); return; } reset(); keys.clear(); - BasicIOParser parser(task.getDecodedOutput()); + BasicIOParser parser(task->getDecodedOutput()); I(parser.parse()); StanzaList list = parser.getStanzas(); ============================================================ --- src/model/Keys.h c8a97fb1a99d0e451cd939434b4332443e403d95 +++ src/model/Keys.h 3131df73288c46a0f22f82d5490e5a184666d9a1 @@ -57,7 +57,7 @@ private: void keysRead(); private: - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); QString getLocationString(int) const; QList keys; DatabaseFile databaseFile; ============================================================ --- src/model/Manifest.cpp 6c9e78ed14e8b0889bc1d84bafafe82c46f1ed3c +++ src/model/Manifest.cpp e50bdb95dde92c0bf991c0ce2b4eec714854bf4e @@ -34,20 +34,20 @@ void Manifest::readManifest(const QStrin // reset the view reset(); - MonotoneTask task(QStringList() << "get_manifest_of" << rev); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "get_manifest_of" << rev)); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } -void Manifest::processTaskResult(const MonotoneTask & task) +void Manifest::processTaskResult(const MonotoneTaskPtr & task) { - if (task.getReturnCode() != 0) + if (task->getReturnCode() != 0) { C(QString("Command returned with a non-zero return code (%1)") - .arg(task.getDecodedOutput())); + .arg(task->getDecodedOutput())); return; } - BasicIOParser parser(task.getDecodedOutput()); + BasicIOParser parser(task->getDecodedOutput()); I(parser.parse()); StanzaList list = parser.getStanzas(); ============================================================ --- src/model/Manifest.h 9231a0ed7276006ab96952b04dbb83997a6a48e6 +++ src/model/Manifest.h 87f96415291d30c53cfe236812da7c0f7e8e9840 @@ -86,7 +86,7 @@ private: void manifestRead(); private: - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); DatabaseFile databaseFile; ManifestEntry * root; }; ============================================================ --- src/model/Select.cpp a82a300f0787e9ae330c0c8ca96083da99d82476 +++ src/model/Select.cpp e77b9594f21232a0e6c7396a3fccf4c78f874dfe @@ -38,30 +38,30 @@ void Select::readSelection(const QString // reset the view reset(); - MonotoneTask task(QStringList() << "select" << selector); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "select" << selector)); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } -void Select::processTaskResult(const MonotoneTask & task) +void Select::processTaskResult(const MonotoneTaskPtr & task) { // since there is no other indication we assume that errCode 2 // is always fired if a invalid selector syntax has been given - if (task.getReturnCode() == 2) + if (task->getReturnCode() == 2) { - emit invalidSelection(task.getDecodedOutput()); + emit invalidSelection(task->getDecodedOutput()); return; } - if (task.getReturnCode() != 0) + if (task->getReturnCode() != 0) { C(QString("Command returned with a non-zero return code (%1)") - .arg(task.getDecodedOutput())); + .arg(task->getDecodedOutput())); return; } delete selRevisions; selRevisions = new RevisionList( - task.getDecodedOutput().split('\n', QString::SkipEmptyParts) + task->getDecodedOutput().split('\n', QString::SkipEmptyParts) ); // reset the view reset(); ============================================================ --- src/model/Select.h 520e6de98e71ac10e9e72ac5341f725302096816 +++ src/model/Select.h b8dc238d172c17c51ae3bf80a9cd2b2ad394939d @@ -47,7 +47,7 @@ private: void invalidSelection(QString); private: - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); RevisionList * selRevisions; bool sorted; ============================================================ --- src/model/Tags.cpp 31c3f32539c54fb7bc7d676d18ad0581356f844c +++ src/model/Tags.cpp a7caf48663871fe5e12a75451dafd8c6f95d7f0a @@ -40,22 +40,22 @@ void Tags::readTags(const QString & bran cmd << branch; } - MonotoneTask task(cmd); + MonotoneTaskPtr task(new MonotoneTask(cmd)); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } -void Tags::processTaskResult(const MonotoneTask & task) +void Tags::processTaskResult(const MonotoneTaskPtr & task) { - if (task.getReturnCode() != 0) + if (task->getReturnCode() != 0) { C(QString("Command returned with a non-zero return code (%1)") - .arg(task.getDecodedOutput())); + .arg(task->getDecodedOutput())); return; } tags->clear(); - BasicIOParser parser(task.getDecodedOutput()); + BasicIOParser parser(task->getDecodedOutput()); I(parser.parse()); StanzaList list = parser.getStanzas(); ============================================================ --- src/model/Tags.h f2fba601247219ecee7aae5c7ddff42aacfb872f +++ src/model/Tags.h 81fec9954f65235ce921988b55da5039cdd9b9c2 @@ -55,7 +55,7 @@ private: void tagsRead(); private: - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); TagList * tags; DatabaseFile databaseFile; }; ============================================================ --- src/model/Toposort.cpp c5f0896d43e6e9763571e201281ee49db94ad22e +++ src/model/Toposort.cpp bff816b44fd93172dd2388c8f67ba9cfda1cd300 @@ -111,20 +111,20 @@ void Toposort::sortModel() } while (true); - MonotoneTask task(QStringList() << "toposort" << revs); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "toposort" << revs)); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } -void Toposort::processTaskResult(const MonotoneTask & task) +void Toposort::processTaskResult(const MonotoneTaskPtr & task) { - if (task.getReturnCode() != 0) + if (task->getReturnCode() != 0) { C(QString("Command returned with a non-zero return code (%1)") - .arg(task.getDecodedOutput())); + .arg(task->getDecodedOutput())); return; } - QStringList sortedRevs(task.getDecodedOutput().split("\n")); + QStringList sortedRevs(task->getDecodedOutput().split("\n")); for (int i=0, j=sortedRevs.size(); iinsert(sortedRevs.at(i), i); ============================================================ --- src/model/Toposort.h 85ef196576a29c5d66202858fbe131e4a53e9332 +++ src/model/Toposort.h c077c6787ee68374b47d19961df83adf71258ea5 @@ -39,7 +39,7 @@ private: void sortingFinished(); private: - void processTaskResult(const MonotoneTask &); + void processTaskResult(const MonotoneTaskPtr &); bool lessThan(const QModelIndex &, const QModelIndex &) const; bool filterAcceptsRow(int, const QModelIndex &) const; ============================================================ --- src/monotone/FileExporter.cpp 8d23af2f0072da14f8c79d2d71b3db6701693729 +++ src/monotone/FileExporter.cpp 4cea02c79f62a4d0b83a192b453be081e3c9c7e6 @@ -81,19 +81,19 @@ bool FileExporter::exportFile(const File return true; } - MonotoneTask out = MonotoneUtil::runSynchronousDatabaseTask( - databaseFile, - MonotoneTask( - QStringList() << "get_file_of" << entry.path, - QStringList() << "r" << revision - ) - ); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask( + QStringList() << "get_file_of" << entry.path, + QStringList() << "r" << revision + )); - if (out.getReturnCode() > 0) + MonotoneUtil::runSynchronousDatabaseTask(databaseFile, task); + + if (!task->isFinished()) F("task aborted"); + + if (task->getReturnCode() > 0) { C(QString("get_file_of '%1' (rev: %2) failed: %3") - .arg(entry.path).arg(revision).arg(out.getDecodedOutput())); + .arg(entry.path).arg(revision).arg(task->getDecodedOutput())); return false; } @@ -106,7 +106,7 @@ bool FileExporter::exportFile(const File return false; } - I(file.write(out.getOutput())); + I(file.write(task->getOutput())); if (entry.attrs.contains("mtn:execute") && entry.attrs.value("mtn:execute") == "true") ============================================================ --- src/monotone/MonotoneManager.cpp 6b9181533c8b8c3b7729b49b63bdbb2052f798f1 +++ src/monotone/MonotoneManager.cpp bf41ba111c4aa62c3232eab437a90c9e2ce90610 @@ -31,18 +31,15 @@ MonotoneManager::~MonotoneManager() MonotoneManager::~MonotoneManager() { - QMapIterator it(threadMap); - while(it.hasNext()) + QMapIterator it(threadMap); + while (it.hasNext()) { it.next(); - int threadNumber = it.key(); - MonotoneThread * thread = it.value(); - D(QString("aborting thread %1").arg(threadNumber)); + MonotoneThreadPtr thread = it.value(); thread->abort(); thread->wait(); - threadMap.remove(threadNumber); - delete thread; } + threadMap.clear(); } bool MonotoneManager::setMonotoneBinaryPath(const QString & mtnBinary, @@ -66,9 +63,7 @@ bool MonotoneManager::setMonotoneBinaryP return true; } -// FIXME: I think we need to care somehow if we pass -// threads around - i.e. use shared ptrs or something -MonotoneThread * MonotoneManager::getThreadForWorkspace(const WorkspacePath & workspace) +MonotoneThreadPtr MonotoneManager::getThreadForWorkspace(const WorkspacePath & workspace) { // ensure that its normalized WorkspacePath normalizedWorkspace = normalizeWorkspacePath(workspace); @@ -76,7 +71,7 @@ MonotoneThread * MonotoneManager::getThr return getThread(databaseFile, normalizedWorkspace); } -MonotoneThread * MonotoneManager::getThreadForDatabase(const DatabaseFile & database) +MonotoneThreadPtr MonotoneManager::getThreadForDatabase(const DatabaseFile & database) { if (database.isEmpty()) { @@ -106,7 +101,7 @@ MonotoneThread * MonotoneManager::getThr return getThread(database, QString()); } -MonotoneThread * MonotoneManager::getThreadByNumber(int threadNumber) +MonotoneThreadPtr MonotoneManager::getThreadByNumber(int threadNumber) { if (!threadMap.contains(threadNumber)) { @@ -115,7 +110,7 @@ MonotoneThread * MonotoneManager::getThr return threadMap.value(threadNumber); } -MonotoneThread * MonotoneManager::getThread(const DatabaseFile & database, const WorkspacePath & workspace) +MonotoneThreadPtr MonotoneManager::getThread(const DatabaseFile & database, const WorkspacePath & workspace) { QMutexLocker locker(&lock); @@ -131,8 +126,8 @@ MonotoneThread * MonotoneManager::getThr { threadNumber++; - MonotoneThread * thread = - new MonotoneThread(threadNumber, mtnPath, database, workspace); + MonotoneThreadPtr thread + (new MonotoneThread(threadNumber, mtnPath, database, workspace)); threadMap.insert(threadNumber, thread); identMap.insert(threadNumber, database + "|"); @@ -143,12 +138,12 @@ MonotoneThread * MonotoneManager::getThr threadIDs.append(threadNumber); connect( - thread, SIGNAL(stopped(int)), + thread.data(), SIGNAL(stopped(int)), this, SLOT(stopped(int)) ); connect( - thread, SIGNAL(aborted(int, QProcess::ProcessError, const QString &)), + thread.data(), SIGNAL(aborted(int, QProcess::ProcessError, const QString &)), this, SLOT(aborted(int, QProcess::ProcessError, const QString &)) ); @@ -251,18 +246,15 @@ void MonotoneManager::removeThread(int t I(threadMap.contains(threadNumber)); - MonotoneThread * thread = threadMap.value(threadNumber); + MonotoneThreadPtr thread = threadMap.value(threadNumber); - QString databaseFile = thread->getDatabaseFilePath(); - QString workspacePath = thread->getWorkspacePath(); - disconnect( - thread, SIGNAL(stopped(int)), + thread.data(), SIGNAL(stopped(int)), this, SLOT(stopped(int)) ); disconnect( - thread, SIGNAL(aborted(int, QProcess::ProcessError, const QString &)), + thread.data(), SIGNAL(aborted(int, QProcess::ProcessError, const QString &)), this, SLOT(aborted(int, QProcess::ProcessError, const QString &)) ); @@ -271,8 +263,6 @@ void MonotoneManager::removeThread(int t // wait until the thread has finished execution thread->wait(); - - delete thread; } void MonotoneManager::stopped(int threadNumber) @@ -285,7 +275,7 @@ void MonotoneManager::aborted(int thread { I(threadMap.contains(threadNumber)); - MonotoneThread * thread = threadMap.value(threadNumber); + MonotoneThreadPtr thread = threadMap.value(threadNumber); QString databaseFile = thread->getDatabaseFilePath(); QString workspacePath = thread->getWorkspacePath(); ============================================================ --- src/monotone/MonotoneManager.h f611b78a5ed1ddfa0e1df4b71f4df6f7ca4cf552 +++ src/monotone/MonotoneManager.h d3bef0429a337b707bbba48dd882c6e1049fcc9b @@ -40,13 +40,13 @@ public: DatabaseFile getDatabaseFilePath(const WorkspacePath &); //! returns an appropriate MonotoneThread for the given workspace - MonotoneThread * getThreadForWorkspace(const WorkspacePath &); + MonotoneThreadPtr getThreadForWorkspace(const WorkspacePath &); //! returns an appropriate MonotoneThread for the given database - MonotoneThread * getThreadForDatabase(const DatabaseFile &); + MonotoneThreadPtr getThreadForDatabase(const DatabaseFile &); //! returns a thread by a given thread number - MonotoneThread * getThreadByNumber(int); + MonotoneThreadPtr getThreadByNumber(int); //! runs a single command and returns its output static bool singleRun(const QString &, const QStringList &, QByteArray &); @@ -70,10 +70,10 @@ private: void threadAborted(const QString &); private: - MonotoneThread * getThread(const DatabaseFile &, const WorkspacePath &); + MonotoneThreadPtr getThread(const DatabaseFile &, const WorkspacePath &); void removeThread(int); - QMap threadMap; + QMap threadMap; QMultiMap identMap; QMap workspaceMap; ============================================================ --- src/monotone/MonotoneThread.cpp de00a3b90083487af0c8e0617a85cbf7d836d862 +++ src/monotone/MonotoneThread.cpp 53d99bd42b9b62caf3d720ced1ac673b900c28f8 @@ -145,36 +145,37 @@ MonotoneThread::~MonotoneThread() {} MonotoneThread::~MonotoneThread() {} - +//! returns true if the process started successfully, +//! false in case of an abortion (whatever comes first) bool MonotoneThread::waitForStarted() { QEventLoop * ev = new QEventLoop(this); connect(this, SIGNAL(started(int)), ev, SLOT(quit())); - connect(this, SIGNAL(aborted(int, QProcess::ProcessError, const QString &)), + connect(this, SIGNAL(terminated()), ev, SLOT(quit())); ev->exec(); - delete ev; - return !doAbort; + + return isRunning(); } -int MonotoneThread::enqueueTask(const MonotoneTask & task) +int MonotoneThread::enqueueTask(const MonotoneTaskPtr & task) { QMutexLocker locker(&lock); if (doAbort) return -1; commandNumber++; - MonotoneTask workItem(task); - workItem.setCommandNumber(commandNumber); - workItem.setThreadNumber(threadNumber); - queue.enqueue(workItem); + task->setCommandNumber(commandNumber); + task->setThreadNumber(threadNumber); + queue.enqueue(task); waitForTasks.wakeAll(); - D(QString("thread %1: new task enqueued: %2").arg(threadNumber).arg(QString(task.getEncodedInput()))); + D(QString("thread %1: new task enqueued: %2") + .arg(threadNumber).arg(QString(task->getEncodedInput()))); return commandNumber; } @@ -189,11 +190,9 @@ void MonotoneThread::cleanup(QProcess * { QMutexLocker locker(&lock); - doAbort = true; - if (queue.size() > 0) { - foreach (MonotoneTask task, queue) + foreach (MonotoneTaskPtr task, queue) { emit taskAborted(task); } @@ -315,10 +314,10 @@ void MonotoneThread::run() return; } - MonotoneTask task = queue.head(); + MonotoneTaskPtr task = queue.head(); // check if we should cancel the processing of this task - if (task.isAborted()) + if (task->isAborted()) { processingTask = false; buffer.clear(); @@ -331,7 +330,7 @@ void MonotoneThread::run() if (!processingTask) { - QByteArray in(task.getEncodedInput()); + QByteArray in(task->getEncodedInput()); if (process->write(in) == -1) { @@ -341,8 +340,8 @@ void MonotoneThread::run() err.append(")"); task = queue.dequeue(); - task.setOutput(err); - task.setReturnCode(-1); + task->setOutput(err); + task->setReturnCode(-1); emit taskAborted(task); continue; @@ -353,15 +352,16 @@ void MonotoneThread::run() tickers.clear(); processingTask = true; - D(QString("thread %1: task %2 (%3) started").arg(threadNumber) - .arg(task.getCommandNumber()).arg(QString(task.getEncodedInput()))); + D(QString("thread %1: task %2 (%3) started") + .arg(threadNumber) + .arg(task->getCommandNumber()) + .arg(QString(task->getEncodedInput()))); } while (!process->waitForReadyRead(500) && !doAbort) { if (process->error() == QProcess::Timedout) { - L("waiting just a little longer"); continue; } @@ -375,8 +375,8 @@ void MonotoneThread::run() QByteArray err = process->readAllStandardError(); if (err.size() != 0 || doAbort) { - task.setOutput(err); - task.setReturnCode(-1); + task->setOutput(err); + task->setReturnCode(-1); processingTask = false; buffer.clear(); @@ -414,9 +414,19 @@ void MonotoneThread::run() foreach (char ident, tickerUpdates.keys()) { if (tickers.contains(ident)) - tickers[ident].update(tickerUpdates[ident]); + { + // ticker symbols might not be unique during + // program execution and new tickers may share + // the symbol of an already completed ticker + if (tickers[ident].complete) + tickers[ident] = tickerUpdates[ident]; + else + tickers[ident].update(tickerUpdates[ident]); + } else + { tickers[ident] = tickerUpdates[ident]; + } } } @@ -437,16 +447,18 @@ void MonotoneThread::run() if (returnCode < 0) continue; - task.setOutput(output); - task.setReturnCode(returnCode); - task.setFinished(); + task->setOutput(output); + task->setReturnCode(returnCode); + task->setFinished(); queue.dequeue(); processingTask = false; - D(QString("thread %1: task %2 (%3) finished").arg(threadNumber) - .arg(task.getCommandNumber()).arg(QString(task.getEncodedInput()))); + D(QString("thread %1: task %2 (%3) finished") + .arg(threadNumber) + .arg(task->getCommandNumber()) + .arg(QString(task->getEncodedInput()))); emit taskFinished(task); } ============================================================ --- src/monotone/MonotoneThread.h eeff1fd68782cbe6f82820ff217aecd70d7d24a9 +++ src/monotone/MonotoneThread.h d7d6864ee1f51c6d24d161afebfec7110badd985 @@ -126,7 +126,7 @@ public: inline int getThreadNumber() const { return threadNumber; } //! enqueue a new task for this thread - int enqueueTask(const MonotoneTask &); + int enqueueTask(const MonotoneTaskPtr &); //! abort task execution on this thread /*! @@ -143,10 +143,10 @@ signals: signals: //! signaled if a task has been finished - void taskFinished(const MonotoneTask &); + void taskFinished(const MonotoneTaskPtr &); //! signaled for each task which has been aborted - void taskAborted(const MonotoneTask &); + void taskAborted(const MonotoneTaskPtr &); //! signaled if the internal mtn process was successfully started void started(int); @@ -171,12 +171,16 @@ private: bool doAbort; int commandNumber; int threadNumber; + QString mtnBinary; QString databasePath; QString workspacePath; - QQueue queue; + + QQueue queue; QMutex lock; + QWaitCondition waitForTasks; + TickerMap tickers; }; ============================================================ --- src/monotone/MonotoneUtil.cpp bfebdb733f088ed3707d9ffaf755575ce3a48d18 +++ src/monotone/MonotoneUtil.cpp 61c5dbbd2cac122916b4905ef577b68740a283a0 @@ -20,60 +20,71 @@ #include "GuitoneCore.h" #include "BasicIOParser.h" -MonotoneUtil::MonotoneUtil(MonotoneThread * thread, const MonotoneTask & in) +void MonotoneUtil::taskFinished(const MonotoneTaskPtr & task) { - connect( - thread, SIGNAL(taskFinished(const MonotoneTask &)), - this, SLOT(taskFinished(const MonotoneTask &)) - ); - commandNumber = thread->enqueueTask(in); + if (task->getCommandNumber() != currentCommandNumber) + return; + + emit finished(); } -MonotoneTask & MonotoneUtil::getTaskResult() +void MonotoneUtil::taskAborted(const MonotoneTaskPtr & task) { - eventLoop.exec(); - return result; + if (task->getCommandNumber() != currentCommandNumber) + return; + + C(QString("Task %1 (thread %2) aborted (%3)") + .arg(task->getCommandNumber()) + .arg(task->getThreadNumber()) + .arg(QString::fromUtf8(task->getEncodedInput())) + ); + + emit finished(); } -void MonotoneUtil::taskFinished(const MonotoneTask & task) +void MonotoneUtil::run(const MonotoneThreadPtr & thread, const MonotoneTaskPtr & task) { - if (task.getCommandNumber() != commandNumber) return; - result = task; - eventLoop.quit(); -} + connect( + thread.data(), SIGNAL(taskFinished(const MonotoneTaskPtr &)), + this, SLOT(taskFinished(const MonotoneTaskPtr &)) + ); -void MonotoneUtil::taskAborted(const MonotoneTask & task) -{ - if (task.getCommandNumber() != commandNumber) return; - C(QString("Task %1 (thread %2) aborted (%3)") - .arg(task.getCommandNumber()) - .arg(task.getThreadNumber()) - .arg(QString::fromUtf8(task.getEncodedInput())) + connect( + thread.data(), SIGNAL(taskAborted(const MonotoneTaskPtr &)), + this, SLOT(taskAborted(const MonotoneTaskPtr &)) ); - result = task; - eventLoop.quit(); -} -// -// static methods -// + currentCommandNumber = thread->enqueueTask(task); -MonotoneTask MonotoneUtil::runSynchronousWorkspaceTask(const WorkspacePath & workspace, const MonotoneTask & task) + QEventLoop * ev = new QEventLoop(this); + connect(this, SIGNAL(finished()), ev, SLOT(quit())); + ev->exec(); + + delete ev; + + disconnect( + thread.data(), SIGNAL(taskFinished(const MonotoneTaskPtr &)), + this, SLOT(taskFinished(const MonotoneTaskPtr &)) + ); + + disconnect( + thread.data(), SIGNAL(taskAborted(const MonotoneTaskPtr &)), + this, SLOT(taskAborted(const MonotoneTaskPtr &)) + ); +} + +void MonotoneUtil::runSynchronousWorkspaceTask(const WorkspacePath & workspace, const MonotoneTaskPtr & task) { - MonotoneThread * thread = APP->manager()->getThreadForWorkspace(workspace); - MonotoneUtil * instance = new MonotoneUtil(thread, task); - MonotoneTask result = instance->getTaskResult(); + MonotoneUtil * instance = new MonotoneUtil(); + instance->run(APP->manager()->getThreadForWorkspace(workspace), task); delete instance; - return result; } -MonotoneTask MonotoneUtil::runSynchronousDatabaseTask(const DatabaseFile & database, const MonotoneTask & task) +void MonotoneUtil::runSynchronousDatabaseTask(const DatabaseFile & database, const MonotoneTaskPtr & task) { - MonotoneThread * thread = APP->manager()->getThreadForDatabase(database); - MonotoneUtil * instance = new MonotoneUtil(thread, task); - MonotoneTask result = instance->getTaskResult(); + MonotoneUtil * instance = new MonotoneUtil(); + instance->run(APP->manager()->getThreadForDatabase(database), task); delete instance; - return result; } DatabaseFile MonotoneUtil::getDatabaseFile(const WorkspacePath & workspace) @@ -83,12 +94,16 @@ QString MonotoneUtil::getBaseWorkspaceRe QString MonotoneUtil::getBaseWorkspaceRevision(const WorkspacePath & workspace) { - MonotoneTask in(QStringList() << "get_base_revision_id"); - MonotoneTask out = runSynchronousWorkspaceTask(workspace, in); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "get_base_revision_id")); + runSynchronousWorkspaceTask(workspace, task); + if (!task->isFinished()) + { + C(QString("task '%1' aborted").arg(QString(task->getEncodedInput()))); + return QString(); + } - QString data = out.getDecodedOutput(); - if (out.getReturnCode() > 0) + QString data = task->getDecodedOutput(); + if (task->getReturnCode() > 0) { C(QString("Could not execute get_base_revision_id: %1").arg(data)); return QString(); @@ -105,12 +120,16 @@ QString MonotoneUtil::getOption(const Wo QString MonotoneUtil::getOption(const WorkspacePath & workspace, const QString & opt) { - MonotoneTask in(QStringList() << "get_option" << opt); - MonotoneTask out = runSynchronousWorkspaceTask(workspace, in); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "get_option" << opt)); + runSynchronousWorkspaceTask(workspace, task); + if (!task->isFinished()) + { + C(QString("task '%1' aborted").arg(QString(task->getEncodedInput()))); + return QString(); + } - QString data = out.getDecodedOutput(); - if (out.getReturnCode() > 0) + QString data = task->getDecodedOutput(); + if (task->getReturnCode() > 0) { C(QString("Couldn't retrieve option %1: %2").arg(opt).arg(data)); return QString(); @@ -166,12 +185,16 @@ QStringList MonotoneUtil::resolveSelecto QStringList MonotoneUtil::resolveSelector(const DatabaseFile & db, const QString & selector) { - MonotoneTask in(QStringList() << "select" << selector); - MonotoneTask out = runSynchronousDatabaseTask(db, in); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "select" << selector)); + runSynchronousDatabaseTask(db, task); + if (!task->isFinished()) + { + C(QString("task '%1' aborted").arg(QString(task->getEncodedInput()))); + return QStringList(); + } - QString data = out.getDecodedOutput(); - if (out.getReturnCode() > 0) + QString data = task->getDecodedOutput(); + if (task->getReturnCode() > 0) { C(QString("Couldn't resolve selector %1: %2").arg(selector).arg(data)); return QStringList(); @@ -183,12 +206,16 @@ RevisionCerts MonotoneUtil::getRevisionC RevisionCerts MonotoneUtil::getRevisionCerts(const DatabaseFile & db, const QString & revision) { - MonotoneTask in(QStringList() << "certs" << revision); - MonotoneTask out = runSynchronousDatabaseTask(db, in); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "certs" << revision)); + runSynchronousDatabaseTask(db, task); + if (!task->isFinished()) + { + C(QString("task '%1' aborted").arg(QString(task->getEncodedInput()))); + return RevisionCerts(); + } - QString data = out.getDecodedOutput(); - if (out.getReturnCode() > 0) + QString data = task->getDecodedOutput(); + if (task->getReturnCode() > 0) { C(QString("Couldn't query revision certs for %1: %2").arg(revision).arg(data)); return RevisionCerts(); @@ -228,12 +255,16 @@ FileEntryList MonotoneUtil::getRevisionM FileEntryList MonotoneUtil::getRevisionManifest(const DatabaseFile & db, const QString & revision) { - MonotoneTask in(QStringList() << "get_manifest_of" << revision); - MonotoneTask out = runSynchronousDatabaseTask(db, in); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "get_manifest_of" << revision)); + runSynchronousDatabaseTask(db, task); + if (!task->isFinished()) + { + C(QString("task '%1' aborted").arg(QString(task->getEncodedInput()))); + return FileEntryList(); + } - QString data = out.getDecodedOutput(); - if (out.getReturnCode() > 0) + QString data = task->getDecodedOutput(); + if (task->getReturnCode() > 0) { C(QString("Couldn't query manifest entries for %1: %2").arg(revision).arg(data)); return FileEntryList(); @@ -291,14 +322,18 @@ QMap MonotoneUtil::get QMap MonotoneUtil::getPrivateKeyList(const DatabaseFile & db) { - MonotoneTask in(QStringList() << "keys"); - MonotoneTask out = runSynchronousDatabaseTask(db, in); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "keys")); + runSynchronousDatabaseTask(db, task); + if (!task->isFinished()) + { + C(QString("task '%1' aborted").arg(QString(task->getEncodedInput()))); + return QMap(); + } QMap keys; - QString data = out.getDecodedOutput(); - if (out.getReturnCode() > 0) + QString data = task->getDecodedOutput(); + if (task->getReturnCode() > 0) { C(QString("Couldn't query keys: %1").arg(data)); return keys; @@ -345,12 +380,16 @@ QString MonotoneUtil::getFileId(const Da QString MonotoneUtil::getFileId(const DatabaseFile & db, const QString & path) { - MonotoneTask in(QStringList() << "identify" << path); - MonotoneTask out = runSynchronousDatabaseTask(db, in); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "identify" << path)); + runSynchronousDatabaseTask(db, task); + if (!task->isFinished()) + { + C(QString("task '%1' aborted").arg(QString(task->getEncodedInput()))); + return QString(); + } - QString data = out.getDecodedOutput(); - if (out.getReturnCode() > 0) + QString data = task->getDecodedOutput(); + if (task->getReturnCode() > 0) { C(QString("Couldn't identify path: %1").arg(data)); return QString(); @@ -364,14 +403,18 @@ QStringList MonotoneUtil::getPreviousCon { QStringList args; args << "get_content_changed" << startRev << file; - MonotoneTask in(args); - MonotoneTask out = runSynchronousDatabaseTask(db, in); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask(args)); + runSynchronousDatabaseTask(db, task); + if (!task->isFinished()) + { + C(QString("task '%1' aborted").arg(QString(task->getEncodedInput()))); + return QStringList(); + } QStringList revs; - QString data = out.getDecodedOutput(); - if (out.getReturnCode() > 0) + QString data = task->getDecodedOutput(); + if (task->getReturnCode() > 0) { C(QString("Couldn't query content marks for '%1' (%2)").arg(file).arg(startRev)); return revs; @@ -393,12 +436,16 @@ QStringList MonotoneUtil::topsortRevisio QStringList args; args << "toposort"; args += revs; - MonotoneTask in(args); - MonotoneTask out = runSynchronousDatabaseTask(db, in); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask(args)); + runSynchronousDatabaseTask(db, task); + if (!task->isFinished()) + { + C(QString("task '%1' aborted").arg(QString(task->getEncodedInput()))); + return QStringList(); + } - QString data = out.getDecodedOutput(); - if (out.getReturnCode() > 0) + QString data = task->getDecodedOutput(); + if (task->getReturnCode() > 0) { C(QString("Couldn't toposort revisions: %1").arg(data)); // return the list unchanged @@ -411,12 +458,16 @@ bool MonotoneUtil::getAttribute(const Wo bool MonotoneUtil::getAttribute(const WorkspacePath & ws, const QString & path, const QString & attrname, QPair & attrval) { - MonotoneTask in(QStringList() << "get_attributes" << path); - MonotoneTask out = runSynchronousWorkspaceTask(ws, in); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "get_attributes" << path)); + runSynchronousWorkspaceTask(ws, task); + if (!task->isFinished()) + { + C(QString("task '%1' aborted").arg(QString(task->getEncodedInput()))); + return false; + } - QString data = out.getDecodedOutput(); - if (out.getReturnCode() > 0) + QString data = task->getDecodedOutput(); + if (task->getReturnCode() > 0) { C(QString("Couldn't run get_attributes: %1").arg(data)); return false; @@ -463,14 +514,18 @@ QMap MonotoneUtil::get { QStringList args; args << "get_db_variables" << domain; - MonotoneTask in(args); - MonotoneTask out = runSynchronousDatabaseTask(db, in); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask(args)); + runSynchronousDatabaseTask(db, task); + if (!task->isFinished()) + { + C(QString("task '%1' aborted").arg(QString(task->getEncodedInput()))); + return QMap(); + } QMap entries; - QString data = out.getDecodedOutput(); - if (out.getReturnCode() > 0) + QString data = task->getDecodedOutput(); + if (task->getReturnCode() > 0) { C(QString("Couldn't run get_db_variables: %1").arg(data)); return entries; ============================================================ --- src/monotone/MonotoneUtil.h 6650b2c4ebddee165d9c7e3acb7d8fd2743e9d1c +++ src/monotone/MonotoneUtil.h ec6bcdda19209c8633eef251ef19972db8027cb8 @@ -28,8 +28,8 @@ public: { Q_OBJECT public: - static MonotoneTask runSynchronousWorkspaceTask(const WorkspacePath &, const MonotoneTask &); - static MonotoneTask runSynchronousDatabaseTask(const DatabaseFile &, const MonotoneTask &); + static void runSynchronousWorkspaceTask(const WorkspacePath &, const MonotoneTaskPtr &); + static void runSynchronousDatabaseTask(const DatabaseFile &, const MonotoneTaskPtr &); static DatabaseFile getDatabaseFile(const WorkspacePath &); static QString getBaseWorkspaceRevision(const WorkspacePath &); static QString getOption(const WorkspacePath &, const QString &); @@ -49,16 +49,16 @@ public: // FIXME: decide what to do with that static QString stripMtnPrefix(const QString &); +signals: + void finished(); + private: - MonotoneUtil(MonotoneThread *, const MonotoneTask &); - MonotoneTask & getTaskResult(); - QEventLoop eventLoop; - MonotoneTask result; - int commandNumber; + void run(const MonotoneThreadPtr &, const MonotoneTaskPtr &); + int currentCommandNumber; private slots: - void taskFinished(const MonotoneTask &); - void taskAborted(const MonotoneTask &); + void taskFinished(const MonotoneTaskPtr &); + void taskAborted(const MonotoneTaskPtr &); }; #endif ============================================================ --- src/monotone/WorkspaceCommitter.cpp 3efc567b8ef22e48f152f8b728a3b168ea0f3d0d +++ src/monotone/WorkspaceCommitter.cpp 94b1e92f38a51f424c06c3ce4cf4ac0195c22fa5 @@ -78,14 +78,16 @@ bool WorkspaceCommitter::run(const QStri // // FIXME: this may cause problems with utf-8 encoded filenames - MonotoneTask out = MonotoneUtil::runSynchronousWorkspaceTask( - workspacePath, - MonotoneTask(QStringList() << "put_revision" << revModel->getRevisionText()) - ); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask( + QStringList() << "put_revision" << revModel->getRevisionText() + )); - QString data = out.getDecodedOutput(); - if (out.getReturnCode() > 0) + MonotoneUtil::runSynchronousWorkspaceTask(workspacePath, task); + + if (!task->isFinished()) F("task aborted"); + + QString data = task->getDecodedOutput(); + if (task->getReturnCode() > 0) { C(QString("Couldn't commit revision: %1").arg(data)); return false; @@ -210,12 +212,12 @@ bool WorkspaceCommitter::putFile(const Q command << file.readAll(); file.close(); - MonotoneTask in(command); - MonotoneTask out = MonotoneUtil::runSynchronousWorkspaceTask(workspacePath, in); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask(command)); + MonotoneUtil::runSynchronousWorkspaceTask(workspacePath, task); + if (!task->isFinished()) F("task aborted"); - QString data = out.getDecodedOutput(); - if (out.getReturnCode() > 0) + QString data = task->getDecodedOutput(); + if (task->getReturnCode() > 0) { C(QString("Cannot execute put_file: %1").arg(data)); return false; @@ -239,17 +241,16 @@ bool WorkspaceCommitter::putCert(const Q bool WorkspaceCommitter::putCert(const QString & rev, const QString & commitKey, const QString & key, const QString & value) { - MonotoneTask out = MonotoneUtil::runSynchronousWorkspaceTask( - workspacePath, - MonotoneTask( - QStringList() << "cert" << rev << key << value, - QStringList() << "key" << commitKey - ) - ); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask( + QStringList() << "cert" << rev << key << value, + QStringList() << "key" << commitKey + )); - QString data = out.getDecodedOutput(); - if (out.getReturnCode() > 0) + MonotoneUtil::runSynchronousWorkspaceTask(workspacePath, task); + if (!task->isFinished()) F("task aborted"); + + QString data = task->getDecodedOutput(); + if (task->getReturnCode() > 0) { C(QString("Couldn't attach cert %1: %2").arg(key).arg(data)); return false; ============================================================ --- src/util/Platform.cpp 6c034a340f5fb9adf6a7e46e4210b89b3da14e56 +++ src/util/Platform.cpp 60434a883a279fb6ec5992d47271388bc46a0e4e @@ -81,8 +81,8 @@ bool Platform::openFile(const QString & Settings::getString("AskFileOpenExt", ASK_OPEN_FILE_EXT) .split(",", QString::SkipEmptyParts); - if (!fileInfo.isDir() && - (fileInfo.isExecutable() || harmfulSuffixes.contains(suffix))) + if (!fileInfo.isDir() && + (fileInfo.isExecutable() || harmfulSuffixes.contains(suffix))) { QMessageBox::StandardButton btn = QMessageBox::question( NULL, @@ -115,8 +115,7 @@ bool Platform::openFile(const QString & s += filename.toUtf8().data(); s += "\""; // just cross your fingers - system(s.c_str()); - retval = 0; + retval = system(s.c_str()); } else if (system("which gnome-open >/dev/null 2>&1") == 0) ============================================================ --- src/view/dialogs/FileDiff.cpp 6e8ff5dbbb84e9fba38d899f7ed619169bd03cd3 +++ src/view/dialogs/FileDiff.cpp 44fc4a74f158ae9a6d8a5e855521dc7b8527977b @@ -336,16 +336,19 @@ void FileDiff::switchOutputEncoding(cons if (!workspace.isEmpty()) { - MonotoneTask in(QStringList() << "set_attribute" - << fileName - << "guitone:file-encoding" - << encoding); - MonotoneTask out = MonotoneUtil::runSynchronousWorkspaceTask(workspace, in); + MonotoneTaskPtr task(new MonotoneTask( + QStringList() << "set_attribute" + << fileName + << "guitone:file-encoding" + << encoding + )); - if (out.getReturnCode() != 0) + MonotoneUtil::runSynchronousWorkspaceTask(workspace, task); + + if (task->getReturnCode() != 0) { W(QString("couldn't set guitone:file-encoding on %1: %2") - .arg(fileName).arg(out.getDecodedOutput())); + .arg(fileName).arg(task->getDecodedOutput())); } } } ============================================================ --- src/view/dialogs/GenerateKeypair.cpp 9b53712e884c27fabeb6b076c31d32de7266c7a6 +++ src/view/dialogs/GenerateKeypair.cpp ed77400baeffdea21382a03f2dd29d33dd33085c @@ -63,23 +63,23 @@ void GenerateKeypair::accept() options << "force-duplicate-key" << "1"; } - MonotoneTask out = MonotoneUtil::runSynchronousDatabaseTask( - databaseFile, - MonotoneTask(QStringList() << "genkey" - << lineKeyName->text() - << lineKeyPasswd->text(), - options - ) - ); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask( + QStringList() << "genkey" + << lineKeyName->text() + << lineKeyPasswd->text(), + options + )); + MonotoneUtil::runSynchronousDatabaseTask(databaseFile, task); - if (out.getReturnCode() > 0) + if (!task->isFinished()) F("task aborted"); + + if (task->getReturnCode() > 0) { QMessageBox::critical( this, tr("Error creating keypair"), tr("There was an error creating the keypair:\n%1") - .arg(out.getDecodedOutput()), + .arg(task->getDecodedOutput()), QMessageBox::Ok, 0, 0 ); return; ============================================================ --- src/view/dialogs/Netsync.cpp 3d62c51dffa72aadfe2e4b791fc7d823cbfa331e +++ src/view/dialogs/Netsync.cpp 14449784c6e3a36a9fb4a7c362b0ba669e9564ca @@ -102,7 +102,7 @@ void Netsync::start(Action act, opts << "key" << key; } - MonotoneTask task(cmd, opts); + MonotoneTaskPtr task(new MonotoneTask(cmd, opts)); AutomateCommand::enqueueDatabaseTask(db, task); progressText->setText(tr("Connecting to %1...").arg(host)); @@ -114,21 +114,11 @@ void Netsync::start(Action act, running = true; } -void Netsync::stop() -{ - AutomateCommand::abortThreads(); - progressWidget->hide(); - startStopButton->setText(tr("Start")); - settingsGroup->setEnabled(true); - actionsGroup->setEnabled(true); - running = false; -} - void Netsync::startStopClicked() { if (running) { - stop(); + AutomateCommand::abortThreads(); return; } @@ -160,7 +150,7 @@ void Netsync::startStopClicked() start(act, host->currentText(), key, include, exclude); } -void Netsync::processTaskResult(const MonotoneTask & task) +void Netsync::processTaskResult(const MonotoneTaskPtr & task) { running = false; startStopButton->setText(tr("Start")); @@ -170,17 +160,28 @@ void Netsync::processTaskResult(const Mo overallProgress->setMaximum(1); overallProgress->setValue(1); - if (task.getReturnCode() != 0) + if (task->getReturnCode() != 0) { progressText->setText(tr("Connection failed: %1") - .arg(task.getDecodedOutput())); + .arg(task->getDecodedOutput())); return; } progressText->setText(tr("Successful exchange with %1") - .arg(QString(task.getArguments().at(1)))); + .arg(QString(task->getArguments().at(1)))); } +void Netsync::processTaskAbortion(const MonotoneTaskPtr & task) +{ + Q_UNUSED(task); + + progressWidget->hide(); + startStopButton->setText(tr("Start")); + settingsGroup->setEnabled(true); + actionsGroup->setEnabled(true); + running = false; +} + void Netsync::tickerUpdate(const TickerMap & tickers) { // we "compress" the values of all found tickers into one progress bar @@ -227,12 +228,10 @@ void Netsync::tickerUpdate(const TickerM progressWidget->show(); } -void Netsync::accept() +void Netsync::closeEvent(QCloseEvent *event) { if (running) - stop(); - - progressWidget->hide(); - done(QDialog::Accepted); + AutomateCommand::abortThreads(); + event->accept(); } ============================================================ --- src/view/dialogs/Netsync.h 33cb539497a787d27d32cb594a901ffd8584f4f7 +++ src/view/dialogs/Netsync.h e3ad8ceb0e995647c2ffd2b6494703076be331b3 @@ -40,13 +40,14 @@ public slots: const QString &, const QString &, const QString &); - void stop(); protected: - void accept(); - void processTaskResult(const MonotoneTask &); - virtual void tickerUpdate(const TickerMap &); + void processTaskResult(const MonotoneTaskPtr &); + void processTaskAbortion(const MonotoneTaskPtr &); + void tickerUpdate(const TickerMap &); + void closeEvent(QCloseEvent *); + protected slots: void startStopClicked(); ============================================================ --- src/view/dialogs/RevisionManifest.cpp bf15341a35fbdd082baaa951b3f7b91b6594bff4 +++ src/view/dialogs/RevisionManifest.cpp c7b0722f1a40388a22c2ca0d71e412ead65e9395 @@ -78,15 +78,14 @@ void RevisionManifest::openFile(const QM // return silently if (entry->is_directory) return; - MonotoneTask out = MonotoneUtil::runSynchronousDatabaseTask( - databaseFile, - MonotoneTask(QStringList() << "get_file" << entry->hash) - ); - if (!out.isFinished()) F("task aborted"); + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "get_file" << entry->hash)); + MonotoneUtil::runSynchronousDatabaseTask(databaseFile, task); - if (out.getReturnCode() > 0) + if (!task->isFinished()) F("task aborted"); + + if (task->getReturnCode() > 0) { - C(QString("Cannot execute get_file: %1").arg(out.getDecodedOutput())); + C(QString("Cannot execute get_file: %1").arg(task->getDecodedOutput())); return; } @@ -117,7 +116,7 @@ void RevisionManifest::openFile(const QM return; } - file.write(out.getOutput()); + file.write(task->getOutput()); file.close(); // if the action was successful, block execution (i.e. deleting of the ============================================================ --- src/vocab.h 47f7cac5d9cfea1f8308980d3de9268b1e97a674 +++ src/vocab.h 358c7aa5fe4b611e8339e6af5bead601fc24691f @@ -151,6 +151,12 @@ typedef QMap TickerMap; typedef QMap TickerMap; +#include +class MonotoneThread; +class MonotoneTask; +typedef QSharedPointer MonotoneThreadPtr; +typedef QSharedPointer MonotoneTaskPtr; + // FIXME: just a few stupid typedefs which should be expanded later on // to more "intelligent" objects typedef QString GuitoneException;