# # # add_file "src/monotone/MonotoneTask.cpp" # content [6e493a87db98e3ab2a4f946567ad00ff2350fe1c] # # add_file "src/monotone/MonotoneTask.h" # content [453abd7667d7e6f5985357924a4ec8b51383aed7] # # patch "attic/Graph.cpp" # from [fa58d4e3fd6ebe3f1beb05a9682b7efced6ffed1] # to [d905e342b04c6e5d7a4c389d1dee12905fb18bb8] # # patch "attic/Graph.h" # from [12331956dd8457649a45dbfe59f4f10b48676d9d] # to [daf89efa3846299c6f2f222bcf993affe5aa4a8f] # # patch "sources.pri" # from [cefb814a1688136f1b9e3c5d966a1caa44412cf7] # to [41d8ea59039763d8848a4e8341c8a8b5beacf41b] # # patch "src/GuitoneCore.cpp" # from [9a3f1bcbf6a588c168628ca225fb3cea16125c97] # to [a966acff1ec0e7f7e4b1f5af3b37ff9b766bc477] # # patch "src/GuitoneDriver.cpp" # from [8dbb735dc9e81597e9067b8f75729ab20bf81c68] # to [9570f67e85087c5ee44715b87e0ea41ba46ab265] # # patch "src/GuitoneStandalone.cpp" # from [a0119c50ce85d5ae9f1c4ce9fea53a98175ecf0b] # to [2f030462cb9f3b2149c007887525f27d37564aec] # # patch "src/main.cpp" # from [c24800c171147aa0b208a9dfb3e1d082e18d3a94] # to [f423ded5d47fb45db87d35c6fabe00bd016a5c85] # # patch "src/model/Branches.cpp" # from [f90b1629937d69ddb9f977c7a605b58b38ad86e0] # to [218625b884da26c15feaa195f59ce6989724cd43] # # patch "src/model/CertList.cpp" # from [2e39df6bfe9544ac5ac0b66e8adc75eb319f0be7] # to [334807e02e68d7345007f3ef379d826fdc96ac2a] # # patch "src/model/CertList.h" # from [e3dc9f3e1a0d8f64e069a2dfaa3a3b661337c596] # to [f3ac36bbc9a9f07633289e5503932a4e764fc02e] # # patch "src/model/GetBranchLog.h" # from [5cb47c8223ddac917701fcc9bb1c6fd154d9f805] # to [edeb9d50ffabcf4fb037ddced0ba9609fd427536] # # patch "src/model/Inventory.cpp" # from [80516d48c7027b0f859980cb5317fe2e6108e823] # to [7113a85da7282bd5bb68a024534e7e325cea163b] # # patch "src/monotone/MonotoneHandle.cpp" # from [0cc36e2f493d405977390077fd1a9b6b2294876b] # to [f73ac1b2215cefb68bd5f67dbf8e81df2593c40a] # # patch "src/monotone/MonotoneHandle.h" # from [17bc070f1e4fdbdf59b69c4d513bc5ad37b21764] # to [bb4a37a2bc3a467700d4ba9728ad168dd5e80d05] # # patch "src/monotone/MonotoneManager.cpp" # from [8b63e64f9501773062d8444415188b6727ca300e] # to [e799ccaabc21a843e664ae4c620824dfe70a7bf9] # # patch "src/monotone/MonotoneManager.h" # from [9a4a725a495b7ba94eca66cad0502641e176f092] # to [86af126b0641f8c434689d60cf2f77ba5f1a55aa] # # patch "src/monotone/MonotoneProcess.cpp" # from [98bd69c312ea0ccacb895d03457b32989d40919d] # to [cad863bf78ebbd3f915be62ed4fcc38606d2d68a] # # patch "src/monotone/MonotoneThread.cpp" # from [a93a51b63026f7f64be172ec26d2cd106d16f304] # to [6cc5a4613d4c02559c7d9d7b3d513647ac645a33] # # patch "src/monotone/MonotoneThread.h" # from [2b118fb88e52b782623fbc2242d0fa93b4058c0e] # to [69c65cb863641399e615fd2dbfa3e49d6ed8b384] # # patch "src/monotone/MonotoneUtil.cpp" # from [8e1f9f6b125bf9651cfa9e16649a9675a956caa4] # to [9f6c42f935b4950dbed92cf6681ad56d4d49eb18] # # patch "src/util/Settings.cpp" # from [66eea129ecb197d95578dc3abc07a9415922690a] # to [df71f25d2ca2cc8393d6ffbacd28f44364b4af91] # # patch "src/util/Settings.h" # from [824bd489f11a42d8bf1753a61edac64e52918ff1] # to [82f4ab58c9ad8ed6ec15708c375b93d6d79fc9db] # # patch "src/view/dialogs/OpenPrompt.cpp" # from [f4b707f26ca5b624d17ff5b007d74fba042f8387] # to [eebc742dce8d55bad628ab33f1a5c2ece399adc0] # # patch "src/view/dialogs/OpenPrompt.h" # from [6d5d30a70469851c90e94c5e5d2e252dde59745f] # to [35502b67323d4deff525e1b79c6dd6066fa45a3c] # # patch "src/view/dialogs/Preferences.cpp" # from [bbfd35ef1eb2cce93eace1e023f06296102fcd97] # to [459b2bbe76e27e7ae2817f730c1180602fb22e8f] # # patch "src/view/mainwindows/DatabaseWindow.cpp" # from [354dab579537397804c14943e4afcb0f90e6f33a] # to [eab02d0c1715637bab6627b63d0c6aad8e4470c3] # # patch "src/view/mainwindows/MainWindow.cpp" # from [82c2c385f918af05a8165acfda5eccb5e8b602e0] # to [9c3f199deff033bb24420956450e520cc36b35ef] # # patch "src/view/panels/NodeInfo.cpp" # from [15616533343a9ef542a0de22dc4f738a1fd8d9d7] # to [5d1c70aa410ff30baa12af5002950288c9b1239c] # # patch "src/view/widgets/MenuBar.cpp" # from [5f1ad3b61efcb9615d2bd81543bbe1ec4d99d0e2] # to [368e1539daa1058938786875240385835ea7b5cb] # # patch "src/view/widgets/MenuBar.h" # from [5bbbaac501c215f53fc2905b15fc9660a4b0e175] # to [261ef742ffacd45bde12543579989b2e0e8c97b1] # # patch "src/vocab.h" # from [167b8a99825b50f32712ab63f5b23271d35c6159] # to [e98da12225f2bc46b4c67132f6402a6a7c439a91] # ============================================================ --- src/monotone/MonotoneTask.cpp 6e493a87db98e3ab2a4f946567ad00ff2350fe1c +++ src/monotone/MonotoneTask.cpp 6e493a87db98e3ab2a4f946567ad00ff2350fe1c @@ -0,0 +1,160 @@ +/*************************************************************************** + * Copyright (C) 2010 by Thomas Keler * + * address@hidden * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#include "MonotoneTask.h" +#include + +MonotoneTask::MonotoneTask() +{ + init(ByteArrayList(), ByteArrayList()); +} + +MonotoneTask::MonotoneTask(const MonotoneTask & other) +{ + returnCode = other.returnCode; + commandNumber = other.commandNumber; + threadNumber = other.threadNumber; + finished = other.finished; + arguments = other.arguments; + options = other.options; + output = other.output; + abortTask = other.abortTask; + outputEncoding = other.outputEncoding; +} + +MonotoneTask::MonotoneTask(const QStringList & args) +{ + init(stringToByteArrayList(args), ByteArrayList()); +} + +MonotoneTask::MonotoneTask(const QStringList & args, const QStringList & opts) +{ + init(stringToByteArrayList(args), stringToByteArrayList(opts)); +} + +MonotoneTask::MonotoneTask(const ByteArrayList & args) +{ + init(args, ByteArrayList()); +} + +MonotoneTask::MonotoneTask(const ByteArrayList & args, const ByteArrayList & opts) +{ + init(args, opts); +} + +void MonotoneTask::init(const ByteArrayList & args, const ByteArrayList & opts) +{ + arguments = args; + options = opts; + returnCode = -1; + finished = false; + abortTask = false; + outputEncoding = "UTF-8"; +} + +ByteArrayList MonotoneTask::stringToByteArrayList(const QStringList & list) +{ + ByteArrayList byteArrayList; + foreach (QString entry, list) + { + byteArrayList.append(entry.toUtf8()); + } + return byteArrayList; +} + +QByteArray MonotoneTask::getEncodedInput() const +{ + QByteArray commandLine; + + if (options.size() > 0) + { + // currently mtn can only understand key => value option pairs + I(options.size() % 2 == 0); + + commandLine.append('o'); + for (int i=0, c=options.size(); i 0); + + commandLine.append('l'); + for (int i=0, c=arguments.size(); itoUnicode(output); +} + +void MonotoneTask::appendOutOfBandMessages(const QList & msgs) +{ + if (msgs.size() == 0) + return; + oobMessages.append(msgs); +} + +bool MonotoneTask::outOfBandMessagesMatch(MessageType type, const QRegExp & regex) +{ + foreach (MessagePair pair, oobMessages) + { + if (pair.first != type) + continue; + if (regex.indexIn(QString(pair.second)) >= 0) + return true; + } + return false; +} + +QString MonotoneTask::getLast(MessageType type) +{ + for (int i = oobMessages.size() - 1; i >= 0; i--) + { + if (oobMessages.at(i).first == type) + return oobMessages.at(i).second; + } + return QString(); +} + ============================================================ --- src/monotone/MonotoneTask.h 453abd7667d7e6f5985357924a4ec8b51383aed7 +++ src/monotone/MonotoneTask.h 453abd7667d7e6f5985357924a4ec8b51383aed7 @@ -0,0 +1,114 @@ +/*************************************************************************** + * Copyright (C) 2010 by Thomas Keller * + * address@hidden * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#ifndef MONOTONE_TASK_H +#define MONOTONE_TASK_H + +#include "vocab.h" + +class MonotoneTask +{ +public: + typedef enum {Warning = 'w', Info = 'p', Error = 'e' } MessageType; + + MonotoneTask(); + MonotoneTask(const MonotoneTask &); + MonotoneTask(const QStringList &); + MonotoneTask(const QStringList &, const QStringList &); + MonotoneTask(const ByteArrayList &); + MonotoneTask(const ByteArrayList &, const ByteArrayList &); + + //! sets the command number of this task (increased internally by the thread) + void setCommandNumber(int num) { commandNumber = num; } + + //! sets the thread number to identify the thread + void setThreadNumber(int num) { threadNumber = num; } + + //! sets the raw command output + void setOutput(const QByteArray & out) { output = out; } + + //! sets the return code of the command + void setReturnCode(int code) { returnCode = code; } + + //! marks that the task has been finished + void setFinished() { finished = true; } + + //! set the output encoding + void setOutputEncoding(const QString & e) { outputEncoding = e; } + + //! appends more out-of-band messages for this task + void appendOutOfBandMessages(const QList &); + + //! returns true if one or more out-of-band messages match the given regex + bool outOfBandMessagesMatch(MessageType, const QRegExp &); + + //! returns the last out-of-band message of the given type + QString getLast(MessageType); + + //! returns the command input stdio-encoded + QByteArray getEncodedInput() const; + + //! returns the given arguments for the command + ByteArrayList getArguments() const { return arguments; } + + //! returns the given options for the command + ByteArrayList getOptions() const { return options; } + + //! returns the raw monotone output + QByteArray getOutput() const { return output; } + + //! converts the raw byte output into a unicode encoded QString + QString getDecodedOutput(const QString & enc = QString()) const; + + //! returns the command's return code + int getReturnCode() const { return returnCode; } + + //! returns the command's number (i.e. sequential number of the running mtn process) + int getCommandNumber() const { return commandNumber; } + + //! returns the number of the thread on which this task should/has been run + int getThreadNumber() const { return threadNumber; } + + //! true, if the task has already been completed + bool isFinished() const { return finished; } + + //! aborts the processing of the task + void setAborted() { abortTask = true; } + + //! checks if the task should be aborted + bool isAborted() const { return abortTask; } + +private: + void init(const ByteArrayList &, const ByteArrayList &); + ByteArrayList stringToByteArrayList(const QStringList &); + + int returnCode; + int commandNumber; + int threadNumber; + bool finished; + bool abortTask; + + ByteArrayList arguments; + ByteArrayList options; + QByteArray output; + QString outputEncoding; + QList oobMessages; +}; + +#endif + ============================================================ --- attic/Graph.cpp fa58d4e3fd6ebe3f1beb05a9682b7efced6ffed1 +++ attic/Graph.cpp d905e342b04c6e5d7a4c389d1dee12905fb18bb8 @@ -112,164 +112,5 @@ void Graph::processTaskResult(const Mono } } -void Graph::buildLanes(QStringList & newRevisions, const QStringList & lastRevisions) -{ - QString rev = newRevisions.takeFirst(); - QStringList nextRevisions = lastRevisions; - QList lanes; - bool removedDeadLine = false; - // initialize all lanes with plain vertical bars first; - // if we stumble upon dead lines (empty revisions), we re-use - // their slot for the next revision(s) - but only one lane per row - for (int i=0; i 0); - i--; - removedDeadLine = true; - continue; - } - - // preserve further dead lines - if (nextRevisions.at(i).isEmpty()) - { - lanes.push_back(Revision::Empty); - } - else - { - lanes.push_back(removedDeadLine ? Revision::BarToLeft - : Revision::Bar); - } - } - - I(lanes.size() == nextRevisions.size()); - - Revision * revObj = revisionMap.value(rev); - int idx = lastRevisions.indexOf(rev); - - if (idx == -1) - { - Revision::LaneType type; - switch (revObj->parents.size()) - { - case 0: type = Revision::SingleNode; break; - case 1: type = Revision::Head; break; - case 2: type = Revision::HeadMerge; break; - default: I(false); - } - nextRevisions += revObj->parents; - lanes.push_back(type); - } - else - { - // add revisions for the next round - newRevisions += revObj->parents; - - Revision::LaneType type, defaultNextType; - switch (revObj->parents.size()) - { - case 0: - type = Revision::Tail; - defaultNextType = Revision::BarToLeft; - nextRevisions.replace(idx, QString()); - break; - case 1: - type = Revision::Node; - defaultNextType = Revision::Bar; - nextRevisions.replace(idx, revObj->parents.at(0)); - break; - case 2: - type = Revision::Merge; - nextRevisions.replace(idx, revObj->parents.at(0)); - - // check the special case where a dead line is right - // beside the current merge node, which allows us to - // re-use its space - if (idx + 1 < nextRevisions.size() && - nextRevisions.at(idx + 1).isEmpty()) - { - defaultNextType = Revision::Bar; - nextRevisions.replace(idx + 1, revObj->parents.at(1)); - } - else - { - defaultNextType = Revision::BarToRight; - nextRevisions.insert(idx + 1, revObj->parents.at(1)); - } - break; - default: I(false); - } - - bool hasFork = false; - - for (int i=lanes.size() - 1; i > idx; i--) - { - if (lastRevisions[i] == rev) - { - switch (defaultNextType) - { - case Revision::BarToLeft: - defaultNextType = Revision::BarToLeftCrossing; - break; - case Revision::Bar: - defaultNextType = Revision::Crossing; - break; - case Revision::BarToRight: - defaultNextType = Revision::BarToRightCrossing; - break; - default: I(false); - } - - // do we join the line to a previous fork line? - if (!hasFork) - { - lanes[i] = Revision::BarToFork; - } - else - { - lanes[i] = Revision::BarToForkJoin; - } - - // mark this line as not being continued - int deadLine = nextRevisions.indexOf(lastRevisions.at(i)); - I(deadLine >= 0); - nextRevisions.replace(deadLine, QString()); - - hasFork = true; - continue; - } - - lanes[i] = defaultNextType; - } - - if (hasFork) - { - switch (type) - { - case Revision::Tail: type = Revision::TailFork; break; - case Revision::Node: type = Revision::Fork; break; - case Revision::Merge: type = Revision::MergeFork; break; - default: I(false); - } - } - - lanes[idx] = type; - } - - revObj->lanes = lanes; - - if (newRevisions.size() == 0) - { - // FIXME: next thing is to draw the mess - emit lanesCreated(); - return; - } - - // recursion - buildLanes(newRevisions, nextRevisions); -} - ============================================================ --- attic/Graph.h 12331956dd8457649a45dbfe59f4f10b48676d9d +++ attic/Graph.h daf89efa3846299c6f2f222bcf993affe5aa4a8f @@ -25,6 +25,14 @@ public: class Revision { public: + void paint(QPainter * painter, const QRect & rect, const QPalette & palette) const + { + } + + QSize sizeHint() const + { + } + QString hash; QStringList parents; QStringList children; @@ -88,6 +96,167 @@ public: }; QList lanes; + + static void buildLanes(QStringList & newRevisions, const QStringList & lastRevisions) + { + QString rev = newRevisions.takeFirst(); + QStringList nextRevisions = lastRevisions; + + QList lanes; + bool removedDeadLine = false; + + // initialize all lanes with plain vertical bars first; + // if we stumble upon dead lines (empty revisions), we re-use + // their slot for the next revision(s) - but only one lane per row + for (int i=0; i 0); + i--; + removedDeadLine = true; + continue; + } + + // preserve further dead lines + if (nextRevisions.at(i).isEmpty()) + { + lanes.push_back(Revision::Empty); + } + else + { + lanes.push_back(removedDeadLine ? Revision::BarToLeft + : Revision::Bar); + } + } + + I(lanes.size() == nextRevisions.size()); + + Revision * revObj = revisionMap.value(rev); + int idx = lastRevisions.indexOf(rev); + + if (idx == -1) + { + Revision::LaneType type; + switch (revObj->parents.size()) + { + case 0: type = Revision::SingleNode; break; + case 1: type = Revision::Head; break; + case 2: type = Revision::HeadMerge; break; + default: I(false); + } + nextRevisions += revObj->parents; + lanes.push_back(type); + } + else + { + // add revisions for the next round + newRevisions += revObj->parents; + + Revision::LaneType type, defaultNextType; + switch (revObj->parents.size()) + { + case 0: + type = Revision::Tail; + defaultNextType = Revision::BarToLeft; + nextRevisions.replace(idx, QString()); + break; + case 1: + type = Revision::Node; + defaultNextType = Revision::Bar; + nextRevisions.replace(idx, revObj->parents.at(0)); + break; + case 2: + type = Revision::Merge; + nextRevisions.replace(idx, revObj->parents.at(0)); + + // check the special case where a dead line is right + // beside the current merge node, which allows us to + // re-use its space + if (idx + 1 < nextRevisions.size() && + nextRevisions.at(idx + 1).isEmpty()) + { + defaultNextType = Revision::Bar; + nextRevisions.replace(idx + 1, revObj->parents.at(1)); + } + else + { + defaultNextType = Revision::BarToRight; + nextRevisions.insert(idx + 1, revObj->parents.at(1)); + } + break; + default: I(false); + } + + bool hasFork = false; + + for (int i=lanes.size() - 1; i > idx; i--) + { + if (lastRevisions[i] == rev) + { + switch (defaultNextType) + { + case Revision::BarToLeft: + defaultNextType = Revision::BarToLeftCrossing; + break; + case Revision::Bar: + defaultNextType = Revision::Crossing; + break; + case Revision::BarToRight: + defaultNextType = Revision::BarToRightCrossing; + break; + default: I(false); + } + + // do we join the line to a previous fork line? + if (!hasFork) + { + lanes[i] = Revision::BarToFork; + } + else + { + lanes[i] = Revision::BarToForkJoin; + } + + // mark this line as not being continued + int deadLine = nextRevisions.indexOf(lastRevisions.at(i)); + I(deadLine >= 0); + nextRevisions.replace(deadLine, QString()); + + hasFork = true; + continue; + } + + lanes[i] = defaultNextType; + } + + if (hasFork) + { + switch (type) + { + case Revision::Tail: type = Revision::TailFork; break; + case Revision::Node: type = Revision::Fork; break; + case Revision::Merge: type = Revision::MergeFork; break; + default: I(false); + } + } + + lanes[idx] = type; + } + + revObj->lanes = lanes; + + if (newRevisions.size() == 0) + { + // FIXME: next thing is to draw the mess + emit lanesCreated(); + return; + } + + // recursion + buildLanes(newRevisions, nextRevisions); + } }; class Graph : public AutomateCommand ============================================================ --- sources.pri cefb814a1688136f1b9e3c5d966a1caa44412cf7 +++ sources.pri 41d8ea59039763d8848a4e8341c8a8b5beacf41b @@ -63,6 +63,7 @@ HEADERS = src/view/widgets/TreeView.h \ src/monotone/FileExporter.h \ src/monotone/WorkspaceCreator.h \ src/monotone/WorkspaceCommitter.h \ + src/monotone/MonotoneTask.h \ src/monotone/MonotoneThread.h \ src/monotone/MonotoneManager.h \ src/monotone/MonotoneHandle.h \ @@ -77,6 +78,7 @@ HEADERS = src/view/widgets/TreeView.h \ src/model/InventoryWatcher.h \ src/model/GetAttributes.h \ src/model/Select.h \ + src/model/CertList.h \ src/model/Certs.h \ src/model/ContentDiff.h \ src/model/GetFile.h \ @@ -165,6 +167,7 @@ SOURCES += src/view/widgets/TreeView.cpp src/monotone/FileExporter.cpp \ src/monotone/WorkspaceCreator.cpp \ src/monotone/WorkspaceCommitter.cpp \ + src/monotone/MonotoneTask.cpp \ src/monotone/MonotoneThread.cpp \ src/monotone/MonotoneManager.cpp \ src/monotone/MonotoneHandle.cpp \ @@ -179,6 +182,7 @@ SOURCES += src/view/widgets/TreeView.cpp src/model/InventoryWatcher.cpp \ src/model/GetAttributes.cpp \ src/model/Select.cpp \ + src/model/CertList.cpp \ src/model/Certs.cpp \ src/model/ContentDiff.cpp \ src/model/GetFile.cpp \ ============================================================ --- src/GuitoneCore.cpp 9a3f1bcbf6a588c168628ca225fb3cea16125c97 +++ src/GuitoneCore.cpp a966acff1ec0e7f7e4b1f5af3b37ff9b766bc477 @@ -61,7 +61,7 @@ void GuitoneCore::appSetup() QString installedVersion; if (!monotoneManager->setMonotoneBinaryPath( - Settings::getMtnBinaryPath(), + Settings::getString("MtnExePath"), Settings::getBool("RelaxedVersionCheck"), installedVersion)) { ============================================================ --- src/GuitoneDriver.cpp 8dbb735dc9e81597e9067b8f75729ab20bf81c68 +++ src/GuitoneDriver.cpp 9570f67e85087c5ee44715b87e0ea41ba46ab265 @@ -22,6 +22,7 @@ #include "DatabaseDialogManager.h" #include "WorkspaceDialogManager.h" +#include "ServerDialogManager.h" #include "Message.h" #include @@ -63,53 +64,40 @@ void GuitoneDriver::processCommands() } else { - QFileInfo fileInfo(path); - if (!fileInfo.exists()) + MonotoneHandlePtr handle; + try { - msg(QString("path '%1' does not exist").arg(path)); + handle = MonotoneHandle::create(path); + } + catch (GuitoneException & e) + { + msg( + QString("path '%1' could not be loaded: %2") + .arg(path).arg(e.what()) + ); QCoreApplication::exit(1); return; } - path = fileInfo.absoluteFilePath(); + APP->manager()->getThread(handle)->waitForStarted(); - if (fileInfo.isDir()) + if (handle->getType() == MonotoneHandle::workspace_handle) { dialogManager = new WorkspaceDialogManager(NULL); - try - { - path = MonotoneManager::normalizeWorkspacePath(path); - APP->manager()->getThreadForWorkspace(path)->waitForStarted(); - } - catch (GuitoneException & e) - { - msg(QString("could not startup monotone: %1").arg(e.what())); - QCoreApplication::exit(1); - return; - } - qobject_cast(dialogManager)->init(path); + qobject_cast(dialogManager)->init(handle); } - else if (fileInfo.isFile()) + else if (handle->getType() == MonotoneHandle::database_handle) { dialogManager = new DatabaseDialogManager(NULL); - try - { - APP->manager()->getThreadForDatabase(path)->waitForStarted(); - } - catch (GuitoneException & e) - { - msg(QString("could not startup monotone: %1").arg(e.what())); - QCoreApplication::exit(1); - return; - } - qobject_cast(dialogManager)->init(path); + qobject_cast(dialogManager)->init(handle); } - else + else if (handle->getType() == MonotoneHandle::server_handle) { - msg(QString("path '%1' is neither a file nor a directory").arg(path)); - QCoreApplication::exit(1); - return; + dialogManager = new ServerDialogManager(NULL); + qobject_cast(dialogManager)->init(handle); } + else + I(false); } // if all dialogs have been closed, quit the event loop and exit @@ -145,7 +133,8 @@ void GuitoneDriver::processCommands() ); } else - if (m.parameterTypes().size() == 1 && m.parameterTypes().at(0) == "QString") + if (m.parameterTypes().size() == 1 && + m.parameterTypes().at(0) == "QString") { connect( dialogManager, sig, @@ -154,7 +143,8 @@ void GuitoneDriver::processCommands() } else { - W(QString("could not connect to signal '%1'").arg(sig.constData())); + W(QString("could not connect to signal '%1'") + .arg(sig.constData())); } } @@ -252,10 +242,13 @@ void GuitoneDriver::processCommands() } const char * methodName = static_cast(reqMethod.toLatin1().data()); - bool ok = QMetaObject::invokeMethod(dialogManager, methodName, Qt::QueuedConnection, - genArgs[0], genArgs[1], genArgs[2], genArgs[3], - genArgs[4], genArgs[5], genArgs[6], genArgs[7], - genArgs[8], genArgs[9]); + bool ok = QMetaObject::invokeMethod( + dialogManager, methodName, Qt::QueuedConnection, + genArgs[0], genArgs[1], genArgs[2], genArgs[3], + genArgs[4], genArgs[5], genArgs[6], genArgs[7], + genArgs[8], genArgs[9] + ); + D(QString("execution successful: %1").arg(ok)); } ============================================================ --- src/GuitoneStandalone.cpp a0119c50ce85d5ae9f1c4ce9fea53a98175ecf0b +++ src/GuitoneStandalone.cpp 2f030462cb9f3b2149c007887525f27d37564aec @@ -225,7 +225,7 @@ void GuitoneStandalone::load(const QStri if (wnd) delete wnd; Settings::removeItemFromList("RecentWorkspaceList", pathOrURI); Settings::removeItemFromList("RecentDatabaseList", pathOrURI); - Settings::removeItemFromList("RecentConnectionList", pathOrURI); + Settings::removeItemFromList("RecentServerList", pathOrURI); emit updateRecentLists(); throw e; } ============================================================ --- src/main.cpp c24800c171147aa0b208a9dfb3e1d082e18d3a94 +++ src/main.cpp f423ded5d47fb45db87d35c6fabe00bd016a5c85 @@ -26,6 +26,8 @@ #include "GuitoneStandalone.h" #include "GuitoneDriver.h" +#include "CertList.h" + #include #include #include @@ -43,7 +45,7 @@ void guitoneMsgHandler(QtMsgType type, c typeMap.insert(QtCriticalMsg, DebugLog::Critical); typeMap.insert(QtFatalMsg, DebugLog::Fatal); } - + if (typeMap.contains(type)) DebugLog::log(typeMap.value(type), QString::fromUtf8(msg)); else ============================================================ --- src/model/Branches.cpp f90b1629937d69ddb9f977c7a605b58b38ad86e0 +++ src/model/Branches.cpp 218625b884da26c15feaa195f59ce6989724cd43 @@ -19,6 +19,7 @@ #include "Branches.h" #include "BasicIOParser.h" #include "Settings.h" +#include "CertList.h" /* * We use two hacks here: ============================================================ --- src/model/CertList.cpp 2e39df6bfe9544ac5ac0b66e8adc75eb319f0be7 +++ src/model/CertList.cpp 334807e02e68d7345007f3ef379d826fdc96ac2a @@ -114,7 +114,7 @@ QStringList CertList::signers() const return signers; } -QList CertList::findBySigner(const QString & key = QString()) const +QList CertList::findBySigner(const QString & key) const { QList foundCerts; foreach (const Cert & cert, certs) @@ -126,7 +126,7 @@ QList CertList::findByName(const Q } QList CertList::findByName(const QString & name, - const QString & key = QString()) const + const QString & key) const { QList foundCerts; foreach (const Cert & cert, findBySigner(key)) @@ -139,7 +139,7 @@ QStringList CertList::findByNameValues(c } QStringList CertList::findByNameValues(const QString & name, - const QString & key = QString()) const + const QString & key) const { QStringList values; QList certs = findByName(name, key); ============================================================ --- src/model/CertList.h e3dc9f3e1a0d8f64e069a2dfaa3a3b661337c596 +++ src/model/CertList.h f3ac36bbc9a9f07633289e5503932a4e764fc02e @@ -19,6 +19,7 @@ #ifndef CERT_LIST_H #define CERT_LIST_H +#include "vocab.h" #include struct Cert ============================================================ --- src/model/GetBranchLog.h 5cb47c8223ddac917701fcc9bb1c6fd154d9f805 +++ src/model/GetBranchLog.h edeb9d50ffabcf4fb037ddced0ba9609fd427536 @@ -22,6 +22,7 @@ #include "Ancestors.h" #include "Select.h" #include "Toposort.h" +#include "CertList.h" #include ============================================================ --- src/model/Inventory.cpp 80516d48c7027b0f859980cb5317fe2e6108e823 +++ src/model/Inventory.cpp 7113a85da7282bd5bb68a024534e7e325cea163b @@ -40,7 +40,7 @@ void Inventory::setMonotoneHandle(const void Inventory::setMonotoneHandle(const MonotoneHandlePtr & handle) { - monotoneHandle = handle + monotoneHandle = handle; } void Inventory::read(const QString & path, bool fullQuery) ============================================================ --- src/monotone/MonotoneHandle.cpp 0cc36e2f493d405977390077fd1a9b6b2294876b +++ src/monotone/MonotoneHandle.cpp f73ac1b2215cefb68bd5f67dbf8e81df2593c40a @@ -20,9 +20,12 @@ #include "MonotoneProcess.h" #include "BasicIOParser.h" +#include +#include + MonotoneHandle::MonotoneHandle(const QString & d, Type t) : data(d), type(t) {} -void MonotoneHandle::validateMonotoneHandlePtr(QString & database) +void MonotoneHandle::validateDatabaseFile(const QString & database) { QFile dbfile(database); if (!dbfile.open(QIODevice::ReadOnly)) @@ -56,7 +59,7 @@ void MonotoneHandle::validateWorkspacePa QString & database) { QDir tempDir(workspace); - I(!tempDir.exists()); + I(tempDir.exists()); bool found = false; do @@ -126,17 +129,18 @@ void MonotoneHandle::validateServerConne void MonotoneHandle::validateServerConnection(const QString & host) { - QStringList hostAndPort = host.split(":"); + QStringList hostAndPort = host.split(":", QString::SkipEmptyParts); if (hostAndPort.size() == 1) { hostAndPort.append("4691"); } - QTCPSocket sock; + QTcpSocket sock; sock.connectToHost(hostAndPort.at(0), hostAndPort.at(1).toUInt()); - sock.waitForConnected(5000); + sock.waitForConnected(1000); - if (!sock.isValid()) + if (sock.state() == QAbstractSocket::UnconnectedState || + !sock.isValid()) { sock.disconnectFromHost(); if (sock.state() != QAbstractSocket::UnconnectedState) @@ -144,7 +148,7 @@ void MonotoneHandle::validateServerConne throw GuitoneException(QObject::tr( "Could not connect to '%1':\n%2" - ).arg(pathOrURI).arg(sock.errorString())); + ).arg(host).arg(sock.errorString())); } sock.disconnectFromHost(); @@ -169,7 +173,7 @@ void MonotoneHandle::resolveDatabaseAlia QRegExp rx("\\[\\d+\\] = \"([^\"]+)\";"); int pos = 0; - while ((pos = rx.indexIn(str, pos)) != -1) + while ((pos = rx.indexIn(output, pos)) != -1) { pos += rx.matchedLength(); QString location = rx.cap(1); @@ -197,11 +201,9 @@ MonotoneHandlePtr MonotoneHandle::create Type type; QRegExp rx("^mtn://([\\w\\-]+(?:\\.[\\w\\-]+)*(?::\\d+)?)$"); - if (rx.indexIn(cleanedPathOrURI)) + if (rx.indexIn(cleanedPathOrURI) != -1) { - cleanedPathOrURI = rx.cap(1); - validateServerConnection(cleanedPathOrURI); - + validateServerConnection(rx.cap(1)); type = server_handle; } else @@ -212,21 +214,22 @@ MonotoneHandlePtr MonotoneHandle::create cleanedPathOrURI = finfo.canonicalFilePath(); QString database; - validateWorkspace(cleanedPathOrURI, database); + validateWorkspacePath(cleanedPathOrURI, database); resolveDatabaseAlias(database); - validateDatabase(database); + validateDatabaseFile(database); type = workspace_handle; } else { resolveDatabaseAlias(cleanedPathOrURI); - validateDatabase(cleanedPathOrURI); + validateDatabaseFile(cleanedPathOrURI); type = database_handle; } } + I(!cleanedPathOrURI.isEmpty()); return MonotoneHandlePtr(new MonotoneHandle(cleanedPathOrURI, type)); } ============================================================ --- src/monotone/MonotoneHandle.h 17bc070f1e4fdbdf59b69c4d513bc5ad37b21764 +++ src/monotone/MonotoneHandle.h bb4a37a2bc3a467700d4ba9728ad168dd5e80d05 @@ -24,19 +24,22 @@ public: class MonotoneHandle { public: - enum Type { workspace_handle, database_handle, server_handle } type; + typedef enum { workspace_handle = 1, database_handle, server_handle } Type; Type getType() const { return type; } QString getData() const { return data; } + QString identify() const { return QString("%1:%2").arg((int)type).arg(data); } static MonotoneHandlePtr create(const QString &); private: QString data; + Type type; + MonotoneHandle(const QString &, Type); static void validateWorkspacePath(QString &, QString &); - static void validateMonotoneHandlePtr(const QString &); + static void validateDatabaseFile(const QString &); static void validateServerConnection(const QString &); static void resolveDatabaseAlias(QString &); ============================================================ --- src/monotone/MonotoneManager.cpp 8b63e64f9501773062d8444415188b6727ca300e +++ src/monotone/MonotoneManager.cpp e799ccaabc21a843e664ae4c620824dfe70a7bf9 @@ -69,10 +69,8 @@ MonotoneThreadPtr MonotoneManager::getTh if (mtnPath.isEmpty()) throw GuitoneException(tr("Monotone binary path not set")); - // since we cannot set the workspace directory after we've - // started the process, we need to ensure that each workspace runs with - // its own process - QList threadIDs = identMap.keys(database + "|" + workspace); + QString ident = handle->identify(); + QList threadIDs = identMap.keys(ident); QList availableThreads; foreach (int threadID, threadIDs) @@ -87,14 +85,10 @@ MonotoneThreadPtr MonotoneManager::getTh int newThreadID = ++threadNumber; MonotoneThreadPtr thread - (new MonotoneThread(newThreadID, mtnPath, database, workspace)); + (new MonotoneThread(newThreadID, mtnPath, handle)); threadMap.insert(newThreadID, thread); - identMap.insert(newThreadID, database + "|"); - if (!workspace.isEmpty()) - { - identMap.insert(newThreadID, database + "|" + workspace); - } + identMap.insert(newThreadID, ident); availableThreads.append(newThreadID); connect( @@ -103,8 +97,10 @@ MonotoneThreadPtr MonotoneManager::getTh ); connect( - thread.data(), SIGNAL(aborted(int, QProcess::ProcessError, const QString &)), - this, SLOT(aborted(int, QProcess::ProcessError, const QString &)) + thread.data(), SIGNAL(aborted(int, QProcess::ProcessError, + const QString &)), + this, SLOT(aborted(int, QProcess::ProcessError, + const QString &)) ); thread->start(); @@ -133,14 +129,12 @@ void MonotoneManager::stopThread(int thr stoppingThreads.insert(threadID); } -void MonotoneManager::stopWorkspaceThreads(const MonotoneHandlePtr & workspace) +void MonotoneManager::stopThreads(const MonotoneHandlePtr & handle) { - MonotoneHandlePtr normalizedWorkspace = normalizeWorkspacePath(workspace); - MonotoneHandlePtr monotoneHandle = getMonotoneHandlePtrPath(normalizedWorkspace); - QList threadIDs = identMap.keys(monotoneHandle + "|" + normalizedWorkspace); + QList threadIDs = identMap.keys(handle->identify()); - L(QString("stopping %1 threads for workspace %2") - .arg(threadIDs.size()).arg(normalizedWorkspace)); + L(QString("stopping %1 threads for handle %2") + .arg(threadIDs.size()).arg(handle->getData())); foreach (int threadID, threadIDs) { @@ -148,59 +142,6 @@ void MonotoneManager::stopWorkspaceThrea } } -// we assume that the workspace was already normalized here -MonotoneHandlePtr MonotoneManager::getMonotoneHandlePtrPath(const MonotoneHandlePtr & workspace) -{ - // now check again if we know it - if (workspaceMap.contains(workspace)) - { - return workspaceMap.value(workspace); - } - - QFile optionsFile(workspace + "/_MTN/options"); - if (!optionsFile.open(QIODevice::ReadOnly | QIODevice::Text)) - { - throw GuitoneException(tr("could not open _MTN/options for reading")); - } - - QByteArray contents = optionsFile.readAll(); - optionsFile.close(); - - if (contents.size() == 0) - { - throw GuitoneException(tr("file _MTN/options is empty")); - } - - BasicIOParser parser(QString::fromUtf8(contents)); - if (!parser.parse()) - { - throw GuitoneException(tr("could not parse basic_io from _MTN/options")); - } - StanzaList stanzas = parser.getStanzas(); - I(stanzas.size() == 1); - Stanza st = stanzas.at(0); - - MonotoneHandlePtr databaseFilePath; - foreach (const StanzaEntry & entry, st) - { - if (entry.sym == "database") - { - I(entry.vals.size() == 1); - databaseFilePath = entry.vals.at(0); - break; - } - } - - if (databaseFilePath.isEmpty()) - { - throw GuitoneException(tr("could not find database for workspace")); - } - - // remember what we've just found for later requests - workspaceMap.insert(workspace, databaseFilePath); - return databaseFilePath; -} - void MonotoneManager::removeThread(int threadID) { QMutexLocker locker(&lock); @@ -243,8 +184,7 @@ void MonotoneManager::aborted(int thread MonotoneThreadPtr thread = threadMap.value(threadID); - QString monotoneHandle = thread->getMonotoneHandlePtrPath(); - QString monotoneHandle = thread->getWorkspacePath(); + MonotoneHandlePtr handle = thread->getMonotoneHandle(); removeThread(threadID); @@ -283,8 +223,7 @@ void MonotoneManager::aborted(int thread "The monotone process for '%1' died (%2). " "If you think this is a bug in guitone, " "please report it to the author!" - ).arg(monotoneHandle.isEmpty() ? monotoneHandle : monotoneHandle) - .arg(processErrorTranslated) + ).arg(handle->getData()).arg(processErrorTranslated) ); if (!mtnError.isEmpty()) @@ -298,7 +237,7 @@ QString MonotoneManager::getInterfaceVer QString MonotoneManager::getInterfaceVersion(const QString & mtnBinary) { MonotoneProcess proc; - proc.setMtnBinaryPath(mtnBinary); + proc.setMonotoneBinaryPath(mtnBinary); proc.start(QStringList() << "automate" << "interface_version"); proc.waitForFinished(); ============================================================ --- src/monotone/MonotoneManager.h 9a4a725a495b7ba94eca66cad0502641e176f092 +++ src/monotone/MonotoneManager.h 86af126b0641f8c434689d60cf2f77ba5f1a55aa @@ -66,7 +66,6 @@ private: QMap threadMap; QMultiMap identMap; - QMap workspaceMap; QSet stoppingThreads; QString mtnPath; ============================================================ --- src/monotone/MonotoneProcess.cpp 98bd69c312ea0ccacb895d03457b32989d40919d +++ src/monotone/MonotoneProcess.cpp cad863bf78ebbd3f915be62ed4fcc38606d2d68a @@ -58,7 +58,7 @@ MonotoneProcess::~MonotoneProcess() } } -void MonotoneProcess::setMtnBinaryPath(const QString & path) +void MonotoneProcess::setMonotoneBinaryPath(const QString & path) { monotoneBinaryPath = path; } @@ -74,7 +74,7 @@ void MonotoneProcess::start(const QStrin if (monotoneBinaryPath.isEmpty()) { - monotoneBinaryPath = Settings::getMtnBinaryPath(); + monotoneBinaryPath = Settings::getString("MtnExePath"); } QStringList finalParams; ============================================================ --- src/monotone/MonotoneThread.cpp a93a51b63026f7f64be172ec26d2cd106d16f304 +++ src/monotone/MonotoneThread.cpp 6cc5a4613d4c02559c7d9d7b3d513647ac645a33 @@ -23,150 +23,8 @@ #include "Settings.h" #include -#include #include -MonotoneTask::MonotoneTask() -{ - init(ByteArrayList(), ByteArrayList()); -} - -MonotoneTask::MonotoneTask(const MonotoneTask & other) -{ - returnCode = other.returnCode; - commandNumber = other.commandNumber; - threadNumber = other.threadNumber; - finished = other.finished; - arguments = other.arguments; - options = other.options; - output = other.output; - abortTask = other.abortTask; - outputEncoding = other.outputEncoding; -} - -MonotoneTask::MonotoneTask(const QStringList & args) -{ - init(stringToByteArrayList(args), ByteArrayList()); -} - -MonotoneTask::MonotoneTask(const QStringList & args, const QStringList & opts) -{ - init(stringToByteArrayList(args), stringToByteArrayList(opts)); -} - -MonotoneTask::MonotoneTask(const ByteArrayList & args) -{ - init(args, ByteArrayList()); -} - -MonotoneTask::MonotoneTask(const ByteArrayList & args, const ByteArrayList & opts) -{ - init(args, opts); -} - -void MonotoneTask::init(const ByteArrayList & args, const ByteArrayList & opts) -{ - arguments = args; - options = opts; - returnCode = -1; - finished = false; - abortTask = false; - outputEncoding = "UTF-8"; -} - -ByteArrayList MonotoneTask::stringToByteArrayList(const QStringList & list) -{ - ByteArrayList byteArrayList; - foreach (QString entry, list) - { - byteArrayList.append(entry.toUtf8()); - } - return byteArrayList; -} - -QByteArray MonotoneTask::getEncodedInput() const -{ - QByteArray commandLine; - - if (options.size() > 0) - { - // currently mtn can only understand key => value option pairs - I(options.size() % 2 == 0); - - commandLine.append('o'); - for (int i=0, c=options.size(); i 0); - - commandLine.append('l'); - for (int i=0, c=arguments.size(); itoUnicode(output); -} - -void MonotoneTask::appendOutOfBandMessages(const QList & msgs) -{ - if (msgs.size() == 0) - return; - oobMessages.append(msgs); -} - -bool MonotoneTask::outOfBandMessagesMatch(MessageType type, const QRegExp & regex) -{ - foreach (MessagePair pair, oobMessages) - { - if (pair.first != type) - continue; - if (regex.indexIn(QString(pair.second)) >= 0) - return true; - } - return false; -} - -QString MonotoneTask::getLast(MessageType type) -{ - for (int i = oobMessages.size() - 1; i >= 0; i--) - { - if (oobMessages.at(i).first == type) - return oobMessages.at(i).second; - } - return QString(); -} - -const int MonotoneThread::StdioBufferSize = 50 * 1024 * 1024; - MonotoneThread::MonotoneThread(int thread, const QString & mtn, const MonotoneHandlePtr & handle) : QThread(), doAbort(false), commandNumber(0), @@ -245,26 +103,44 @@ void MonotoneThread::run() QProcess * process = new QProcess(&threadParent); QStringList args; - args << "automate"; - args << "stdio"; - args << QString("--automate-stdio-size=%1").arg(StdioBufferSize); - args << "--handle" << databasePath; - if (!Settings::getBool("ReadUserRcFiles")) { args << "--norc"; } - MonotoneResourceFile rcFile; args << "--rcfile" << rcFile.fileName(); + args << "--quiet"; - // check whether we need to work on a specific workspace directory or not - if (!monotoneHandle.isEmpty()) + if (monotoneHandle->getType() == MonotoneHandle::database_handle) { - process->setWorkingDirectory(monotoneHandle); + args << "--db" << monotoneHandle->getData(); } else + if (monotoneHandle->getType() == MonotoneHandle::server_handle) { + args << "--db" << ":memory:"; + } + + args << "automate"; + + if (monotoneHandle->getType() == MonotoneHandle::server_handle) + { + // remove the mtn:// prefix - unfortunately monotone does not + // yet understand its URIs everywhere + QString host = monotoneHandle->getData().mid(6); + args << "remote_stdio" << host; + } + else + { + args << "stdio"; + } + + if (monotoneHandle->getType() == MonotoneHandle::workspace_handle) + { + process->setWorkingDirectory(monotoneHandle->getData()); + } + else + { // we need to ensure that the current directory is no workspace // directory, so paths won't get interpreted wrongly QString tmpPath = QDir::tempPath(); @@ -305,14 +181,13 @@ void MonotoneThread::run() } // waitForReadyRead returns false, if there are no data available - // (stdio shouldn't return anything on either channel if everything is ok) // or the time is up // FIXME: find the proper timeout for our use case here or better an // alternative way to detect if something went wrong while setting up // the process _before_ we send the whole thread to sleep later on // waiting silently for his first task... process->setReadChannel(QProcess::StandardError); - if (process->waitForReadyRead(1000)) + if (process->waitForReadyRead(2000)) { QByteArray errout = process->readAllStandardError(); QProcess::ProcessError error = process->error(); ============================================================ --- src/monotone/MonotoneThread.h 2b118fb88e52b782623fbc2242d0fa93b4058c0e +++ src/monotone/MonotoneThread.h 69c65cb863641399e615fd2dbfa3e49d6ed8b384 @@ -28,101 +28,12 @@ #include "vocab.h" -class MonotoneTask -{ -public: - typedef enum {Warning = 'w', Info = 'p', Error = 'e' } MessageType; - - MonotoneTask(); - MonotoneTask(const MonotoneTask &); - MonotoneTask(const QStringList &); - MonotoneTask(const QStringList &, const QStringList &); - MonotoneTask(const ByteArrayList &); - MonotoneTask(const ByteArrayList &, const ByteArrayList &); - - //! sets the command number of this task (increased internally by the thread) - void setCommandNumber(int num) { commandNumber = num; } - - //! sets the thread number to identify the thread - void setThreadNumber(int num) { threadNumber = num; } - - //! sets the raw command output - void setOutput(const QByteArray & out) { output = out; } - - //! sets the return code of the command - void setReturnCode(int code) { returnCode = code; } - - //! marks that the task has been finished - void setFinished() { finished = true; } - - //! set the output encoding - void setOutputEncoding(const QString & e) { outputEncoding = e; } - - //! appends more out-of-band messages for this task - void appendOutOfBandMessages(const QList &); - - //! returns true if one or more out-of-band messages match the given regex - bool outOfBandMessagesMatch(MessageType, const QRegExp &); - - //! returns the last out-of-band message of the given type - QString getLast(MessageType); - - //! returns the command input stdio-encoded - QByteArray getEncodedInput() const; - - //! returns the given arguments for the command - ByteArrayList getArguments() const { return arguments; } - - //! returns the given options for the command - ByteArrayList getOptions() const { return options; } - - //! returns the raw monotone output - QByteArray getOutput() const { return output; } - - //! converts the raw byte output into a unicode encoded QString - QString getDecodedOutput(const QString & enc = QString()) const; - - //! returns the command's return code - int getReturnCode() const { return returnCode; } - - //! returns the command's number (i.e. sequential number of the running mtn process) - int getCommandNumber() const { return commandNumber; } - - //! returns the number of the thread on which this task should/has been run - int getThreadNumber() const { return threadNumber; } - - //! true, if the task has already been completed - bool isFinished() const { return finished; } - - //! aborts the processing of the task - void setAborted() { abortTask = true; } - - //! checks if the task should be aborted - bool isAborted() const { return abortTask; } - -private: - void init(const ByteArrayList &, const ByteArrayList &); - ByteArrayList stringToByteArrayList(const QStringList &); - - int returnCode; - int commandNumber; - int threadNumber; - bool finished; - bool abortTask; - - ByteArrayList arguments; - ByteArrayList options; - QByteArray output; - QString outputEncoding; - QList oobMessages; -}; - class MonotoneThread : public QThread { Q_OBJECT public: - MonotoneThread(int, const QString &, const QString &, const QString & workspace = QString()); + MonotoneThread(int, const QString &, const MonotoneHandlePtr &); ~MonotoneThread(); //! returns the monotone handle which has been loaded by this thread @@ -175,8 +86,6 @@ private: void cleanup(QProcess *); private: - static const int StdioBufferSize; - bool doAbort; int commandNumber; int threadNumber; ============================================================ --- src/monotone/MonotoneUtil.cpp 8e1f9f6b125bf9651cfa9e16649a9675a956caa4 +++ src/monotone/MonotoneUtil.cpp 9f6c42f935b4950dbed92cf6681ad56d4d49eb18 @@ -565,7 +565,7 @@ bool MonotoneUtil::getFileAttribute(cons { if (!rev.isEmpty()) { - FileEntryList entryList = getRevisionManifest(handle, revision); + FileEntryList entryList = getRevisionManifest(handle, rev); foreach (const FileEntry & en, entryList) { ============================================================ --- src/util/Settings.cpp 66eea129ecb197d95578dc3abc07a9415922690a +++ src/util/Settings.cpp df71f25d2ca2cc8393d6ffbacd28f44364b4af91 @@ -168,16 +168,6 @@ void Settings::clear() singleton()->doClear(); } -QString Settings::getMtnBinaryPath() -{ - return singleton()->value("MtnExePath").toString(); -} - -void Settings::setMtnBinaryPath(const QString & path) -{ - singleton()->setValue("MtnExePath", path); -} - int Settings::getLogLevel() { return singleton()->value("LogLevel").toInt(); ============================================================ --- src/util/Settings.h 824bd489f11a42d8bf1753a61edac64e52918ff1 +++ src/util/Settings.h 82f4ab58c9ad8ed6ec15708c375b93d6d79fc9db @@ -47,9 +47,6 @@ public: static void removeItemFromMap(const QString &, const QString &); static QVariant getItemFromMap(const QString &, const QString &); - static QString getMtnBinaryPath(); - static void setMtnBinaryPath(const QString &); - static int getLogLevel(); static void setLogLevel(int); ============================================================ --- src/view/dialogs/OpenPrompt.cpp f4b707f26ca5b624d17ff5b007d74fba042f8387 +++ src/view/dialogs/OpenPrompt.cpp eebc742dce8d55bad628ab33f1a5c2ece399adc0 @@ -54,45 +54,21 @@ OpenPrompt::OpenPrompt(QWidget * parent) this, SIGNAL(quitApp()) ); - QStringList workspaces = Settings::getItemList("RecentWorkspaceList"); + connect( + recentWorkspaces, SIGNAL(currentIndexChanged(int)), + this, SLOT(recentWorkspacesChanged(int)) + ); - if (workspaces.size() > 0) - { - recentWorkspaces->addItems(workspaces); - recentWorkspaces->setEnabled(true); + connect( + recentDatabases, SIGNAL(currentIndexChanged(int)), + this, SLOT(recentDatabasesChanged(int)) + ); - connect( - recentWorkspaces, SIGNAL(currentIndexChanged(int)), - this, SLOT(recentWorkspacesChanged(int)) - ); - } + connect( + recentServers, SIGNAL(currentIndexChanged(int)), + this, SLOT(recentServersChanged(int)) + ); - QStringList databases = Settings::getItemList("RecentDatabaseList"); - - if (databases.size() > 0) - { - recentDatabases->addItems(databases); - recentDatabases->setEnabled(true); - - connect( - recentDatabases, SIGNAL(currentIndexChanged(int)), - this, SLOT(recentDatabasesChanged(int)) - ); - } - - QStringList servers = Settings::getItemList("RecentServerList"); - - if (servers.size() > 0) - { - recentServers->addItems(servers); - recentServers->setEnabled(true); - - connect( - recentServers, SIGNAL(currentIndexChanged(int)), - this, SLOT(recentServersChanged(int)) - ); - } - dialogManager = new DialogManager(this); connect( @@ -114,6 +90,13 @@ OpenPrompt::OpenPrompt(QWidget * parent) btnPreferences, SIGNAL(clicked()), dialogManager, SLOT(showPreferences()) ); + + connect( + qApp, SIGNAL(updateRecentLists()), + this, SLOT(updateRecentLists()) + ); + + updateRecentLists(); } OpenPrompt::~OpenPrompt() @@ -190,3 +173,42 @@ void OpenPrompt::recentServersChanged(in emit connectToServer(recentServers->itemText(idx)); } +void OpenPrompt::updateRecentLists() +{ + QStringList workspaces = Settings::getItemList("RecentWorkspaceList"); + + if (workspaces.size() > 0) + { + recentWorkspaces->addItems(workspaces); + recentWorkspaces->setEnabled(true); + } + else + { + recentWorkspaces->setEnabled(false); + } + + QStringList databases = Settings::getItemList("RecentDatabaseList"); + + if (databases.size() > 0) + { + recentDatabases->addItems(databases); + recentDatabases->setEnabled(true); + } + else + { + recentDatabases->setEnabled(false); + } + + QStringList servers = Settings::getItemList("RecentServerList"); + + if (servers.size() > 0) + { + recentServers->addItems(servers); + recentServers->setEnabled(true); + } + else + { + recentServers->setEnabled(false); + } +} + ============================================================ --- src/view/dialogs/OpenPrompt.h 6d5d30a70469851c90e94c5e5d2e252dde59745f +++ src/view/dialogs/OpenPrompt.h 35502b67323d4deff525e1b79c6dd6066fa45a3c @@ -43,6 +43,7 @@ private slots: void recentDatabasesChanged(int); void recentWorkspacesChanged(int); void recentServersChanged(int); + void updateRecentLists(); private: DialogManager * dialogManager; ============================================================ --- src/view/dialogs/Preferences.cpp bbfd35ef1eb2cce93eace1e023f06296102fcd97 +++ src/view/dialogs/Preferences.cpp 459b2bbe76e27e7ae2817f730c1180602fb22e8f @@ -56,7 +56,7 @@ void Preferences::init() void Preferences::init() { - mtnExecutablePath->setText(Settings::getMtnBinaryPath()); + mtnExecutablePath->setText(Settings::getString("MtnExePath")); enableConsoleLog->setCheckState( Settings::getBool("ConsoleLogEnabled") ? @@ -173,7 +173,7 @@ void Preferences::accept() Settings::setBool("FileLogEnabled", enableFileLog->isChecked()); Settings::setLogLevel(logLevel->itemData(logLevel->currentIndex()).toInt()); - QString oldPath = Settings::getMtnBinaryPath(); + QString oldPath = Settings::getString("MtnExePath"); QString newPath = mtnExecutablePath->text(); bool checkUpperBound = relaxedVersionCheck->isChecked(); @@ -206,7 +206,7 @@ void Preferences::accept() if (oldPath != newPath) { requireRestart = true; - Settings::setMtnBinaryPath(newPath); + Settings::setString("MtnExePath", newPath); } Settings::setBool("CheckForUpdates", checkForUpdates->isChecked()); ============================================================ --- src/view/mainwindows/DatabaseWindow.cpp 354dab579537397804c14943e4afcb0f90e6f33a +++ src/view/mainwindows/DatabaseWindow.cpp eab02d0c1715637bab6627b63d0c6aad8e4470c3 @@ -152,7 +152,7 @@ void DatabaseWindow::load(const Monotone void DatabaseWindow::load(const MonotoneHandlePtr & handle) { - I(handle->getType() == MonotoneHandle::workspace_handle); + I(handle->getType() == MonotoneHandle::database_handle); APP->manager()->getThread(handle); monotoneHandle = handle; ============================================================ --- src/view/mainwindows/MainWindow.cpp 82c2c385f918af05a8165acfda5eccb5e8b602e0 +++ src/view/mainwindows/MainWindow.cpp 9c3f199deff033bb24420956450e520cc36b35ef @@ -105,6 +105,11 @@ void MainWindow::init() ); connect( + menuBar, SIGNAL(connectToServer(const QString &)), + app, SLOT(connectToServer(const QString &)) + ); + + connect( menuBar, SIGNAL(checkForApplicationUpdates()), app, SLOT(checkForApplicationUpdates()) ); ============================================================ --- src/view/panels/NodeInfo.cpp 15616533343a9ef542a0de22dc4f738a1fd8d9d7 +++ src/view/panels/NodeInfo.cpp 5d1c70aa410ff30baa12af5002950288c9b1239c @@ -18,6 +18,7 @@ #include "NodeInfo.h" #include "MonotoneUtil.h" +#include "CertList.h" #include #include ============================================================ --- src/view/widgets/MenuBar.cpp 5f1ad3b61efcb9615d2bd81543bbe1ec4d99d0e2 +++ src/view/widgets/MenuBar.cpp 368e1539daa1058938786875240385835ea7b5cb @@ -22,6 +22,7 @@ #include #include +#include #include MenuBar::MenuBar(QWidget * parent) : QMenuBar(parent) @@ -41,6 +42,8 @@ MenuBar::MenuBar(QWidget * parent) : QMe actionCreate_Database->setShortcut(tr("Ctrl+N")); actionOpen_Database = new QAction(tr("Open Database"), this); actionOpen_Database->setShortcut(tr("Ctrl+Shift+O")); + actionConnect_to_Server = new QAction(tr("Connect to Server"), this); + actionConnect_to_Server->setShortcut(tr("Ctrl+Alt+O")); actionPreferences = new QAction(tr("Preferences..."), this); actionPreferences->setMenuRole(QAction::PreferencesRole); actionPreferences->setShortcut(tr("Ctrl+P")); @@ -54,6 +57,7 @@ MenuBar::MenuBar(QWidget * parent) : QMe menuFile = new QMenu(tr("File"), this); menuRecent_Databases = new QMenu(tr("Recent databases..."), menuFile); menuRecent_Workspaces = new QMenu(tr("Recent workspaces..."), menuFile); + menuRecent_Servers = new QMenu(tr("Recent servers..."), menuFile); menuFile->addAction(actionOpen_Workspace); menuFile->addAction(menuRecent_Workspaces->menuAction()); @@ -62,6 +66,9 @@ MenuBar::MenuBar(QWidget * parent) : QMe menuFile->addAction(actionOpen_Database); menuFile->addAction(menuRecent_Databases->menuAction()); menuFile->addSeparator(); + menuFile->addAction(actionConnect_to_Server); + menuFile->addAction(menuRecent_Servers->menuAction()); + menuFile->addSeparator(); menuFile->addAction(actionPreferences); menuFile->addAction(actionCheck_for_updates); menuFile->addSeparator(); @@ -113,6 +120,11 @@ MenuBar::MenuBar(QWidget * parent) : QMe ); connect( + actionConnect_to_Server, SIGNAL(triggered()), + this, SLOT(newServerConnection()) + ); + + connect( actionMonotone_manual, SIGNAL(triggered()), this, SIGNAL(showMonotoneManual()) ); @@ -164,6 +176,7 @@ void MenuBar::updateRecentLists() { menuRecent_Workspaces->clear(); menuRecent_Databases->clear(); + menuRecent_Servers->clear(); QStringList previousWs = Settings::getItemList("RecentWorkspaceList"); int elemCount = previousWs.size(); @@ -204,6 +217,26 @@ void MenuBar::updateRecentLists() act->setData(previousDb[i]); } } + + QStringList previousServers = Settings::getItemList("RecentServerList"); + elemCount = previousServers.size(); + if (elemCount == 0) + { + menuRecent_Servers->addAction(tr("No previous servers available.")); + } + else + { + QAction * act; + for (int i = 0; i < elemCount; ++i) + { + act = menuRecent_Servers->addAction( + tr("&%1 %2").arg(i + 1).arg(previousServers[i]), + this, + SLOT(connectRecentServer()) + ); + act->setData(previousServers[i]); + } + } } void MenuBar::openDatabase() @@ -231,6 +264,21 @@ void MenuBar::openWorkspace() emit loadWorkspace(fn); } +void MenuBar::newServerConnection() +{ + bool ok; + QString connection = QInputDialog::getText( + this, + tr("Enter a new server connection"), + tr("Please enter a new server connection (f.e. mtn://my.server.com:4691):"), + QLineEdit::Normal, "mtn://", &ok).trimmed(); + + if (!ok || connection.isEmpty()) + return; + + emit connectToServer(connection); +} + void MenuBar::openRecentWorkspace() { QAction * action = qobject_cast(sender()); @@ -243,6 +291,12 @@ void MenuBar::openRecentDatabase() emit loadDatabase(action->data().toString()); } +void MenuBar::connectRecentServer() +{ + QAction * action = qobject_cast(sender()); + emit connectToServer(action->data().toString()); +} + void MenuBar::updateWindowList(const QStringList & windowTitles) { // remove old actions ============================================================ --- src/view/widgets/MenuBar.h 5bbbaac501c215f53fc2905b15fc9660a4b0e175 +++ src/view/widgets/MenuBar.h 261ef742ffacd45bde12543579989b2e0e8c97b1 @@ -35,6 +35,7 @@ signals: signals: void loadWorkspace(const QString &); void loadDatabase(const QString &); + void connectToServer(const QString &); void showCreateDatabase(); void showPreferences(); void showMonotoneManual(); @@ -48,6 +49,7 @@ protected: QAction * actionCreate_Database; QAction * actionOpen_Database; QAction * actionOpen_Workspace; + QAction * actionConnect_to_Server; QAction * actionPreferences; QAction * actionCheck_for_updates; QAction * actionClose; @@ -61,14 +63,17 @@ protected: QMenu * menuFile; QMenu * menuRecent_Databases; QMenu * menuRecent_Workspaces; + QMenu * menuRecent_Servers; QMenu * menuWindow; QMenu * menuHelp; private slots: void openDatabase(); void openWorkspace(); + void newServerConnection(); void openRecentDatabase(); void openRecentWorkspace(); + void connectRecentServer(); void activateOtherWindow(); }; ============================================================ --- src/vocab.h 167b8a99825b50f32712ab63f5b23271d35c6159 +++ src/vocab.h e98da12225f2bc46b4c67132f6402a6a7c439a91 @@ -149,8 +149,9 @@ typedef QSharedPointer M class MonotoneHandle; typedef QSharedPointer MonotoneHandlePtr; -// this is used almost everywhere, so include it here +// these are used almost everywhere, so include them here #include "MonotoneHandle.h" +#include "MonotoneTask.h" #include class GuitoneException : public std::exception