186 lines
5.0 KiB
C++
186 lines
5.0 KiB
C++
/*
|
|
* SPDX-License-Identifier: GPL-3.0-only
|
|
* MuseScore-CLA-applies
|
|
*
|
|
* MuseScore
|
|
* Music Composition & Notation
|
|
*
|
|
* Copyright (C) 2021 MuseScore BVBA and others
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 3 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "updateservice.h"
|
|
|
|
#include <QBuffer>
|
|
#include <QJsonParseError>
|
|
#include <QJsonObject>
|
|
#include <QJsonValue>
|
|
#include <QJsonArray>
|
|
#include <QJsonDocument>
|
|
|
|
#include "../updateerrors.h"
|
|
#include "types/version.h"
|
|
#include "muversion.h"
|
|
|
|
#include "translation.h"
|
|
#include "log.h"
|
|
|
|
using namespace mu::update;
|
|
using namespace mu::network;
|
|
using namespace mu::framework;
|
|
|
|
static std::string platformFileSuffix()
|
|
{
|
|
#if defined(Q_OS_WIN)
|
|
return "msi";
|
|
#elif defined(Q_OS_MACOS)
|
|
return "dmg";
|
|
#elif defined(Q_OS_LINUX)
|
|
return "appimage";
|
|
#endif
|
|
}
|
|
|
|
mu::RetVal<ReleaseInfo> UpdateService::checkForUpdate()
|
|
{
|
|
RetVal<ReleaseInfo> result;
|
|
result.ret = make_ret(Err::NoUpdate);
|
|
|
|
clear();
|
|
|
|
QBuffer buff;
|
|
m_networkManager = networkManagerCreator()->makeNetworkManager();
|
|
Ret getUpdateInfo = m_networkManager->get(QString::fromStdString(configuration()->checkForUpdateUrl()), &buff,
|
|
configuration()->checkForUpdateHeaders());
|
|
|
|
if (!getUpdateInfo) {
|
|
result.ret = make_ret(Err::NetworkError);
|
|
return result;
|
|
}
|
|
|
|
QByteArray json = buff.data();
|
|
|
|
RetVal<ReleaseInfo> releaseInfo = parseRelease(json);
|
|
if (!releaseInfo.ret) {
|
|
return result;
|
|
}
|
|
|
|
if (!releaseInfo.val.isValid()) {
|
|
return result;
|
|
}
|
|
|
|
Version current(MUVersion::fullVersion());
|
|
Version update(String::fromStdString(releaseInfo.val.version));
|
|
if (update <= current) {
|
|
return result;
|
|
}
|
|
|
|
result.ret = make_ok();
|
|
result.val = releaseInfo.val;
|
|
|
|
m_lastCheckResult = result.val;
|
|
return result;
|
|
}
|
|
|
|
mu::RetVal<mu::io::path_t> UpdateService::downloadRelease()
|
|
{
|
|
RetVal<io::path_t> result;
|
|
|
|
QBuffer buff;
|
|
QUrl fileUrl = QUrl::fromUserInput(QString::fromStdString(m_lastCheckResult.fileUrl));
|
|
|
|
m_updateProgress.started.notify();
|
|
|
|
m_networkManager = networkManagerCreator()->makeNetworkManager();
|
|
m_networkManager->progress().progressChanged.onReceive(this, [this](int64_t current, int64_t total, const std::string&) {
|
|
m_updateProgress.progressChanged.send(current, total, trc("update", "Downloading MuseScore") + " " + m_lastCheckResult.version);
|
|
});
|
|
|
|
Ret ret = m_networkManager->get(fileUrl, &buff);
|
|
if (!ret) {
|
|
result.ret = ret;
|
|
return result;
|
|
}
|
|
|
|
io::path_t installerPath = configuration()->updateDataPath() + "/" + m_lastCheckResult.fileName;
|
|
fileSystem()->makePath(io::absoluteDirpath(installerPath));
|
|
|
|
ret = fileSystem()->writeFile(installerPath, ByteArray::fromQByteArrayNoCopy(buff.data()));
|
|
if (ret) {
|
|
result.ret = ret;
|
|
result.val = installerPath;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void UpdateService::cancelUpdate()
|
|
{
|
|
if (m_networkManager) {
|
|
m_networkManager->abort();
|
|
}
|
|
}
|
|
|
|
mu::framework::Progress UpdateService::updateProgress()
|
|
{
|
|
return m_updateProgress;
|
|
}
|
|
|
|
mu::RetVal<ReleaseInfo> UpdateService::parseRelease(const QByteArray& json) const
|
|
{
|
|
RetVal<ReleaseInfo> result;
|
|
|
|
QJsonParseError err;
|
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(json, &err);
|
|
if (err.error != QJsonParseError::NoError || !jsonDoc.isObject()) {
|
|
LOGE() << "failed parse, err: " << err.errorString();
|
|
result.ret = make_ret(Ret::Code::InternalError);
|
|
return result;
|
|
}
|
|
|
|
result.ret = make_ok();
|
|
|
|
QJsonObject release = jsonDoc.object();
|
|
result.val.title = release.value("name").toString().toStdString();
|
|
result.val.notes = release.value("body").toString().toStdString();
|
|
|
|
QString tagName = release.value("tag_name").toString();
|
|
result.val.version = tagName.replace("v", "").toStdString();
|
|
|
|
std::string fileSuffix = platformFileSuffix();
|
|
|
|
QJsonArray assets = release.value("assets").toArray();
|
|
for (const QJsonValue asset : assets) {
|
|
QJsonObject assetObj = asset.toObject();
|
|
|
|
QString name = assetObj.value("name").toString();
|
|
if (io::suffix(name) != fileSuffix) {
|
|
continue;
|
|
}
|
|
|
|
result.val.fileName = name.toStdString();
|
|
result.val.fileUrl = assetObj.value("browser_download_url").toString().toStdString();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void UpdateService::clear()
|
|
{
|
|
m_lastCheckResult = ReleaseInfo();
|
|
|
|
#if !defined(Q_OS_LINUX)
|
|
fileSystem()->remove(configuration()->updateDataPath());
|
|
#endif
|
|
}
|