From d15a6490f6f2d6b1252fc48feaaba9dd89608569 Mon Sep 17 00:00:00 2001
From: Petr Mrázek <peterix@gmail.com>
Date: Sat, 14 Dec 2013 19:26:50 +0100
Subject: Fix bugs introduced by unit test branch

Account json was getting rewritten by a folder
Missing icon on Windows (hopefully fixed, `doing it live`)
---
 CMakeLists.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'CMakeLists.txt')

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8ea5803d..b3e89fc1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -482,10 +482,10 @@ QT5_ADD_RESOURCES(GENERATED_QRC ${CMAKE_CURRENT_BINARY_DIR}/generated.qrc)
 QT5_ADD_RESOURCES(GRAPHICS_QRC graphics.qrc)
 
 # Add common library
-ADD_LIBRARY(MultiMC_common STATIC ${MULTIMC_SOURCES} ${MULTIMC_UI} ${GENERATED_QRC} ${GRAPHICS_QRC} ${MULTIMC_RCS})
+ADD_LIBRARY(MultiMC_common STATIC ${MULTIMC_SOURCES} ${MULTIMC_UI} ${GENERATED_QRC} ${GRAPHICS_QRC})
 
 # Add executable
-ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32 main.cpp)
+ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32 main.cpp ${MULTIMC_RCS})
 
 # Link
 TARGET_LINK_LIBRARIES(MultiMC MultiMC_common)
-- 
cgit 


From 5a3043398e45cbe39455609a42463f2e6e5d3fd2 Mon Sep 17 00:00:00 2001
From: Petr Mrázek <peterix@gmail.com>
Date: Sun, 15 Dec 2013 15:00:09 +0100
Subject: Use asset sizes from the index to make the progress bar better

---
 CMakeLists.txt                  |   2 -
 logic/OneSixUpdate.cpp          |   1 +
 logic/net/ByteArrayDownload.cpp |   8 +-
 logic/net/CacheDownload.cpp     |  14 ++--
 logic/net/ForgeMirrors.cpp      |   8 +-
 logic/net/ForgeXzDownload.cpp   |  18 +++--
 logic/net/MD5EtagDownload.cpp   |  16 ++--
 logic/net/NetAction.h           |  23 +++++-
 logic/net/NetJob.h              |  12 ++-
 logic/net/PasteUpload.cpp       |   2 +
 logic/net/S3ListBucket.cpp      | 175 ----------------------------------------
 logic/net/S3ListBucket.h        |  57 -------------
 12 files changed, 70 insertions(+), 266 deletions(-)
 delete mode 100644 logic/net/S3ListBucket.cpp
 delete mode 100644 logic/net/S3ListBucket.h

(limited to 'CMakeLists.txt')

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b3e89fc1..33f74a8a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -300,8 +300,6 @@ logic/net/NetJob.h
 logic/net/NetJob.cpp
 logic/net/HttpMetaCache.h
 logic/net/HttpMetaCache.cpp
-logic/net/S3ListBucket.h
-logic/net/S3ListBucket.cpp
 logic/net/PasteUpload.h
 logic/net/PasteUpload.cpp
 logic/net/URLConstants.h
diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp
index 66950fc4..62332267 100644
--- a/logic/OneSixUpdate.cpp
+++ b/logic/OneSixUpdate.cpp
@@ -243,6 +243,7 @@ void OneSixUpdate::assetIndexFinished()
 			auto objectDL = MD5EtagDownload::make(
 				QUrl("http://" + URLConstants::RESOURCE_BASE + objectName),
 				objectFile.filePath());
+			objectDL->m_total_progress = object.size;
 			dls.append(objectDL);
 		}
 	}
diff --git a/logic/net/ByteArrayDownload.cpp b/logic/net/ByteArrayDownload.cpp
index af5af8e9..27d2a250 100644
--- a/logic/net/ByteArrayDownload.cpp
+++ b/logic/net/ByteArrayDownload.cpp
@@ -42,7 +42,9 @@ void ByteArrayDownload::start()
 
 void ByteArrayDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
 {
-	emit progress(index_within_job, bytesReceived, bytesTotal);
+	m_total_progress = bytesTotal;
+	m_progress = bytesReceived;
+	emit progress(m_index_within_job, bytesReceived, bytesTotal);
 }
 
 void ByteArrayDownload::downloadError(QNetworkReply::NetworkError error)
@@ -62,14 +64,14 @@ void ByteArrayDownload::downloadFinished()
 		m_status = Job_Finished;
 		m_data = m_reply->readAll();
 		m_reply.reset();
