mirror of
https://github.com/etlegacy/Update-Installer.git
synced 2024-11-10 06:31:49 +00:00
Add the core logic for installing and uninstalling files in UpdateInstaller
This commit is contained in:
parent
e3cec64375
commit
0a6630bc8c
5 changed files with 241 additions and 6 deletions
|
@ -4,6 +4,10 @@
|
|||
|
||||
#include <unistd.h>
|
||||
|
||||
FileOps::IOException::~IOException() throw ()
|
||||
{
|
||||
}
|
||||
|
||||
bool FileOps::fileExists(const char* path) throw (IOException)
|
||||
{
|
||||
#ifdef PLATFORM_UNIX
|
||||
|
@ -54,3 +58,24 @@ void FileOps::createSymLink(const char* link, const char* target) throw (IOExcep
|
|||
#endif
|
||||
}
|
||||
|
||||
void FileOps::removeFile(const char* src) throw (IOException)
|
||||
{
|
||||
#ifdef PLATFORM_UNIX
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string FileOps::dirname(const char* path)
|
||||
{
|
||||
#ifdef PLATFORM_UNIX
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
void FileOps::touch(const char* path) throw (IOException)
|
||||
{
|
||||
#ifdef PLATFORM_UNIX
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -9,10 +9,17 @@ class FileOps
|
|||
class IOException : public std::exception
|
||||
{
|
||||
public:
|
||||
IOException(const std::string& error);
|
||||
IOException(const std::string& error)
|
||||
: m_error(error)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~IOException() throw ();
|
||||
|
||||
virtual const char* what();
|
||||
virtual const char* what() const throw ()
|
||||
{
|
||||
return m_error.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_error;
|
||||
|
@ -21,9 +28,12 @@ class FileOps
|
|||
static bool fileExists(const char* path) throw (IOException);
|
||||
static void setPermissions(const char* path, int permissions) throw (IOException);
|
||||
static void moveFile(const char* src, const char* dest) throw (IOException);
|
||||
static void removeFile(const char* src) throw (IOException);
|
||||
static void extractFromZip(const char* zipFile, const char* src, const char* dest) throw (IOException);
|
||||
static void mkdir(const char* dir) throw (IOException);
|
||||
static void rmdir(const char* dir) throw (IOException);
|
||||
static void createSymLink(const char* link, const char* target) throw (IOException);
|
||||
static void touch(const char* path) throw (IOException);
|
||||
static std::string dirname(const char* path);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
#include "UpdateInstaller.h"
|
||||
|
||||
#include "FileOps.h"
|
||||
#include "Log.h"
|
||||
#include "ProcessUtils.h"
|
||||
#include "UpdateObserver.h"
|
||||
|
||||
UpdateInstaller::UpdateInstaller()
|
||||
: m_mode(Setup)
|
||||
, m_script(0)
|
||||
, m_waitPid(0)
|
||||
, m_observer(0)
|
||||
{
|
||||
}
|
||||
|
||||
void UpdateInstaller::setWaitPid(long long pid)
|
||||
{
|
||||
m_waitPid = pid;
|
||||
}
|
||||
|
||||
void UpdateInstaller::setInstallDir(const std::string& path)
|
||||
{
|
||||
m_installDir = path;
|
||||
|
@ -33,18 +43,188 @@ void UpdateInstaller::setScript(UpdateScript* script)
|
|||
m_script = script;
|
||||
}
|
||||
|
||||
void UpdateInstaller::run()
|
||||
void UpdateInstaller::run() throw ()
|
||||
{
|
||||
LOG(Info,"Starting update installation");
|
||||
|
||||
if (m_mode == Setup)
|
||||
{
|
||||
ProcessUtils::waitForProcess(m_waitPid);
|
||||
|
||||
std::string updaterPath;
|
||||
std::list<std::string> args;
|
||||
if (!checkAccess())
|
||||
{
|
||||
// start a copy of the updater with admin rights
|
||||
ProcessUtils::runElevated(updaterPath,args);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO - Change this to run synchronously
|
||||
ProcessUtils::runAsync(updaterPath,args);
|
||||
}
|
||||
}
|
||||
else if (m_mode == Main)
|
||||
{
|
||||
std::string error;
|
||||
try
|
||||
{
|
||||
installFiles();
|
||||
uninstallFiles();
|
||||
removeBackups();
|
||||
}
|
||||
catch (const FileOps::IOException& exception)
|
||||
{
|
||||
error = exception.what();
|
||||
}
|
||||
catch (const std::string& genericError)
|
||||
{
|
||||
error = genericError;
|
||||
}
|
||||
|
||||
if (!error.empty())
|
||||
{
|
||||
LOG(Error,std::string("Error installing update ") + error);
|
||||
revert();
|
||||
if (m_observer)
|
||||
{
|
||||
m_observer->updateError(error);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_observer)
|
||||
{
|
||||
m_observer->updateFinished();
|
||||
}
|
||||
}
|
||||
else if (m_mode == Cleanup)
|
||||
{
|
||||
ProcessUtils::waitForProcess(m_waitPid);
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateInstaller::cleanup()
|
||||
{
|
||||
// TODO - Remove the temp dir which the installer was copied to
|
||||
}
|
||||
|
||||
void UpdateInstaller::revert()
|
||||
{
|
||||
std::map<std::string,std::string>::const_iterator iter = m_backups.begin();
|
||||
for (;iter != m_backups.end();iter++)
|
||||
{
|
||||
const std::string& installedFile = iter->first;
|
||||
const std::string& backupFile = iter->second;
|
||||
|
||||
if (FileOps::fileExists(installedFile.c_str()))
|
||||
{
|
||||
FileOps::removeFile(installedFile.c_str());
|
||||
}
|
||||
FileOps::moveFile(backupFile.c_str(),installedFile.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateInstaller::installFile(const UpdateScriptFile& file)
|
||||
{
|
||||
std::string packageFile = m_installDir + '/' + file.package;
|
||||
std::string destPath = m_installDir + '/' + file.path;
|
||||
std::string target = file.linkTarget;
|
||||
|
||||
if (!FileOps::fileExists(packageFile.c_str()))
|
||||
{
|
||||
throw "Package file does not exist: " + packageFile;
|
||||
}
|
||||
|
||||
// backup the existing file if any
|
||||
backupFile(destPath);
|
||||
|
||||
// create the target directory if it does not exist
|
||||
std::string destDir = FileOps::dirname(destPath.c_str());
|
||||
if (!FileOps::fileExists(destDir.c_str()))
|
||||
{
|
||||
FileOps::mkdir(destDir.c_str());
|
||||
}
|
||||
|
||||
if (target.empty())
|
||||
{
|
||||
// extract the file from the package and copy it to
|
||||
// the destination
|
||||
FileOps::extractFromZip(packageFile.c_str(),file.path.c_str(),destPath.c_str());
|
||||
|
||||
// set the permissions on the newly extracted file
|
||||
FileOps::setPermissions(destPath.c_str(),file.permissions);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create the symlink
|
||||
FileOps::createSymLink(destPath.c_str(),target.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateInstaller::installFiles()
|
||||
{
|
||||
std::vector<UpdateScriptFile>::const_iterator iter = m_script->filesToInstall().begin();
|
||||
int filesInstalled = 0;
|
||||
for (;iter != m_script->filesToInstall().end();iter++)
|
||||
{
|
||||
installFile(*iter);
|
||||
++filesInstalled;
|
||||
if (m_observer)
|
||||
{
|
||||
m_observer->updateProgress(static_cast<float>(filesInstalled) / m_script->filesToInstall().size() * 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateInstaller::uninstallFiles()
|
||||
{
|
||||
std::vector<std::string>::const_iterator iter = m_script->filesToUninstall().begin();
|
||||
for (;iter != m_script->filesToUninstall().end();iter++)
|
||||
{
|
||||
FileOps::removeFile(iter->c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateInstaller::backupFile(const std::string& path)
|
||||
{
|
||||
if (!FileOps::fileExists(path.c_str()))
|
||||
{
|
||||
// no existing file to backup
|
||||
return;
|
||||
}
|
||||
|
||||
std::string backupPath = path + ".bak";
|
||||
FileOps::removeFile(backupPath.c_str());
|
||||
FileOps::moveFile(path.c_str(), backupPath.c_str());
|
||||
m_backups[path] = backupPath;
|
||||
}
|
||||
|
||||
void UpdateInstaller::removeBackups()
|
||||
{
|
||||
std::map<std::string,std::string>::const_iterator iter = m_backups.begin();
|
||||
for (;iter != m_backups.end();iter++)
|
||||
{
|
||||
const std::string& installedFile = iter->first;
|
||||
const std::string& backupFile = iter->second;
|
||||
FileOps::removeFile(backupFile.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
bool UpdateInstaller::checkAccess()
|
||||
{
|
||||
std::string testFile = m_installDir + "/update-installer-test-file";
|
||||
FileOps::removeFile(testFile.c_str());
|
||||
|
||||
try
|
||||
{
|
||||
FileOps::touch(testFile.c_str());
|
||||
FileOps::removeFile(testFile.c_str());
|
||||
return true;
|
||||
}
|
||||
catch (const FileOps::IOException& error)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "UpdateScript.h"
|
||||
|
||||
class UpdateScript;
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
class UpdateObserver;
|
||||
|
||||
class UpdateInstaller
|
||||
{
|
||||
|
@ -20,14 +23,30 @@ class UpdateInstaller
|
|||
void setBackupDir(const std::string& path);
|
||||
void setMode(Mode mode);
|
||||
void setScript(UpdateScript* script);
|
||||
void setWaitPid(long long pid);
|
||||
|
||||
void run();
|
||||
void setObserver(UpdateObserver* observer);
|
||||
|
||||
void run() throw ();
|
||||
|
||||
private:
|
||||
void cleanup();
|
||||
void revert();
|
||||
void removeBackups();
|
||||
bool checkAccess();
|
||||
|
||||
void installFiles();
|
||||
void uninstallFiles();
|
||||
void installFile(const UpdateScriptFile& file);
|
||||
void backupFile(const std::string& path);
|
||||
|
||||
Mode m_mode;
|
||||
std::string m_installDir;
|
||||
std::string m_packageDir;
|
||||
std::string m_backupDir;
|
||||
long long m_waitPid;
|
||||
UpdateScript* m_script;
|
||||
UpdateObserver* m_observer;
|
||||
std::map<std::string,std::string> m_backups;
|
||||
};
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ int main(int argc, char** argv)
|
|||
installer.setInstallDir(options.installDir);
|
||||
installer.setPackageDir(options.packageDir);
|
||||
installer.setScript(&script);
|
||||
installer.setWaitPid(options.waitPid);
|
||||
installer.run();
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue