Merge remote-tracking branch 'upstream/master'

This commit is contained in:
jackeri 2014-12-10 12:23:36 +02:00
commit 9b72b1ad18
16 changed files with 119 additions and 106 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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;
}
}

View file

@ -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);
};

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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());
}

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -7,4 +7,5 @@ class TestFileUtils
void testIsRelative();
void testSymlinkFileExists();
void testStandardDirs();
void testRemoveEmptyDirs();
};

View file

@ -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>

View file

@ -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"

View file

@ -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>

View file

@ -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