mirror of
https://github.com/etlegacy/Update-Installer.git
synced 2024-11-21 19:31:49 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
9b72b1ad18
16 changed files with 119 additions and 106 deletions
|
@ -47,10 +47,12 @@ if (APPLE)
|
|||
# of the updater binary
|
||||
set(CMAKE_OSX_ARCHITECTURES i386;x86_64)
|
||||
|
||||
# Build the updater so that it works on OS X 10.5 and above.
|
||||
set(MIN_OSX_VERSION 10.5)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${MIN_OSX_VERSION}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${MIN_OSX_VERSION}")
|
||||
# Build the updater so that it works on OS X 10.6 and above.
|
||||
if (NOT (DEFINED MIN_OSX_DEPLOYMENT_VERSION))
|
||||
set(MIN_OSX_DEPLOYMENT_VERSION 10.6)
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${MIN_OSX_DEPLOYMENT_VERSION}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${MIN_OSX_DEPLOYMENT_VERSION}")
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
|
|
|
@ -47,7 +47,6 @@ if (APPLE)
|
|||
set(SOURCES ${SOURCES}
|
||||
MacBundle.cpp
|
||||
StandardDirs.mm
|
||||
StlSymbolsLeopard.cpp
|
||||
UpdateDialogCocoa.mm
|
||||
mac_dock_icon.cpp
|
||||
mac_info_plist.cpp)
|
||||
|
|
|
@ -629,3 +629,41 @@ std::string FileUtils::getcwd() throw (IOException)
|
|||
#endif
|
||||
}
|
||||
|
||||
bool FileUtils::removeEmptyDirs(const char* path)
|
||||
{
|
||||
DirIterator iter(path);
|
||||
int fileCount = 0;
|
||||
while (iter.next())
|
||||
{
|
||||
if (iter.fileName() == "." || iter.fileName() == "..")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!iter.isDir() || !removeEmptyDirs(iter.filePath().c_str()))
|
||||
{
|
||||
// entry is either not a directory or is a
|
||||
// directory hierarchy which contains one or more non-directories
|
||||
// once all empty dirs have been recursively removed
|
||||
++fileCount;
|
||||
}
|
||||
}
|
||||
if (fileCount == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileUtils::rmdir(path);
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
LOG(Error,"Unable to remove empty directory " + std::string(ex.what()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -145,5 +145,12 @@ class FileUtils
|
|||
|
||||
/** Returns the current working directory of the application. */
|
||||
static std::string getcwd() throw (IOException);
|
||||
|
||||
/** Recursively remove all empty directories from the path rooted at
|
||||
* @p path.
|
||||
*
|
||||
* Returns true if @p path was removed.
|
||||
*/
|
||||
static bool removeEmptyDirs(const char* path);
|
||||
};
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
// platform-specific type aliases
|
||||
#if defined(PLATFORM_UNIX)
|
||||
#include <unistd.h>
|
||||
#define PLATFORM_PID pid_t
|
||||
#else
|
||||
#define PLATFORM_PID DWORD
|
||||
|
|
|
@ -201,6 +201,11 @@ int ProcessUtils::runElevatedLinux(const std::string& executable,
|
|||
#endif
|
||||
|
||||
#ifdef PLATFORM_MAC
|
||||
|
||||
// suppress warning about AuthorizationExecuteWithPriviledges
|
||||
// being deprecated since OS X 10.7
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
int ProcessUtils::runElevatedMac(const std::string& executable,
|
||||
const std::list<std::string>& args)
|
||||
{
|
||||
|
@ -315,6 +320,7 @@ int ProcessUtils::runElevatedMac(const std::string& executable,
|
|||
return RunElevatedFailed;
|
||||
}
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
// convert a list of arguments in a space-separated string.
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
// Workarounds for iostream symbols that are referenced when building on OS X 10.7 but missing from
|
||||
// OS X 10.5's stdlibc++.dylib.
|
||||
//
|
||||
// In the <iostream> headers these are declared as extern templates but the symbols are not present under 10.5.
|
||||
// This file forces the compiler to instantiate the templates.
|
||||
//
|
||||
// see http://stackoverflow.com/questions/3484043/os-x-program-runs-on-dev-machine-crashing-horribly-on-others
|
||||
|
||||
#include <iostream>
|
||||
|
||||
_GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
// From ostream_insert.h
|
||||
template ostream& __ostream_insert(ostream&, const char*, streamsize);
|
||||
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
template wostream& __ostream_insert(wostream&, const wchar_t*, streamsize);
|
||||
#endif
|
||||
|
||||
// From ostream.tcc
|
||||
template ostream& ostream::_M_insert(long);
|
||||
template ostream& ostream::_M_insert(unsigned long);
|
||||
template ostream& ostream::_M_insert(bool);
|
||||
#ifdef _GLIBCXX_USE_LONG_LONG
|
||||
template ostream& ostream::_M_insert(long long);
|
||||
template ostream& ostream::_M_insert(unsigned long long);
|
||||
#endif
|
||||
template ostream& ostream::_M_insert(double);
|
||||
template ostream& ostream::_M_insert(long double);
|
||||
template ostream& ostream::_M_insert(const void*);
|
||||
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
template wostream& wostream::_M_insert(long);
|
||||
template wostream& wostream::_M_insert(unsigned long);
|
||||
template wostream& wostream::_M_insert(bool);
|
||||
#ifdef _GLIBCXX_USE_LONG_LONG
|
||||
template wostream& wostream::_M_insert(long long);
|
||||
template wostream& wostream::_M_insert(unsigned long long);
|
||||
#endif
|
||||
template wostream& wostream::_M_insert(double);
|
||||
template wostream& wostream::_M_insert(long double);
|
||||
template wostream& wostream::_M_insert(const void*);
|
||||
#endif
|
||||
|
||||
// From istream.tcc
|
||||
template istream& istream::_M_extract(unsigned short&);
|
||||
template istream& istream::_M_extract(unsigned int&);
|
||||
template istream& istream::_M_extract(long&);
|
||||
template istream& istream::_M_extract(unsigned long&);
|
||||
template istream& istream::_M_extract(bool&);
|
||||
#ifdef _GLIBCXX_USE_LONG_LONG
|
||||
template istream& istream::_M_extract(long long&);
|
||||
template istream& istream::_M_extract(unsigned long long&);
|
||||
#endif
|
||||
template istream& istream::_M_extract(float&);
|
||||
template istream& istream::_M_extract(double&);
|
||||
template istream& istream::_M_extract(long double&);
|
||||
template istream& istream::_M_extract(void*&);
|
||||
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
template wistream& wistream::_M_extract(unsigned short&);
|
||||
template wistream& wistream::_M_extract(unsigned int&);
|
||||
template wistream& wistream::_M_extract(long&);
|
||||
template wistream& wistream::_M_extract(unsigned long&);
|
||||
template wistream& wistream::_M_extract(bool&);
|
||||
#ifdef _GLIBCXX_USE_LONG_LONG
|
||||
template wistream& wistream::_M_extract(long long&);
|
||||
template wistream& wistream::_M_extract(unsigned long long&);
|
||||
#endif
|
||||
template wistream& wistream::_M_extract(float&);
|
||||
template wistream& wistream::_M_extract(double&);
|
||||
template wistream& wistream::_M_extract(long double&);
|
||||
template wistream& wistream::_M_extract(void*&);
|
||||
#endif
|
||||
|
||||
_GLIBCXX_END_NAMESPACE
|
|
@ -1,5 +1,6 @@
|
|||
#include "UpdateDialogGtkFactory.h"
|
||||
|
||||
#include "FileUtils.h"
|
||||
#include "Log.h"
|
||||
#include "UpdateDialog.h"
|
||||
#include "StringUtils.h"
|
||||
|
@ -21,34 +22,41 @@ extern unsigned int libupdatergtk_so_len;
|
|||
// pointers to helper functions in the GTK updater UI library
|
||||
UpdateDialogGtk* (*update_dialog_gtk_new)() = 0;
|
||||
|
||||
#define BIND_FUNCTION(library,function) \
|
||||
function = reinterpret_cast<typeof(function)>(dlsym(library,#function));
|
||||
#if __cplusplus >= 201103L
|
||||
#define TYPEOF(x) decltype(x)
|
||||
#else
|
||||
#define TYPEOF(x) typeof(x)
|
||||
#endif
|
||||
|
||||
bool extractFileFromBinary(const char* path, const void* buffer, size_t length)
|
||||
#define BIND_FUNCTION(library,function) \
|
||||
function = reinterpret_cast<TYPEOF(function)>(dlsym(library,#function));
|
||||
|
||||
#define MAX_FILE_PATH 4096
|
||||
|
||||
bool extractFileFromBinary(int fd, const void* buffer, size_t length)
|
||||
{
|
||||
int fd = open(path,O_CREAT | O_WRONLY | O_TRUNC,0755);
|
||||
size_t count = write(fd,buffer,length);
|
||||
if (fd < 0 || count < length)
|
||||
{
|
||||
if (fd >= 0)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
close(fd);
|
||||
return true;
|
||||
return count >= length;
|
||||
}
|
||||
|
||||
UpdateDialog* UpdateDialogGtkFactory::createDialog()
|
||||
{
|
||||
const char* libPath = "/tmp/libupdatergtk.so";
|
||||
char libPath[MAX_FILE_PATH];
|
||||
strncpy(libPath, "/tmp/mendeley-libUpdaterGtk.so.XXXXXX", MAX_FILE_PATH);
|
||||
|
||||
if (!extractFileFromBinary(libPath,libupdatergtk_so,libupdatergtk_so_len))
|
||||
int libFd = mkostemp(libPath, O_CREAT | O_WRONLY | O_TRUNC);
|
||||
if (libFd == -1)
|
||||
{
|
||||
LOG(Warn,"Failed to create temporary file - " + std::string(strerror(errno)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!extractFileFromBinary(libFd,libupdatergtk_so,libupdatergtk_so_len))
|
||||
{
|
||||
LOG(Warn,"Failed to load the GTK UI library - " + std::string(strerror(errno)));
|
||||
return 0;
|
||||
}
|
||||
close(libFd);
|
||||
|
||||
void* gtkLib = dlopen(libPath,RTLD_LAZY);
|
||||
if (!gtkLib)
|
||||
|
@ -58,6 +66,7 @@ UpdateDialog* UpdateDialogGtkFactory::createDialog()
|
|||
}
|
||||
|
||||
BIND_FUNCTION(gtkLib,update_dialog_gtk_new);
|
||||
|
||||
FileUtils::removeFile(libPath);
|
||||
return reinterpret_cast<UpdateDialog*>(update_dialog_gtk_new());
|
||||
}
|
||||
|
||||
|
|
|
@ -448,6 +448,10 @@ void UpdateInstaller::postInstallUpdate()
|
|||
// Info.plist file.
|
||||
FileUtils::touch(m_installDir.c_str());
|
||||
#endif
|
||||
|
||||
// recursively remove any empty directories in the installation dir
|
||||
// remove any empty directories in the installation dir
|
||||
FileUtils::removeEmptyDirs(m_installDir.c_str());
|
||||
}
|
||||
|
||||
void UpdateInstaller::setAutoClose(bool autoClose)
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/..")
|
||||
|
||||
if (APPLE)
|
||||
set(HELPER_SHARED_SOURCES ../StlSymbolsLeopard.cpp)
|
||||
endif()
|
||||
|
||||
# Create helper binaries for unit tests
|
||||
add_executable(oldapp
|
||||
old_app.cpp
|
||||
${HELPER_SHARED_SOURCES}
|
||||
)
|
||||
add_executable(newapp
|
||||
new_app.cpp
|
||||
${HELPER_SHARED_SOURCES}
|
||||
)
|
||||
|
||||
# Install data files required by unit tests
|
||||
|
|
|
@ -39,6 +39,25 @@ void TestFileUtils::testStandardDirs()
|
|||
TEST_COMPARE(FileUtils::fileExists(tmpDir.data()), true);
|
||||
}
|
||||
|
||||
void TestFileUtils::testRemoveEmptyDirs()
|
||||
{
|
||||
std::string tmpDir = FileUtils::tempPath();
|
||||
std::string rootDir = tmpDir + "/TestFileUtils-testRemoveEmptyDirs";
|
||||
std::string content = "non-empty-file-content";
|
||||
|
||||
FileUtils::mkpath((rootDir + "/nested/empty/dir").c_str());
|
||||
FileUtils::mkpath((rootDir + "/nested/empty2/dir").c_str());
|
||||
FileUtils::writeFile((rootDir + "/nonempty.txt").c_str(), content.c_str(), content.size());
|
||||
FileUtils::removeEmptyDirs(rootDir.c_str());
|
||||
|
||||
// root dir and the regular file should still exist
|
||||
TEST_COMPARE(FileUtils::fileExists(rootDir.c_str()), true);
|
||||
TEST_COMPARE(FileUtils::fileExists((rootDir + "/nonempty.txt").c_str()), true);
|
||||
|
||||
// the empty nested directories should have been removed
|
||||
TEST_COMPARE(FileUtils::fileExists((rootDir + "/nested").c_str()), true);
|
||||
}
|
||||
|
||||
int main(int,char**)
|
||||
{
|
||||
TestList<TestFileUtils> tests;
|
||||
|
|
|
@ -7,4 +7,5 @@ class TestFileUtils
|
|||
void testIsRelative();
|
||||
void testSymlinkFileExists();
|
||||
void testStandardDirs();
|
||||
void testRemoveEmptyDirs();
|
||||
};
|
||||
|
|
|
@ -45,8 +45,8 @@
|
|||
</file>
|
||||
</install>
|
||||
<uninstall>
|
||||
<!-- TODO - List some files to uninstall here !-->
|
||||
<file>file-to-uninstall.txt</file>
|
||||
<file>symlink-to-file-to-uninstall.txt</file>
|
||||
<file>will-become-empty-after-update/nested/file-to-uninstall.txt</file>
|
||||
</uninstall>
|
||||
</update>
|
||||
|
|
|
@ -141,6 +141,12 @@ else
|
|||
create_test_file("#{INSTALL_DIR}/symlink-to-file-to-uninstall.txt", "dummy file. this is a symlink on Unix")
|
||||
end
|
||||
|
||||
# Create a dummy file to uninstall in a directory
|
||||
# which becomes empty after the update
|
||||
empty_dir_path = "#{INSTALL_DIR}/will-become-empty-after-update/nested"
|
||||
FileUtils.mkdir_p(empty_dir_path)
|
||||
create_test_file("#{empty_dir_path}/file-to-uninstall.txt", "this file and its containing dir should be removed after the update")
|
||||
|
||||
# Populate package source dir with files to install
|
||||
Dir.mkdir(PACKAGE_SRC_DIR)
|
||||
nested_dir_path = "#{PACKAGE_SRC_DIR}/new-dir/new-dir2"
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
<name>test-dir/app-symlink</name>
|
||||
<target>../app</target>
|
||||
</file>
|
||||
<!-- Test file in new directory !-->
|
||||
<file>
|
||||
<name>new-dir/new-dir2/new-file.txt</name>
|
||||
<hash>$TEST_FILENAME</hash>
|
||||
|
@ -60,8 +61,8 @@
|
|||
</file>
|
||||
</install-v3>
|
||||
<uninstall>
|
||||
<!-- TODO - List some files to uninstall here !-->
|
||||
<file>file-to-uninstall.txt</file>
|
||||
<file>symlink-to-file-to-uninstall.txt</file>
|
||||
<file>will-become-empty-after-update/nested/file-to-uninstall.txt</file>
|
||||
</uninstall>
|
||||
</update>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#!/usr/bin/ruby
|
||||
|
||||
require 'digest/sha1'
|
||||
require 'fileutils'
|
||||
require 'rubygems'
|
||||
require 'find'
|
||||
|
@ -82,7 +83,7 @@ def strip_prefix(string,prefix)
|
|||
end
|
||||
|
||||
def file_sha1(path)
|
||||
return `sha1sum "#{path}"`.split(' ')[0]
|
||||
Digest::SHA1.file(path).to_s
|
||||
end
|
||||
|
||||
class UpdateScriptGenerator
|
||||
|
|
Loading…
Reference in a new issue