Lock down the version cache. Just enough to make it annoying to corrupt the files.

This commit is contained in:
Petr Mrázek 2014-05-13 23:57:34 +02:00
parent f3900f2966
commit 55a0d110b6
8 changed files with 99 additions and 46 deletions

View File

@ -50,6 +50,7 @@
#include "CustomMessageBox.h" #include "CustomMessageBox.h"
#include <QDesktopServices> #include <QDesktopServices>
#include <QMessageBox> #include <QMessageBox>
#include <QListView>
#include <QString> #include <QString>
#include <QUrl> #include <QUrl>
@ -171,6 +172,26 @@ void InstanceEditDialog::on_removeLibraryBtn_clicked()
} }
} }
void InstanceEditDialog::on_jarmodBtn_clicked()
{
QFileDialog w;
w.setFileMode(QFileDialog::AnyFile);
// w.setOption(QFileDialog::DontUseNativeDialog, true);
QListView *l = w.findChild<QListView *>("listView");
if (l)
{
l->setSelectionMode(QAbstractItemView::ExtendedSelection);
}
QTreeView *t = w.findChild<QTreeView *>();
if (t)
{
t->setSelectionMode(QAbstractItemView::ExtendedSelection);
}
int result = w.exec();
auto list = w.selectedFiles();
QLOG_INFO() << list.join(" ");
}
void InstanceEditDialog::on_resetLibraryOrderBtn_clicked() void InstanceEditDialog::on_resetLibraryOrderBtn_clicked()
{ {
try try
@ -192,8 +213,10 @@ void InstanceEditDialog::on_moveLibraryUpBtn_clicked()
try try
{ {
const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row(); const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row();
const int newRow = 0;m_version->move(row, VersionFinal::MoveUp); const int newRow = 0;
//ui->libraryTreeView->selectionModel()->setCurrentIndex(m_version->index(newRow), QItemSelectionModel::ClearAndSelect); m_version->move(row, VersionFinal::MoveUp);
// ui->libraryTreeView->selectionModel()->setCurrentIndex(m_version->index(newRow),
// QItemSelectionModel::ClearAndSelect);
} }
catch (MMCError &e) catch (MMCError &e)
{ {
@ -210,8 +233,10 @@ void InstanceEditDialog::on_moveLibraryDownBtn_clicked()
try try
{ {
const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row(); const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row();
const int newRow = 0;m_version->move(row, VersionFinal::MoveDown); const int newRow = 0;
//ui->libraryTreeView->selectionModel()->setCurrentIndex(m_version->index(newRow), QItemSelectionModel::ClearAndSelect); m_version->move(row, VersionFinal::MoveDown);
// ui->libraryTreeView->selectionModel()->setCurrentIndex(m_version->index(newRow),
// QItemSelectionModel::ClearAndSelect);
} }
catch (MMCError &e) catch (MMCError &e)
{ {
@ -221,7 +246,8 @@ void InstanceEditDialog::on_moveLibraryDownBtn_clicked()
void InstanceEditDialog::on_changeMCVersionBtn_clicked() void InstanceEditDialog::on_changeMCVersionBtn_clicked()
{ {
VersionSelectDialog vselect(m_inst->versionList().get(), tr("Change Minecraft version"), this); VersionSelectDialog vselect(m_inst->versionList().get(), tr("Change Minecraft version"),
this);
if (!vselect.exec() || !vselect.selectedVersion()) if (!vselect.exec() || !vselect.selectedVersion())
return; return;
@ -266,7 +292,8 @@ void InstanceEditDialog::on_forgeBtn_clicked()
// FIXME: use actual model, not reloading. Move logic to model. // FIXME: use actual model, not reloading. Move logic to model.
if (m_version->hasFtbPack()) if (m_version->hasFtbPack())
{ {
if (QMessageBox::question(this, tr("Revert?"), if (QMessageBox::question(
this, tr("Revert?"),
tr("This action will remove the FTB pack version patch. Continue?")) != tr("This action will remove the FTB pack version patch. Continue?")) !=
QMessageBox::Yes) QMessageBox::Yes)
{ {
@ -293,7 +320,8 @@ void InstanceEditDialog::on_forgeBtn_clicked()
if (vselect.exec() && vselect.selectedVersion()) if (vselect.exec() && vselect.selectedVersion())
{ {
ProgressDialog dialog(this); ProgressDialog dialog(this);
dialog.exec(ForgeInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this)); dialog.exec(
ForgeInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this));
} }
} }
@ -301,7 +329,8 @@ void InstanceEditDialog::on_liteloaderBtn_clicked()
{ {
if (m_version->hasFtbPack()) if (m_version->hasFtbPack())
{ {
if (QMessageBox::question(this, tr("Revert?"), if (QMessageBox::question(
this, tr("Revert?"),
tr("This action will remove the FTB pack version patch. Continue?")) != tr("This action will remove the FTB pack version patch. Continue?")) !=
QMessageBox::Yes) QMessageBox::Yes)
{ {
@ -329,7 +358,8 @@ void InstanceEditDialog::on_liteloaderBtn_clicked()
if (vselect.exec() && vselect.selectedVersion()) if (vselect.exec() && vselect.selectedVersion())
{ {
ProgressDialog dialog(this); ProgressDialog dialog(this);
dialog.exec(LiteLoaderInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this)); dialog.exec(
LiteLoaderInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this));
} }
} }
@ -497,8 +527,7 @@ void InstanceEditDialog::loaderCurrent(QModelIndex current, QModelIndex previous
ui->frame->updateWithMod(m); ui->frame->updateWithMod(m);
} }
void InstanceEditDialog::versionCurrent(const QModelIndex &current, void InstanceEditDialog::versionCurrent(const QModelIndex &current, const QModelIndex &previous)
const QModelIndex &previous)
{ {
if (!current.isValid()) if (!current.isValid())
{ {

View File

@ -44,6 +44,7 @@ slots:
void on_resetLibraryOrderBtn_clicked(); void on_resetLibraryOrderBtn_clicked();
void on_moveLibraryUpBtn_clicked(); void on_moveLibraryUpBtn_clicked();
void on_moveLibraryDownBtn_clicked(); void on_moveLibraryDownBtn_clicked();
void on_jarmodBtn_clicked();
// loader mod tab // loader mod tab
void on_addModBtn_clicked(); void on_addModBtn_clicked();

View File

@ -24,6 +24,7 @@
#include "logic/OneSixInstance_p.h" #include "logic/OneSixInstance_p.h"
#include "logic/OneSixUpdate.h" #include "logic/OneSixUpdate.h"
#include "logic/minecraft/VersionFinal.h" #include "logic/minecraft/VersionFinal.h"
#include "minecraft/VersionBuildError.h"
#include "logic/assets/AssetsUtils.h" #include "logic/assets/AssetsUtils.h"
#include "icons/IconList.h" #include "icons/IconList.h"
@ -42,21 +43,13 @@ OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings,
void OneSixInstance::init() void OneSixInstance::init()
{ {
// FIXME: why is this decided here? what does this even mean?
if (QDir(instanceRoot()).exists("version.json"))
{
try try
{ {
reloadVersion(); reloadVersion();
} }
catch (MMCError &e) catch (MMCError &e)
{ {
// QLOG_ERROR() << "Caught exception on instance init: " << e.cause(); QLOG_ERROR() << "Caught exception on instance init: " << e.cause();
}
}
else
{
clearVersion();
} }
} }
@ -388,6 +381,10 @@ void OneSixInstance::reloadVersion()
d->version->reload(externalPatches()); d->version->reload(externalPatches());
d->m_flags.remove(VersionBrokenFlag); d->m_flags.remove(VersionBrokenFlag);
emit versionReloaded(); emit versionReloaded();
}
catch (VersionIncomplete & error)
{
} }
catch (MMCError &error) catch (MMCError &error)
{ {

View File

@ -56,9 +56,9 @@ bool MinecraftVersion::isMinecraftVersion()
// 2. if discrepancies are found, fall out and fail (impossible to apply incomplete version). // 2. if discrepancies are found, fall out and fail (impossible to apply incomplete version).
void MinecraftVersion::applyFileTo(VersionFinal *version) void MinecraftVersion::applyFileTo(VersionFinal *version)
{ {
QFileInfo versionFile(QString("versions/%1/%1.json").arg(m_descriptor)); QFileInfo versionFile(QString("versions/%1/%1.dat").arg(m_descriptor));
auto versionObj = VersionBuilder::parseJsonFile(versionFile, false, false); auto versionObj = VersionBuilder::parseBinaryJsonFile(versionFile);
versionObj->applyTo(version); versionObj->applyTo(version);
} }

View File

@ -29,6 +29,8 @@
#include <logic/VersionFilterData.h> #include <logic/VersionFilterData.h>
#include <pathutils.h> #include <pathutils.h>
static const char * localVersionCache = "versions/versions.dat";
class ListLoadError : public MMCError class ListLoadError : public MMCError
{ {
public: public:
@ -78,7 +80,7 @@ void MinecraftVersionList::sortInternal()
void MinecraftVersionList::loadCachedList() void MinecraftVersionList::loadCachedList()
{ {
QFile localIndex("versions/versions.json"); QFile localIndex(localVersionCache);
if (!localIndex.exists()) if (!localIndex.exists())
{ {
return; return;
@ -92,13 +94,18 @@ void MinecraftVersionList::loadCachedList()
auto data = localIndex.readAll(); auto data = localIndex.readAll();
try try
{ {
loadMojangList(data, Local); localIndex.close();
QJsonDocument jsonDoc = QJsonDocument::fromBinaryData(data);
if (jsonDoc.isNull())
{
throw ListLoadError(tr("Error reading the version list."));
}
loadMojangList(jsonDoc, Local);
} }
catch (MMCError &e) catch (MMCError &e)
{ {
// the cache has gone bad for some reason... flush it. // the cache has gone bad for some reason... flush it.
QLOG_ERROR() << "The minecraft version cache is corrupted. Flushing cache."; QLOG_ERROR() << "The minecraft version cache is corrupted. Flushing cache.";
localIndex.close();
localIndex.remove(); localIndex.remove();
return; return;
} }
@ -172,17 +179,9 @@ void MinecraftVersionList::loadBuiltinList()
} }
} }
void MinecraftVersionList::loadMojangList(QByteArray data, VersionSource source) void MinecraftVersionList::loadMojangList(QJsonDocument jsonDoc, VersionSource source)
{ {
QLOG_INFO() << "Loading" << ((source == Remote) ? "remote" : "local") << "version list."; QLOG_INFO() << "Loading" << ((source == Remote) ? "remote" : "local") << "version list.";
QJsonParseError jsonError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
if (jsonError.error != QJsonParseError::NoError)
{
throw ListLoadError(
tr("Error parsing version list JSON: %1").arg(jsonError.errorString()));
}
if (!jsonDoc.isObject()) if (!jsonDoc.isObject())
{ {
@ -391,7 +390,14 @@ void MCVListLoadTask::list_downloaded()
vlistReply->deleteLater(); vlistReply->deleteLater();
try try
{ {
m_list->loadMojangList(data, Remote); QJsonParseError jsonError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
if (jsonError.error != QJsonParseError::NoError)
{
throw ListLoadError(
tr("Error parsing version list JSON: %1").arg(jsonError.errorString()));
}
m_list->loadMojangList(jsonDoc, Remote);
} }
catch (MMCError &e) catch (MMCError &e)
{ {
@ -474,9 +480,9 @@ void MCVListVersionUpdateTask::json_downloaded()
// now dump the file to disk // now dump the file to disk
auto doc = file->toJson(false); auto doc = file->toJson(false);
auto newdata = doc.toJson(); auto newdata = doc.toBinaryData();
QLOG_INFO() << newdata; QLOG_INFO() << newdata;
QString targetPath = "versions/" + versionToUpdate + "/" + versionToUpdate + ".json"; QString targetPath = "versions/" + versionToUpdate + "/" + versionToUpdate + ".dat";
ensureFilePathExists(targetPath); ensureFilePathExists(targetPath);
QSaveFile vfile1(targetPath); QSaveFile vfile1(targetPath);
if (!vfile1.open(QIODevice::Truncate | QIODevice::WriteOnly)) if (!vfile1.open(QIODevice::Truncate | QIODevice::WriteOnly))
@ -511,9 +517,9 @@ std::shared_ptr<Task> MinecraftVersionList::createUpdateTask(QString version)
void MinecraftVersionList::saveCachedList() void MinecraftVersionList::saveCachedList()
{ {
// FIXME: throw. // FIXME: throw.
if (!ensureFilePathExists("versions/versions.json")) if (!ensureFilePathExists(localVersionCache))
return; return;
QSaveFile tfile("versions/versions.json"); QSaveFile tfile(localVersionCache);
if (!tfile.open(QIODevice::WriteOnly | QIODevice::Truncate)) if (!tfile.open(QIODevice::WriteOnly | QIODevice::Truncate))
return; return;
QJsonObject toplevel; QJsonObject toplevel;
@ -554,7 +560,7 @@ void MinecraftVersionList::saveCachedList()
} }
QJsonDocument doc(toplevel); QJsonDocument doc(toplevel);
QByteArray jsonData = doc.toJson(); QByteArray jsonData = doc.toBinaryData();
qint64 result = tfile.write(jsonData); qint64 result = tfile.write(jsonData);
if (result == -1) if (result == -1)
return; return;

View File

@ -34,7 +34,7 @@ class MinecraftVersionList : public BaseVersionList
private: private:
void sortInternal(); void sortInternal();
void loadBuiltinList(); void loadBuiltinList();
void loadMojangList(QByteArray data, VersionSource source); void loadMojangList(QJsonDocument jsonDoc, VersionSource source);
void loadCachedList(); void loadCachedList();
void saveCachedList(); void saveCachedList();
void finalizeUpdate(QString version); void finalizeUpdate(QString version);

View File

@ -237,6 +237,25 @@ VersionFilePtr VersionBuilder::parseJsonFile(const QFileInfo &fileInfo, const bo
// info.").arg(file.fileName()); // info.").arg(file.fileName());
} }
VersionFilePtr VersionBuilder::parseBinaryJsonFile(const QFileInfo &fileInfo)
{
QFile file(fileInfo.absoluteFilePath());
if (!file.open(QFile::ReadOnly))
{
throw JSONValidationError(QObject::tr("Unable to open the version file %1: %2.")
.arg(fileInfo.fileName(), file.errorString()));
}
QJsonDocument doc = QJsonDocument::fromBinaryData(file.readAll());
file.close();
if (doc.isNull())
{
file.remove();
throw JSONValidationError(
QObject::tr("Unable to process the version file %1.").arg(fileInfo.fileName()));
}
return VersionFile::fromJson(doc, file.fileName(), false, false);
}
QMap<QString, int> VersionBuilder::readOverrideOrders(OneSixInstance *instance) QMap<QString, int> VersionBuilder::readOverrideOrders(OneSixInstance *instance)
{ {
QMap<QString, int> out; QMap<QString, int> out;

View File

@ -31,6 +31,7 @@ public:
static void build(VersionFinal *version, OneSixInstance *instance, const QStringList &external); static void build(VersionFinal *version, OneSixInstance *instance, const QStringList &external);
static void readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj); static void readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj);
static VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB = false); static VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB = false);
static VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo);
static QMap<QString, int> readOverrideOrders(OneSixInstance *instance); static QMap<QString, int> readOverrideOrders(OneSixInstance *instance);
static bool writeOverrideOrders(const QMap<QString, int> &order, OneSixInstance *instance); static bool writeOverrideOrders(const QMap<QString, int> &order, OneSixInstance *instance);