GH-967 make libraries handle their own path prefix
Makes it possible to mix libraries managed by FTB and MultiMC Backport from unstable
This commit is contained in:
		| @@ -87,8 +87,8 @@ void ForgeInstaller::prepare(const QString &filename, const QString &universalUr | ||||
| 	// where do we put the library? decode the mojang path | ||||
| 	OneSixLibrary lib(libraryName); | ||||
|  | ||||
| 	auto cacheentry = ENV.metacache()->resolveEntry("libraries", lib.storagePath()); | ||||
| 	finalPath = "libraries/" + lib.storagePath(); | ||||
| 	auto cacheentry = ENV.metacache()->resolveEntry("libraries", lib.storageSuffix()); | ||||
| 	finalPath = "libraries/" + lib.storageSuffix(); | ||||
| 	if (!ensureFilePathExists(finalPath)) | ||||
| 		return; | ||||
|  | ||||
|   | ||||
| @@ -41,6 +41,7 @@ void FTBProfileStrategy::loadDefaultBuiltinPatches() | ||||
| 	} | ||||
| 	profile->appendPatch(minecraftPatch); | ||||
|  | ||||
| 	auto nativeInstance = dynamic_cast<OneSixFTBInstance *>(m_instance); | ||||
| 	ProfilePatchPtr packPatch; | ||||
| 	{ | ||||
| 		auto mcJson = m_instance->minecraftRoot() + "/pack.json"; | ||||
| @@ -58,6 +59,7 @@ void FTBProfileStrategy::loadDefaultBuiltinPatches() | ||||
| 			{ | ||||
| 				addLib->m_hint = "local"; | ||||
| 				addLib->insertType = RawLibrary::Prepend; | ||||
| 				addLib->setStoragePrefix(nativeInstance->librariesPath().absolutePath()); | ||||
| 			} | ||||
| 			file->fileId = "org.multimc.ftb.pack"; | ||||
| 			file->setVanilla(true); | ||||
|   | ||||
| @@ -78,7 +78,7 @@ void OneSixFTBInstance::copy(const QDir &newDir) | ||||
| 		for (auto library : libraryNames) | ||||
| 		{ | ||||
| 			OneSixLibrary *lib = new OneSixLibrary(library); | ||||
| 			const QString out = QDir::current().absoluteFilePath("libraries/" + lib->storagePath()); | ||||
| 			const QString out = QDir::current().absoluteFilePath("libraries/" + lib->storageSuffix()); | ||||
| 			if (QFile::exists(out)) | ||||
| 			{ | ||||
| 				continue; | ||||
| @@ -87,7 +87,7 @@ void OneSixFTBInstance::copy(const QDir &newDir) | ||||
| 			{ | ||||
| 				qCritical() << "Couldn't create folder structure for" << out; | ||||
| 			} | ||||
| 			if (!QFile::copy(librariesPath().absoluteFilePath(lib->storagePath()), out)) | ||||
| 			if (!QFile::copy(librariesPath().absoluteFilePath(lib->storageSuffix()), out)) | ||||
| 			{ | ||||
| 				qCritical() << "Couldn't copy" << lib->rawName(); | ||||
| 			} | ||||
|   | ||||
| @@ -139,7 +139,7 @@ BaseProcess *OneSixInstance::prepareForLaunch(AuthSessionPtr session) | ||||
| 		auto libs = m_version->getActiveNormalLibs(); | ||||
| 		for (auto lib : libs) | ||||
| 		{ | ||||
| 			launchScript += "cp " + librariesPath().absoluteFilePath(lib->storagePath()) + "\n"; | ||||
| 			launchScript += "cp " + QFileInfo(lib->storagePath()).absoluteFilePath() + "\n"; | ||||
| 		} | ||||
| 		auto jarMods = getJarMods(); | ||||
| 		if (!jarMods.isEmpty()) | ||||
| @@ -191,7 +191,7 @@ BaseProcess *OneSixInstance::prepareForLaunch(AuthSessionPtr session) | ||||
| 		QDir natives_dir(PathCombine(instanceRoot(), "natives/")); | ||||
| 		for (auto native : m_version->getActiveNativeLibs()) | ||||
| 		{ | ||||
| 			QFileInfo finfo(PathCombine("libraries", native->storagePath())); | ||||
| 			QFileInfo finfo(native->storagePath()); | ||||
| 			launchScript += "ext " + finfo.absoluteFilePath() + "\n"; | ||||
| 		} | ||||
| 		launchScript += "natives " + natives_dir.absolutePath() + "\n"; | ||||
|   | ||||
| @@ -29,6 +29,7 @@ OneSixLibrary::OneSixLibrary(RawLibraryPtr base) | ||||
| 	m_native_classifiers = base->m_native_classifiers; | ||||
| 	m_rules = base->m_rules; | ||||
| 	dependType = base->dependType; | ||||
| 	m_storagePrefix = base->m_storagePrefix; | ||||
| 	// these only make sense for raw libraries. OneSix | ||||
| 	/* | ||||
| 	insertType = base->insertType; | ||||
|   | ||||
| @@ -227,8 +227,8 @@ void OneSixUpdate::jarlibStart() | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		QString raw_storage = lib->storagePath(); | ||||
| 		QString raw_dl = lib->downloadUrl(); | ||||
| 		QString raw_storage = lib->storageSuffix(); | ||||
| 		QString raw_dl = lib->url().toString(); | ||||
|  | ||||
| 		auto f = [&](QString storage, QString dl) | ||||
| 		{ | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
| using namespace MMCJson; | ||||
|  | ||||
| #include "RawLibrary.h" | ||||
| #include <pathutils.h> | ||||
|  | ||||
| RawLibraryPtr RawLibrary::fromJson(const QJsonObject &libObj, const QString &filename) | ||||
| { | ||||
| @@ -29,7 +30,9 @@ RawLibraryPtr RawLibrary::fromJson(const QJsonObject &libObj, const QString &fil | ||||
| 		return true; | ||||
| 	}; | ||||
|  | ||||
| 	readString("url", out->m_base_url); | ||||
| 	QString urlStr; | ||||
| 	readString("url", urlStr); | ||||
| 	out->m_base_url = urlStr; | ||||
| 	readString("MMC-hint", out->m_hint); | ||||
| 	readString("MMC-absulute_url", out->m_absolute_url); | ||||
| 	readString("MMC-absoluteUrl", out->m_absolute_url); | ||||
| @@ -109,7 +112,7 @@ RawLibraryPtr RawLibrary::fromJsonPlus(const QJsonObject &libObj, const QString | ||||
| 				throw JSONValidationError("Empty compound insert rule in " + filename); | ||||
| 			} | ||||
| 			QString insertString = insertObj.keys().first(); | ||||
| 			// really, only replace makes sense in combination with  | ||||
| 			// really, only replace makes sense in combination with | ||||
| 			if(insertString != "replace") | ||||
| 			{ | ||||
| 				throw JSONValidationError("Compound insert rule is not 'replace' in " + filename); | ||||
| @@ -154,7 +157,7 @@ QJsonObject RawLibrary::toJson() const | ||||
| 		m_base_url != "https://" + URLConstants::AWS_DOWNLOAD_LIBRARIES && | ||||
| 		m_base_url != "https://" + URLConstants::LIBRARY_BASE && !m_base_url.isEmpty()) | ||||
| 	{ | ||||
| 		libRoot.insert("url", m_base_url); | ||||
| 		libRoot.insert("url", m_base_url.toString()); | ||||
| 	} | ||||
| 	if (isNative()) | ||||
| 	{ | ||||
| @@ -194,7 +197,7 @@ QJsonObject RawLibrary::toJson() const | ||||
| QStringList RawLibrary::files() const | ||||
| { | ||||
| 	QStringList retval; | ||||
| 	QString storage = storagePath(); | ||||
| 	QString storage = storageSuffix(); | ||||
| 	if (storage.contains("${arch}")) | ||||
| 	{ | ||||
| 		QString cooked_storage = storage; | ||||
| @@ -221,17 +224,19 @@ bool RawLibrary::filesExist(const QDir &base) const | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
| QString RawLibrary::downloadUrl() const | ||||
| QUrl RawLibrary::url() const | ||||
| { | ||||
| 	if (m_absolute_url.size()) | ||||
| 	if (!m_absolute_url.isEmpty()) | ||||
| 	{ | ||||
| 		return m_absolute_url; | ||||
| 	} | ||||
|  | ||||
| 	if (m_base_url.isEmpty()) | ||||
| 	{ | ||||
| 		return QString("https://" + URLConstants::LIBRARY_BASE) + storagePath(); | ||||
| 		return QString("https://" + URLConstants::LIBRARY_BASE) + storageSuffix(); | ||||
| 	} | ||||
|  | ||||
| 	return m_base_url + storagePath(); | ||||
| 	return m_base_url.resolved(storageSuffix()); | ||||
| } | ||||
|  | ||||
| bool RawLibrary::isActive() const | ||||
| @@ -259,7 +264,26 @@ bool RawLibrary::isActive() const | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| QString RawLibrary::storagePath() const | ||||
| void RawLibrary::setStoragePrefix(QString prefix) | ||||
| { | ||||
| 	m_storagePrefix = prefix; | ||||
| } | ||||
|  | ||||
| QString RawLibrary::defaultStoragePrefix() | ||||
| { | ||||
| 	return "libraries/"; | ||||
| } | ||||
|  | ||||
| QString RawLibrary::storagePrefix() const | ||||
| { | ||||
| 	if(m_storagePrefix.isEmpty()) | ||||
| 	{ | ||||
| 		return defaultStoragePrefix(); | ||||
| 	} | ||||
| 	return m_storagePrefix; | ||||
| } | ||||
|  | ||||
| QString RawLibrary::storageSuffix() const | ||||
| { | ||||
| 	// non-native? use only the gradle specifier | ||||
| 	if (!isNative()) | ||||
| @@ -269,7 +293,7 @@ QString RawLibrary::storagePath() const | ||||
|  | ||||
| 	// otherwise native, override classifiers. Mojang HACK! | ||||
| 	GradleSpecifier nativeSpec = m_name; | ||||
| 	if(m_native_classifiers.contains(currentSystem)) | ||||
| 	if (m_native_classifiers.contains(currentSystem)) | ||||
| 	{ | ||||
| 		nativeSpec.setClassifier(m_native_classifiers[currentSystem]); | ||||
| 	} | ||||
| @@ -279,3 +303,13 @@ QString RawLibrary::storagePath() const | ||||
| 	} | ||||
| 	return nativeSpec.toPath(); | ||||
| } | ||||
|  | ||||
| QString RawLibrary::storagePath() const | ||||
| { | ||||
| 	return PathCombine(storagePrefix(), storageSuffix()); | ||||
| } | ||||
|  | ||||
| bool RawLibrary::storagePathIsDefault() const | ||||
| { | ||||
| 	return m_storagePrefix.isEmpty(); | ||||
| } | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| #include <QStringList> | ||||
| #include <QMap> | ||||
| #include <QDir> | ||||
| #include <QUrl> | ||||
| #include <memory> | ||||
|  | ||||
| #include "minecraft/OneSixRule.h" | ||||
| @@ -33,7 +34,7 @@ public: /* methods */ | ||||
| 	{ | ||||
| 		return m_name; | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	void setRawName(const GradleSpecifier & spec) | ||||
| 	{ | ||||
| 		m_name = spec; | ||||
| @@ -43,7 +44,7 @@ public: /* methods */ | ||||
| 	{ | ||||
| 		m_name.setClassifier(spec); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/// returns the full group and artifact prefix | ||||
| 	QString artifactPrefix() const | ||||
| 	{ | ||||
| @@ -68,8 +69,24 @@ public: /* methods */ | ||||
| 		return m_native_classifiers.size() != 0; | ||||
| 	} | ||||
|  | ||||
| 	void setStoragePrefix(QString prefix = QString()); | ||||
|  | ||||
| 	/// the default storage prefix used by MultiMC | ||||
| 	static QString defaultStoragePrefix(); | ||||
|  | ||||
| 	bool storagePathIsDefault() const; | ||||
|  | ||||
| 	/// Get the prefix - root of the storage to be used | ||||
| 	QString storagePrefix() const; | ||||
|  | ||||
| 	/// Get the relative path where the library should be saved | ||||
| 	QString storageSuffix() const; | ||||
|  | ||||
| 	/// Get the absolute path where the library should be saved | ||||
| 	QString storagePath() const; | ||||
|  | ||||
| 	/// Set the url base for downloads | ||||
| 	void setBaseUrl(const QString &base_url) | ||||
| 	void setBaseUrl(const QUrl &base_url) | ||||
| 	{ | ||||
| 		m_base_url = base_url; | ||||
| 	} | ||||
| @@ -110,11 +127,7 @@ public: /* methods */ | ||||
| 	bool isActive() const; | ||||
|  | ||||
| 	/// Get the URL to download the library from | ||||
| 	QString downloadUrl() const; | ||||
|  | ||||
| 	/// Get the relative path where the library should be saved | ||||
| 	QString storagePath() const; | ||||
|  | ||||
| 	QUrl url() const; | ||||
|  | ||||
| protected: /* data */ | ||||
| 	/// the basic gradle dependency specifier. | ||||
| @@ -128,7 +141,7 @@ protected: /* data */ | ||||
| public: /* data */ | ||||
| 	// TODO: make all of these protected, clean up semantics of implicit vs. explicit values. | ||||
| 	/// URL where the file can be downloaded | ||||
| 	QString m_base_url; | ||||
| 	QUrl m_base_url; | ||||
|  | ||||
| 	/// DEPRECATED: absolute URL. takes precedence the normal download URL, if defined | ||||
| 	QString m_absolute_url; | ||||
| @@ -136,6 +149,9 @@ public: /* data */ | ||||
| 	/// type hint - modifies how the library is treated | ||||
| 	QString m_hint; | ||||
|  | ||||
| 	/// storage - by default the local libraries folder in multimc, but could be elsewhere | ||||
| 	QString m_storagePrefix; | ||||
|  | ||||
| 	/// true if the library had an extract/excludes section (even empty) | ||||
| 	bool applyExcludes = false; | ||||
|  | ||||
| @@ -160,7 +176,7 @@ public: /* data */ | ||||
| 		Replace | ||||
| 	} insertType = Append; | ||||
| 	QString insertData; | ||||
| 	 | ||||
|  | ||||
| 	/// determines how can libraries be applied. conflicting dependencies cause errors. | ||||
| 	enum DependType | ||||
| 	{ | ||||
|   | ||||
| @@ -369,7 +369,7 @@ void VersionFile::applyTo(MinecraftProfile *version) | ||||
| 			if (index >= 0) | ||||
| 			{ | ||||
| 				auto existingLibrary = version->libraries[index]; | ||||
| 				if (!addedLibrary->m_base_url.isNull()) | ||||
| 				if (!addedLibrary->m_base_url.isEmpty()) | ||||
| 				{ | ||||
| 					existingLibrary->setBaseUrl(addedLibrary->m_base_url); | ||||
| 				} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user