From d3eb05791747cf9389395e49a85bc493352c4ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Kera=CC=88nen?= Date: Fri, 20 Jan 2017 19:34:32 +0200 Subject: [PATCH] libcore|FS: Keeping track of the version of loaded packages The version is kept in Package for querying later. Both the file name and the metadata are checked. --- .../sdk/libcore/include/de/filesys/package.h | 7 ++++ doomsday/sdk/libcore/src/filesys/package.cpp | 36 +++++++++++++++++-- .../sdk/libcore/src/filesys/packageloader.cpp | 12 +++++-- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/doomsday/sdk/libcore/include/de/filesys/package.h b/doomsday/sdk/libcore/include/de/filesys/package.h index c501c834e3..58a44e6da6 100644 --- a/doomsday/sdk/libcore/include/de/filesys/package.h +++ b/doomsday/sdk/libcore/include/de/filesys/package.h @@ -121,6 +121,12 @@ class DENG2_PUBLIC Package : public IObject */ String identifier() const; + /** + * Version of the loaded package. The version can be specified either in the + * file name (following an underscore) or in the metadata. + */ + Version version() const; + /** * Composes a list of assets contained in the package. * @@ -236,6 +242,7 @@ class DENG2_PUBLIC Package : public IObject static String const VAR_PACKAGE_TITLE; static String const VAR_ID; static String const VAR_TITLE; + static String const VAR_VERSION; private: DENG2_PRIVATE(d) diff --git a/doomsday/sdk/libcore/src/filesys/package.cpp b/doomsday/sdk/libcore/src/filesys/package.cpp index 189893070d..dae8aaf0b6 100644 --- a/doomsday/sdk/libcore/src/filesys/package.cpp +++ b/doomsday/sdk/libcore/src/filesys/package.cpp @@ -27,6 +27,8 @@ #include "de/ScriptedInfo" #include "de/TimeValue" +#include + namespace de { String const Package::VAR_PACKAGE ("package"); @@ -35,6 +37,7 @@ String const Package::VAR_PACKAGE_ALIAS("package.alias"); String const Package::VAR_PACKAGE_TITLE("package.title"); String const Package::VAR_ID ("ID"); String const Package::VAR_TITLE ("title"); +String const Package::VAR_VERSION ("version"); static String const PACKAGE_ORDER ("package.__order__"); static String const PACKAGE_IMPORT_PATH("package.importPath"); @@ -45,6 +48,7 @@ static String const PACKAGE_TAGS ("package.tags"); static String const VAR_ID ("ID"); static String const VAR_PATH("path"); +static String const VAR_TAGS("tags"); Package::Asset::Asset(Record const &rec) : RecordAccessor(rec) {} @@ -66,12 +70,23 @@ DENG2_PIMPL(Package) , DENG2_OBSERVES(File, Deletion) { File const *file; + Version version; // version of the loaded package Impl(Public *i, File const *f) : Base(i) , file(f) { - if (file) file->audienceForDeletion() += this; + if (file) + { + file->audienceForDeletion() += this; + + // Check the file name first, then metadata. + version = split(versionedIdentifierForFile(*file)).second; + if (!version.isValid()) + { + version = Version(metadata(*file).gets(VAR_VERSION, String())); + } + } } void fileBeingDeleted(File const &) @@ -153,9 +168,14 @@ String Package::identifier() const return identifierForFile(*d->file); } +Version Package::version() const +{ + return d->version; +} + Package::Assets Package::assets() const { - return ScriptedInfo::allBlocksOfType("asset", d->packageInfo()); + return ScriptedInfo::allBlocksOfType(QStringLiteral("asset"), d->packageInfo()); } bool Package::executeFunction(String const &name) @@ -309,7 +329,7 @@ void Package::validateMetadata(Record const &packageInfo) .arg(packageInfo.gets("path"))); } - static String const required[] = { "title", "version", "license", "tags" }; + static String const required[] = { "title", "version", "license", VAR_TAGS }; for (auto const &req : required) { if (!packageInfo.has(req)) @@ -320,6 +340,16 @@ void Package::validateMetadata(Record const &packageInfo) .arg(req)); } } + + static QRegularExpression const regexReservedTags("\\b(loaded)\\b"); + auto match = regexReservedTags.match(packageInfo.gets(VAR_TAGS)); + if (match.hasMatch()) + { + throw ValidationError("Package::validateMetadata", + QString("Package \"%1\" has a tag that is reserved for internal use (%2)") + .arg(packageInfo.gets("path")) + .arg(match.captured(1))); + } } Record &Package::initializeMetadata(File &packageFile, String const &id) diff --git a/doomsday/sdk/libcore/src/filesys/packageloader.cpp b/doomsday/sdk/libcore/src/filesys/packageloader.cpp index 6e74a5f442..e967ef921c 100644 --- a/doomsday/sdk/libcore/src/filesys/packageloader.cpp +++ b/doomsday/sdk/libcore/src/filesys/packageloader.cpp @@ -39,7 +39,7 @@ static String const VAR_PACKAGE_VERSION("package.version"); DENG2_PIMPL(PackageLoader) { - LoadedPackages loaded; + LoadedPackages loaded; ///< Identifiers are unversioned; only one version can be loaded at a time. int loadCounter; Impl(Public *i) : Base(i), loadCounter(0) @@ -464,7 +464,15 @@ void PackageLoader::unloadAll() bool PackageLoader::isLoaded(String const &packageId) const { - return d->loaded.contains(packageId); + // Split ID, check version too if specified. + auto const id_ver = Package::split(packageId); + auto found = d->loaded.constFind(id_ver.first); + if (found == d->loaded.constEnd()) + { + return false; + } + return (!id_ver.second.isValid() /* no valid version provided in argumnet */ || + id_ver.second == found.value()->version()); } bool PackageLoader::isLoaded(File const &file) const