Implement gradle spec reader/writer

This commit is contained in:
Petr Mrázek 2014-07-16 02:03:52 +02:00
parent 71575a5022
commit 8a56ab6780
9 changed files with 241 additions and 15 deletions

View File

@ -427,6 +427,9 @@ SET(MULTIMC_SOURCES
# RW lock protected map
logic/RWStorage.h
# A variable that has an implicit default value and keeps track of changes
logic/DefaultVariable.h
# network stuffs
logic/net/NetAction.h
logic/net/MD5EtagDownload.h
@ -493,6 +496,7 @@ SET(MULTIMC_SOURCES
logic/OneSixInstance_p.h
# OneSix version json infrastructure
logic/minecraft/GradleSpecifier.h
logic/minecraft/InstanceVersion.cpp
logic/minecraft/InstanceVersion.h
logic/minecraft/JarMod.cpp

35
logic/DefaultVariable.h Normal file
View 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;
};

View File

@ -331,7 +331,29 @@ QSet<FTBRecord> InstanceList::discoverFTBInstances()
continue;
record.name = attrs.value("name").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();
records.insert(record);
}

View 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;
};

View File

@ -65,7 +65,10 @@ void OneSixLibrary::finalize()
m_decentname = parts[1];
m_decentversion = minVersion = parts[2];
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())
{

View File

@ -13,20 +13,20 @@ RawLibraryPtr RawLibrary::fromJson(const QJsonObject &libObj, const QString &fil
}
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);
if (!val.isString())
{
QLOG_WARN() << key << "is not a string in" << filename << "(skipping)";
}
else
{
variable = val.toString();
}
QLOG_WARN() << key << "is not a string in" << filename << "(skipping)";
return false;
}
variable = val.toString();
return true;
};
readString("url", out->m_base_url);

View File

@ -28,10 +28,11 @@ public: /* methods */
public: /* data */
QString m_name;
QString m_base_url = "https://" + URLConstants::LIBRARY_BASE;
QString m_base_url;
/// type hint - modifies how the library is treated
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;
bool applyExcludes = false;

View File

@ -22,6 +22,7 @@ endmacro()
# Tests START #
add_unit_test(pathutils tst_pathutils.cpp)
add_unit_test(gradlespecifier tst_gradlespecifier.cpp)
add_unit_test(userutils tst_userutils.cpp)
add_unit_test(inifile tst_inifile.cpp)
add_unit_test(UpdateChecker tst_UpdateChecker.cpp)

View 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"