# # # add_file "guitone/src/monotone/WorkspaceCreator.cpp" # content [1c21599fe53b44512ca412e8e50ce99ea3439359] # # add_file "guitone/src/monotone/WorkspaceCreator.h" # content [2265014895962e9fd5ad67cb6d7800962e52cea0] # # add_file "guitone/src/vocab.h" # content [f8c1dd7d5d3deb6b9d48666a335764a282432e06] # # patch "guitone/guitone.pro" # from [25e4e5caf9d2f4b8c6771f0826f74efd9a84b766] # to [fb457fe29f87bea89e6510eadbead366bdc3fcb3] # # patch "guitone/src/monotone/FileExporter.cpp" # from [8d796b49755d5498781271b4a3e3145e3b010c36] # to [ea8fcb16287034dcd019a9f25cbb79c97130d507] # # patch "guitone/src/monotone/FileExporter.h" # from [0db9abfd0c7c716ee600c8c7024e198f1b7a7034] # to [646c474fbb4cb23a22419193b31475705f187796] # # patch "guitone/src/monotone/MonotoneDelegate.cpp" # from [7ff79f09f2f3e612c5b24171374db3df9b2a40bc] # to [21c4fd2e06811021f2bcdcf3aa35bfc8dd2ea599] # # patch "guitone/src/monotone/MonotoneDelegate.h" # from [cc1fa1480e54e8f31e454babc9faa80e380a11db] # to [47d291e3613ebb60a71c68499a0659fedd37cbb0] # # patch "guitone/src/view/dialogs/RevisionManifest.cpp" # from [94c245e7f47f66b41818e43ef3d4a081cd1cab4c] # to [b8a500aec70d3b8e3ed02a41c175c48d20e07151] # # patch "guitone/src/view/dialogs/RevisionManifest.h" # from [54a0eed45ca8feea0df87f5e46f9821e493a876d] # to [55c5f87ddce26d91aa7b2331ceba4c6e665eb947] # ============================================================ --- guitone/src/monotone/WorkspaceCreator.cpp 1c21599fe53b44512ca412e8e50ce99ea3439359 +++ guitone/src/monotone/WorkspaceCreator.cpp 1c21599fe53b44512ca412e8e50ce99ea3439359 @@ -0,0 +1,144 @@ +/*************************************************************************** + * Copyright (C) 2007 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 2 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "WorkspaceCreator.h" +#include "Guitone.h" +#include "MonotoneDelegate.h" + +#include +#include + +WorkspaceCreator::WorkspaceCreator(QObject * parent, QString rev, QString path) + : FileExporter(parent, rev, path) +{} + +WorkspaceCreator::~WorkspaceCreator() +{} + +bool WorkspaceCreator::run() +{ + // + // at first determine the branch name(s) of the revision and let the + // user select one branch of a list of branches + // + RevisionCerts certs = MonotoneDelegate::getRevisionCerts(this, revision); + + QStringList branches; + for (int i=0,j=certs.size(); i 1) + { + bool ok; + QString branch = QInputDialog::getItem( + NULL, tr("Select a branch"), + tr("The selected revision has more than one " + "branch cert attached - please select one:"), + branches, 0, false, &ok); + if (!ok || branch.isEmpty()) + { + D("User aborted checkout"); + return false; + } + selectedBranch = branch; + } + + // + // now we query the manifest contents + // + FileEntryList entries = + MonotoneDelegate::getRevisionManifest(this, revision); + + // + // finally before we export anything, we create the _MTN directory layout + // + if (!rootDir.mkdir("_MTN")) + { + C("WorkspaceCreator::run: cannot create directory"); + return false; + } + + Q_ASSERT(rootDir.cd("_MTN")); + + // _MTN/revision + QFile revfile(rootDir.filePath("revision")); + if (!revfile.open(QIODevice::WriteOnly)) + { + C("WorkspaceCreator::run: can't open revision for writing"); + return false; + } + QString rev = QString("format_version \"1\"\n\n" + "new_manifest [0000000000000000000000000000000000000000]\n\n" + "old_revision [%1]\n").arg(revision); + Q_ASSERT(revfile.write(rev.toLatin1())); + revfile.close(); + + // _MTN/version + QFile verfile(rootDir.filePath("version")); + if (!revfile.open(QIODevice::WriteOnly)) + { + C("WorkspaceCreator::run: can't open version for writing"); + return false; + } + Q_ASSERT(verfile.write(QString("2\n").toLatin1())); + verfile.close(); + + // _MTN/log (initally empty) + QFile logfile(rootDir.filePath("log")); + if (!logfile.open(QIODevice::WriteOnly)) + { + C("WorkspaceCreator::run: can't open log for writing"); + return false; + } + logfile.close(); + + // _MTN/options + QFile optfile(rootDir.filePath("options")); + if (!optfile.open(QIODevice::WriteOnly)) + { + C("WorkspaceCreator::run: can't open revision for writing"); + return false; + } + // the keydir entry is not needed and automatically added to the + // list of options on the first commit + QString options = QString("database \"%1\"\n\nbranch \"%2\"\n") + .arg(MonotoneDelegate::getDatabaseFilePath(this)) + .arg(selectedBranch); + Q_ASSERT(optfile.write(options.toLatin1())); + optfile.close(); + + // change back to the root dir + Q_ASSERT(rootDir.cdUp()); + + return FileExporter::run(entries); +} + ============================================================ --- guitone/src/monotone/WorkspaceCreator.h 2265014895962e9fd5ad67cb6d7800962e52cea0 +++ guitone/src/monotone/WorkspaceCreator.h 2265014895962e9fd5ad67cb6d7800962e52cea0 @@ -0,0 +1,35 @@ +/*************************************************************************** + * Copyright (C) 2007 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 2 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef WORKSPACE_CREATOR_H +#define WORKSPACE_CREATOR_H + +#include "FileExporter.h" + +class WorkspaceCreator : public FileExporter +{ + Q_OBJECT +public: + WorkspaceCreator(QObject *, QString, QString); + ~WorkspaceCreator(); + bool run(); +}; + +#endif ============================================================ --- guitone/src/vocab.h f8c1dd7d5d3deb6b9d48666a335764a282432e06 +++ guitone/src/vocab.h f8c1dd7d5d3deb6b9d48666a335764a282432e06 @@ -0,0 +1,12 @@ +#ifndef VOCAB_H +#define VOCAB_H + +#include +#include + +typedef QPair FileEntry; +typedef QList FileEntryList; + +typedef QPair RevisionCert; +typedef QList RevisionCerts; +#endif ============================================================ --- guitone/guitone.pro 25e4e5caf9d2f4b8c6771f0826f74efd9a84b766 +++ guitone/guitone.pro fb457fe29f87bea89e6510eadbead366bdc3fcb3 @@ -40,6 +40,7 @@ HEADERS += src/view/MainWindow.h \ src/monotone/Monotone.h \ src/monotone/MonotoneDelegate.h \ src/monotone/FileExporter.h \ + src/monotone/WorkspaceCreator.h \ src/model/Inventory.h \ src/model/InventoryItem.h \ src/model/InventoryProxyModel.h \ @@ -69,7 +70,8 @@ HEADERS += src/view/MainWindow.h \ src/util/TreeBuilder.h \ src/util/DebugLog.h \ src/util/StdioParser.h \ - src/Guitone.h + src/Guitone.h \ + src/vocab.h SOURCES += src/view/MainWindow.cpp \ src/view/TreeView.cpp \ src/view/Splitter.cpp \ @@ -95,6 +97,7 @@ SOURCES += src/view/MainWindow.cpp \ src/monotone/Monotone.cpp \ src/monotone/MonotoneDelegate.cpp \ src/monotone/FileExporter.cpp \ + src/monotone/WorkspaceCreator.cpp \ src/model/Inventory.cpp \ src/model/InventoryItem.cpp \ src/model/InventoryProxyModel.cpp \ ============================================================ --- guitone/src/monotone/FileExporter.cpp 8d796b49755d5498781271b4a3e3145e3b010c36 +++ guitone/src/monotone/FileExporter.cpp ea8fcb16287034dcd019a9f25cbb79c97130d507 @@ -19,25 +19,26 @@ ***************************************************************************/ #include "FileExporter.h" +#include "MonotoneDelegate.h" #include "Guitone.h" #include -FileExporter::FileExporter(QObject * parent, QString rev, FileEntryList en) - : QObject(parent), revision(rev), entries(en) -{} +FileExporter::FileExporter(QObject * parent, QString rev, QString p) + : QObject(parent), revision(rev) +{ + rootDir = QDir(p); + Q_ASSERT(rootDir.exists()); +} FileExporter::~FileExporter() { } -bool FileExporter::run(QString exportDir) +bool FileExporter::run(const FileEntryList & entries) { - rootDir = QDir(exportDir); - Q_ASSERT(rootDir.exists()); - QProgressDialog progress( - tr("Exporting files..."), tr("Abort"), 0, entries.size() + tr("Processing files..."), tr("Abort"), 0, entries.size() ); progress.setWindowModality(Qt::WindowModal); @@ -68,13 +69,13 @@ bool FileExporter::run(QString exportDir return success; } -bool FileExporter::exportFile(FileEntry entry) +bool FileExporter::exportFile(const FileEntry & entry) { if (entry.second) { if (!rootDir.mkpath(entry.first)) { - qCritical("FileExporter::exportFile: cannot create directory"); + C("FileExporter::exportFile: cannot create directory"); return false; } return true; @@ -88,7 +89,7 @@ bool FileExporter::exportFile(FileEntry QStringList() << "r" << revision, commandNumber) || mtn->getReturnCode(commandNumber) > 0) { - qCritical("FileExporter::exportFile: cannot execute get_file_of"); + C("FileExporter::exportFile: cannot execute get_file_of"); return false; } @@ -97,11 +98,11 @@ bool FileExporter::exportFile(FileEntry if (!file.open(QIODevice::WriteOnly)) { - qCritical("FileExporter::exportFile: can't open file for writing"); + C("FileExporter::exportFile: can't open file for writing"); return false; } - file.write(mtn->getRawData(commandNumber)); + Q_ASSERT(file.write(mtn->getRawData(commandNumber))); file.close(); return true; ============================================================ --- guitone/src/monotone/FileExporter.h 0db9abfd0c7c716ee600c8c7024e198f1b7a7034 +++ guitone/src/monotone/FileExporter.h 646c474fbb4cb23a22419193b31475705f187796 @@ -23,23 +23,21 @@ #include -#include "MonotoneDelegate.h" -#include "RevisionManifest.h" +#include "vocab.h" class FileExporter : public QObject { Q_OBJECT public: - FileExporter(QObject *, QString, FileEntryList); + FileExporter(QObject *, QString, QString); ~FileExporter(); - bool run(QString); + virtual bool run(const FileEntryList &); -private: - bool exportFile(FileEntry); +protected: + bool exportFile(const FileEntry &); QDir rootDir; QString revision; - FileEntryList entries; }; #endif ============================================================ --- guitone/src/monotone/MonotoneDelegate.cpp 7ff79f09f2f3e612c5b24171374db3df9b2a40bc +++ guitone/src/monotone/MonotoneDelegate.cpp 21c4fd2e06811021f2bcdcf3aa35bfc8dd2ea599 @@ -174,7 +174,7 @@ QStringList MonotoneDelegate::resolveSel return revList; } -QMap MonotoneDelegate::getRevisionCerts(QObject * obj, const QString & revision) +RevisionCerts MonotoneDelegate::getRevisionCerts(QObject * obj, const QString & revision) { Monotone * mtn = MTN(obj); @@ -182,42 +182,100 @@ QMap MonotoneDelegate: mtn->executeCommand(QStringList() << "certs" << revision, cmdNum); QString data = mtn->getDecodedData(cmdNum); - QMap map; + RevisionCerts certs; if (mtn->getReturnCode(cmdNum) > 0) { qCritical("Couldn't query revision certs for %s: %s", qPrintable(revision), qPrintable(data)); - return map; + return certs; } BasicIOParser parser(data); if (!parser.parse()) { qCritical("Could not parse basic_io."); - return map; + return certs; } StanzaList stanzas = parser.getStanzas(); foreach (Stanza st, stanzas) { - QString lastName; + RevisionCert cert; + foreach (StanzaEntry en, st) { if (en.sym == "name") { - QString lastName = en.vals.at(0); - map.insert(lastName, ""); + cert.first = en.vals.at(0); } if (en.sym == "value") { - Q_ASSERT(lastName.length() > 0); - map[lastName] = en.vals.at(0); + cert.second = en.vals.at(0); } } + Q_ASSERT(!cert.first.isEmpty() && !cert.second.isEmpty()); + certs.append(cert); } - return map; + return certs; } +QString MonotoneDelegate::getDatabaseFilePath(QObject * obj) +{ + Monotone * mtn = MTN(obj); + QString path = mtn->getDatabaseFilePath(); + + // apparently a workspace is loaded... + if (path.isEmpty()) + { + path = getOption(obj, "database"); + } + + Q_ASSERT(!path.isEmpty()); + return path; +} +FileEntryList MonotoneDelegate::getRevisionManifest(QObject * obj, const QString & revision) +{ + Monotone * mtn = MTN(obj); + + int cmdNum; + mtn->executeCommand(QStringList() << "get_manifest_of" << revision, cmdNum); + + QString data = mtn->getDecodedData(cmdNum); + FileEntryList entries; + + if (mtn->getReturnCode(cmdNum) > 0) + { + qCritical("Couldn't query manifest entries for %s: %s", + qPrintable(revision), qPrintable(data)); + return entries; + } + + BasicIOParser parser(data); + if (!parser.parse()) + { + qCritical("Could not parse basic_io."); + return entries; + } + + StanzaList stanzas = parser.getStanzas(); + foreach (Stanza st, stanzas) + { + foreach (StanzaEntry en, st) + { + if (en.sym == "format_version") break; + + FileEntry entry; + entry.first = en.vals.at(0); + Q_ASSERT(en.sym == "dir" || en.sym == "file"); + entry.second = en.sym == "dir"; + + entries.append(entry); + break; + } + } + return entries; +} + ============================================================ --- guitone/src/monotone/MonotoneDelegate.h cc1fa1480e54e8f31e454babc9faa80e380a11db +++ guitone/src/monotone/MonotoneDelegate.h 47d291e3613ebb60a71c68499a0659fedd37cbb0 @@ -22,10 +22,11 @@ #define MONOTONE_DELEGATE_H #include "AutomateCommand.h" +#include "vocab.h" #include -#include + class MonotoneDelegate : public QObject { Q_OBJECT @@ -41,7 +42,9 @@ public: static QString getBranchName(QObject *); static QString getBranchNameShort(QObject *); static QStringList resolveSelector(QObject *, const QString &); - static QMap getRevisionCerts(QObject *, const QString &); + static RevisionCerts getRevisionCerts(QObject *, const QString &); + static QString getDatabaseFilePath(QObject *); + static FileEntryList getRevisionManifest(QObject *, const QString &); private: AutomateCommand * cmdModel; ============================================================ --- guitone/src/view/dialogs/RevisionManifest.cpp 94c245e7f47f66b41818e43ef3d4a081cd1cab4c +++ guitone/src/view/dialogs/RevisionManifest.cpp b8a500aec70d3b8e3ed02a41c175c48d20e07151 @@ -194,14 +194,15 @@ void RevisionManifest::saveAllFiles() if (!index.isValid()) break; list.append(index); } - FileEntryList entries = extractSelectedEntries(list); QString exportDir = QFileDialog::getExistingDirectory(0, tr("Select your export directory...")); if (!exportDir.isEmpty()) { - FileExporter exporter(this, revision, entries); - if (!exporter.run(exportDir)) + FileExporter exporter(this, revision, exportDir); + + FileEntryList entries = extractSelectedEntries(list); + if (!exporter.run(entries)) { QMessageBox::critical( this, @@ -232,8 +233,8 @@ void RevisionManifest::saveSelectedFiles QFileDialog::getExistingDirectory(0, tr("Select your export directory...")); if (!exportDir.isEmpty()) { - FileExporter exporter(this, revision, entries); - if (!exporter.run(exportDir)) + FileExporter exporter(this, revision, exportDir); + if (!exporter.run(entries)) { QMessageBox::critical( this, ============================================================ --- guitone/src/view/dialogs/RevisionManifest.h 54a0eed45ca8feea0df87f5e46f9821e493a876d +++ guitone/src/view/dialogs/RevisionManifest.h 55c5f87ddce26d91aa7b2331ceba4c6e665eb947 @@ -24,13 +24,10 @@ #include "Dialog.h" #include "ui_manifest.h" #include "Manifest.h" +#include "vocab.h" #include -// FIXME: this should be removed into some vocab.h file -typedef QPair FileEntry; -typedef QList FileEntryList; - class RevisionManifest : public Dialog, private Ui::ManifestDialog { Q_OBJECT