-		emit succeeded(index_within_job);
+		emit succeeded(m_index_within_job);
 		return;
 	}
 	// else the download failed
 	else
 	{
 		m_reply.reset();
-		emit failed(index_within_job);
+		emit failed(m_index_within_job);
 		return;
 	}
 }
diff --git a/logic/net/CacheDownload.cpp b/logic/net/CacheDownload.cpp
index 873d3a2e..6eadae39 100644
--- a/logic/net/CacheDownload.cpp
+++ b/logic/net/CacheDownload.cpp
@@ -35,14 +35,14 @@ void CacheDownload::start()
 {
 	if (!m_entry->stale)
 	{
-		emit succeeded(index_within_job);
+		emit succeeded(m_index_within_job);
 		return;
 	}
 	m_output_file.setFileName(m_target_path);
 	// if there already is a file and md5 checking is in effect and it can be opened
 	if (!ensureFilePathExists(m_target_path))
 	{
-		emit failed(index_within_job);
+		emit failed(m_index_within_job);
 		return;
 	}
 	QLOG_INFO() << "Downloading " << m_url.toString();
@@ -69,7 +69,9 @@ void CacheDownload::start()
 
 void CacheDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
 {
-	emit progress(index_within_job, bytesReceived, bytesTotal);
+	m_total_progress = bytesTotal;
+	m_progress = bytesReceived;
+	emit progress(m_index_within_job, bytesReceived, bytesTotal);
 }
 
 void CacheDownload::downloadError(QNetworkReply::NetworkError error)
@@ -116,7 +118,7 @@ void CacheDownload::downloadFinished()
 		MMC->metacache()->updateEntry(m_entry);
 
 		m_reply.reset();
-		emit succeeded(index_within_job);
+		emit succeeded(m_index_within_job);
 		return;
 	}
 	// else the download failed
@@ -125,7 +127,7 @@ void CacheDownload::downloadFinished()
 		m_output_file.close();
 		m_output_file.remove();
 		m_reply.reset();
-		emit failed(index_within_job);
+		emit failed(m_index_within_job);
 		return;
 	}
 }
@@ -140,7 +142,7 @@ void CacheDownload::downloadReadyRead()
 			* Can't open the file... the job failed
 			*/
 			m_reply->abort();
-			emit failed(index_within_job);
+			emit failed(m_index_within_job);
 			return;
 		}
 	}
diff --git a/logic/net/ForgeMirrors.cpp b/logic/net/ForgeMirrors.cpp
index fd7eccca..b224306f 100644
--- a/logic/net/ForgeMirrors.cpp
+++ b/logic/net/ForgeMirrors.cpp
@@ -68,7 +68,7 @@ void ForgeMirrors::deferToFixedList()
 					  "https://www.creeperhost.net/link.php?id=1",
 					  "http://new.creeperrepo.net/forge/maven/"});
 	injectDownloads();
-	emit succeeded(index_within_job);
+	emit succeeded(m_index_within_job);
 }
 
 void ForgeMirrors::parseMirrorList()
@@ -88,7 +88,7 @@ void ForgeMirrors::parseMirrorList()
 	if(!m_mirrors.size())
 		deferToFixedList();
 	injectDownloads();
-	emit succeeded(index_within_job);
+	emit succeeded(m_index_within_job);
 }
 
 void ForgeMirrors::injectDownloads()
@@ -108,7 +108,9 @@ void ForgeMirrors::injectDownloads()
 
 void ForgeMirrors::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
 {
-	emit progress(index_within_job, bytesReceived, bytesTotal);
+	m_total_progress = bytesTotal;
+	m_progress = bytesReceived;
+	emit progress(m_index_within_job, bytesReceived, bytesTotal);
 }
 
 void ForgeMirrors::downloadReadyRead()
diff --git a/logic/net/ForgeXzDownload.cpp b/logic/net/ForgeXzDownload.cpp
index f119878a..1771d304 100644
--- a/logic/net/ForgeXzDownload.cpp
+++ b/logic/net/ForgeXzDownload.cpp
@@ -44,20 +44,20 @@ void ForgeXzDownload::start()
 	if (!m_entry->stale)
 	{
 		m_status = Job_Finished;
-		emit succeeded(index_within_job);
+		emit succeeded(m_index_within_job);
 		return;
 	}
 	// can we actually create the real, final file?
 	if (!ensureFilePathExists(m_target_path))
 	{
 		m_status = Job_Failed;
-		emit failed(index_within_job);
+		emit failed(m_index_within_job);
 		return;
 	}
 	if (m_mirrors.empty())
 	{
 		m_status = Job_Failed;
-		emit failed(index_within_job);
+		emit failed(m_index_within_job);
 		return;
 	}
 
