# # # patch "res/forms/preferences.ui" # from [c9f2e477b8119f70eda6fcc2f8bcfb3fae7f53a9] # to [a9a465be6c538be9e4fbba44725483c44243f4c5] # # patch "src/model/ContentDiff.cpp" # from [fba40b0f3894f67596c8ea99293ab78212535b53] # to [d5f9c1f13e38f6aee86944e9a30cc70ed4aa07dd] # # patch "src/monotone/MonotoneUtil.cpp" # from [c18789f0f92cceb714cca6b981e50ab2437ea9ff] # to [1e21ab79a5d485224d25e9764623c5011840cc8e] # # patch "src/monotone/MonotoneUtil.h" # from [2859545454f0987d0bb5141a06a1f34667a9dc51] # to [13e7aebbd695979af145534728db918ab6effa2c] # # patch "src/view/dialogs/Preferences.cpp" # from [211cc5978c8f41c19d41165fe4e56951043989cf] # to [965a695baebe0fe9f6c4330e90b657cacc772145] # ============================================================ --- res/forms/preferences.ui c9f2e477b8119f70eda6fcc2f8bcfb3fae7f53a9 +++ res/forms/preferences.ui a9a465be6c538be9e4fbba44725483c44243f4c5 @@ -294,6 +294,19 @@ + + + This option effectively disables the generation of reverse diffs. + + + fix parent-child selection for diff views + + + true + + + + save encoding preference as file attribute ============================================================ --- src/model/ContentDiff.cpp fba40b0f3894f67596c8ea99293ab78212535b53 +++ src/model/ContentDiff.cpp d5f9c1f13e38f6aee86944e9a30cc70ed4aa07dd @@ -53,8 +53,21 @@ void ContentDiff::readDatabaseDiff(const cmd << fileName; } + QStringList revs; + revs << base << target; + // sort base and target topologically in case the user accidently chosed + // the child as base and the parent as target (and would therefor get a + // reverse diff) + if (Settings::getBool("FixUnwantedReverseDiffs", true)) + { + revs = MonotoneUtil::topsortRevisions(db, revs); + } + QStringList opts; - opts << "r" << base << "r" << target; + foreach (QString r, revs) + { + opts << "r" << r; + } MonotoneTask task(cmd, opts); @@ -78,17 +91,30 @@ void ContentDiff::readWorkspaceDiff(cons cmd << fileName; } - QStringList opts; + QStringList revs; if (!base.isEmpty()) { - opts << "r" << base; + revs << base; } + if (!target.isEmpty()) + { + revs << target; + } - if (!target.isEmpty()) + // sort base and target topologically in case the user accidently chosed + // the child as base and the parent as target (and would therefor get a + // reverse diff) + if (revs.size() == 2 && Settings::getBool("FixUnwantedReverseDiffs", true)) { - opts << "r" << target; + revs = MonotoneUtil::topsortRevisions(MonotoneUtil::getDatabaseFile(ws), revs); } + QStringList opts; + foreach (QString r, revs) + { + opts << "r" << r; + } + MonotoneTask task(cmd, opts); if (!encoding.isEmpty()) ============================================================ --- src/monotone/MonotoneUtil.cpp c18789f0f92cceb714cca6b981e50ab2437ea9ff +++ src/monotone/MonotoneUtil.cpp 1e21ab79a5d485224d25e9764623c5011840cc8e @@ -94,6 +94,7 @@ QString MonotoneUtil::getBaseWorkspaceRe return QString(); } + data.chop(1); // we cannot handle workspaces with multiple parents yet @@ -349,6 +350,26 @@ QString MonotoneUtil::getFileId(const Da return data; } +QStringList MonotoneUtil::topsortRevisions(const DatabaseFile & db, const QStringList & revs) +{ + QStringList args; + args << "toposort"; + args += revs; + MonotoneTask in(args); + MonotoneTask out = runSynchronousDatabaseTask(db, in); + if (!out.isFinished()) F("task aborted"); + + QString data = out.getDecodedOutput(); + if (out.getReturnCode() > 0) + { + C(QString("Couldn't toposort revisions: %1").arg(data)); + // return the list unchanged + return revs; + } + + return data.split("\n", QString::SkipEmptyParts); +} + bool MonotoneUtil::getAttribute(const WorkspacePath & ws, const QString & path, const QString & attrname, QPair & attrval) { ============================================================ --- src/monotone/MonotoneUtil.h 2859545454f0987d0bb5141a06a1f34667a9dc51 +++ src/monotone/MonotoneUtil.h 13e7aebbd695979af145534728db918ab6effa2c @@ -40,6 +40,7 @@ public: static FileEntryList getRevisionManifest(const DatabaseFile &, const QString &); static QStringList getPrivateKeyList(const DatabaseFile &); static QString getFileId(const DatabaseFile &, const QString &); + static QStringList topsortRevisions(const DatabaseFile &, const QStringList &); static bool getAttribute(const WorkspacePath &, const QString &, const QString &, QPair &); static bool getAttribute(const DatabaseFile &, const QString &, const QString &, const QString &, QString &); ============================================================ --- src/view/dialogs/Preferences.cpp 211cc5978c8f41c19d41165fe4e56951043989cf +++ src/view/dialogs/Preferences.cpp 965a695baebe0fe9f6c4330e90b657cacc772145 @@ -100,6 +100,11 @@ void Preferences::init() Qt::Checked : Qt::Unchecked ); + fixUnwantedReverseDiffs->setCheckState( + Settings::getBool("FixUnwantedReverseDiffs", true) ? + Qt::Checked : Qt::Unchecked + ); + saveEncodingAsFileAttribute->setCheckState( Settings::getBool("SaveEncodingAsFileAttribute", true) ? Qt::Checked : Qt::Unchecked @@ -186,6 +191,7 @@ void Preferences::accept() Settings::setBool("CheckForUpdates", checkForUpdates->isChecked()); Settings::setBool("SaveEncodingAsFileAttribute", saveEncodingAsFileAttribute->isChecked()); + Settings::setBool("FixUnwantedReverseDiffs", fixUnwantedReverseDiffs->isChecked()); Settings::setBool("RelaxedVersionCheck", relaxedVersionCheck->isChecked()); Settings::setBool("AskFileOpen", askFileOpen->isChecked()); Settings::setString("AskFileOpenExt", askFileOpenExtensions->text());