# # # add_file "guitone/src/monotone/WorkspaceCommitter.cpp" # content [24c20dd54d53c980f930dc569ffd8ef77838f12d] # # add_file "guitone/src/monotone/WorkspaceCommitter.h" # content [df5912a27f8f00ff7c954bb50dfe354125a855fc] # # patch "guitone/guitone.pro" # from [fb457fe29f87bea89e6510eadbead366bdc3fcb3] # to [e7a4a243f865a6366969a654ea8b4dabf9f8ba7f] # # patch "guitone/res/forms/commit_revision.ui" # from [c81cdb40189d873524fd833f832a700006a5394b] # to [f1e90933bd268b597bff6a668ea336e94c676314] # # patch "guitone/res/i18n/guitone_de.ts" # from [c547c0e7baf808aec3368eefa5f97d01a9981c6a] # to [7b403b0ae716911cc11af94a607db5d236eeaa5f] # # patch "guitone/src/monotone/FileExporter.cpp" # from [ea8fcb16287034dcd019a9f25cbb79c97130d507] # to [f16b44b3a580b963fc66c1407b7a7203b1dc4c40] # # patch "guitone/src/monotone/Monotone.cpp" # from [eecfb2cd2d994160207be138cce8dbfcc1a2fd97] # to [41d1cd952e4a3799fb8795dfe1f4e49204dca519] # # patch "guitone/src/monotone/Monotone.h" # from [213aa23621ca345b374b3f6ef790f09dd69b3cf0] # to [25860d5a6a916ffcefd83275f203bd3d49be55ac] # # patch "guitone/src/monotone/MonotoneDelegate.cpp" # from [e0957447664f2171062462577580c793b04ddb62] # to [84dbd3a0dff4a0ffddf39e6a7e25d1735d3b5f14] # # patch "guitone/src/monotone/MonotoneDelegate.h" # from [47d291e3613ebb60a71c68499a0659fedd37cbb0] # to [907a718c030f96ed3c2951e5b5b1442b72b6891a] # # patch "guitone/src/monotone/WorkspaceCreator.cpp" # from [1c21599fe53b44512ca412e8e50ce99ea3439359] # to [ff6dd8f1e13381614edd6a7ee6d8f453d0c1566b] # # patch "guitone/src/view/dialogs/CommitRevision.cpp" # from [e796042390241526ff2848e24f0bebd8b432dc9c] # to [ffe771b0f74202063686e3d30bcff6f6b9d0636a] # # patch "guitone/src/view/dialogs/CommitRevision.h" # from [7d02ef0a24613fc88485823db77d5a9cfdbc6b35] # to [82f533b5b65f320a31dd7c1e728d72564b3f2915] # # patch "guitone/src/vocab.h" # from [f8c1dd7d5d3deb6b9d48666a335764a282432e06] # to [9badd48e5b9420e8fb663d32e93bab8bc751a93d] # ============================================================ --- guitone/src/monotone/WorkspaceCommitter.cpp 24c20dd54d53c980f930dc569ffd8ef77838f12d +++ guitone/src/monotone/WorkspaceCommitter.cpp 24c20dd54d53c980f930dc569ffd8ef77838f12d @@ -0,0 +1,201 @@ +/*************************************************************************** + * 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 "WorkspaceCommitter.h" +#include "MonotoneDelegate.h" +#include "Guitone.h" +#include "BasicIOParser.h" + +#include +#include + +WorkspaceCommitter::WorkspaceCommitter(QObject * parent, QString k, QString b, QString a, QString c) + : QObject(parent), key(k) +{ + // use the signing key as default author cert value + if (a.isEmpty()) a = k; + + certs.insert("branch", b); + certs.insert("author", a); + certs.insert("changelog", c); + certs.insert("date", + QDateTime::currentDateTime().toUTC().toString(Qt::ISODate)); + + workspaceDir = QDir(MTN(this)->getNormalizedWorkspacePath()); + Q_ASSERT(workspaceDir.exists()); +} + +WorkspaceCommitter::~WorkspaceCommitter() +{ +} + +bool WorkspaceCommitter::run() +{ + // at first get the current revision text + // FIXME: we don't yet check here if this has change since we openend the + // commit dialog! + Monotone * mtn = MTN(this); + + int cmdNum; + mtn->executeCommand(QStringList() << "get_revision", cmdNum); + + QString data = mtn->getDecodedData(cmdNum); + + if (mtn->getReturnCode(cmdNum) > 0) + { + C(QString("Couldn't query workspace revision: %1").arg(data)); + return false; + } + + QString fullRevision = data; + + BasicIOParser parser(fullRevision); + if (!parser.parse()) + { + C("Could not parse basic_io."); + return false; + } + + QList > fileChanges; + + StanzaList stanzas = parser.getStanzas(); + foreach (Stanza st, stanzas) + { + QPair pair; + bool isPatch = false; + + foreach (StanzaEntry en, st) + { + if (en.sym == "add_file") + { + pair.first = en.vals.at(0); + fileChanges.append(pair); + break; + } + + if (en.sym == "patch") + { + pair.first = en.vals.at(0); + isPatch = true; + continue; + } + + if (isPatch && en.sym == "from") + { + Q_ASSERT(!pair.first.isEmpty()); + pair.second = en.vals.at(0); + fileChanges.append(pair); + break; + } + } + } + + // put files + for (int i=0, j=fileChanges.size(); i < j; i++) + { + QPair pair = fileChanges.at(i); + if (!putFile(pair.first, pair.second)) + { + // FIXME: what to do with already added file deltas? + return false; + } + } + + // commit revision + mtn->executeCommand(QStringList() << "put_revision" << fullRevision, cmdNum); + + data = mtn->getDecodedData(cmdNum); + + if (mtn->getReturnCode(cmdNum) > 0) + { + C(QString("Couldn't commit revision: %1").arg(data)); + return false; + } + + data.chop(1); + revisionId = data; + + // attach certificates + QMapIterator i(certs); + while (i.hasNext()) + { + i.next(); + + int cmdNum; + mtn->executeCommand( + QStringList() << "cert" << revisionId << i.key() << i.value(), + QStringList() << "key" << key, + cmdNum + ); + + QString data = mtn->getDecodedData(cmdNum); + + if (mtn->getReturnCode(cmdNum) > 0) + { + C(QString("Couldn't attach cert %1: %2").arg(i.key()).arg(data)); + return false; + } + } + + D(QString("Committed revision %1").arg(revisionId)); + return true; +} + +bool WorkspaceCommitter::putFile(const QString & fileName, const QString & baseId) +{ + QFile file(workspaceDir.filePath(fileName)); + if (!file.exists()) + { + // FIXME: we need to bubble this up to the user, this typically + // happens if there are missing files in the workspace + C(QString("File %1 does not exist in workpace.").arg(fileName)); + return false; + } + + if (!file.open(QIODevice::ReadOnly)) + { + C("Can't open file for reading."); + return false; + } + + Monotone * mtn = MTN(this); + + int commandNumber; + + ByteArrayList command; + command << "put_file"; + if (!baseId.isEmpty()) + { + command << baseId.toAscii(); + } + command << file.readAll(); + file.close(); + + if (!mtn->executeCommand(command, commandNumber) || + mtn->getReturnCode(commandNumber) > 0) + { + C(QString("Cannot execute put_file: %1") + .arg(mtn->getDecodedData(commandNumber))); + return false; + } + + return true; +} + ============================================================ --- guitone/src/monotone/WorkspaceCommitter.h df5912a27f8f00ff7c954bb50dfe354125a855fc +++ guitone/src/monotone/WorkspaceCommitter.h df5912a27f8f00ff7c954bb50dfe354125a855fc @@ -0,0 +1,47 @@ +/*************************************************************************** + * 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_COMMITTER_H +#define WORKSPACE_COMMITTER_H + +#include "vocab.h" + +#include +#include + +class WorkspaceCommitter : public QObject +{ + Q_OBJECT +public: + WorkspaceCommitter(QObject *, QString, QString, QString, QString); + ~WorkspaceCommitter(); + bool run(); + inline QString getRevisionId() const { return revisionId; } + +protected: + bool putFile(const QString &, const QString & baseId = QString()); + + QString revisionId; + QString key; + QDir workspaceDir; + QMap certs; +}; + +#endif ============================================================ --- guitone/guitone.pro fb457fe29f87bea89e6510eadbead366bdc3fcb3 +++ guitone/guitone.pro e7a4a243f865a6366969a654ea8b4dabf9f8ba7f @@ -41,6 +41,7 @@ HEADERS += src/view/MainWindow.h \ src/monotone/MonotoneDelegate.h \ src/monotone/FileExporter.h \ src/monotone/WorkspaceCreator.h \ + src/monotone/WorkspaceCommitter.h \ src/model/Inventory.h \ src/model/InventoryItem.h \ src/model/InventoryProxyModel.h \ @@ -98,6 +99,7 @@ SOURCES += src/view/MainWindow.cpp \ src/monotone/MonotoneDelegate.cpp \ src/monotone/FileExporter.cpp \ src/monotone/WorkspaceCreator.cpp \ + src/monotone/WorkspaceCommitter.cpp \ src/model/Inventory.cpp \ src/model/InventoryItem.cpp \ src/model/InventoryProxyModel.cpp \ ============================================================ --- guitone/res/forms/commit_revision.ui c81cdb40189d873524fd833f832a700006a5394b +++ guitone/res/forms/commit_revision.ui f1e90933bd268b597bff6a668ea336e94c676314 @@ -70,7 +70,7 @@ - QAbstractItemView::ExtendedSelection + QAbstractItemView::NoSelection false @@ -88,33 +88,6 @@ 6 - - - - Select all - - - - - - - Invert Selection - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - @@ -355,22 +328,6 @@ - selectAll - clicked() - changeView - selectAll() - - - 64 - 180 - - - 78 - 98 - - - - abort clicked() CommitRevision ============================================================ --- guitone/res/i18n/guitone_de.ts c547c0e7baf808aec3368eefa5f97d01a9981c6a +++ guitone/res/i18n/guitone_de.ts 7b403b0ae716911cc11af94a607db5d236eeaa5f @@ -370,53 +370,125 @@ Select all - Alle auswählen + Alle auswählen Invert Selection - Auswahl umkehren + Auswahl umkehren - + Changelog entry Changelog-Eintrag - + Previous changelog entries Vorherige Changelog-Einträge - + use alternative branch alternativen Zweig benutzen - + use alternative author alternativen Autor benutzen - + Abort Abbrechen - + Commit Einpflegen - + No changes Keine Änderungen - + The current workspace has no committable changes. Der derzeitige Arbeitsbereich hat keine Änderungen zum Einpflegen. + + + Workspace has no branch set + Arbeitsbereich hat keinen Zweig gesetzt + + + + The workspace has no branch set. Please enter one. + Der Arbeitsbereich hat keinen Zweig gesetzt. Bitte geben Sie einen Zweig an. + + + + No branch specified + Kein Zweig angegeben + + + + Please enter the name of an alternative author. + Bitte geben Sie den Namen eines alternativen Autors an. + + + + No author specified + Kein Autor angegeben + + + + No private key found + Kein privater Schlüssel gefunden + + + + There are no private keys available with which to sign your commit. Please go to Database > Key Management and create a new private key first. + Es sind keine privaten Schlüssel verfügbar, um die neue Revision zu unterschreiben. Bitte öffnen Sie die Schlüsselverwaltung im Menü "Datenbank" und generieren Sie zunächst einen neuen privaten Schlüssel. + + + + Please select a key + Bitte wählen Sie einen Schlüssel + + + + More than one private key is available. +Please select the key with which you like to sign this commit: + Mehr als ein privater Schlüssel ist verfügbar. Bitte wählen Sie +den Schlüssel, mit dem Sie diese Revision unterschreiben möchten: + + + + Revision committed + Revision eingepflegt + + + + The revision was successfully committed, however since there is no update command available over automate yet, your workspace cannot be updated automatically. +You need to do this by hand or check out the new revision: + +%1 + +In any case close the current view to avoid committing the same revision again. + Die Revision wurde erfolgreich eingepflegt. Da jedoch momentan noch kein "update"-Kommando über die monotone-Schnittstelle verfügbar ist, konnte Ihr Arbeitsbereich nicht automatisch aktualisiert werden. +Sie müssen dies entweder per Hand erledigen oder die neue Revision auschecken: + +%1 + +In jedem Fall sollte der derzeitige Arbeitsbereich geschlossen werden, um zu verhindern, diesselbe Revision ein weiteres Mal einzupflegen. + + + + Please enter the name of an alternative branch. + Bitte geben Sie den Namen eines alternativen Zweigs an. + ContentDiff @@ -507,13 +579,18 @@ Exporting files... - Exportiere Dateien... + Exportiere Dateien... - + Abort Abbrechen + + + Processing files... + Bearbeite Dateien... + GenerateKeypair @@ -645,47 +722,47 @@ Status - + Rename Source Quelle für Umbenennen - + Rename Target Ziel für Umbenennen - + Added hinzugefügt - + Dropped entfernt - + Missing fehlend - + Unchanged unverändert - + Unknown unbekannt - + Ignored ignoriert - + Modified verändert @@ -695,12 +772,12 @@ Zusätzliche Informationen - + new name: %1 neuer Name: %1 - + old name: %1 alter Name: %1 @@ -1604,7 +1681,7 @@ monotone gab zurück: MonotoneDelegate - + [unknown branch] [unbekannter Zweig] @@ -1783,7 +1860,7 @@ value "%3" '%1' to '%2' for %3 - '%1' nach '%2' für %3 + '%1' auf '%2' für %3 @@ -1843,7 +1920,7 @@ value "%3" RevisionManifest - + Error Fehler @@ -1853,7 +1930,7 @@ value "%3" Kann keine Dateien auf Ihrer Plattform öffnen - bitte kontaktieren Sie den Autor über dieses Problem. - + Information Information @@ -1878,17 +1955,17 @@ value "%3" Alle speichern - + Select your export directory... Wählen Sie Ihr Exportverzeichnis... - + The file export was aborted - please look in the log for more details. Der Dateiexport wurde abgebrochen - im Log finden Sie weitere Details. - + Please select one or more files you want to save locally. Bitte wählen Sie eine oder mehrere Dateien, die Sie lokal speichern möchten. @@ -2125,4 +2202,17 @@ value "%3" Für Ihre Auswahl wurden mehrere Revisionen gefunden. Bitte wählen Sie eine. + + WorkspaceCreator + + + Select a branch + Wählen Sie einen Zweig + + + + The selected revision has more than one branch cert attached - please select one: + Die ausgewählte Revision besitzt mehr als ein Zweigzertifikat - bitte wählen Sie eins: + + ============================================================ --- guitone/src/monotone/FileExporter.cpp ea8fcb16287034dcd019a9f25cbb79c97130d507 +++ guitone/src/monotone/FileExporter.cpp f16b44b3a580b963fc66c1407b7a7203b1dc4c40 @@ -64,7 +64,7 @@ bool FileExporter::run(const FileEntryLi if (cleanup) { - qDebug("FileExporter::run: TODO: clean up written files"); + D("TODO: clean up written files"); } return success; } @@ -75,7 +75,7 @@ bool FileExporter::exportFile(const File { if (!rootDir.mkpath(entry.first)) { - C("FileExporter::exportFile: cannot create directory"); + C("Cannot create directory"); return false; } return true; @@ -89,7 +89,7 @@ bool FileExporter::exportFile(const File QStringList() << "r" << revision, commandNumber) || mtn->getReturnCode(commandNumber) > 0) { - C("FileExporter::exportFile: cannot execute get_file_of"); + C("Cannot execute get_file_of"); return false; } @@ -98,7 +98,7 @@ bool FileExporter::exportFile(const File if (!file.open(QIODevice::WriteOnly)) { - C("FileExporter::exportFile: can't open file for writing"); + C("Can't open file for writing"); return false; } ============================================================ --- guitone/src/monotone/Monotone.cpp eecfb2cd2d994160207be138cce8dbfcc1a2fd97 +++ guitone/src/monotone/Monotone.cpp 41d1cd952e4a3799fb8795dfe1f4e49204dca519 @@ -89,8 +89,8 @@ // - if not, we additionally check the interface version in case the user // compiled his own version with all needed commands // -const QString Monotone::RequiredProgramVersion = "0.32"; -const QString Monotone::RequiredInterfaceVersion = "4.0"; +const QString Monotone::RequiredProgramVersion = "0.34"; +const QString Monotone::RequiredInterfaceVersion = "4.1"; const int Monotone::StdioBufferSize = 50 * 1024 * 1024; const int Monotone::WaitForMonotoneStart = 15000; // milliseconds @@ -356,12 +356,25 @@ bool Monotone::executeCommand(const QStr bool Monotone::executeCommand(const QStringList & command, int & commandNumber) { - QStringList opts; - return executeCommand(command, opts, commandNumber); + return executeCommand(command, QStringList(), commandNumber); } +bool Monotone::executeCommand(const ByteArrayList & command, int & commandNumber) +{ + return executeCommand(command, ByteArrayList(), commandNumber); +} + bool Monotone::executeCommand(const QStringList & command, const QStringList & options, int & commandNumber) { + return executeCommand( + stringToByteArrayList(command), + stringToByteArrayList(options), + commandNumber + ); +} + +bool Monotone::executeCommand(const ByteArrayList & command, const ByteArrayList & options, int & commandNumber) +{ if (doAbortRequests || process->state() != QProcess::Running) { D("monotone is not running"); @@ -385,8 +398,22 @@ bool Monotone::triggerCommand(const QStr return triggerCommand(command, QStringList(), commandNumber); } +bool Monotone::triggerCommand(const ByteArrayList & command, int & commandNumber) +{ + return triggerCommand(command, ByteArrayList(), commandNumber); +} + bool Monotone::triggerCommand(const QStringList & command, const QStringList & options, int & commandNumber) { + return triggerCommand( + stringToByteArrayList(command), + stringToByteArrayList(options), + commandNumber + ); +} + +bool Monotone::triggerCommand(const ByteArrayList & command, const ByteArrayList & options, int & commandNumber) +{ if (doAbortRequests || process->state() != QProcess::Running) { D("monotone is not running"); @@ -397,16 +424,17 @@ bool Monotone::triggerCommand(const QStr return true; } -int Monotone::writeStdin(const QStringList & command, const QStringList & options) +int Monotone::writeStdin(const ByteArrayList & command, const ByteArrayList & options) { - QString commandLine = ""; + QByteArray commandLine; + QTextStream streamCmdLine(&commandLine); if (options.size() > 0) { // currently mtn can only understand key => value option pairs Q_ASSERT(options.size() % 2 == 0); - commandLine += "o"; + streamCmdLine << "o"; for (int i=0, c=options.size(); i 0); - commandLine += "l"; + streamCmdLine << "l"; for (int i=0, c=command.size(); i #include #include @@ -36,6 +38,7 @@ class Monotone : public QObject static bool checkInterfaceVersion(const QString &); static QString stripMtnPrefix(const QString &); static int versionCompare(const QString &, const QString &); + static ByteArrayList stringToByteArrayList(const QStringList &); static const QString RequiredProgramVersion; static const QString RequiredInterfaceVersion; static const int StdioBufferSize; @@ -52,10 +55,14 @@ class Monotone : public QObject QString getStderr(); bool triggerCommand(const QStringList &, int &); + bool triggerCommand(const ByteArrayList &, int &); bool triggerCommand(const QStringList &, const QStringList &, int &); + bool triggerCommand(const ByteArrayList &, const ByteArrayList &, int &); bool executeCommand(const QStringList &, int &); + bool executeCommand(const ByteArrayList &, int &); bool executeCommand(const QStringList &, const QStringList &, int &); + bool executeCommand(const ByteArrayList &, const ByteArrayList &, int &); QString getDecodedData(int); QByteArray getRawData(int); @@ -69,7 +76,7 @@ class Monotone : public QObject bool setupNewCommand(); bool setupNewProcess(); void shutdownCurrentProcess(); - int writeStdin(const QStringList &, const QStringList &); + int writeStdin(const ByteArrayList &, const ByteArrayList &); void timerEvent(QTimerEvent *); QByteArray input; ============================================================ --- guitone/src/monotone/MonotoneDelegate.cpp e0957447664f2171062462577580c793b04ddb62 +++ guitone/src/monotone/MonotoneDelegate.cpp 84dbd3a0dff4a0ffddf39e6a7e25d1735d3b5f14 @@ -125,13 +125,13 @@ QString MonotoneDelegate::getOption(QObj return data; } -QString MonotoneDelegate::getBranchName(QObject * obj) +QString MonotoneDelegate::getBranchName(QObject * obj, const QString & defaultBranch) { QString branchName = getOption(obj, "branch"); if (branchName.size() == 0) { - branchName = QString(tr("[unknown branch]")); + branchName = defaultBranch; } return branchName; } @@ -280,3 +280,48 @@ FileEntryList MonotoneDelegate::getRevis return entries; } +QStringList MonotoneDelegate::getPrivateKeyList(QObject * obj) +{ + Monotone * mtn = MTN(obj); + + int cmdNum; + mtn->executeCommand(QStringList() << "keys", cmdNum); + + QString data = mtn->getDecodedData(cmdNum); + QStringList keys; + + if (mtn->getReturnCode(cmdNum) > 0) + { + qCritical("Couldn't query keys: %s", qPrintable(data)); + return keys; + } + + BasicIOParser parser(data); + if (!parser.parse()) + { + qCritical("Could not parse basic_io."); + return keys; + } + + StanzaList stanzas = parser.getStanzas(); + foreach (Stanza st, stanzas) + { + QString lastKey; + foreach (StanzaEntry en, st) + { + if (en.sym == "name") + { + lastKey = en.vals.at(0); + continue; + } + + if (en.sym == "private_location") + { + Q_ASSERT(!lastKey.isEmpty()); + keys.append(lastKey); + break; + } + } + } + return keys; +} ============================================================ --- guitone/src/monotone/MonotoneDelegate.h 47d291e3613ebb60a71c68499a0659fedd37cbb0 +++ guitone/src/monotone/MonotoneDelegate.h 907a718c030f96ed3c2951e5b5b1442b72b6891a @@ -39,12 +39,13 @@ public: static QString getBaseWorkspaceRevision(QObject *); static QString getOption(QObject *, const QString &); - static QString getBranchName(QObject *); + static QString getBranchName(QObject *, const QString & defaultBranch = tr("[unknown branch]")); static QString getBranchNameShort(QObject *); static QStringList resolveSelector(QObject *, const QString &); static RevisionCerts getRevisionCerts(QObject *, const QString &); static QString getDatabaseFilePath(QObject *); static FileEntryList getRevisionManifest(QObject *, const QString &); + static QStringList getPrivateKeyList(QObject *); private: AutomateCommand * cmdModel; ============================================================ --- guitone/src/monotone/WorkspaceCreator.cpp 1c21599fe53b44512ca412e8e50ce99ea3439359 +++ guitone/src/monotone/WorkspaceCreator.cpp ff6dd8f1e13381614edd6a7ee6d8f453d0c1566b @@ -50,7 +50,7 @@ bool WorkspaceCreator::run() if (branches.size() == 0) { // TODO: shall we ask the user here for a new branch name? - C(QString("revision '%1' has no branch cert attached").arg(revision)); + C(QString("Revision '%1' has no branch cert attached").arg(revision)); return false; } @@ -83,7 +83,7 @@ bool WorkspaceCreator::run() // if (!rootDir.mkdir("_MTN")) { - C("WorkspaceCreator::run: cannot create directory"); + C("Cannot create directory"); return false; } @@ -93,7 +93,7 @@ bool WorkspaceCreator::run() QFile revfile(rootDir.filePath("revision")); if (!revfile.open(QIODevice::WriteOnly)) { - C("WorkspaceCreator::run: can't open revision for writing"); + C("Can't open revision for writing"); return false; } QString rev = QString("format_version \"1\"\n\n" @@ -106,7 +106,7 @@ bool WorkspaceCreator::run() QFile verfile(rootDir.filePath("version")); if (!revfile.open(QIODevice::WriteOnly)) { - C("WorkspaceCreator::run: can't open version for writing"); + C("Can't open version for writing"); return false; } Q_ASSERT(verfile.write(QString("2\n").toLatin1())); @@ -116,7 +116,7 @@ bool WorkspaceCreator::run() QFile logfile(rootDir.filePath("log")); if (!logfile.open(QIODevice::WriteOnly)) { - C("WorkspaceCreator::run: can't open log for writing"); + C("Can't open log for writing"); return false; } logfile.close(); @@ -125,7 +125,7 @@ bool WorkspaceCreator::run() QFile optfile(rootDir.filePath("options")); if (!optfile.open(QIODevice::WriteOnly)) { - C("WorkspaceCreator::run: can't open revision for writing"); + C("Can't open revision for writing"); return false; } // the keydir entry is not needed and automatically added to the ============================================================ --- guitone/src/view/dialogs/CommitRevision.cpp e796042390241526ff2848e24f0bebd8b432dc9c +++ guitone/src/view/dialogs/CommitRevision.cpp ffe771b0f74202063686e3d30bcff6f6b9d0636a @@ -22,10 +22,12 @@ #include "Monotone.h" #include "Settings.h" #include "Guitone.h" +#include "WorkspaceCommitter.h" #include #include #include +#include CommitRevision::CommitRevision(QWidget* parent) : Dialog(parent) { @@ -57,11 +59,6 @@ CommitRevision::CommitRevision(QWidget* ); connect( - invertSelection, SIGNAL(clicked()), - this, SLOT(invertChangesetSelection()) - ); - - connect( previousChangelogEntryList, SIGNAL(currentIndexChanged(int)), this, SLOT(setChangelogEntryFromList(int)) ); @@ -89,25 +86,112 @@ void CommitRevision::accept() void CommitRevision::accept() { - qDebug("CommitRevision::accept: do actual commit"); Settings::addItemToList("ChangelogEntries", changelogEntry->toPlainText(), 10); - done(0); -} - -void CommitRevision::invertChangesetSelection() -{ - QItemSelectionModel * selectionModel = changeView->selectionModel(); - QModelIndex parent; - QModelIndex topLeft = revModel->index(0, 0, parent); - QModelIndex bottomRight = revModel->index( - revModel->rowCount(parent)-1, - revModel->columnCount(parent)-1, - parent + QString branch = MonotoneDelegate::getBranchName(this, QString()); + + if (branch.isEmpty() && !checkAltBranch->isChecked()) + { + QMessageBox::critical( + this, + tr("Workspace has no branch set"), + tr("The workspace has no branch set. Please enter one."), + QMessageBox::Ok + ); + checkAltBranch->setChecked(true); + return; + } + + if (checkAltBranch->isChecked()) + { + QString altBranchStr = altBranch->text().trimmed(); + if (altBranchStr.isEmpty()) + { + QMessageBox::critical( + this, + tr("No branch specified"), + tr("Please enter the name of an alternative branch."), + QMessageBox::Ok + ); + return; + } + branch = altBranchStr; + } + + QString author; + + if (checkAltAuthor->isChecked()) + { + QString altAuthorStr = altAuthor->text().trimmed(); + if (altAuthorStr.isEmpty()) + { + QMessageBox::critical( + this, + tr("No author specified"), + tr("Please enter the name of an alternative author."), + QMessageBox::Ok + ); + return; + } + author = altAuthorStr; + } + + QStringList keys = MonotoneDelegate::getPrivateKeyList(this); + + if (keys.size() == 0) + { + QMessageBox::critical( + this, + tr("No private key found"), + tr("There are no private keys available with which to sign your " + "commit. Please go to Database > Key Management and create a " + "new private key first."), + QMessageBox::Ok + ); + return; + } + + QString selectedKey = keys.at(0); + + if (keys.size() > 1) + { + bool ok; + QString key = QInputDialog::getItem( + this, tr("Please select a key"), + tr("More than one private key is available.\n" + "Please select the key with which you like to sign this commit:"), + keys, 0, false, &ok); + if (key.isEmpty() || !ok) + { + return; + } + selectedKey = key; + } + + WorkspaceCommitter committer( + this, selectedKey, branch, author, changelogEntry->toPlainText() ); - QItemSelection selection(topLeft, bottomRight); - selectionModel->select(selection, QItemSelectionModel::Toggle); + if (!committer.run()) + { + C("Could not commit revision."); + return; + } + + QMessageBox::information( + this, + tr("Revision committed"), + tr("The revision was successfully committed, however " + "since there is no update command available over automate yet, " + "your workspace cannot be updated automatically.\n" + "You need to do this by hand or check out the new revision:\n\n" + "\t%1\n\n" + "In any case close the current view to avoid committing the " + "same revision again.").arg(committer.getRevisionId()), + QMessageBox::Ok + ); + + done(0); } void CommitRevision::revisionRead() ============================================================ --- guitone/src/view/dialogs/CommitRevision.h 7d02ef0a24613fc88485823db77d5a9cfdbc6b35 +++ guitone/src/view/dialogs/CommitRevision.h 82f533b5b65f320a31dd7c1e728d72564b3f2915 @@ -37,7 +37,6 @@ private slots: GetRevision * revModel; private slots: - void invertChangesetSelection(); void setChangelogEntryFromList(int); void revisionRead(); void accept(); ============================================================ --- guitone/src/vocab.h f8c1dd7d5d3deb6b9d48666a335764a282432e06 +++ guitone/src/vocab.h 9badd48e5b9420e8fb663d32e93bab8bc751a93d @@ -9,4 +9,7 @@ typedef QList RevisionCert typedef QPair RevisionCert; typedef QList RevisionCerts; + +typedef QList ByteArrayList; + #endif