@@ -80,7 +80,9 @@ void ForgeXzDownload::start()
 
 void ForgeXzDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
 {
-	emit progress(index_within_job, bytesReceived, bytesTotal);
+	m_total_progress = bytesTotal;
+	m_progress = bytesReceived;
+	emit progress(m_index_within_job, bytesReceived, bytesTotal);
 }
 
 void ForgeXzDownload::downloadError(QNetworkReply::NetworkError error)
@@ -100,7 +102,7 @@ void ForgeXzDownload::failAndTryNextMirror()
 		m_mirror_index = next;
 
 	updateUrl();
-	emit failed(index_within_job);
+	emit failed(m_index_within_job);
 }
 
 void ForgeXzDownload::updateUrl()
@@ -148,7 +150,7 @@ void ForgeXzDownload::downloadFinished()
 			m_status = Job_Failed;
 			m_pack200_xz_file.remove();
 			m_reply.reset();
-			emit failed(index_within_job);
+			emit failed(m_index_within_job);
 			return;
 		}
 	}
@@ -175,7 +177,7 @@ void ForgeXzDownload::downloadReadyRead()
 			* Can't open the file... the job failed
 			*/
 			m_reply->abort();
-			emit failed(index_within_job);
+			emit failed(m_index_within_job);
 			return;
 		}
 	}
@@ -347,5 +349,5 @@ void ForgeXzDownload::decompressAndInstall()
 	MMC->metacache()->updateEntry(m_entry);
 
 	m_reply.reset();
-	emit succeeded(index_within_job);
+	emit succeeded(m_index_within_job);
 }
diff --git a/logic/net/MD5EtagDownload.cpp b/logic/net/MD5EtagDownload.cpp
index 4b9f52af..435e854e 100644
--- a/logic/net/MD5EtagDownload.cpp
+++ b/logic/net/MD5EtagDownload.cpp
@@ -44,7 +44,7 @@ void MD5EtagDownload::start()
 		if (m_check_md5 && hash == m_expected_md5)
 		{
 			QLOG_INFO() << "Skipping " << m_url.toString() << ": md5 match.";
-			emit succeeded(index_within_job);
+			emit succeeded(m_index_within_job);
 			return;
 		}
 		else
@@ -54,7 +54,7 @@ void MD5EtagDownload::start()
 	}
 	if (!ensureFilePathExists(filename))
 	{
-		emit failed(index_within_job);
+		emit failed(m_index_within_job);
 		return;
 	}
 
@@ -68,7 +68,7 @@ void MD5EtagDownload::start()
 	// Plus, this way, we don't end up starting a download for a file we can't open.
 	if (!m_output_file.open(QIODevice::WriteOnly))
 	{
-		emit failed(index_within_job);
+		emit failed(m_index_within_job);
 		return;
 	}
 
@@ -86,7 +86,9 @@ void MD5EtagDownload::start()
 
 void MD5EtagDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
 {
-	emit progress(index_within_job, bytesReceived, bytesTotal);
+	m_total_progress = bytesTotal;
+	m_progress = bytesReceived;
+	emit progress(m_index_within_job, bytesReceived, bytesTotal);
 }
 
 void MD5EtagDownload::downloadError(QNetworkReply::NetworkError error)
@@ -107,7 +109,7 @@ void MD5EtagDownload::downloadFinished()
 
 		QLOG_INFO() << "Finished " << m_url.toString() << " got " << m_reply->rawHeader("ETag").constData();
 		m_reply.reset();
-		emit succeeded(index_within_job);
+		emit succeeded(m_index_within_job);
 		return;
 	}
 	// else the download failed
@@ -115,7 +117,7 @@ void MD5EtagDownload::downloadFinished()
 	{
 		m_output_file.close();
 		m_reply.reset();
-		emit failed(index_within_job);
+		emit failed(m_index_within_job);
 		return;
 	}
 }
@@ -130,7 +132,7 @@ void MD5EtagDownload::downloadReadyRead()
 			* Can't open the file... the job failed
 			*/
 			m_reply->abort();
-			emit failed(index_within_job);
+			emit failed(m_index_within_job);
 			return;
 		}
 	}
