273 lines
8.6 KiB
C++
273 lines
8.6 KiB
C++
// This file is part of RSS Guard.
|
|
//
|
|
// Copyright (C) 2011-2014 by Martin Rotter <rotter.martinos@gmail.com>
|
|
//
|
|
// RSS Guard is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// RSS Guard 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 RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#include "definitions/definitions.h"
|
|
#include "qtsingleapplication/qtsinglecoreapplication.h"
|
|
|
|
#include <QTranslator>
|
|
#include <QDebug>
|
|
#include <QThread>
|
|
#include <QProcess>
|
|
#include <QFileInfo>
|
|
#include <QDir>
|
|
|
|
#include <iostream>
|
|
#include <limits>
|
|
|
|
|
|
bool removeDir(const QString & dirName, const QStringList &exception_file_list = QStringList()) {
|
|
bool result = true;
|
|
QDir dir(dirName);
|
|
|
|
if (dir.exists(dirName)) {
|
|
foreach (QFileInfo info,
|
|
dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst)) {
|
|
if (info.isDir()) {
|
|
result &= removeDir(info.absoluteFilePath(), exception_file_list);
|
|
}
|
|
else if (!exception_file_list.contains(info.fileName())) {
|
|
result &= QFile::remove(info.absoluteFilePath());
|
|
}
|
|
}
|
|
|
|
result &= dir.rmdir(dirName);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool copyPath(QString src, QString dst) {
|
|
QDir dir(src);
|
|
|
|
if (! dir.exists()) {
|
|
return false;
|
|
}
|
|
|
|
foreach (QString d, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
|
|
QString dst_path = dst + QDir::separator() + d;
|
|
dir.mkpath(dst_path);
|
|
copyPath(src + QDir::separator() + d, dst_path);
|
|
}
|
|
|
|
foreach (QString f, dir.entryList(QDir::Files)) {
|
|
QString original_file = src + QDir::separator() + f;
|
|
QString destination_file = dst + QDir::separator() + f;
|
|
|
|
if (!QFile::exists(destination_file) || QFile::remove(destination_file)) {
|
|
if (QFile::copy(original_file, destination_file)) {
|
|
qDebug("Copied file %s", qPrintable(f));
|
|
}
|
|
else {
|
|
qDebug("Failed to copy file %s", qPrintable(original_file));
|
|
}
|
|
}
|
|
else {
|
|
qDebug("Failed to remove file %s", qPrintable(original_file));
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Main entry point to "rssguard_updater.exe".
|
|
// It expects 4 ARGUMENTS:
|
|
// 0) - the actual path of this process,
|
|
// 1) - string with current version,
|
|
// 2) - string with future version,
|
|
// 3) - path to RSS Guard ("rssguard.exe") file,
|
|
// 4) - path to update file (stored in TEMP folder).
|
|
int main(int argc, char *argv[]) {
|
|
// Instantiate base application object.
|
|
QtSingleCoreApplication application(APP_LOW_NAME, argc, argv);
|
|
|
|
qDebug("\n===== RSS Guard updater ====\n");
|
|
|
|
if (argc != 5) {
|
|
qDebug("Insufficient arguments passed. Update process cannot proceed.");
|
|
qDebug("Press any key to exit updater...");
|
|
|
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
|
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
QString this_process_path = QDir::toNativeSeparators(application.applicationFilePath());
|
|
QString current_version(argv[1]);
|
|
QString next_version(argv[2]);
|
|
QString rssguard_executable_path(argv[3]);
|
|
QString rssguard_path = QDir::toNativeSeparators(QFileInfo(rssguard_executable_path).absolutePath());
|
|
QString update_file_path(argv[4]);
|
|
QString temp_path = QDir::toNativeSeparators(QFileInfo(update_file_path).absolutePath());
|
|
QString output_temp_path = temp_path + QDir::separator() + APP_LOW_NAME;
|
|
|
|
qDebug("Starting updater.");
|
|
qDebug("Version changes from %s to %s.",
|
|
qPrintable(current_version),
|
|
qPrintable(next_version));
|
|
|
|
qDebug("\n===== Files & versions ====\n");
|
|
|
|
qDebug("This process:\n -> %s", qPrintable(this_process_path));
|
|
qDebug("Application executable:\n -> %s", qPrintable(rssguard_executable_path));
|
|
qDebug("TEMP path:\n -> %s", qPrintable(temp_path));
|
|
|
|
qDebug("\n===== Update file metadata ====\n");
|
|
|
|
bool update_file_exists = QFile::exists(update_file_path);
|
|
|
|
qDebug("Update file exists:\n -> %s", update_file_exists ? "yes" : "no");
|
|
qDebug("Update file path:\n -> %s", qPrintable(update_file_path));
|
|
qDebug("Update file size:\n -> %lld bytes", QFileInfo(update_file_path).size());
|
|
|
|
if (!update_file_exists) {
|
|
qDebug("\nUpdate file does NOT exist. Updater cannot proceed.");
|
|
qDebug("Press any key to exit updater...");
|
|
|
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
|
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
qDebug("\n===== Cleanup ====\n");
|
|
|
|
// Check if main RSS Guard instance is running.
|
|
if (application.sendMessage(APP_QUIT_INSTANCE)) {
|
|
qDebug("RSS Guard application is running. Quitting it.");
|
|
}
|
|
|
|
// Remove old folders.
|
|
if (QDir(output_temp_path).exists()) {
|
|
if (!removeDir(output_temp_path)) {
|
|
qDebug("Cleanup of old temporary files failed.");
|
|
qDebug("Press any key to exit updater...");
|
|
|
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
|
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
|
|
QString extractor(APP_7ZA_EXECUTABLE);
|
|
QStringList extractor_arguments;
|
|
|
|
qDebug("Old temporary files removed.");
|
|
|
|
if (!removeDir(rssguard_path, QStringList() << extractor)) {
|
|
qDebug("Full cleanup of actual RSS Guard installation failed.");
|
|
qDebug("Some files from old installation may persist.");
|
|
}
|
|
|
|
if (!QFile::rename(this_process_path, this_process_path + ".old")) {
|
|
qDebug("Updater executable was not renamed and it will not be updated.");
|
|
}
|
|
|
|
qDebug("Update files are ready. Press any key to proceed...");
|
|
|
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
|
|
|
extractor_arguments << "x" << update_file_path << "-r" <<
|
|
"-y" << QString("-o%1").arg(output_temp_path);
|
|
|
|
qDebug("\n===== Decompression =====\n");
|
|
|
|
switch (QProcess::execute(extractor, extractor_arguments)) {
|
|
case -1:
|
|
qDebug("Decompressor crashed. Upgrading process failed.");
|
|
|
|
qDebug("Press any key to exit updater...");
|
|
|
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
case -2:
|
|
qDebug("Decompressor was not started successfully. Upgrading process failed.");
|
|
|
|
qDebug("Press any key to exit updater...");
|
|
|
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
case 0:
|
|
qDebug("Decompression is done. Proceeding to copying files to application directory.");
|
|
break;
|
|
|
|
default:
|
|
qDebug("Unspecified error occured.");
|
|
|
|
qDebug("Press any key to exit updater...");
|
|
|
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
|
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
qDebug("\n===== Copying =====\n");
|
|
|
|
// Find "rssguard" subfolder path in
|
|
QFileInfoList rssguard_temp_root = QDir(output_temp_path).entryInfoList(QDir::Dirs |
|
|
QDir::NoDotAndDotDot |
|
|
QDir::NoSymLinks);
|
|
|
|
if (rssguard_temp_root.size() != 1) {
|
|
qDebug("Could not find root of downloaded application data.");
|
|
|
|
qDebug("Press any key to exit updater...");
|
|
|
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
|
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
QString rssguard_single_temp_root = rssguard_temp_root.at(0).absoluteFilePath();
|
|
|
|
if (!copyPath(rssguard_single_temp_root, rssguard_path)) {
|
|
qDebug("Critical error appeared during copying of application files.");
|
|
|
|
qDebug("Press any key to exit updater...");
|
|
|
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
|
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
qDebug("\n===== Cleanup =====\n");
|
|
|
|
removeDir(output_temp_path);
|
|
QFile::remove(update_file_path);
|
|
|
|
qDebug("Temporary files removed.");
|
|
|
|
qDebug("Press any key to exit updater and start RSS Guard.");
|
|
|
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
|
|
|
if (!QProcess::startDetached(rssguard_executable_path)) {
|
|
qDebug("RSS Guard was not started successfully. Start it manually.");
|
|
|
|
qDebug("Press any key to exit updater...");
|
|
|
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
|
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|