309 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			309 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "Library.h"
 | |
| #include "MinecraftInstance.h"
 | |
| 
 | |
| #include <net/Download.h>
 | |
| #include <net/ChecksumValidator.h>
 | |
| #include <FileSystem.h>
 | |
| #include <BuildConfig.h>
 | |
| 
 | |
| 
 | |
| void Library::getApplicableFiles(OpSys system, QStringList& jar, QStringList& native, QStringList& native32,
 | |
|                                  QStringList& native64, const QString &overridePath) const
 | |
| {
 | |
|     bool local = isLocal();
 | |
|     auto actualPath = [&](QString relPath)
 | |
|     {
 | |
|         QFileInfo out(FS::PathCombine(storagePrefix(), relPath));
 | |
|         if(local && !overridePath.isEmpty())
 | |
|         {
 | |
|             QString fileName = out.fileName();
 | |
|             return QFileInfo(FS::PathCombine(overridePath, fileName)).absoluteFilePath();
 | |
|         }
 | |
|         return out.absoluteFilePath();
 | |
|     };
 | |
|     QString raw_storage = storageSuffix(system);
 | |
|     if(isNative())
 | |
|     {
 | |
|         if (raw_storage.contains("${arch}"))
 | |
|         {
 | |
|             auto nat32Storage = raw_storage;
 | |
|             nat32Storage.replace("${arch}", "32");
 | |
|             auto nat64Storage = raw_storage;
 | |
|             nat64Storage.replace("${arch}", "64");
 | |
|             native32 += actualPath(nat32Storage);
 | |
|             native64 += actualPath(nat64Storage);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             native += actualPath(raw_storage);
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         jar += actualPath(raw_storage);
 | |
|     }
 | |
| }
 | |
| 
 | |
| QList<NetAction::Ptr> Library::getDownloads(
 | |
|     OpSys system,
 | |
|     class HttpMetaCache* cache,
 | |
|     QStringList& failedLocalFiles,
 | |
|     const QString & overridePath
 | |
| ) const
 | |
| {
 | |
|     QList<NetAction::Ptr> out;
 | |
|     bool stale = isAlwaysStale();
 | |
|     bool local = isLocal();
 | |
| 
 | |
|     auto check_local_file = [&](QString storage)
 | |
|     {
 | |
|         QFileInfo fileinfo(storage);
 | |
|         QString fileName = fileinfo.fileName();
 | |
|         auto fullPath = FS::PathCombine(overridePath, fileName);
 | |
|         QFileInfo localFileInfo(fullPath);
 | |
|         if(!localFileInfo.exists())
 | |
|         {
 | |
|             failedLocalFiles.append(localFileInfo.filePath());
 | |
|             return false;
 | |
|         }
 | |
|         return true;
 | |
|     };
 | |
| 
 | |
|     auto add_download = [&](QString storage, QString url, QString sha1)
 | |
|     {
 | |
|         if(local)
 | |
|         {
 | |
|             return check_local_file(storage);
 | |
|         }
 | |
|         auto entry = cache->resolveEntry("libraries", storage);
 | |
|         if(stale)
 | |
|         {
 | |
|             entry->setStale(true);
 | |
|         }
 | |
|         if (!entry->isStale())
 | |
|             return true;
 | |
|         Net::Download::Options options;
 | |
|         if(stale)
 | |
|         {
 | |
|             options |= Net::Download::Option::AcceptLocalFiles;
 | |
|         }
 | |
| 
 | |
|         if(sha1.size())
 | |
|         {
 | |
|             auto rawSha1 = QByteArray::fromHex(sha1.toLatin1());
 | |
|             auto dl = Net::Download::makeCached(url, entry, options);
 | |
|             dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
 | |
|             qDebug() << "Checksummed Download for:" << rawName().serialize() << "storage:" << storage << "url:" << url;
 | |
|             out.append(dl);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             out.append(Net::Download::makeCached(url, entry, options));
 | |
|             qDebug() << "Download for:" << rawName().serialize() << "storage:" << storage << "url:" << url;
 | |
|         }
 | |
|         return true;
 | |
|     };
 | |
| 
 | |
|     QString raw_storage = storageSuffix(system);
 | |
|     if(m_mojangDownloads)
 | |
|     {
 | |
|         if(isNative())
 | |
|         {
 | |
|             if(m_nativeClassifiers.contains(system))
 | |
|             {
 | |
|                 auto nativeClassifier = m_nativeClassifiers[system];
 | |
|                 if(nativeClassifier.contains("${arch}"))
 | |
|                 {
 | |
|                     auto nat32Classifier = nativeClassifier;
 | |
|                     nat32Classifier.replace("${arch}", "32");
 | |
|                     auto nat64Classifier = nativeClassifier;
 | |
|                     nat64Classifier.replace("${arch}", "64");
 | |
|                     auto nat32info = m_mojangDownloads->getDownloadInfo(nat32Classifier);
 | |
|                     if(nat32info)
 | |
|                     {
 | |
|                         auto cooked_storage = raw_storage;
 | |
|                         cooked_storage.replace("${arch}", "32");
 | |
|                         add_download(cooked_storage, nat32info->url, nat32info->sha1);
 | |
|                     }
 | |
|                     auto nat64info = m_mojangDownloads->getDownloadInfo(nat64Classifier);
 | |
|                     if(nat64info)
 | |
|                     {
 | |
|                         auto cooked_storage = raw_storage;
 | |
|                         cooked_storage.replace("${arch}", "64");
 | |
|                         add_download(cooked_storage, nat64info->url, nat64info->sha1);
 | |
|                     }
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     auto info = m_mojangDownloads->getDownloadInfo(nativeClassifier);
 | |
|                     if(info)
 | |
|                     {
 | |
|                         add_download(raw_storage, info->url, info->sha1);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 qDebug() << "Ignoring native library" << m_name.serialize() << "because it has no classifier for current OS";
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             if(m_mojangDownloads->artifact)
 | |
|             {
 | |
|                 auto artifact = m_mojangDownloads->artifact;
 | |
|                 add_download(raw_storage, artifact->url, artifact->sha1);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 qDebug() << "Ignoring java library" << m_name.serialize() << "because it has no artifact";
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         auto raw_dl = [&]()
 | |
|         {
 | |
|             if (!m_absoluteURL.isEmpty())
 | |
|             {
 | |
|                 return m_absoluteURL;
 | |
|             }
 | |
| 
 | |
|             if (m_repositoryURL.isEmpty())
 | |
|             {
 | |
|                 return BuildConfig.LIBRARY_BASE + raw_storage;
 | |
|             }
 | |
| 
 | |
|             if(m_repositoryURL.endsWith('/'))
 | |
|             {
 | |
|                 return m_repositoryURL + raw_storage;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 return m_repositoryURL + QChar('/') + raw_storage;
 | |
|             }
 | |
|         }();
 | |
|         if (raw_storage.contains("${arch}"))
 | |
|         {
 | |
|             QString cooked_storage = raw_storage;
 | |
|             QString cooked_dl = raw_dl;
 | |
|             add_download(cooked_storage.replace("${arch}", "32"), cooked_dl.replace("${arch}", "32"), QString());
 | |
|             cooked_storage = raw_storage;
 | |
|             cooked_dl = raw_dl;
 | |
|             add_download(cooked_storage.replace("${arch}", "64"), cooked_dl.replace("${arch}", "64"), QString());
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             add_download(raw_storage, raw_dl, QString());
 | |
|         }
 | |
|     }
 | |
|     return out;
 | |
| }
 | |
| 
 | |
| bool Library::isActive() const
 | |
| {
 | |
|     bool result = true;
 | |
|     if (m_rules.empty())
 | |
|     {
 | |
|         result = true;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         RuleAction ruleResult = Disallow;
 | |
|         for (auto rule : m_rules)
 | |
|         {
 | |
|             RuleAction temp = rule->apply(this);
 | |
|             if (temp != Defer)
 | |
|                 ruleResult = temp;
 | |
|         }
 | |
|         result = result && (ruleResult == Allow);
 | |
|     }
 | |
|     if (isNative())
 | |
|     {
 | |
|         result = result && m_nativeClassifiers.contains(currentSystem);
 | |
|     }
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| bool Library::isLocal() const
 | |
| {
 | |
|     return m_hint == "local";
 | |
| }
 | |
| 
 | |
| bool Library::isAlwaysStale() const
 | |
| {
 | |
|     return m_hint == "always-stale";
 | |
| }
 | |
| 
 | |
| void Library::setStoragePrefix(QString prefix)
 | |
| {
 | |
|     m_storagePrefix = prefix;
 | |
| }
 | |
| 
 | |
| QString Library::defaultStoragePrefix()
 | |
| {
 | |
|     return "libraries/";
 | |
| }
 | |
| 
 | |
| QString Library::storagePrefix() const
 | |
| {
 | |
|     if(m_storagePrefix.isEmpty())
 | |
|     {
 | |
|         return defaultStoragePrefix();
 | |
|     }
 | |
|     return m_storagePrefix;
 | |
| }
 | |
| 
 | |
| QString Library::filename(OpSys system) const
 | |
| {
 | |
|     if(!m_filename.isEmpty())
 | |
|     {
 | |
|         return m_filename;
 | |
|     }
 | |
|     // non-native? use only the gradle specifier
 | |
|     if (!isNative())
 | |
|     {
 | |
|         return m_name.getFileName();
 | |
|     }
 | |
| 
 | |
|     // otherwise native, override classifiers. Mojang HACK!
 | |
|     GradleSpecifier nativeSpec = m_name;
 | |
|     if (m_nativeClassifiers.contains(system))
 | |
|     {
 | |
|         nativeSpec.setClassifier(m_nativeClassifiers[system]);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         nativeSpec.setClassifier("INVALID");
 | |
|     }
 | |
|     return nativeSpec.getFileName();
 | |
| }
 | |
| 
 | |
| QString Library::displayName(OpSys system) const
 | |
| {
 | |
|     if(!m_displayname.isEmpty())
 | |
|         return m_displayname;
 | |
|     return filename(system);
 | |
| }
 | |
| 
 | |
| QString Library::storageSuffix(OpSys system) const
 | |
| {
 | |
|     // non-native? use only the gradle specifier
 | |
|     if (!isNative())
 | |
|     {
 | |
|         return m_name.toPath(m_filename);
 | |
|     }
 | |
| 
 | |
|     // otherwise native, override classifiers. Mojang HACK!
 | |
|     GradleSpecifier nativeSpec = m_name;
 | |
|     if (m_nativeClassifiers.contains(system))
 | |
|     {
 | |
|         nativeSpec.setClassifier(m_nativeClassifiers[system]);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         nativeSpec.setClassifier("INVALID");
 | |
|     }
 | |
|     return nativeSpec.toPath(m_filename);
 | |
| }
 |