diff --git a/logic/net/NetAction.h b/logic/net/NetAction.h
index c96d8f8f..97c96e5d 100644
--- a/logic/net/NetAction.h
+++ b/logic/net/NetAction.h
@@ -38,6 +38,19 @@ protected:
 public:
 	virtual ~NetAction() {};
 
+public:
+	virtual qint64 totalProgress() const
+	{
+		return m_total_progress;
+	}
+	virtual qint64 currentProgress() const
+	{
+		return m_progress;
+	}
+	virtual qint64 numberOfFailures() const
+	{
+		return m_failures;
+	}
 public:
 	/// the network reply
 	std::shared_ptr<QNetworkReply> m_reply;
@@ -46,10 +59,16 @@ public:
 	QUrl m_url;
 
 	/// The file's status
-	JobStatus m_status;
+	JobStatus m_status = Job_NotStarted;
 
 	/// index within the parent job
-	int index_within_job = 0;
+	int m_index_within_job = 0;
+
+	qint64 m_progress = 0;
+	qint64 m_total_progress = 1;
+
+	/// number of failures up to this point
+	int m_failures = 0;
 
 signals:
 	void started(int index);
diff --git a/logic/net/NetJob.h b/logic/net/NetJob.h
index 6e2e7607..68c4c408 100644
--- a/logic/net/NetJob.h
+++ b/logic/net/NetJob.h
@@ -36,10 +36,16 @@ public:
 	template <typename T> bool addNetAction(T action)
 	{
 		NetActionPtr base = std::static_pointer_cast<NetAction>(action);
-		base->index_within_job = downloads.size();
+		base->m_index_within_job = downloads.size();
 		downloads.append(action);
-		parts_progress.append(part_info());
-		total_progress++;
+		part_info pi;
+		{
+			pi.current_progress = base->currentProgress();
+			pi.total_progress = base->totalProgress();
+			pi.failures = base->numberOfFailures();
+		}
+		parts_progress.append(pi);
+		total_progress += pi.total_progress;
 		// if this is already running, the action needs to be started right away!
 		if (isRunning())
 		{
diff --git a/logic/net/PasteUpload.cpp b/logic/net/PasteUpload.cpp
index acf09291..fa54d084 100644
--- a/logic/net/PasteUpload.cpp
+++ b/logic/net/PasteUpload.cpp
@@ -78,7 +78,9 @@ bool PasteUpload::parseResult(QJsonDocument doc, QString *parseError)
 		parseError = new QString(object.value("error").toString());
 		return false;
 	}
+	// FIXME: not the place for GUI things.
 	QString pasteUrl = object.value("paste").toObject().value("link").toString();
 	QDesktopServices::openUrl(pasteUrl);
 	return true;
 }
