From 0946c7c138d73a6e11835dc95da764ff1c0db5ad Mon Sep 17 00:00:00 2001 From: Petr Mrázek Date: Sun, 11 Oct 2020 23:20:35 +0200 Subject: NOISSUE basic code for downloading JREs from Mojang Not integrated yet, but the logic has tests and shouldn't be too shaky. Integration comes next. --- api/logic/CMakeLists.txt | 19 ++ api/logic/mojang/PackageManifest.cpp | 366 +++++++++++++++++++++++++++ api/logic/mojang/PackageManifest.h | 169 +++++++++++++ api/logic/mojang/PackageManifest_test.cpp | 333 ++++++++++++++++++++++++ api/logic/mojang/testdata/1.8.0_202-x64.json | 1 + api/logic/mojang/testdata/inspect/a/b.txt | 0 api/logic/mojang/testdata/inspect/a/b/b.txt | 1 + 7 files changed, 889 insertions(+) create mode 100644 api/logic/mojang/PackageManifest.cpp create mode 100644 api/logic/mojang/PackageManifest.h create mode 100644 api/logic/mojang/PackageManifest_test.cpp create mode 100644 api/logic/mojang/testdata/1.8.0_202-x64.json create mode 100755 api/logic/mojang/testdata/inspect/a/b.txt create mode 120000 api/logic/mojang/testdata/inspect/a/b/b.txt (limited to 'api') diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt index 740cd886..6e9aec08 100644 --- a/api/logic/CMakeLists.txt +++ b/api/logic/CMakeLists.txt @@ -306,6 +306,9 @@ set(MINECRAFT_SOURCES # Skin upload utilities minecraft/SkinUpload.cpp minecraft/SkinUpload.h + + mojang/PackageManifest.h + mojang/PackageManifest.cpp ) add_unit_test(GradleSpecifier @@ -313,6 +316,22 @@ add_unit_test(GradleSpecifier LIBS MultiMC_logic ) +add_executable(PackageManifest + mojang/PackageManifest_test.cpp +) +target_link_libraries(PackageManifest + MultiMC_logic + Qt5::Test +) +target_include_directories(PackageManifest + PRIVATE ../../cmake/UnitTest/ +) +add_test( + NAME PackageManifest + COMMAND PackageManifest + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + add_unit_test(MojangVersionFormat SOURCES minecraft/MojangVersionFormat_test.cpp LIBS MultiMC_logic diff --git a/api/logic/mojang/PackageManifest.cpp b/api/logic/mojang/PackageManifest.cpp new file mode 100644 index 00000000..42a66442 --- /dev/null +++ b/api/logic/mojang/PackageManifest.cpp @@ -0,0 +1,366 @@ +#include "PackageManifest.h" +#include +#include +#include +#include +#include + +namespace mojang_files { + +const Hash hash_of_empty_string = "da39a3ee5e6b4b0d3255bfef95601890afd80709"; + +int Path::compare(const Path& rhs) const +{ + auto left_cursor = begin(); + auto left_end = end(); + auto right_cursor = rhs.begin(); + auto right_end = rhs.end(); + + while (left_cursor != left_end && right_cursor != right_end) + { + if(*left_cursor < *right_cursor) + { + return -1; + } + else if(*left_cursor > *right_cursor) + { + return 1; + } + left_cursor++; + right_cursor++; + } + + if(left_cursor == left_end) + { + if(right_cursor == right_end) + { + return 0; + } + return -1; + } + return 1; +} + +void Package::addFile(const Path& path, const File& file) { + addFolder(path.parent_path()); + files[path] = file; +} + +void Package::addFolder(Path folder) { + if(!folder.has_parent_path()) { + return; + } + do { + folders.insert(folder); + folder = folder.parent_path(); + } while(folder.has_parent_path()); +} + +void Package::addLink(const Path& path, const Path& target) { + addFolder(path.parent_path()); + symlinks[path] = target; +} + +void Package::addSource(const FileSource& source) { + sources[source.hash] = source; +} + + +namespace { +void fromJson(QJsonDocument & doc, Package & out) { + std::set seen_paths; + if (!doc.isObject()) + { + throw JSONValidationError("file manifest is not an object"); + } + QJsonObject root = doc.object(); + + auto filesObj = Json::ensureObject(root, "files"); + auto iter = filesObj.begin(); + while (iter != filesObj.end()) + { + Path objectPath = Path(iter.key()); + auto value = iter.value(); + iter++; + if(seen_paths.count(objectPath)) { + throw JSONValidationError("duplicate path inside manifest, the manifest is invalid"); + } + if (!value.isObject()) + { + throw JSONValidationError("file entry inside manifest is not an an object"); + } + seen_paths.insert(objectPath); + + auto fileObject = value.toObject(); + auto type = Json::requireString(fileObject, "type"); + if(type == "directory") { + out.addFolder(objectPath); + continue; + } + else if(type == "file") { + FileSource bestSource; + File file; + file.executable = Json::ensureBoolean(fileObject, "executable", false); + auto downloads = Json::requireObject(fileObject, "downloads"); + for(auto iter2 = downloads.begin(); iter2 != downloads.end(); iter2++) { + FileSource source; + + auto downloadObject = Json::requireObject(iter2.value()); + source.hash = Json::requireString(downloadObject, "sha1"); + source.size = Json::requireInteger(downloadObject, "size"); + source.url = Json::requireString(downloadObject, "url"); + + auto compression = iter2.key(); + if(compression == "raw") { + file.hash = source.hash; + file.size = source.size; + source.compression = Compression::Raw; + } + else if (compression == "lzma") { + source.compression = Compression::Lzma; + } + else { + continue; + } + bestSource.upgrade(source); + } + if(bestSource.isBad()) { + throw JSONValidationError("No valid compression method for file " + iter.key()); + } + out.addFile(objectPath, file); + out.addSource(bestSource); + } + else if(type == "link") { + auto target = Json::requireString(fileObject, "target"); + out.symlinks[objectPath] = target; + out.addLink(objectPath, target); + } + else { + throw JSONValidationError("Invalid item type in manifest: " + type); + } + } + // make sure the containing folder exists + out.folders.insert(Path()); +} +} + +Package Package::fromManifestContents(const QByteArray& contents) +{ + Package out; + try + { + auto doc = Json::requireDocument(contents, "Manifest"); + fromJson(doc, out); + return out; + } + catch (const Exception &e) + { + qDebug() << QString("Unable to parse manifest: %1").arg(e.cause()); + out.valid = false; + return out; + } +} + +Package Package::fromManifestFile(const QString & filename) { + Package out; + try + { + auto doc = Json::requireDocument(filename, filename); + fromJson(doc, out); + return out; + } + catch (const Exception &e) + { + qDebug() << QString("Unable to parse manifest file %1: %2").arg(filename, e.cause()); + out.valid = false; + return out; + } +} + +// FIXME: Qt filesystem abstraction is bad, but ... let's hope it doesn't break too much? +// FIXME: The error handling is just DEFICIENT +Package Package::fromInspectedFolder(const QString& folderPath) +{ + QDir root(folderPath); + + Package out; + QDirIterator iterator(folderPath, QDir::NoDotAndDotDot | QDir::AllEntries | QDir::System | QDir::Hidden, QDirIterator::Subdirectories); + while(iterator.hasNext()) { + iterator.next(); + + auto fileInfo = iterator.fileInfo(); + auto relPath = root.relativeFilePath(fileInfo.filePath()); + if(fileInfo.isSymLink()) { + out.addLink(relPath, fileInfo.symLinkTarget()); + } + else if(fileInfo.isDir()) { + out.addFolder(relPath); + } + else if(fileInfo.isFile()) { + File f; + f.executable = fileInfo.isExecutable(); + f.size = fileInfo.size(); + // FIXME: async / optimize the hashing + QFile input(fileInfo.absoluteFilePath()); + if(!input.open(QIODevice::ReadOnly)) { + qCritical() << "Folder inspection: Failed to open file:" << fileInfo.absoluteFilePath(); + out.valid = false; + break; + } + f.hash = QCryptographicHash::hash(input.readAll(), QCryptographicHash::Sha1).toHex().constData(); + out.addFile(relPath, f); + } + else { + // Something else... oh my + qCritical() << "Folder inspection: Unknown filesystem object:" << fileInfo.absoluteFilePath(); + out.valid = false; + break; + } + } + out.folders.insert(Path(".")); + out.valid = true; + return out; +} + +namespace { +struct shallow_first_sort +{ + bool operator()(const Path &lhs, const Path &rhs) const + { + auto lhs_depth = lhs.length(); + auto rhs_depth = rhs.length(); + if(lhs_depth < rhs_depth) + { + return true; + } + else if(lhs_depth == rhs_depth) + { + if(lhs < rhs) + { + return true; + } + } + return false; + } +}; + +struct deep_first_sort +{ + bool operator()(const Path &lhs, const Path &rhs) const + { + auto lhs_depth = lhs.length(); + auto rhs_depth = rhs.length(); + if(lhs_depth > rhs_depth) + { + return true; + } + else if(lhs_depth == rhs_depth) + { + if(lhs < rhs) + { + return true; + } + } + return false; + } +}; +} + +UpdateOperations UpdateOperations::resolve(const Package& from, const Package& to) +{ + UpdateOperations out; + + if(!from.valid || !to.valid) { + out.valid = false; + return out; + } + + // Files + for(auto iter = from.files.begin(); iter != from.files.end(); iter++) { + const auto ¤t_hash = iter->second.hash; + const auto ¤t_executable = iter->second.executable; + const auto &path = iter->first; + + auto iter2 = to.files.find(path); + if(iter2 == to.files.end()) { + // removed + out.deletes.push_back(path); + continue; + } + auto new_hash = iter2->second.hash; + auto new_executable = iter2->second.executable; + if (current_hash != new_hash) { + out.deletes.push_back(path); + out.downloads.emplace( + std::pair{ + path, + FileDownload(to.sources.at(iter2->second.hash), iter2->second.executable) + } + ); + } + else if (current_executable != new_executable) { + out.executable_fixes[path] = new_executable; + } + } + for(auto iter = to.files.begin(); iter != to.files.end(); iter++) { + auto path = iter->first; + if(!from.files.count(path)) { + out.downloads.emplace( + std::pair{ + path, + FileDownload(to.sources.at(iter->second.hash), iter->second.executable) + } + ); + } + } + + // Folders + std::set remove_folders; + std::set make_folders; + for(auto from_path: from.folders) { + auto iter = to.folders.find(from_path); + if(iter == to.folders.end()) { + remove_folders.insert(from_path); + } + } + for(auto & rmdir: remove_folders) { + out.rmdirs.push_back(rmdir); + } + for(auto to_path: to.folders) { + auto iter = from.folders.find(to_path); + if(iter == from.folders.end()) { + make_folders.insert(to_path); + } + } + for(auto & mkdir: make_folders) { + out.mkdirs.push_back(mkdir); + } + + // Symlinks + for(auto iter = from.symlinks.begin(); iter != from.symlinks.end(); iter++) { + const auto ¤t_target = iter->second; + const auto &path = iter->first; + + auto iter2 = to.symlinks.find(path); + if(iter2 == to.symlinks.end()) { + // removed + out.deletes.push_back(path); + continue; + } + const auto &new_target = iter2->second; + if (current_target != new_target) { + out.deletes.push_back(path); + out.mklinks[path] = iter2->second; + } + } + for(auto iter = to.symlinks.begin(); iter != to.symlinks.end(); iter++) { + auto path = iter->first; + if(!from.symlinks.count(path)) { + out.mklinks[path] = iter->second; + } + } + out.valid = true; + return out; +} + +} diff --git a/api/logic/mojang/PackageManifest.h b/api/logic/mojang/PackageManifest.h new file mode 100644 index 00000000..893d4c50 --- /dev/null +++ b/api/logic/mojang/PackageManifest.h @@ -0,0 +1,169 @@ +#pragma once + +#include +#include +#include +#include +#include "tasks/Task.h" + +#include "multimc_logic_export.h" + +namespace mojang_files { + +using Hash = QString; +extern const Hash empty_hash; + +// simple-ish path implementation. assumes always relative and does not allow '..' entries +class MULTIMC_LOGIC_EXPORT Path +{ +public: + using parts_type = QStringList; + + Path() = default; + Path(QString string) { + auto parts_in = string.split('/'); + for(auto & part: parts_in) { + if(part.isEmpty() || part == ".") { + continue; + } + if(part == "..") { + if(parts.size()) { + parts.pop_back(); + } + continue; + } + parts.push_back(part); + } + } + + bool has_parent_path() const + { + return parts.size() > 0; + } + + Path parent_path() const + { + if (parts.empty()) + return Path(); + return Path(parts.begin(), std::prev(parts.end())); + } + + bool empty() const + { + return parts.empty(); + } + + int length() const + { + return parts.length(); + } + + bool operator==(const Path & rhs) const { + return parts == rhs.parts; + } + + bool operator!=(const Path & rhs) const { + return parts != rhs.parts; + } + + inline bool operator<(const Path& rhs) const + { + return compare(rhs) < 0; + } + + parts_type::const_iterator begin() const + { + return parts.begin(); + } + + parts_type::const_iterator end() const + { + return parts.end(); + } + + QString toString() const { + return parts.join("/"); + } + +private: + Path(const parts_type::const_iterator & start, const parts_type::const_iterator & end) { + parts = QStringList(start, end); + } + int compare(const Path& p) const; + + parts_type parts; +}; + + +enum class Compression { + Raw, + Lzma, + Unknown +}; + + +struct MULTIMC_LOGIC_EXPORT FileSource +{ + Compression compression = Compression::Unknown; + Hash hash; + QString url; + std::size_t size = 0; + void upgrade(const FileSource & other) { + if(compression == Compression::Unknown || other.size < size) { + *this = other; + } + } + bool isBad() const { + return compression == Compression::Unknown; + } +}; + +struct MULTIMC_LOGIC_EXPORT File +{ + Hash hash; + bool executable; + std::uint64_t size = 0; +}; + +struct MULTIMC_LOGIC_EXPORT Package { + static Package fromInspectedFolder(const QString &folderPath); + static Package fromManifestFile(const QString &path); + static Package fromManifestContents(const QByteArray& contents); + + explicit operator bool() const + { + return valid; + } + void addFolder(Path folder); + void addFile(const Path & path, const File & file); + void addLink(const Path & path, const Path & target); + void addSource(const FileSource & source); + + std::map sources; + bool valid = true; + std::set folders; + std::map files; + std::map symlinks; +}; + +struct MULTIMC_LOGIC_EXPORT FileDownload : FileSource +{ + FileDownload(const FileSource& source, bool executable) { + static_cast (*this) = source; + this->executable = executable; + } + bool executable = false; +}; + +struct MULTIMC_LOGIC_EXPORT UpdateOperations { + static UpdateOperations resolve(const Package & from, const Package & to); + bool valid = false; + std::vector deletes; + std::vector rmdirs; + std::vector mkdirs; + std::map downloads; + std::map mklinks; + std::map executable_fixes; +}; + +} diff --git a/api/logic/mojang/PackageManifest_test.cpp b/api/logic/mojang/PackageManifest_test.cpp new file mode 100644 index 00000000..08628973 --- /dev/null +++ b/api/logic/mojang/PackageManifest_test.cpp @@ -0,0 +1,333 @@ +#include +#include +#include "TestUtil.h" + +#include "mojang/PackageManifest.h" + +using namespace mojang_files; + +QDebug operator<<(QDebug debug, const Path &path) +{ + debug << path.toString(); + return debug; +} + +class PackageManifestTest : public QObject +{ + Q_OBJECT + +private slots: + void test_parse(); + void test_parse_file(); + void test_inspect(); + void test_diff(); + + void mkdir_deep(); + void rmdir_deep(); + + void identical_file(); + void changed_file(); + void added_file(); + void removed_file(); +}; + +namespace { +QByteArray basic_manifest = R"END( +{ + "files": { + "a/b.txt": { + "type": "file", + "downloads": { + "raw": { + "url": "http://dethware.org/b.txt", + "sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709", + "size": 0 + } + }, + "executable": true + }, + "a/b/c": { + "type": "directory" + }, + "a/b/c.txt": { + "type": "link", + "target": "../b.txt" + } + } +} +)END"; +} + +void PackageManifestTest::test_parse() +{ + auto manifest = Package::fromManifestContents(basic_manifest); + QCOMPARE(manifest.valid, true); + QCOMPARE(manifest.files.size(), 1); + QCOMPARE(manifest.files.count(Path("a/b.txt")), 1); + auto &file = manifest.files[Path("a/b.txt")]; + QCOMPARE(file.executable, true); + QCOMPARE(file.hash, "da39a3ee5e6b4b0d3255bfef95601890afd80709"); + QCOMPARE(file.size, 0); + QCOMPARE(manifest.folders.size(), 4); + QCOMPARE(manifest.folders.count(Path(".")), 1); + QCOMPARE(manifest.folders.count(Path("a")), 1); + QCOMPARE(manifest.folders.count(Path("a/b")), 1); + QCOMPARE(manifest.folders.count(Path("a/b/c")), 1); + QCOMPARE(manifest.symlinks.size(), 1); + auto symlinkPath = Path("a/b/c.txt"); + QCOMPARE(manifest.symlinks.count(symlinkPath), 1); + auto &symlink = manifest.symlinks[symlinkPath]; + QCOMPARE(symlink, Path("../b.txt")); + QCOMPARE(manifest.sources.size(), 1); +} + +void PackageManifestTest::test_parse_file() { + auto path = QFINDTESTDATA("testdata/1.8.0_202-x64.json"); + auto manifest = Package::fromManifestFile(path); + QCOMPARE(manifest.valid, true); +} + +void PackageManifestTest::test_inspect() { + auto path = QFINDTESTDATA("testdata/inspect/"); + auto manifest = Package::fromInspectedFolder(path); + QCOMPARE(manifest.valid, true); + QCOMPARE(manifest.files.size(), 1); + QCOMPARE(manifest.files.count(Path("a/b.txt")), 1); + auto &file = manifest.files[Path("a/b.txt")]; + QCOMPARE(file.executable, true); + QCOMPARE(file.hash, "da39a3ee5e6b4b0d3255bfef95601890afd80709"); + QCOMPARE(file.size, 0); + QCOMPARE(manifest.folders.size(), 3); + QCOMPARE(manifest.folders.count(Path(".")), 1); + QCOMPARE(manifest.folders.count(Path("a")), 1); + QCOMPARE(manifest.folders.count(Path("a/b")), 1); + QCOMPARE(manifest.symlinks.size(), 1); +} + +void PackageManifestTest::test_diff() { + auto path = QFINDTESTDATA("testdata/inspect/"); + auto from = Package::fromInspectedFolder(path); + auto to = Package::fromManifestContents(basic_manifest); + auto operations = UpdateOperations::resolve(from, to); + QCOMPARE(operations.valid, true); + QCOMPARE(operations.mkdirs.size(), 1); + QCOMPARE(operations.mkdirs[0], Path("a/b/c")); + + QCOMPARE(operations.rmdirs.size(), 0); + QCOMPARE(operations.deletes.size(), 1); + QCOMPARE(operations.deletes[0], Path("a/b/b.txt")); + QCOMPARE(operations.downloads.size(), 0); + QCOMPARE(operations.mklinks.size(), 1); + QCOMPARE(operations.mklinks.count(Path("a/b/c.txt")), 1); + QCOMPARE(operations.mklinks[Path("a/b/c.txt")], Path("../b.txt")); +} + +void PackageManifestTest::mkdir_deep() { + + Package from; + auto to = Package::fromManifestContents(R"END( +{ + "files": { + "a/b/c/d/e": { + "type": "directory" + } + } +} +)END"); + auto operations = UpdateOperations::resolve(from, to); + QCOMPARE(operations.deletes.size(), 0); + QCOMPARE(operations.rmdirs.size(), 0); + + QCOMPARE(operations.mkdirs.size(), 6); + QCOMPARE(operations.mkdirs[0], Path(".")); + QCOMPARE(operations.mkdirs[1], Path("a")); + QCOMPARE(operations.mkdirs[2], Path("a/b")); + QCOMPARE(operations.mkdirs[3], Path("a/b/c")); + QCOMPARE(operations.mkdirs[4], Path("a/b/c/d")); + QCOMPARE(operations.mkdirs[5], Path("a/b/c/d/e")); + + QCOMPARE(operations.downloads.size(), 0); + QCOMPARE(operations.mklinks.size(), 0); + QCOMPARE(operations.executable_fixes.size(), 0); +} + +void PackageManifestTest::rmdir_deep() { + + Package to; + auto from = Package::fromManifestContents(R"END( +{ + "files": { + "a/b/c/d/e": { + "type": "directory" + } + } +} +)END"); + auto operations = UpdateOperations::resolve(from, to); + QCOMPARE(operations.deletes.size(), 0); + + QCOMPARE(operations.rmdirs.size(), 6); + QCOMPARE(operations.rmdirs[0], Path("a/b/c/d/e")); + QCOMPARE(operations.rmdirs[1], Path("a/b/c/d")); + QCOMPARE(operations.rmdirs[2], Path("a/b/c")); + QCOMPARE(operations.rmdirs[3], Path("a/b")); + QCOMPARE(operations.rmdirs[4], Path("a")); + QCOMPARE(operations.rmdirs[5], Path(".")); + + QCOMPARE(operations.mkdirs.size(), 0); + QCOMPARE(operations.downloads.size(), 0); + QCOMPARE(operations.mklinks.size(), 0); + QCOMPARE(operations.executable_fixes.size(), 0); +} + +void PackageManifestTest::identical_file() { + QByteArray manifest = R"END( +{ + "files": { + "a/b/c/d/empty.txt": { + "type": "file", + "downloads": { + "raw": { + "url": "http://dethware.org/empty.txt", + "sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709", + "size": 0 + } + }, + "executable": false + } + } +} +)END"; + auto from = Package::fromManifestContents(manifest); + auto to = Package::fromManifestContents(manifest); + auto operations = UpdateOperations::resolve(from, to); + QCOMPARE(operations.deletes.size(), 0); + QCOMPARE(operations.rmdirs.size(), 0); + QCOMPARE(operations.mkdirs.size(), 0); + QCOMPARE(operations.downloads.size(), 0); + QCOMPARE(operations.mklinks.size(), 0); + QCOMPARE(operations.executable_fixes.size(), 0); +} + +void PackageManifestTest::changed_file() { + auto from = Package::fromManifestContents(R"END( +{ + "files": { + "a/b/c/d/file": { + "type": "file", + "downloads": { + "raw": { + "url": "http://dethware.org/empty.txt", + "sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709", + "size": 0 + } + }, + "executable": false + } + } +} +)END"); + auto to = Package::fromManifestContents(R"END( +{ + "files": { + "a/b/c/d/file": { + "type": "file", + "downloads": { + "raw": { + "url": "http://dethware.org/space.txt", + "sha1": "dd122581c8cd44d0227f9c305581ffcb4b6f1b46", + "size": 1 + } + }, + "executable": false + } + } +} +)END"); + auto operations = UpdateOperations::resolve(from, to); + QCOMPARE(operations.deletes.size(), 1); + QCOMPARE(operations.deletes[0], Path("a/b/c/d/file")); + QCOMPARE(operations.rmdirs.size(), 0); + QCOMPARE(operations.mkdirs.size(), 0); + QCOMPARE(operations.downloads.size(), 1); + QCOMPARE(operations.mklinks.size(), 0); + QCOMPARE(operations.executable_fixes.size(), 0); +} + +void PackageManifestTest::added_file() { + auto from = Package::fromManifestContents(R"END( +{ + "files": { + "a/b/c/d": { + "type": "directory" + } + } +} +)END"); + auto to = Package::fromManifestContents(R"END( +{ + "files": { + "a/b/c/d/file": { + "type": "file", + "downloads": { + "raw": { + "url": "http://dethware.org/space.txt", + "sha1": "dd122581c8cd44d0227f9c305581ffcb4b6f1b46", + "size": 1 + } + }, + "executable": false + } + } +} +)END"); + auto operations = UpdateOperations::resolve(from, to); + QCOMPARE(operations.deletes.size(), 0); + QCOMPARE(operations.rmdirs.size(), 0); + QCOMPARE(operations.mkdirs.size(), 0); + QCOMPARE(operations.downloads.size(), 1); + QCOMPARE(operations.mklinks.size(), 0); + QCOMPARE(operations.executable_fixes.size(), 0); +} + +void PackageManifestTest::removed_file() { + auto from = Package::fromManifestContents(R"END( +{ + "files": { + "a/b/c/d/file": { + "type": "file", + "downloads": { + "raw": { + "url": "http://dethware.org/space.txt", + "sha1": "dd122581c8cd44d0227f9c305581ffcb4b6f1b46", + "size": 1 + } + }, + "executable": false + } + } +} +)END"); + auto to = Package::fromManifestContents(R"END( +{ + "files": { + "a/b/c/d": { + "type": "directory" + } + } +} +)END"); + auto operations = UpdateOperations::resolve(from, to); + QCOMPARE(operations.deletes.size(), 1); + QCOMPARE(operations.deletes[0], Path("a/b/c/d/file")); + QCOMPARE(operations.rmdirs.size(), 0); + QCOMPARE(operations.mkdirs.size(), 0); + QCOMPARE(operations.downloads.size(), 0); + QCOMPARE(operations.mklinks.size(), 0); + QCOMPARE(operations.executable_fixes.size(), 0); +} + +QTEST_GUILESS_MAIN(PackageManifestTest) + +#include "PackageManifest_test.moc" + diff --git a/api/logic/mojang/testdata/1.8.0_202-x64.json b/api/logic/mojang/testdata/1.8.0_202-x64.json new file mode 100644 index 00000000..3d99d719 --- /dev/null +++ b/api/logic/mojang/testdata/1.8.0_202-x64.json @@ -0,0 +1 @@ +{"files": {"COPYRIGHT": {"downloads": {"lzma": {"sha1": "dd860e040807f7e53ae89da5f28dd73d57ac605d", "size": 1431, "url": "https://launcher.mojang.com/v1/objects/dd860e040807f7e53ae89da5f28dd73d57ac605d/COPYRIGHT"}, "raw": {"sha1": "c725183c757011e7ba96c83c1e86ee7e8b516a2b", "size": 3244, "url": "https://launcher.mojang.com/v1/objects/c725183c757011e7ba96c83c1e86ee7e8b516a2b/COPYRIGHT"}}, "executable": false, "type": "file"}, "LICENSE": {"downloads": {"raw": {"sha1": "3e86865deec0814c958bcf7fb87f790bccc0e8bd", "size": 40, "url": "https://launcher.mojang.com/v1/objects/3e86865deec0814c958bcf7fb87f790bccc0e8bd/LICENSE"}}, "executable": false, "type": "file"}, "README": {"downloads": {"raw": {"sha1": "f90331df1e5badeadc501d8dd70714c62a920204", "size": 46, "url": "https://launcher.mojang.com/v1/objects/f90331df1e5badeadc501d8dd70714c62a920204/README"}}, "executable": false, "type": "file"}, "THIRDPARTYLICENSEREADME-JAVAFX.txt": {"downloads": {"lzma": {"sha1": "4fee85109d7ff04b982d0576dabd15397f599125", "size": 15455, "url": "https://launcher.mojang.com/v1/objects/4fee85109d7ff04b982d0576dabd15397f599125/THIRDPARTYLICENSEREADME-JAVAFX.txt"}, "raw": {"sha1": "56ff42f87607b997b52ae0ef8bf315e36932e870", "size": 112724, "url": "https://launcher.mojang.com/v1/objects/56ff42f87607b997b52ae0ef8bf315e36932e870/THIRDPARTYLICENSEREADME-JAVAFX.txt"}}, "executable": false, "type": "file"}, "THIRDPARTYLICENSEREADME.txt": {"downloads": {"lzma": {"sha1": "419c1414ba46ae9dbfd38cf4e0601fff61644429", "size": 32266, "url": "https://launcher.mojang.com/v1/objects/419c1414ba46ae9dbfd38cf4e0601fff61644429/THIRDPARTYLICENSEREADME.txt"}, "raw": {"sha1": "b83c3f32261de3e48ccd20614a11e066b1ec9027", "size": 153824, "url": "https://launcher.mojang.com/v1/objects/b83c3f32261de3e48ccd20614a11e066b1ec9027/THIRDPARTYLICENSEREADME.txt"}}, "executable": false, "type": "file"}, "Welcome.html": {"downloads": {"lzma": {"sha1": "01c21a74b4aafb7cbe0388233c43cbdf77dcaaea", "size": 528, "url": "https://launcher.mojang.com/v1/objects/01c21a74b4aafb7cbe0388233c43cbdf77dcaaea/Welcome.html"}, "raw": {"sha1": "d98ae54f03dac87419abc19b97e315830c2da55f", "size": 955, "url": "https://launcher.mojang.com/v1/objects/d98ae54f03dac87419abc19b97e315830c2da55f/Welcome.html"}}, "executable": false, "type": "file"}, "bin": {"type": "directory"}, "bin/ControlPanel": {"target": "jcontrol", "type": "link"}, "bin/java": {"downloads": {"lzma": {"sha1": "3857eea1d59e1bc545c67a753ed2768254807b8a", "size": 2088, "url": "https://launcher.mojang.com/v1/objects/3857eea1d59e1bc545c67a753ed2768254807b8a/java"}, "raw": {"sha1": "3d20560fb5d1a49cb689c2226972e92e06d27ba6", "size": 8464, "url": "https://launcher.mojang.com/v1/objects/3d20560fb5d1a49cb689c2226972e92e06d27ba6/java"}}, "executable": true, "type": "file"}, "bin/javaws": {"downloads": {"lzma": {"sha1": "a6bec5c049e76c4488294a256a2084ea23ddb440", "size": 38173, "url": "https://launcher.mojang.com/v1/objects/a6bec5c049e76c4488294a256a2084ea23ddb440/javaws"}, "raw": {"sha1": "955c0f0066e2f893b0c2b3ccd83e223722e4ab74", "size": 140296, "url": "https://launcher.mojang.com/v1/objects/955c0f0066e2f893b0c2b3ccd83e223722e4ab74/javaws"}}, "executable": true, "type": "file"}, "bin/jcontrol": {"downloads": {"lzma": {"sha1": "40c5e33748f252e1d950b579a4185ab2c23fc908", "size": 2166, "url": "https://launcher.mojang.com/v1/objects/40c5e33748f252e1d950b579a4185ab2c23fc908/jcontrol"}, "raw": {"sha1": "ed541733c8b51e34349c1f8010b277e58ad73f1e", "size": 6264, "url": "https://launcher.mojang.com/v1/objects/ed541733c8b51e34349c1f8010b277e58ad73f1e/jcontrol"}}, "executable": true, "type": "file"}, "bin/jjs": {"downloads": {"lzma": {"sha1": "d44d1ac421979f7671921986214812095a5b0e3b", "size": 2168, "url": "https://launcher.mojang.com/v1/objects/d44d1ac421979f7671921986214812095a5b0e3b/jjs"}, "raw": {"sha1": "f00f944c3dbe556793b5dc686aaeee3e5722e99b", "size": 8584, "url": "https://launcher.mojang.com/v1/objects/f00f944c3dbe556793b5dc686aaeee3e5722e99b/jjs"}}, "executable": true, "type": "file"}, "bin/keytool": {"downloads": {"lzma": {"sha1": "93c607dce450976667c382f609a367167bdec05c", "size": 2175, "url": "https://launcher.mojang.com/v1/objects/93c607dce450976667c382f609a367167bdec05c/keytool"}, "raw": {"sha1": "7114b561546270e441e9ed1bcc24e5188c068a42", "size": 8584, "url": "https://launcher.mojang.com/v1/objects/7114b561546270e441e9ed1bcc24e5188c068a42/keytool"}}, "executable": true, "type": "file"}, "bin/orbd": {"downloads": {"lzma": {"sha1": "b27dfded5e2b2f6f02c555971c94e46ca14ac81b", "size": 2254, "url": "https://launcher.mojang.com/v1/objects/b27dfded5e2b2f6f02c555971c94e46ca14ac81b/orbd"}, "raw": {"sha1": "7f31217fecb3dbbd89f1dd3783fca58793a66fd2", "size": 8656, "url": "https://launcher.mojang.com/v1/objects/7f31217fecb3dbbd89f1dd3783fca58793a66fd2/orbd"}}, "executable": true, "type": "file"}, "bin/pack200": {"downloads": {"lzma": {"sha1": "b52da4497b49b1508b6225a5740857ddb8f52e97", "size": 2183, "url": "https://launcher.mojang.com/v1/objects/b52da4497b49b1508b6225a5740857ddb8f52e97/pack200"}, "raw": {"sha1": "16ef3e801efb57e50bc6477a27a9d95d02d0775b", "size": 8584, "url": "https://launcher.mojang.com/v1/objects/16ef3e801efb57e50bc6477a27a9d95d02d0775b/pack200"}}, "executable": true, "type": "file"}, "bin/policytool": {"downloads": {"lzma": {"sha1": "87da4c07da45f3d1a1a9d732af197cd39bf69d10", "size": 2182, "url": "https://launcher.mojang.com/v1/objects/87da4c07da45f3d1a1a9d732af197cd39bf69d10/policytool"}, "raw": {"sha1": "a52a29424470cb9b8db5c2fb1751d0b697a7ec8e", "size": 8592, "url": "https://launcher.mojang.com/v1/objects/a52a29424470cb9b8db5c2fb1751d0b697a7ec8e/policytool"}}, "executable": true, "type": "file"}, "bin/rmid": {"downloads": {"lzma": {"sha1": "1494c1174fde0c0a93ea117bc7edf7eb936c0512", "size": 2172, "url": "https://launcher.mojang.com/v1/objects/1494c1174fde0c0a93ea117bc7edf7eb936c0512/rmid"}, "raw": {"sha1": "5c8710e1ab924e5b09a07bcb4c6e106293bbd1a8", "size": 8584, "url": "https://launcher.mojang.com/v1/objects/5c8710e1ab924e5b09a07bcb4c6e106293bbd1a8/rmid"}}, "executable": true, "type": "file"}, "bin/rmiregistry": {"downloads": {"lzma": {"sha1": "7070cf2ec5a5e520a880bae699431edf02083e7e", "size": 2174, "url": "https://launcher.mojang.com/v1/objects/7070cf2ec5a5e520a880bae699431edf02083e7e/rmiregistry"}, "raw": {"sha1": "5f518daa7050028d5d9d849634c73136f2b23a54", "size": 8592, "url": "https://launcher.mojang.com/v1/objects/5f518daa7050028d5d9d849634c73136f2b23a54/rmiregistry"}}, "executable": true, "type": "file"}, "bin/servertool": {"downloads": {"lzma": {"sha1": "1db683a11cc9b7313426c84412f4d95be2fa7ccd", "size": 2185, "url": "https://launcher.mojang.com/v1/objects/1db683a11cc9b7313426c84412f4d95be2fa7ccd/servertool"}, "raw": {"sha1": "49d0ebfeb265ce5a8733e1014541ea2525674a60", "size": 8592, "url": "https://launcher.mojang.com/v1/objects/49d0ebfeb265ce5a8733e1014541ea2525674a60/servertool"}}, "executable": true, "type": "file"}, "bin/tnameserv": {"downloads": {"lzma": {"sha1": "36da9c9a2c5a8b662a3f8d52ca67339bce1c2714", "size": 2291, "url": "https://launcher.mojang.com/v1/objects/36da9c9a2c5a8b662a3f8d52ca67339bce1c2714/tnameserv"}, "raw": {"sha1": "09d998f8efcb6f55d0d87f59e08f8b89662796d9", "size": 8656, "url": "https://launcher.mojang.com/v1/objects/09d998f8efcb6f55d0d87f59e08f8b89662796d9/tnameserv"}}, "executable": true, "type": "file"}, "bin/unpack200": {"downloads": {"lzma": {"sha1": "344959e32fc7ee19eebe7b3cf5ab6d1a7d6641f2", "size": 79721, "url": "https://launcher.mojang.com/v1/objects/344959e32fc7ee19eebe7b3cf5ab6d1a7d6641f2/unpack200"}, "raw": {"sha1": "5dd933132f1b202e19e0c8e093f7113711cfdfc1", "size": 182616, "url": "https://launcher.mojang.com/v1/objects/5dd933132f1b202e19e0c8e093f7113711cfdfc1/unpack200"}}, "executable": true, "type": "file"}, "lib": {"type": "directory"}, "lib/amd64": {"type": "directory"}, "lib/amd64/jli": {"type": "directory"}, "lib/amd64/jli/libjli.so": {"downloads": {"lzma": {"sha1": "372331ee8e375888f798a2e88180a94493e141b0", "size": 48327, "url": "https://launcher.mojang.com/v1/objects/372331ee8e375888f798a2e88180a94493e141b0/libjli.so"}, "raw": {"sha1": "73b0cf8b7415686bc40c561ff77ff2740ccf7a44", "size": 108616, "url": "https://launcher.mojang.com/v1/objects/73b0cf8b7415686bc40c561ff77ff2740ccf7a44/libjli.so"}}, "executable": true, "type": "file"}, "lib/amd64/jvm.cfg": {"downloads": {"lzma": {"sha1": "86bcfebec37b38415525ffd77d3eaf70d0b1b4ca", "size": 435, "url": "https://launcher.mojang.com/v1/objects/86bcfebec37b38415525ffd77d3eaf70d0b1b4ca/jvm.cfg"}, "raw": {"sha1": "84b38bdc745de446ba0ca0232ea3aaf2efd721da", "size": 627, "url": "https://launcher.mojang.com/v1/objects/84b38bdc745de446ba0ca0232ea3aaf2efd721da/jvm.cfg"}}, "executable": false, "type": "file"}, "lib/amd64/libavplugin-53.so": {"downloads": {"lzma": {"sha1": "a332366762d9efc7b845a682b7edce62db44618c", "size": 14747, "url": "https://launcher.mojang.com/v1/objects/a332366762d9efc7b845a682b7edce62db44618c/libavplugin-53.so"}, "raw": {"sha1": "9bd1473dd8a0dc7950c7af1cc69a45548df26eb5", "size": 51720, "url": "https://launcher.mojang.com/v1/objects/9bd1473dd8a0dc7950c7af1cc69a45548df26eb5/libavplugin-53.so"}}, "executable": true, "type": "file"}, "lib/amd64/libavplugin-54.so": {"downloads": {"lzma": {"sha1": "2c615852a0720a275163e00597c1f711f11341da", "size": 15153, "url": "https://launcher.mojang.com/v1/objects/2c615852a0720a275163e00597c1f711f11341da/libavplugin-54.so"}, "raw": {"sha1": "8808050c5949c4800b42d1b19b1f8b0d120bcacb", "size": 51768, "url": "https://launcher.mojang.com/v1/objects/8808050c5949c4800b42d1b19b1f8b0d120bcacb/libavplugin-54.so"}}, "executable": true, "type": "file"}, "lib/amd64/libavplugin-55.so": {"downloads": {"lzma": {"sha1": "39ee8e7fe14f0010c78973962800f539c3e4c16b", "size": 15168, "url": "https://launcher.mojang.com/v1/objects/39ee8e7fe14f0010c78973962800f539c3e4c16b/libavplugin-55.so"}, "raw": {"sha1": "f10ea4ea3489e96d8d161a96790133c417ec44e1", "size": 51784, "url": "https://launcher.mojang.com/v1/objects/f10ea4ea3489e96d8d161a96790133c417ec44e1/libavplugin-55.so"}}, "executable": true, "type": "file"}, "lib/amd64/libavplugin-56.so": {"downloads": {"lzma": {"sha1": "abe7feced5a559f1bdc868526dc69484e0e591a0", "size": 15169, "url": "https://launcher.mojang.com/v1/objects/abe7feced5a559f1bdc868526dc69484e0e591a0/libavplugin-56.so"}, "raw": {"sha1": "e5bfcbff5a5a5a5993a3e689a05ef358c131a3ed", "size": 51784, "url": "https://launcher.mojang.com/v1/objects/e5bfcbff5a5a5a5993a3e689a05ef358c131a3ed/libavplugin-56.so"}}, "executable": true, "type": "file"}, "lib/amd64/libavplugin-57.so": {"downloads": {"lzma": {"sha1": "4dd26b4ef2294b6929dcb2c7546b47eac5cc78a9", "size": 15174, "url": "https://launcher.mojang.com/v1/objects/4dd26b4ef2294b6929dcb2c7546b47eac5cc78a9/libavplugin-57.so"}, "raw": {"sha1": "2949e7ff9b0ac90e8943c211cff141ab12eec3f8", "size": 51784, "url": "https://launcher.mojang.com/v1/objects/2949e7ff9b0ac90e8943c211cff141ab12eec3f8/libavplugin-57.so"}}, "executable": true, "type": "file"}, "lib/amd64/libavplugin-ffmpeg-56.so": {"downloads": {"lzma": {"sha1": "c688ba1cfa442bf18bee43b2fa870b4dc1ce3fb6", "size": 15231, "url": "https://launcher.mojang.com/v1/objects/c688ba1cfa442bf18bee43b2fa870b4dc1ce3fb6/libavplugin-ffmpeg-56.so"}, "raw": {"sha1": "0d36c971a9ad99fc2292092fdec3a4179b1021b9", "size": 51920, "url": "https://launcher.mojang.com/v1/objects/0d36c971a9ad99fc2292092fdec3a4179b1021b9/libavplugin-ffmpeg-56.so"}}, "executable": true, "type": "file"}, "lib/amd64/libavplugin-ffmpeg-57.so": {"downloads": {"lzma": {"sha1": "087426bdbffebcfa372a438e863785f4ffbe9a6b", "size": 15180, "url": "https://launcher.mojang.com/v1/objects/087426bdbffebcfa372a438e863785f4ffbe9a6b/libavplugin-ffmpeg-57.so"}, "raw": {"sha1": "5e9c4eb4b49eb8e57c01003ec73a1eb8d6d8c462", "size": 51784, "url": "https://launcher.mojang.com/v1/objects/5e9c4eb4b49eb8e57c01003ec73a1eb8d6d8c462/libavplugin-ffmpeg-57.so"}}, "executable": true, "type": "file"}, "lib/amd64/libawt.so": {"downloads": {"lzma": {"sha1": "018be58b205b73c842a55df811b70d0e8237216e", "size": 195720, "url": "https://launcher.mojang.com/v1/objects/018be58b205b73c842a55df811b70d0e8237216e/libawt.so"}, "raw": {"sha1": "02632cd326e3161c00a7e784599dd7b9ee053dce", "size": 759184, "url": "https://launcher.mojang.com/v1/objects/02632cd326e3161c00a7e784599dd7b9ee053dce/libawt.so"}}, "executable": true, "type": "file"}, "lib/amd64/libawt_headless.so": {"downloads": {"lzma": {"sha1": "7ac2517cff75d4bbb0a0412a9b5f18c74ea188fa", "size": 11211, "url": "https://launcher.mojang.com/v1/objects/7ac2517cff75d4bbb0a0412a9b5f18c74ea188fa/libawt_headless.so"}, "raw": {"sha1": "862157ec957008d0911c5daedc004b3a202623a4", "size": 39176, "url": "https://launcher.mojang.com/v1/objects/862157ec957008d0911c5daedc004b3a202623a4/libawt_headless.so"}}, "executable": true, "type": "file"}, "lib/amd64/libawt_xawt.so": {"downloads": {"lzma": {"sha1": "d536a96af27dfe35de6bb2c8759d51c488cdd8d4", "size": 149598, "url": "https://launcher.mojang.com/v1/objects/d536a96af27dfe35de6bb2c8759d51c488cdd8d4/libawt_xawt.so"}, "raw": {"sha1": "28232b3e01b6f11bfe098bfc6eafc3a513dcebf1", "size": 470232, "url": "https://launcher.mojang.com/v1/objects/28232b3e01b6f11bfe098bfc6eafc3a513dcebf1/libawt_xawt.so"}}, "executable": true, "type": "file"}, "lib/amd64/libbci.so": {"downloads": {"lzma": {"sha1": "c36fad091d11e64c815d5ca17c0ef7a55b0776b1", "size": 3509, "url": "https://launcher.mojang.com/v1/objects/c36fad091d11e64c815d5ca17c0ef7a55b0776b1/libbci.so"}, "raw": {"sha1": "33824051db1ccb6332e22c2b63231055240d0af0", "size": 12760, "url": "https://launcher.mojang.com/v1/objects/33824051db1ccb6332e22c2b63231055240d0af0/libbci.so"}}, "executable": true, "type": "file"}, "lib/amd64/libdcpr.so": {"downloads": {"lzma": {"sha1": "70c6b0933a37f2b1124d6e7c131039241fe796ee", "size": 75969, "url": "https://launcher.mojang.com/v1/objects/70c6b0933a37f2b1124d6e7c131039241fe796ee/libdcpr.so"}, "raw": {"sha1": "fa7001bc5d80579e2716590f3eee8027da0beae7", "size": 204456, "url": "https://launcher.mojang.com/v1/objects/fa7001bc5d80579e2716590f3eee8027da0beae7/libdcpr.so"}}, "executable": true, "type": "file"}, "lib/amd64/libdecora_sse.so": {"downloads": {"lzma": {"sha1": "514acc017dfb6cefaf8cc6d18006ce55781cc9bc", "size": 24397, "url": "https://launcher.mojang.com/v1/objects/514acc017dfb6cefaf8cc6d18006ce55781cc9bc/libdecora_sse.so"}, "raw": {"sha1": "d0c84233504c916e548e29f513e25f6a7479abfc", "size": 74912, "url": "https://launcher.mojang.com/v1/objects/d0c84233504c916e548e29f513e25f6a7479abfc/libdecora_sse.so"}}, "executable": true, "type": "file"}, "lib/amd64/libdeploy.so": {"downloads": {"lzma": {"sha1": "6cf31fd98301c749ac0d2c7825f6d925a4409760", "size": 168999, "url": "https://launcher.mojang.com/v1/objects/6cf31fd98301c749ac0d2c7825f6d925a4409760/libdeploy.so"}, "raw": {"sha1": "b3832e97ed8ca794884b56a591b83d02a2c0c06f", "size": 642368, "url": "https://launcher.mojang.com/v1/objects/b3832e97ed8ca794884b56a591b83d02a2c0c06f/libdeploy.so"}}, "executable": true, "type": "file"}, "lib/amd64/libdt_socket.so": {"downloads": {"lzma": {"sha1": "4cc5c880dbb6fa180436d12d60f0abec8ebb59dc", "size": 7784, "url": "https://launcher.mojang.com/v1/objects/4cc5c880dbb6fa180436d12d60f0abec8ebb59dc/libdt_socket.so"}, "raw": {"sha1": "91ce96f252b8139fc12f0f224ed5b1a041767ab7", "size": 24616, "url": "https://launcher.mojang.com/v1/objects/91ce96f252b8139fc12f0f224ed5b1a041767ab7/libdt_socket.so"}}, "executable": true, "type": "file"}, "lib/amd64/libfontmanager.so": {"downloads": {"lzma": {"sha1": "f94e5e94c71c603ff4d3cd1e7e3d9e181fcc145d", "size": 146951, "url": "https://launcher.mojang.com/v1/objects/f94e5e94c71c603ff4d3cd1e7e3d9e181fcc145d/libfontmanager.so"}, "raw": {"sha1": "2428e805f2c53d1283a033dfd11a86fbb7bd7159", "size": 490672, "url": "https://launcher.mojang.com/v1/objects/2428e805f2c53d1283a033dfd11a86fbb7bd7159/libfontmanager.so"}}, "executable": true, "type": "file"}, "lib/amd64/libfxplugins.so": {"downloads": {"lzma": {"sha1": "a640143365d382a5ad743a784bc2f3706d9d6d67", "size": 50048, "url": "https://launcher.mojang.com/v1/objects/a640143365d382a5ad743a784bc2f3706d9d6d67/libfxplugins.so"}, "raw": {"sha1": "0fd4ac04a84c131f1aaee9e6b0898ff9ea69e3ee", "size": 151448, "url": "https://launcher.mojang.com/v1/objects/0fd4ac04a84c131f1aaee9e6b0898ff9ea69e3ee/libfxplugins.so"}}, "executable": true, "type": "file"}, "lib/amd64/libglass.so": {"downloads": {"lzma": {"sha1": "f1ff517714fa5f2c861f33b32db823fe851541f1", "size": 2856, "url": "https://launcher.mojang.com/v1/objects/f1ff517714fa5f2c861f33b32db823fe851541f1/libglass.so"}, "raw": {"sha1": "e7f4fece30ac727be8148d33b8256abd3a41cef9", "size": 13072, "url": "https://launcher.mojang.com/v1/objects/e7f4fece30ac727be8148d33b8256abd3a41cef9/libglass.so"}}, "executable": true, "type": "file"}, "lib/amd64/libglassgtk2.so": {"downloads": {"lzma": {"sha1": "15b90f7a2baacd15e80aa9785d87cf1e4258376d", "size": 220476, "url": "https://launcher.mojang.com/v1/objects/15b90f7a2baacd15e80aa9785d87cf1e4258376d/libglassgtk2.so"}, "raw": {"sha1": "e30a634c2ff2143bdee512360553d6e0304f33b2", "size": 844984, "url": "https://launcher.mojang.com/v1/objects/e30a634c2ff2143bdee512360553d6e0304f33b2/libglassgtk2.so"}}, "executable": true, "type": "file"}, "lib/amd64/libglassgtk3.so": {"downloads": {"lzma": {"sha1": "868c231165f8c9043b7f0e7de208ec023f06a6e7", "size": 220560, "url": "https://launcher.mojang.com/v1/objects/868c231165f8c9043b7f0e7de208ec023f06a6e7/libglassgtk3.so"}, "raw": {"sha1": "762a11a2b376b7b5a2a7cad780715524fdd176d5", "size": 845304, "url": "https://launcher.mojang.com/v1/objects/762a11a2b376b7b5a2a7cad780715524fdd176d5/libglassgtk3.so"}}, "executable": true, "type": "file"}, "lib/amd64/libglib-lite.so": {"downloads": {"lzma": {"sha1": "61b8871242febe1be262de167dc20ae94bf964b4", "size": 457046, "url": "https://launcher.mojang.com/v1/objects/61b8871242febe1be262de167dc20ae94bf964b4/libglib-lite.so"}, "raw": {"sha1": "63afa060fc3f120af76128e51d32603fc4336fa8", "size": 1538352, "url": "https://launcher.mojang.com/v1/objects/63afa060fc3f120af76128e51d32603fc4336fa8/libglib-lite.so"}}, "executable": true, "type": "file"}, "lib/amd64/libgstreamer-lite.so": {"downloads": {"lzma": {"sha1": "2447dc368406ba1b989a29937d41924620e01988", "size": 673056, "url": "https://launcher.mojang.com/v1/objects/2447dc368406ba1b989a29937d41924620e01988/libgstreamer-lite.so"}, "raw": {"sha1": "5505e7ca592ac64371d3db8fe53bcb602e9723d3", "size": 2263872, "url": "https://launcher.mojang.com/v1/objects/5505e7ca592ac64371d3db8fe53bcb602e9723d3/libgstreamer-lite.so"}}, "executable": true, "type": "file"}, "lib/amd64/libhprof.so": {"downloads": {"lzma": {"sha1": "94a5589c818db1fb1cf1881e24e217c309fce2e4", "size": 64471, "url": "https://launcher.mojang.com/v1/objects/94a5589c818db1fb1cf1881e24e217c309fce2e4/libhprof.so"}, "raw": {"sha1": "4bb9bdeef6133b6dd558d52d691b077c03e9b0ee", "size": 175504, "url": "https://launcher.mojang.com/v1/objects/4bb9bdeef6133b6dd558d52d691b077c03e9b0ee/libhprof.so"}}, "executable": true, "type": "file"}, "lib/amd64/libinstrument.so": {"downloads": {"lzma": {"sha1": "84ffea356caf725b42c86a8ebc9587f477ddde29", "size": 18603, "url": "https://launcher.mojang.com/v1/objects/84ffea356caf725b42c86a8ebc9587f477ddde29/libinstrument.so"}, "raw": {"sha1": "cb8009769601e3fecd7ea2b36c344f737b1a9da7", "size": 51560, "url": "https://launcher.mojang.com/v1/objects/cb8009769601e3fecd7ea2b36c344f737b1a9da7/libinstrument.so"}}, "executable": true, "type": "file"}, "lib/amd64/libj2gss.so": {"downloads": {"lzma": {"sha1": "4b2aa699506b126098b585a9617ce1c05707fa29", "size": 14132, "url": "https://launcher.mojang.com/v1/objects/4b2aa699506b126098b585a9617ce1c05707fa29/libj2gss.so"}, "raw": {"sha1": "cbce4a302b255d4d1924ef7606f038af766c5e86", "size": 47688, "url": "https://launcher.mojang.com/v1/objects/cbce4a302b255d4d1924ef7606f038af766c5e86/libj2gss.so"}}, "executable": true, "type": "file"}, "lib/amd64/libj2pcsc.so": {"downloads": {"lzma": {"sha1": "2361d3b2e3da48593c391b29b0d2b5409e4c55e5", "size": 5074, "url": "https://launcher.mojang.com/v1/objects/2361d3b2e3da48593c391b29b0d2b5409e4c55e5/libj2pcsc.so"}, "raw": {"sha1": "1274178492e7a3e997e12f67794616f7c3d8d0b9", "size": 18296, "url": "https://launcher.mojang.com/v1/objects/1274178492e7a3e997e12f67794616f7c3d8d0b9/libj2pcsc.so"}}, "executable": true, "type": "file"}, "lib/amd64/libj2pkcs11.so": {"downloads": {"lzma": {"sha1": "ef927e2790ba05931d0f0bdd63da3d275a834946", "size": 21573, "url": "https://launcher.mojang.com/v1/objects/ef927e2790ba05931d0f0bdd63da3d275a834946/libj2pkcs11.so"}, "raw": {"sha1": "bd4f2af9bfdc6168633d1920c1a1415de06bb45a", "size": 79472, "url": "https://launcher.mojang.com/v1/objects/bd4f2af9bfdc6168633d1920c1a1415de06bb45a/libj2pkcs11.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjaas_unix.so": {"downloads": {"lzma": {"sha1": "7f7e843544ee1eb1454a5826bdd4218685b79430", "size": 2404, "url": "https://launcher.mojang.com/v1/objects/7f7e843544ee1eb1454a5826bdd4218685b79430/libjaas_unix.so"}, "raw": {"sha1": "4c517925c7d464a5b719898eb0bea1b04df31f1f", "size": 8192, "url": "https://launcher.mojang.com/v1/objects/4c517925c7d464a5b719898eb0bea1b04df31f1f/libjaas_unix.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjava.so": {"downloads": {"lzma": {"sha1": "5eee7a42600a44a8bb8d6d7f510fd96a29637ac0", "size": 63113, "url": "https://launcher.mojang.com/v1/objects/5eee7a42600a44a8bb8d6d7f510fd96a29637ac0/libjava.so"}, "raw": {"sha1": "e280aeddf3fc0ec664aef7efc0e0e197a54aaf02", "size": 227672, "url": "https://launcher.mojang.com/v1/objects/e280aeddf3fc0ec664aef7efc0e0e197a54aaf02/libjava.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjava_crw_demo.so": {"downloads": {"lzma": {"sha1": "b197cf23ae3556eb0b45c663f0a8cb62408b961e", "size": 10412, "url": "https://launcher.mojang.com/v1/objects/b197cf23ae3556eb0b45c663f0a8cb62408b961e/libjava_crw_demo.so"}, "raw": {"sha1": "18f20f906977c90d0090b41dbda8dd5cfead5a4c", "size": 26144, "url": "https://launcher.mojang.com/v1/objects/18f20f906977c90d0090b41dbda8dd5cfead5a4c/libjava_crw_demo.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjavafx_font.so": {"downloads": {"lzma": {"sha1": "ffbba0e5022f829412b86063d8a90f95f16709b1", "size": 5608, "url": "https://launcher.mojang.com/v1/objects/ffbba0e5022f829412b86063d8a90f95f16709b1/libjavafx_font.so"}, "raw": {"sha1": "8634a0aca612fc40420a4a7cc8af4cc46cfc6725", "size": 17104, "url": "https://launcher.mojang.com/v1/objects/8634a0aca612fc40420a4a7cc8af4cc46cfc6725/libjavafx_font.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjavafx_font_freetype.so": {"downloads": {"lzma": {"sha1": "310271eda8a2ac264ffc3640a9d847b49438d0bd", "size": 6942, "url": "https://launcher.mojang.com/v1/objects/310271eda8a2ac264ffc3640a9d847b49438d0bd/libjavafx_font_freetype.so"}, "raw": {"sha1": "3e7572d047c12ba2bc43acec7f98a67c20af8042", "size": 27616, "url": "https://launcher.mojang.com/v1/objects/3e7572d047c12ba2bc43acec7f98a67c20af8042/libjavafx_font_freetype.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjavafx_font_pango.so": {"downloads": {"lzma": {"sha1": "a7bcf0669e70b0f43099a99c81e6b6440cb40ac0", "size": 5820, "url": "https://launcher.mojang.com/v1/objects/a7bcf0669e70b0f43099a99c81e6b6440cb40ac0/libjavafx_font_pango.so"}, "raw": {"sha1": "f0b775cc9a514c7ee8b4d6fb300653ce548caf10", "size": 25560, "url": "https://launcher.mojang.com/v1/objects/f0b775cc9a514c7ee8b4d6fb300653ce548caf10/libjavafx_font_pango.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjavafx_font_t2k.so": {"downloads": {"lzma": {"sha1": "551c29dc7c7fc83223aa36a6187f7e0c5d650538", "size": 431450, "url": "https://launcher.mojang.com/v1/objects/551c29dc7c7fc83223aa36a6187f7e0c5d650538/libjavafx_font_t2k.so"}, "raw": {"sha1": "91e5813057c3b852d411540160f8ad05fb9f1ed3", "size": 1486128, "url": "https://launcher.mojang.com/v1/objects/91e5813057c3b852d411540160f8ad05fb9f1ed3/libjavafx_font_t2k.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjavafx_iio.so": {"downloads": {"lzma": {"sha1": "c832998fd5e06ed6dcd6428816194c350785420c", "size": 101479, "url": "https://launcher.mojang.com/v1/objects/c832998fd5e06ed6dcd6428816194c350785420c/libjavafx_iio.so"}, "raw": {"sha1": "dcdf68cb25677b76c1cf0bb94294e6e9880a6678", "size": 256336, "url": "https://launcher.mojang.com/v1/objects/dcdf68cb25677b76c1cf0bb94294e6e9880a6678/libjavafx_iio.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjawt.so": {"downloads": {"lzma": {"sha1": "c1ced6aad5c69ff444dc67d0fd7e333558953831", "size": 1872, "url": "https://launcher.mojang.com/v1/objects/c1ced6aad5c69ff444dc67d0fd7e333558953831/libjawt.so"}, "raw": {"sha1": "c5032f2c6fa40bea24e56605cf76b26a27e87b67", "size": 8048, "url": "https://launcher.mojang.com/v1/objects/c5032f2c6fa40bea24e56605cf76b26a27e87b67/libjawt.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjdwp.so": {"downloads": {"lzma": {"sha1": "c1aabbb3f5a624b9ad10ed871a1d83510a99b646", "size": 94884, "url": "https://launcher.mojang.com/v1/objects/c1aabbb3f5a624b9ad10ed871a1d83510a99b646/libjdwp.so"}, "raw": {"sha1": "a043e97be47937f6f552e94cf79c76c1c57f9594", "size": 272248, "url": "https://launcher.mojang.com/v1/objects/a043e97be47937f6f552e94cf79c76c1c57f9594/libjdwp.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjfr.so": {"downloads": {"lzma": {"sha1": "11b8e6bfffdccbacbf9dd29dea4b90b753f3c1b7", "size": 8780, "url": "https://launcher.mojang.com/v1/objects/11b8e6bfffdccbacbf9dd29dea4b90b753f3c1b7/libjfr.so"}, "raw": {"sha1": "312392dd186b11c418183e818f1928e8685a07e5", "size": 28384, "url": "https://launcher.mojang.com/v1/objects/312392dd186b11c418183e818f1928e8685a07e5/libjfr.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjfxmedia.so": {"downloads": {"lzma": {"sha1": "a4e7a126eb648ce6e5e6dc151831da37d8334139", "size": 391897, "url": "https://launcher.mojang.com/v1/objects/a4e7a126eb648ce6e5e6dc151831da37d8334139/libjfxmedia.so"}, "raw": {"sha1": "5fa54944327a6012c3d34cb5c1c4432762178dc8", "size": 1636376, "url": "https://launcher.mojang.com/v1/objects/5fa54944327a6012c3d34cb5c1c4432762178dc8/libjfxmedia.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjfxwebkit.so": {"downloads": {"lzma": {"sha1": "b274debd222cdcc2ee84160ebb95144b3880bc97", "size": 20492825, "url": "https://launcher.mojang.com/v1/objects/b274debd222cdcc2ee84160ebb95144b3880bc97/libjfxwebkit.so"}, "raw": {"sha1": "ecee564c3b2f645131b35bb3004abd4caeabd291", "size": 91014584, "url": "https://launcher.mojang.com/v1/objects/ecee564c3b2f645131b35bb3004abd4caeabd291/libjfxwebkit.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjpeg.so": {"downloads": {"lzma": {"sha1": "9ad55e370c5eaaa73c3158339db3c368b1aaf0cb", "size": 113072, "url": "https://launcher.mojang.com/v1/objects/9ad55e370c5eaaa73c3158339db3c368b1aaf0cb/libjpeg.so"}, "raw": {"sha1": "651e6d53ae67db1f0efbf7f104447a9b49b7e333", "size": 292520, "url": "https://launcher.mojang.com/v1/objects/651e6d53ae67db1f0efbf7f104447a9b49b7e333/libjpeg.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjsdt.so": {"downloads": {"lzma": {"sha1": "04b6d1361a34c496b5f652b2477784d69b8b6baf", "size": 3964, "url": "https://launcher.mojang.com/v1/objects/04b6d1361a34c496b5f652b2477784d69b8b6baf/libjsdt.so"}, "raw": {"sha1": "82b48a82bf6183d34cf00a0f81661b45c616f31b", "size": 12904, "url": "https://launcher.mojang.com/v1/objects/82b48a82bf6183d34cf00a0f81661b45c616f31b/libjsdt.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjsig.so": {"downloads": {"lzma": {"sha1": "37d3b89abde397216cc4ecb1339d8543d99b8428", "size": 3536, "url": "https://launcher.mojang.com/v1/objects/37d3b89abde397216cc4ecb1339d8543d99b8428/libjsig.so"}, "raw": {"sha1": "42e52ba1bcbe0362ab24bcf65c93797354db6fb9", "size": 13336, "url": "https://launcher.mojang.com/v1/objects/42e52ba1bcbe0362ab24bcf65c93797354db6fb9/libjsig.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjsound.so": {"downloads": {"lzma": {"sha1": "7e3c565d74d8ffae716f32b05544fa4a6f108adc", "size": 2002, "url": "https://launcher.mojang.com/v1/objects/7e3c565d74d8ffae716f32b05544fa4a6f108adc/libjsound.so"}, "raw": {"sha1": "0c0fc63b92d7b83c9960fa80d45c80553ea20254", "size": 8232, "url": "https://launcher.mojang.com/v1/objects/0c0fc63b92d7b83c9960fa80d45c80553ea20254/libjsound.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjsoundalsa.so": {"downloads": {"lzma": {"sha1": "b06c51858a25ff776519495f1b9b3d9f604b089f", "size": 23097, "url": "https://launcher.mojang.com/v1/objects/b06c51858a25ff776519495f1b9b3d9f604b089f/libjsoundalsa.so"}, "raw": {"sha1": "281d37f0326d4a12dc7ea316ead09c198ff7bdf7", "size": 83256, "url": "https://launcher.mojang.com/v1/objects/281d37f0326d4a12dc7ea316ead09c198ff7bdf7/libjsoundalsa.so"}}, "executable": true, "type": "file"}, "lib/amd64/liblcms.so": {"downloads": {"lzma": {"sha1": "7a239baba2086cae49114b382b74b971da02f08e", "size": 176175, "url": "https://launcher.mojang.com/v1/objects/7a239baba2086cae49114b382b74b971da02f08e/liblcms.so"}, "raw": {"sha1": "c8895cc3c3d023d9e059225969ab67954772c0a1", "size": 526872, "url": "https://launcher.mojang.com/v1/objects/c8895cc3c3d023d9e059225969ab67954772c0a1/liblcms.so"}}, "executable": true, "type": "file"}, "lib/amd64/libmanagement.so": {"downloads": {"lzma": {"sha1": "aed3fdbcefd1716abfc6a306687c8b741cbb318e", "size": 12838, "url": "https://launcher.mojang.com/v1/objects/aed3fdbcefd1716abfc6a306687c8b741cbb318e/libmanagement.so"}, "raw": {"sha1": "eba35f61e0d50e30874b7c7b335edf2d52662423", "size": 51808, "url": "https://launcher.mojang.com/v1/objects/eba35f61e0d50e30874b7c7b335edf2d52662423/libmanagement.so"}}, "executable": true, "type": "file"}, "lib/amd64/libmlib_image.so": {"downloads": {"lzma": {"sha1": "1bb181f079492d55c7a458e96488cd17fe0a7b86", "size": 310272, "url": "https://launcher.mojang.com/v1/objects/1bb181f079492d55c7a458e96488cd17fe0a7b86/libmlib_image.so"}, "raw": {"sha1": "c973c450d33873675945d4694be484e3427f58f1", "size": 1048136, "url": "https://launcher.mojang.com/v1/objects/c973c450d33873675945d4694be484e3427f58f1/libmlib_image.so"}}, "executable": true, "type": "file"}, "lib/amd64/libnet.so": {"downloads": {"lzma": {"sha1": "9dd79703b6deb86e0321afe01c6ac508263c8312", "size": 38123, "url": "https://launcher.mojang.com/v1/objects/9dd79703b6deb86e0321afe01c6ac508263c8312/libnet.so"}, "raw": {"sha1": "b3a17b7d53fcdf1e689e1ec29ce851eee6022ead", "size": 116920, "url": "https://launcher.mojang.com/v1/objects/b3a17b7d53fcdf1e689e1ec29ce851eee6022ead/libnet.so"}}, "executable": true, "type": "file"}, "lib/amd64/libnio.so": {"downloads": {"lzma": {"sha1": "5697c89d5d5d9b74f2e1555fcbba79dd4049e287", "size": 24445, "url": "https://launcher.mojang.com/v1/objects/5697c89d5d5d9b74f2e1555fcbba79dd4049e287/libnio.so"}, "raw": {"sha1": "573bf8f64dbcc397f8abd3e1da28f90ab0679f5b", "size": 93872, "url": "https://launcher.mojang.com/v1/objects/573bf8f64dbcc397f8abd3e1da28f90ab0679f5b/libnio.so"}}, "executable": true, "type": "file"}, "lib/amd64/libnpjp2.so": {"downloads": {"lzma": {"sha1": "6fe53b5951ff740e7f2ef7ffe5975af26da06718", "size": 57892, "url": "https://launcher.mojang.com/v1/objects/6fe53b5951ff740e7f2ef7ffe5975af26da06718/libnpjp2.so"}, "raw": {"sha1": "2bb13c53a4280379253475e51216b97eed1d4ce3", "size": 216592, "url": "https://launcher.mojang.com/v1/objects/2bb13c53a4280379253475e51216b97eed1d4ce3/libnpjp2.so"}}, "executable": true, "type": "file"}, "lib/amd64/libnpt.so": {"downloads": {"lzma": {"sha1": "1b170b09a32b1b8b6624fa5d1f94ec60b2bf3876", "size": 5070, "url": "https://launcher.mojang.com/v1/objects/1b170b09a32b1b8b6624fa5d1f94ec60b2bf3876/libnpt.so"}, "raw": {"sha1": "6b1ff6b9b4624f3cc7801f221c82b8046fb76364", "size": 17504, "url": "https://launcher.mojang.com/v1/objects/6b1ff6b9b4624f3cc7801f221c82b8046fb76364/libnpt.so"}}, "executable": true, "type": "file"}, "lib/amd64/libprism_common.so": {"downloads": {"lzma": {"sha1": "f4aca04c90bc7505851c074a08b2c31cae1f94fa", "size": 23315, "url": "https://launcher.mojang.com/v1/objects/f4aca04c90bc7505851c074a08b2c31cae1f94fa/libprism_common.so"}, "raw": {"sha1": "b00866b6ed8646a29a334d46e297267552f27de8", "size": 59008, "url": "https://launcher.mojang.com/v1/objects/b00866b6ed8646a29a334d46e297267552f27de8/libprism_common.so"}}, "executable": true, "type": "file"}, "lib/amd64/libprism_es2.so": {"downloads": {"lzma": {"sha1": "7ff4173c338c7a6f370f231670055737e032da3e", "size": 18416, "url": "https://launcher.mojang.com/v1/objects/7ff4173c338c7a6f370f231670055737e032da3e/libprism_es2.so"}, "raw": {"sha1": "1390a1dc14345e5a948148e59195d62f3a83863f", "size": 63808, "url": "https://launcher.mojang.com/v1/objects/1390a1dc14345e5a948148e59195d62f3a83863f/libprism_es2.so"}}, "executable": true, "type": "file"}, "lib/amd64/libprism_sw.so": {"downloads": {"lzma": {"sha1": "6728e8bf7b214067d715be6fe0325910d63c2468", "size": 29457, "url": "https://launcher.mojang.com/v1/objects/6728e8bf7b214067d715be6fe0325910d63c2468/libprism_sw.so"}, "raw": {"sha1": "7a6c34cb2bbcde411778d1b3f8677c39e32c3ac4", "size": 71608, "url": "https://launcher.mojang.com/v1/objects/7a6c34cb2bbcde411778d1b3f8677c39e32c3ac4/libprism_sw.so"}}, "executable": true, "type": "file"}, "lib/amd64/libresource.so": {"downloads": {"lzma": {"sha1": "1e35e63f1e74915fba620f1febf420b919d49bc5", "size": 2633, "url": "https://launcher.mojang.com/v1/objects/1e35e63f1e74915fba620f1febf420b919d49bc5/libresource.so"}, "raw": {"sha1": "57490353ad0d83ab1930355213dea269795434fe", "size": 13456, "url": "https://launcher.mojang.com/v1/objects/57490353ad0d83ab1930355213dea269795434fe/libresource.so"}}, "executable": true, "type": "file"}, "lib/amd64/libsctp.so": {"downloads": {"lzma": {"sha1": "4340132ed250d7849a016e071be773eaedd33aa8", "size": 9332, "url": "https://launcher.mojang.com/v1/objects/4340132ed250d7849a016e071be773eaedd33aa8/libsctp.so"}, "raw": {"sha1": "4a80e743750f127c0d5a359f5cd60b97e7ee12ae", "size": 29552, "url": "https://launcher.mojang.com/v1/objects/4a80e743750f127c0d5a359f5cd60b97e7ee12ae/libsctp.so"}}, "executable": true, "type": "file"}, "lib/amd64/libsplashscreen.so": {"downloads": {"lzma": {"sha1": "b226c8dbd73a548fc2b042ee6db6cc80e727597c", "size": 190305, "url": "https://launcher.mojang.com/v1/objects/b226c8dbd73a548fc2b042ee6db6cc80e727597c/libsplashscreen.so"}, "raw": {"sha1": "87d6a491f5ba7e6c4d972264a0c9063afea567a2", "size": 441376, "url": "https://launcher.mojang.com/v1/objects/87d6a491f5ba7e6c4d972264a0c9063afea567a2/libsplashscreen.so"}}, "executable": true, "type": "file"}, "lib/amd64/libsunec.so": {"downloads": {"lzma": {"sha1": "6ebba98fab1e3d872d1363235b76497f6f9babdc", "size": 88829, "url": "https://launcher.mojang.com/v1/objects/6ebba98fab1e3d872d1363235b76497f6f9babdc/libsunec.so"}, "raw": {"sha1": "3b262a0a530f6e4e539aed2cd27b4de1d0ed8859", "size": 283368, "url": "https://launcher.mojang.com/v1/objects/3b262a0a530f6e4e539aed2cd27b4de1d0ed8859/libsunec.so"}}, "executable": true, "type": "file"}, "lib/amd64/libt2k.so": {"downloads": {"lzma": {"sha1": "602cb812ef0b350ccf56ce209a260ddbe3743d92", "size": 190720, "url": "https://launcher.mojang.com/v1/objects/602cb812ef0b350ccf56ce209a260ddbe3743d92/libt2k.so"}, "raw": {"sha1": "b072c56df997f61e15e6b5a43b8907b0d25c2043", "size": 504840, "url": "https://launcher.mojang.com/v1/objects/b072c56df997f61e15e6b5a43b8907b0d25c2043/libt2k.so"}}, "executable": true, "type": "file"}, "lib/amd64/libunpack.so": {"downloads": {"lzma": {"sha1": "7107b615e941074f0b14c31c88fb67200aacd37f", "size": 70308, "url": "https://launcher.mojang.com/v1/objects/7107b615e941074f0b14c31c88fb67200aacd37f/libunpack.so"}, "raw": {"sha1": "b05ff862ed87928ed91e80e5604673c5ea710a53", "size": 197712, "url": "https://launcher.mojang.com/v1/objects/b05ff862ed87928ed91e80e5604673c5ea710a53/libunpack.so"}}, "executable": true, "type": "file"}, "lib/amd64/libverify.so": {"downloads": {"lzma": {"sha1": "ecd98efb8c7da441a8c3580e8f5598f3cb4165b1", "size": 21885, "url": "https://launcher.mojang.com/v1/objects/ecd98efb8c7da441a8c3580e8f5598f3cb4165b1/libverify.so"}, "raw": {"sha1": "e2c8d92531c45ab9be69ffb72c87fa12e9e59827", "size": 66112, "url": "https://launcher.mojang.com/v1/objects/e2c8d92531c45ab9be69ffb72c87fa12e9e59827/libverify.so"}}, "executable": true, "type": "file"}, "lib/amd64/libzip.so": {"downloads": {"lzma": {"sha1": "7c562342e3f7b138dc978495447e3e6a96c2cf45", "size": 54876, "url": "https://launcher.mojang.com/v1/objects/7c562342e3f7b138dc978495447e3e6a96c2cf45/libzip.so"}, "raw": {"sha1": "5f4bf35a5c3e8f8c650e891d1031589b8ab6d77f", "size": 127016, "url": "https://launcher.mojang.com/v1/objects/5f4bf35a5c3e8f8c650e891d1031589b8ab6d77f/libzip.so"}}, "executable": true, "type": "file"}, "lib/amd64/server": {"type": "directory"}, "lib/amd64/server/Xusage.txt": {"downloads": {"lzma": {"sha1": "acb2da24a4c765887df83985e4c26d6be302a0a3", "size": 629, "url": "https://launcher.mojang.com/v1/objects/acb2da24a4c765887df83985e4c26d6be302a0a3/Xusage.txt"}, "raw": {"sha1": "6983727eafe140f9dd793c78aa6f3e007438243a", "size": 1423, "url": "https://launcher.mojang.com/v1/objects/6983727eafe140f9dd793c78aa6f3e007438243a/Xusage.txt"}}, "executable": false