From dd0e996081ae820a0f16b5a6854a8a6274c5edf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 28 Oct 2016 02:19:19 +0200 Subject: [PATCH] GH-1697 always stale files tolerate errors if a local copy is present This fixes the situation when liteloader snapshot site is broken and there's an older local snapshot already present. --- api/logic/minecraft/Library.cpp | 9 +++++++-- api/logic/net/ByteArraySink.h | 5 +++++ api/logic/net/Download.cpp | 27 +++++++++++++++++++++++---- api/logic/net/Download.h | 17 +++++++++++++---- api/logic/net/FileSink.cpp | 5 +++++ api/logic/net/FileSink.h | 1 + api/logic/net/MetaCacheSink.cpp | 6 ++++++ api/logic/net/MetaCacheSink.h | 1 + api/logic/net/NetAction.h | 3 ++- api/logic/net/Sink.h | 1 + 10 files changed, 64 insertions(+), 11 deletions(-) diff --git a/api/logic/minecraft/Library.cpp b/api/logic/minecraft/Library.cpp index 8bbd5503..5a75fe79 100644 --- a/api/logic/minecraft/Library.cpp +++ b/api/logic/minecraft/Library.cpp @@ -131,6 +131,11 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads(OpSys system, class } return true; } + Net::Download::Options options; + if(isAlwaysStale) + { + options |= Net::Download::Option::AcceptLocalFiles; + } if (isForge) { out.append(ForgeXzDownload::make(storage, entry)); @@ -140,13 +145,13 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads(OpSys system, class if(sha1.size()) { auto rawSha1 = QByteArray::fromHex(sha1.toLatin1()); - auto dl = Net::Download::makeCached(url, entry); + auto dl = Net::Download::makeCached(url, entry, options); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); out.append(dl); } else - out.append(Net::Download::makeCached(url, entry)); + out.append(Net::Download::makeCached(url, entry, options)); } return true; }; diff --git a/api/logic/net/ByteArraySink.h b/api/logic/net/ByteArraySink.h index 3deef1ed..03b77fcc 100644 --- a/api/logic/net/ByteArraySink.h +++ b/api/logic/net/ByteArraySink.h @@ -51,6 +51,11 @@ public: return Job_Failed; } + bool hasLocalData() override + { + return false; + } + private: QByteArray * m_output; }; diff --git a/api/logic/net/Download.cpp b/api/logic/net/Download.cpp index 7610cae3..3d53ded0 100644 --- a/api/logic/net/Download.cpp +++ b/api/logic/net/Download.cpp @@ -31,10 +31,11 @@ Download::Download():NetAction() m_status = Job_NotStarted; } -Download::Ptr Download::makeCached(QUrl url, MetaEntryPtr entry) +Download::Ptr Download::makeCached(QUrl url, MetaEntryPtr entry, Options options) { Download * dl = new Download(); dl->m_url = url; + dl->m_options = options; auto md5Node = new ChecksumValidator(QCryptographicHash::Md5); auto cachedNode = new MetaCacheSink(entry, md5Node); dl->m_sink.reset(cachedNode); @@ -42,18 +43,20 @@ Download::Ptr Download::makeCached(QUrl url, MetaEntryPtr entry) return std::shared_ptr(dl); } -Download::Ptr Download::makeByteArray(QUrl url, QByteArray *output) +Download::Ptr Download::makeByteArray(QUrl url, QByteArray *output, Options options) { Download * dl = new Download(); dl->m_url = url; + dl->m_options = options; dl->m_sink.reset(new ByteArraySink(output)); return std::shared_ptr(dl); } -Download::Ptr Download::makeFile(QUrl url, QString path) +Download::Ptr Download::makeFile(QUrl url, QString path, Options options) { Download * dl = new Download(); dl->m_url = url; + dl->m_options = options; dl->m_sink.reset(new FileSink(path)); return std::shared_ptr(dl); } @@ -118,6 +121,14 @@ void Download::downloadError(QNetworkReply::NetworkError error) } else { + if(m_options & Option::AcceptLocalFiles) + { + if(m_sink->hasLocalData()) + { + m_status = Job_Failed_Proceed; + return; + } + } // error happened during download. qCritical() << "Failed " << m_url.toString() << " with reason " << error; m_status = Job_Failed; @@ -162,7 +173,15 @@ void Download::downloadFinished() } // if the download failed before this point ... - if (m_status == Job_Failed) + if (m_status == Job_Failed_Proceed) + { + qDebug() << "Download failed but we are allowed to proceed:" << m_url.toString(); + m_sink->abort(); + m_reply.reset(); + emit succeeded(m_index_within_job); + return; + } + else if (m_status == Job_Failed) { qDebug() << "Download failed in previous step:" << m_url.toString(); m_sink->abort(); diff --git a/api/logic/net/Download.h b/api/logic/net/Download.h index fab39ffe..d417f660 100644 --- a/api/logic/net/Download.h +++ b/api/logic/net/Download.h @@ -28,14 +28,20 @@ class MULTIMC_LOGIC_EXPORT Download : public NetAction public: /* types */ typedef std::shared_ptr Ptr; + enum class Option + { + NoOptions = 0, + AcceptLocalFiles = 1 + }; + Q_DECLARE_FLAGS(Options, Option) protected: /* con/des */ explicit Download(); public: virtual ~Download(){}; - static Download::Ptr makeCached(QUrl url, MetaEntryPtr entry); - static Download::Ptr makeByteArray(QUrl url, QByteArray *output); - static Download::Ptr makeFile(QUrl url, QString path); + static Download::Ptr makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions); + static Download::Ptr makeByteArray(QUrl url, QByteArray *output, Options options = Option::NoOptions); + static Download::Ptr makeFile(QUrl url, QString path, Options options = Option::NoOptions); public: /* methods */ QString getTargetFilepath() @@ -62,5 +68,8 @@ private: /* data */ // FIXME: remove this, it has no business being here. QString m_target_path; std::unique_ptr m_sink; + Options m_options; }; -} \ No newline at end of file +} + +Q_DECLARE_OPERATORS_FOR_FLAGS(Net::Download::Options) diff --git a/api/logic/net/FileSink.cpp b/api/logic/net/FileSink.cpp index e912b1c9..7dfc4336 100644 --- a/api/logic/net/FileSink.cpp +++ b/api/logic/net/FileSink.cpp @@ -97,4 +97,9 @@ JobStatus FileSink::finalizeCache(QNetworkReply &) return Job_Finished; } +bool FileSink::hasLocalData() +{ + QFileInfo info(m_filename); + return info.exists() && info.size() != 0; +} } diff --git a/api/logic/net/FileSink.h b/api/logic/net/FileSink.h index 7adc9c47..035d5bfd 100644 --- a/api/logic/net/FileSink.h +++ b/api/logic/net/FileSink.h @@ -14,6 +14,7 @@ public: /* methods */ JobStatus write(QByteArray & data) override; JobStatus abort() override; JobStatus finalize(QNetworkReply & reply) override; + bool hasLocalData() override; protected: /* methods */ virtual JobStatus initCache(QNetworkRequest &); diff --git a/api/logic/net/MetaCacheSink.cpp b/api/logic/net/MetaCacheSink.cpp index 539b4bb3..c9d75310 100644 --- a/api/logic/net/MetaCacheSink.cpp +++ b/api/logic/net/MetaCacheSink.cpp @@ -56,4 +56,10 @@ JobStatus MetaCacheSink::finalizeCache(QNetworkReply & reply) ENV.metacache()->updateEntry(m_entry); return Job_Finished; } + +bool MetaCacheSink::hasLocalData() +{ + QFileInfo info(m_filename); + return info.exists() && info.size() != 0; +} } diff --git a/api/logic/net/MetaCacheSink.h b/api/logic/net/MetaCacheSink.h index 98e9bba1..0f3bbdf6 100644 --- a/api/logic/net/MetaCacheSink.h +++ b/api/logic/net/MetaCacheSink.h @@ -9,6 +9,7 @@ class MetaCacheSink : public FileSink public: /* con/des */ MetaCacheSink(MetaEntryPtr entry, ChecksumValidator * md5sum); virtual ~MetaCacheSink(); + bool hasLocalData() override; protected: /* methods */ JobStatus initCache(QNetworkRequest & request) override; diff --git a/api/logic/net/NetAction.h b/api/logic/net/NetAction.h index 07456ce1..aee68230 100644 --- a/api/logic/net/NetAction.h +++ b/api/logic/net/NetAction.h @@ -29,7 +29,8 @@ enum JobStatus Job_InProgress, Job_Finished, Job_Failed, - Job_Aborted + Job_Aborted, + Job_Failed_Proceed }; typedef std::shared_ptr NetActionPtr; diff --git a/api/logic/net/Sink.h b/api/logic/net/Sink.h index 53f2b221..de9b1722 100644 --- a/api/logic/net/Sink.h +++ b/api/logic/net/Sink.h @@ -17,6 +17,7 @@ public: /* methods */ virtual JobStatus write(QByteArray & data) = 0; virtual JobStatus abort() = 0; virtual JobStatus finalize(QNetworkReply & reply) = 0; + virtual bool hasLocalData() = 0; void addValidator(Validator * validator) {