+
diff --git a/logic/net/S3ListBucket.cpp b/logic/net/S3ListBucket.cpp
deleted file mode 100644
index 439b7086..00000000
--- a/logic/net/S3ListBucket.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/* Copyright 2013 MultiMC Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "S3ListBucket.h"
-#include "MultiMC.h"
-#include "logger/QsLog.h"
-#include <QUrlQuery>
-#include <qxmlstream.h>
-#include <QDomDocument>
-
-inline QDomElement getDomElementByTagName(QDomElement parent, QString tagname)
-{
-	QDomNodeList elementList = parent.elementsByTagName(tagname);
-	if (elementList.count())
-		return elementList.at(0).toElement();
-	else
-		return QDomElement();
-}
-
-S3ListBucket::S3ListBucket(QUrl url) : NetAction()
-{
-	m_url = url;
-	m_status = Job_NotStarted;
-}
-
-void S3ListBucket::start()
-{
-	QUrl finalUrl = m_url;
-	if (current_marker.size())
-	{
-		QUrlQuery query;
-		query.addQueryItem("marker", current_marker);
-		finalUrl.setQuery(query);
-	}
-	QNetworkRequest request(finalUrl);
-	request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)");
-	auto worker = MMC->qnam();
-	QNetworkReply *rep = worker->get(request);
-
-	m_reply = std::shared_ptr<QNetworkReply>(rep);
-	connect(rep, SIGNAL(downloadProgress(qint64, qint64)),
-			SLOT(downloadProgress(qint64, qint64)));
-	connect(rep, SIGNAL(finished()), SLOT(downloadFinished()));
-	connect(rep, SIGNAL(error(QNetworkReply::NetworkError)),
-			SLOT(downloadError(QNetworkReply::NetworkError)));
-	connect(rep, SIGNAL(readyRead()), SLOT(downloadReadyRead()));
-}
-
-void S3ListBucket::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
-{
-	emit progress(index_within_job, bytesSoFar + bytesReceived, bytesSoFar + bytesTotal);
-}
-
-void S3ListBucket::downloadError(QNetworkReply::NetworkError error)
-{
-	// error happened during download.
-	QLOG_ERROR() << "Error getting URL:" << m_url.toString().toLocal8Bit()
-				 << "Network error: " << error;
-	m_status = Job_Failed;
-}
-
-void S3ListBucket::processValidReply()
-{
-	QLOG_TRACE() << "GOT: " << m_url.toString() << " marker:" << current_marker;
-	auto readContents = [&](QXmlStreamReader & xml)
-	{
-		QString Key, ETag, Size;
-		while (!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == "Contents"))
-		{
-			if (xml.tokenType() == QXmlStreamReader::StartElement)
-			{
-				if (xml.name() == "Key")
-				{
-					Key = xml.readElementText();
-				}
-				if (xml.name() == "ETag")
-				{
-					ETag = xml.readElementText();
-				}
-				if (xml.name() == "Size")
-				{
-					Size = xml.readElementText();
-				}
-			}
-			xml.readNext();
-		}
-		if (xml.error() != QXmlStreamReader::NoError)
-			return;
-		objects.append({Key, ETag, Size.toLongLong()});
-	};
-
-	// nothing went wrong...
-	QByteArray ba = m_reply->readAll();
-
-	QString xmlErrorMsg;
-
-	bool is_truncated = false;
-	QXmlStreamReader xml(ba);
-	while (!xml.atEnd() && !xml.hasError())
-	{
-		/* Read next element.*/
-		QXmlStreamReader::TokenType token = xml.readNext();
-		/* If token is just StartDocument, we'll go to next.*/
-		if (token == QXmlStreamReader::StartDocument)
-		{
-			continue;
-		}
-		if (token == QXmlStreamReader::StartElement)
-		{
-			/* If it's named person, we'll dig the information from there.*/
-			if (xml.name() == "Contents")
-			{
-				readContents(xml);
-			}
-			else if (xml.name() == "IsTruncated")
-			{
-				is_truncated = (xml.readElementText() == "true");
-			}
-		}
-	}
-	if (xml.hasError())
-	{
-		QLOG_ERROR() << "Failed to process s3.amazonaws.com/Minecraft.Resources. XML error:"
-					 << xml.errorString() << ba;
-		emit failed(index_within_job);
-		return;
-	}
-	if (is_truncated)
-	{
-		current_marker = objects.last().Key;
-		bytesSoFar += m_reply->size();
-		m_reply.reset();
-		start();
-	}
-	else
-	{
-		m_status = Job_Finished;
-		m_reply.reset();
-		emit succeeded(index_within_job);
-	}
-	return;
-}
-
-void S3ListBucket::downloadFinished()
-{
-	// if the download succeeded
-	if (m_status != Job_Failed)
-	{
-		processValidReply();
-	}
-	// else the download failed
-	else
-	{
-		m_reply.reset();
-		emit failed(index_within_job);
-		return;
-	}
-}
-
-void S3ListBucket::downloadReadyRead()
-{
-	// ~_~
-}
diff --git a/logic/net/S3ListBucket.h b/logic/net/S3ListBucket.h
deleted file mode 100644
index e7c5e05c..00000000
--- a/logic/net/S3ListBucket.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Copyright 2013 MultiMC Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-#include "NetAction.h"
-
-struct S3Object
-{
-	QString Key;
-	QString ETag;
-	qlonglong size;
-};
-
-typedef std::shared_ptr<class S3ListBucket> S3ListBucketPtr;
-class S3ListBucket : public NetAction
-{
-	Q_OBJECT
-public:
-	S3ListBucket(QUrl url);
-	static S3ListBucketPtr make(QUrl url)
-	{
-		return S3ListBucketPtr(new S3ListBucket(url));
-	}
-
-public:
-	QList<S3Object> objects;
-
-public
-slots:
-	virtual void start() override;
-
-protected
-slots:
-	virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override;
-	virtual void downloadError(QNetworkReply::NetworkError error) override;
-	virtual void downloadFinished() override;
-	virtual void downloadReadyRead() override;
-
-private:
-	void processValidReply();
-
-private:
-	qint64 bytesSoFar = 0;
-	QString current_marker;
-};
-- 
cgit