Implement gradle spec reader/writer
This commit is contained in:
parent
71575a5022
commit
8a56ab6780
@ -427,6 +427,9 @@ SET(MULTIMC_SOURCES
|
|||||||
# RW lock protected map
|
# RW lock protected map
|
||||||
logic/RWStorage.h
|
logic/RWStorage.h
|
||||||
|
|
||||||
|
# A variable that has an implicit default value and keeps track of changes
|
||||||
|
logic/DefaultVariable.h
|
||||||
|
|
||||||
# network stuffs
|
# network stuffs
|
||||||
logic/net/NetAction.h
|
logic/net/NetAction.h
|
||||||
logic/net/MD5EtagDownload.h
|
logic/net/MD5EtagDownload.h
|
||||||
@ -493,6 +496,7 @@ SET(MULTIMC_SOURCES
|
|||||||
logic/OneSixInstance_p.h
|
logic/OneSixInstance_p.h
|
||||||
|
|
||||||
# OneSix version json infrastructure
|
# OneSix version json infrastructure
|
||||||
|
logic/minecraft/GradleSpecifier.h
|
||||||
logic/minecraft/InstanceVersion.cpp
|
logic/minecraft/InstanceVersion.cpp
|
||||||
logic/minecraft/InstanceVersion.h
|
logic/minecraft/InstanceVersion.h
|
||||||
logic/minecraft/JarMod.cpp
|
logic/minecraft/JarMod.cpp
|
||||||
|
35
logic/DefaultVariable.h
Normal file
35
logic/DefaultVariable.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class DefaultVariable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DefaultVariable(const T & value)
|
||||||
|
{
|
||||||
|
defaultValue = value;
|
||||||
|
}
|
||||||
|
DefaultVariable<T> & operator =(const T & value)
|
||||||
|
{
|
||||||
|
currentValue = value;
|
||||||
|
is_default = currentValue == defaultValue;
|
||||||
|
is_explicit = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
operator const T &() const
|
||||||
|
{
|
||||||
|
return is_default ? defaultValue : currentValue;
|
||||||
|
}
|
||||||
|
bool isDefault() const
|
||||||
|
{
|
||||||
|
return is_default;
|
||||||
|
}
|
||||||
|
bool isExplicit() const
|
||||||
|
{
|
||||||
|
return is_explicit;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
T currentValue;
|
||||||
|
T defaultValue;
|
||||||
|
bool is_default = true;
|
||||||
|
bool is_explicit = false;
|
||||||
|
};
|
@ -331,7 +331,29 @@ QSet<FTBRecord> InstanceList::discoverFTBInstances()
|
|||||||
continue;
|
continue;
|
||||||
record.name = attrs.value("name").toString();
|
record.name = attrs.value("name").toString();
|
||||||
record.logo = attrs.value("logo").toString();
|
record.logo = attrs.value("logo").toString();
|
||||||
record.mcVersion = attrs.value("mcVersion").toString();
|
auto customVersions = attrs.value("customMCVersions");
|
||||||
|
if(!customVersions.isNull())
|
||||||
|
{
|
||||||
|
QMap<QString, QString> versionMatcher;
|
||||||
|
QString customVersionsStr = customVersions.toString();
|
||||||
|
QStringList list = customVersionsStr.split(';');
|
||||||
|
for(auto item: list)
|
||||||
|
{
|
||||||
|
auto segment = item.split('^');
|
||||||
|
if(segment.size() != 2)
|
||||||
|
{
|
||||||
|
QLOG_ERROR() << "FTB: Segment of size < 2 in " << customVersionsStr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
versionMatcher[segment[0]] = segment[1];
|
||||||
|
}
|
||||||
|
auto actualVersion = attrs.value("version").toString();
|
||||||
|
record.mcVersion = versionMatcher[actualVersion];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
record.mcVersion = attrs.value("mcVersion").toString();
|
||||||
|
}
|
||||||
record.description = attrs.value("description").toString();
|
record.description = attrs.value("description").toString();
|
||||||
records.insert(record);
|
records.insert(record);
|
||||||
}
|
}
|
||||||
|
83
logic/minecraft/GradleSpecifier.h
Normal file
83
logic/minecraft/GradleSpecifier.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
#include "logic/DefaultVariable.h"
|
||||||
|
|
||||||
|
struct GradleSpecifier
|
||||||
|
{
|
||||||
|
GradleSpecifier()
|
||||||
|
{
|
||||||
|
m_valid = false;
|
||||||
|
}
|
||||||
|
GradleSpecifier(QString value)
|
||||||
|
{
|
||||||
|
operator=(value);
|
||||||
|
}
|
||||||
|
GradleSpecifier & operator =(const QString & value)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
org.gradle.test.classifiers : service : 1.0 : jdk15 @ jar
|
||||||
|
DEBUG 0 "org.gradle.test.classifiers:service:1.0:jdk15@jar"
|
||||||
|
DEBUG 1 "org.gradle.test.classifiers"
|
||||||
|
DEBUG 2 "service"
|
||||||
|
DEBUG 3 "1.0"
|
||||||
|
DEBUG 4 ":jdk15"
|
||||||
|
DEBUG 5 "jdk15"
|
||||||
|
DEBUG 6 "@jar"
|
||||||
|
DEBUG 7 "jar"
|
||||||
|
*/
|
||||||
|
QRegExp matcher("([^:@]+):([^:@]+):([^:@]+)" "(:([^:@]+))?" "(@([^:@]+))?");
|
||||||
|
m_valid = matcher.exactMatch(value);
|
||||||
|
auto elements = matcher.capturedTexts();
|
||||||
|
groupId = elements[1];
|
||||||
|
artifactId = elements[2];
|
||||||
|
version = elements[3];
|
||||||
|
classifier = elements[5];
|
||||||
|
if(!elements[7].isEmpty())
|
||||||
|
{
|
||||||
|
extension = elements[7];
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
operator QString() const
|
||||||
|
{
|
||||||
|
if(!m_valid)
|
||||||
|
return "INVALID";
|
||||||
|
QString retval = groupId + ":" + artifactId + ":" + version;
|
||||||
|
if(!classifier.isEmpty())
|
||||||
|
{
|
||||||
|
retval += ":" + classifier;
|
||||||
|
}
|
||||||
|
if(extension.isExplicit())
|
||||||
|
{
|
||||||
|
retval += "@" + extension;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
QString toPath() const
|
||||||
|
{
|
||||||
|
if(!m_valid)
|
||||||
|
return "INVALID";
|
||||||
|
QString path = groupId;
|
||||||
|
path.replace('.', '/');
|
||||||
|
path += '/' + artifactId + '/' + version + '/' + artifactId + '-' + version;
|
||||||
|
if(!classifier.isEmpty())
|
||||||
|
{
|
||||||
|
path += "-" + classifier;
|
||||||
|
}
|
||||||
|
path += "." + extension;
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
bool valid()
|
||||||
|
{
|
||||||
|
return m_valid;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
QString groupId;
|
||||||
|
QString artifactId;
|
||||||
|
QString version;
|
||||||
|
QString classifier;
|
||||||
|
DefaultVariable<QString> extension = DefaultVariable<QString>("jar");
|
||||||
|
bool m_valid = false;
|
||||||
|
};
|
@ -65,7 +65,10 @@ void OneSixLibrary::finalize()
|
|||||||
m_decentname = parts[1];
|
m_decentname = parts[1];
|
||||||
m_decentversion = minVersion = parts[2];
|
m_decentversion = minVersion = parts[2];
|
||||||
m_storage_path = relative;
|
m_storage_path = relative;
|
||||||
m_download_url = m_base_url + relative;
|
if(m_base_url.isEmpty())
|
||||||
|
m_download_url = QString("https://" + URLConstants::LIBRARY_BASE) + relative;
|
||||||
|
else
|
||||||
|
m_download_url = m_base_url + relative;
|
||||||
|
|
||||||
if (m_rules.empty())
|
if (m_rules.empty())
|
||||||
{
|
{
|
||||||
|
@ -13,20 +13,20 @@ RawLibraryPtr RawLibrary::fromJson(const QJsonObject &libObj, const QString &fil
|
|||||||
}
|
}
|
||||||
out->m_name = libObj.value("name").toString();
|
out->m_name = libObj.value("name").toString();
|
||||||
|
|
||||||
auto readString = [libObj, filename](const QString & key, QString & variable)
|
auto readString = [libObj, filename](const QString & key, QString & variable) -> bool
|
||||||
{
|
{
|
||||||
if (libObj.contains(key))
|
if (!libObj.contains(key))
|
||||||
|
return false;
|
||||||
|
QJsonValue val = libObj.value(key);
|
||||||
|
|
||||||
|
if (!val.isString())
|
||||||
{
|
{
|
||||||
QJsonValue val = libObj.value(key);
|
QLOG_WARN() << key << "is not a string in" << filename << "(skipping)";
|
||||||
if (!val.isString())
|
return false;
|
||||||
{
|
|
||||||
QLOG_WARN() << key << "is not a string in" << filename << "(skipping)";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
variable = val.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable = val.toString();
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
readString("url", out->m_base_url);
|
readString("url", out->m_base_url);
|
||||||
|
@ -28,10 +28,11 @@ public: /* methods */
|
|||||||
|
|
||||||
public: /* data */
|
public: /* data */
|
||||||
QString m_name;
|
QString m_name;
|
||||||
QString m_base_url = "https://" + URLConstants::LIBRARY_BASE;
|
QString m_base_url;
|
||||||
|
|
||||||
/// type hint - modifies how the library is treated
|
/// type hint - modifies how the library is treated
|
||||||
QString m_hint;
|
QString m_hint;
|
||||||
/// absolute URL. takes precedence over m_download_path, if defined
|
/// DEPRECATED: absolute URL. takes precedence over m_download_path, if defined
|
||||||
QString m_absolute_url;
|
QString m_absolute_url;
|
||||||
|
|
||||||
bool applyExcludes = false;
|
bool applyExcludes = false;
|
||||||
|
@ -22,6 +22,7 @@ endmacro()
|
|||||||
# Tests START #
|
# Tests START #
|
||||||
|
|
||||||
add_unit_test(pathutils tst_pathutils.cpp)
|
add_unit_test(pathutils tst_pathutils.cpp)
|
||||||
|
add_unit_test(gradlespecifier tst_gradlespecifier.cpp)
|
||||||
add_unit_test(userutils tst_userutils.cpp)
|
add_unit_test(userutils tst_userutils.cpp)
|
||||||
add_unit_test(inifile tst_inifile.cpp)
|
add_unit_test(inifile tst_inifile.cpp)
|
||||||
add_unit_test(UpdateChecker tst_UpdateChecker.cpp)
|
add_unit_test(UpdateChecker tst_UpdateChecker.cpp)
|
||||||
|
77
tests/tst_gradlespecifier.cpp
Normal file
77
tests/tst_gradlespecifier.cpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#include <QTest>
|
||||||
|
#include "TestUtil.h"
|
||||||
|
|
||||||
|
#include "logic/minecraft/GradleSpecifier.h"
|
||||||
|
|
||||||
|
class GradleSpecifierTest : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
private
|
||||||
|
slots:
|
||||||
|
void initTestCase()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
void cleanupTestCase()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_Positive_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("through");
|
||||||
|
|
||||||
|
QTest::newRow("3 parter") << "org.gradle.test.classifiers:service:1.0";
|
||||||
|
QTest::newRow("classifier") << "org.gradle.test.classifiers:service:1.0:jdk15";
|
||||||
|
QTest::newRow("jarextension") << "org.gradle.test.classifiers:service:1.0@jar";
|
||||||
|
QTest::newRow("jarboth") << "org.gradle.test.classifiers:service:1.0:jdk15@jar";
|
||||||
|
QTest::newRow("packxz") << "org.gradle.test.classifiers:service:1.0:jdk15@jar.pack.xz";
|
||||||
|
}
|
||||||
|
void test_Positive()
|
||||||
|
{
|
||||||
|
QFETCH(QString, through);
|
||||||
|
|
||||||
|
QString converted = GradleSpecifier(through);
|
||||||
|
|
||||||
|
QCOMPARE(converted, through);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_Path_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("spec");
|
||||||
|
QTest::addColumn<QString>("expected");
|
||||||
|
|
||||||
|
QTest::newRow("3 parter") << "group.id:artifact:1.0" << "group/id/artifact/1.0/artifact-1.0.jar";
|
||||||
|
QTest::newRow("doom") << "id.software:doom:1.666:demons@wad" << "id/software/doom/1.666/doom-1.666-demons.wad";
|
||||||
|
}
|
||||||
|
void test_Path()
|
||||||
|
{
|
||||||
|
QFETCH(QString, spec);
|
||||||
|
QFETCH(QString, expected);
|
||||||
|
|
||||||
|
QString converted = GradleSpecifier(spec).toPath();
|
||||||
|
|
||||||
|
QCOMPARE(converted, expected);
|
||||||
|
}
|
||||||
|
void test_Negative_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("input");
|
||||||
|
|
||||||
|
QTest::newRow("too many :") << "org:gradle.test:class:::ifiers:service:1.0::";
|
||||||
|
QTest::newRow("nonsense") << "I like turtles";
|
||||||
|
QTest::newRow("empty string") << "";
|
||||||
|
QTest::newRow("missing version") << "herp.derp:artifact";
|
||||||
|
}
|
||||||
|
void test_Negative()
|
||||||
|
{
|
||||||
|
QFETCH(QString, input);
|
||||||
|
|
||||||
|
GradleSpecifier spec(input);
|
||||||
|
QVERIFY(!spec.valid());
|
||||||
|
QCOMPARE(spec.operator QString(), QString("INVALID"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_GUILESS_MAIN_MULTIMC(GradleSpecifierTest)
|
||||||
|
|
||||||
|
#include "tst_gradlespecifier.moc"
|
Loading…
Reference in New Issue
Block a user