Fix update installer test on Windows

* Remove the dependency on Cygwin being installed along with zip.exe
   at a specific location.

   Add a small cross-platform tool in zip.cpp which creates a zip
   file using the contents of a given directory.

   This also removes the need for passing different arguments to 'zip'
   depending on the platform.

 * Fix StringUtils::endsWith()

 * Fix UpdateDialogWin32::quit(), when called on a background thread it
   had no effect. Post the WM_QUIT message to the main thread.
This commit is contained in:
Robert Knight 2013-08-30 15:33:46 +01:00
parent 484f8ae37b
commit 2658f1235d
7 changed files with 125 additions and 25 deletions

View file

@ -133,3 +133,7 @@ endif()
install(TARGETS updater RUNTIME DESTINATION bin)
add_executable(zip-tool zip.cpp)
target_link_libraries(zip-tool updatershared)

View file

@ -11,6 +11,7 @@
#include <fstream>
#include <iostream>
#include "minizip/zip.h"
#include "minizip/unzip.h"
#ifdef PLATFORM_UNIX
@ -145,6 +146,37 @@ void FileUtils::moveFile(const char* src, const char* dest) throw (IOException)
#endif
}
void FileUtils::addToZip(const char* archivePath, const char* path, const char* content, int length) throw (IOException)
{
int result = ZIP_OK;
int appendMode = fileExists(archivePath) ? APPEND_STATUS_ADDINZIP : APPEND_STATUS_CREATE;
zipFile archive = zipOpen(archivePath, appendMode);
result = zipOpenNewFileInZip(archive, path, 0 /* file attributes */, 0 /* extra field */, 0 /* extra field size */,
0/* global extra field */, 0 /* global extra field size */, 0 /* comment */, Z_DEFLATED /* method */,
Z_DEFAULT_COMPRESSION /* level */);
if (result != ZIP_OK)
{
throw IOException("Unable to add new file to zip archive");
}
result = zipWriteInFileInZip(archive, content, length);
if (result != ZIP_OK)
{
throw IOException("Unable to write file data to zip archive");
}
result = zipCloseFileInZip(archive);
if (result != ZIP_OK)
{
throw IOException("Unable to close file in zip archive");
}
result = zipClose(archive, 0 /* global comment */);
if (result != ZIP_OK)
{
throw IOException("Unable to close zip archive");
}
}
void FileUtils::extractFromZip(const char* zipFilePath, const char* src, const char* dest) throw (IOException)
{
unzFile zipFile = unzOpen(zipFilePath);
@ -504,6 +536,17 @@ void FileUtils::writeFile(const char* path, const char* data, int length) throw
stream.write(data,length);
}
std::string FileUtils::readFile(const char* path)
{
std::ifstream inputFile(path, std::ios::in | std::ios::binary);
std::string content;
inputFile.seekg(0, std::ios::end);
content.resize(static_cast<unsigned int>(inputFile.tellg()));
inputFile.seekg(0, std::ios::beg);
inputFile.read(&content[0], content.size());
return content;
}
void FileUtils::copyFile(const char* src, const char* dest) throw (IOException)
{
#ifdef PLATFORM_UNIX

View file

@ -109,6 +109,9 @@ class FileUtils
/** Returns the path to a directory for storing temporary files. */
static std::string tempPath();
/** Add a file to a zip archive, creating it if it does not already exist. */
static void addToZip(const char* archivePath, const char* path, const char* content, int length) throw (IOException);
/** Extract the file @p src from the zip archive @p zipFile and
* write it to @p dest.
*/
@ -135,6 +138,8 @@ class FileUtils
static void writeFile(const char* path, const char* data, int length) throw (IOException);
static std::string readFile(const char* path) throw (IOException);
/** Changes the current working directory to @p path */
static void chdir(const char* path) throw (IOException);

View file

@ -36,7 +36,7 @@ inline const char* notNullString(const char* text)
inline bool endsWith(const std::string& str, const char* text)
{
size_t length = strlen(text);
return str.find(text,str.size() - length) != 0;
return str.find(text,str.size() - length) != std::string::npos;
}
inline bool startsWith(const std::string& str, const char* text)

View file

@ -146,7 +146,7 @@ void UpdateDialogWin32::updateFinished()
void UpdateDialogWin32::quit()
{
PostQuitMessage(0);
PostThreadMessage(GetWindowThreadProcessId(m_window.GetHwnd(), 0 /* process ID */), WM_QUIT, 0, 0);
}
LRESULT WINAPI UpdateDialogWin32::windowProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)

View file

@ -18,13 +18,13 @@ if IS_WINDOWS
NEWAPP_NAME = "newapp.exe"
APP_NAME = "app.exe"
UPDATER_NAME = "updater.exe"
ZIP_TOOL = "C:/Cygwin/bin/zip.exe"
ZIP_TOOL = File.expand_path("../zip-tool.exe")
else
OLDAPP_NAME = "oldapp"
NEWAPP_NAME = "newapp"
APP_NAME = "app"
UPDATER_NAME = "updater"
ZIP_TOOL = "zip"
ZIP_TOOL = File.expand_path("../zip-tool")
end
file_list_vars = {
@ -42,13 +42,6 @@ def replace_vars(src_file,dest_file,vars)
end
end
def zip_supports_bzip2(zip_tool)
# Try making an empty zip file with bzip2 compression, if bzip2 is not
# supported, the tool will output an error, otherwise it will output
# "Nothing to do"
return `#{zip_tool} -Z bzip2 testing-bzip2-support.zip`.strip.include?("Nothing to do")
end
# Returns true if |src_file| and |dest_file| have the same contents, type
# and permissions or false otherwise
def compare_files(src_file, dest_file)
@ -124,19 +117,6 @@ OptionParser.new do |parser|
end
end.parse!
BZIP2_AVAILABLE = zip_supports_bzip2(ZIP_TOOL)
if (BZIP2_AVAILABLE)
ZIP_FLAGS = "-Z bzip2"
else
ZIP_FLAGS = ""
end
if (BZIP2_AVAILABLE)
puts "Using bzip2 compression"
else
puts "Using plain old deflate compression - the 'zip' tool does not support bzip2"
end
# Remove the install and package dirs if they
# already exist
FileUtils.rm_rf(INSTALL_DIR)
@ -172,7 +152,7 @@ FileUtils::chmod 0755, "#{PACKAGE_SRC_DIR}/#{APP_NAME}"
# Create .zip packages from source files
Dir.mkdir(PACKAGE_DIR)
Dir.chdir(PACKAGE_SRC_DIR) do
if !system("#{ZIP_TOOL} #{ZIP_FLAGS} -r #{PACKAGE_DIR}/app-pkg.zip .")
if !system("#{ZIP_TOOL} #{PACKAGE_DIR}/app-pkg.zip .")
raise "Unable to create update package"
end
end

68
src/zip.cpp Normal file
View file

@ -0,0 +1,68 @@
#include "DirIterator.h"
#include "Log.h"
#include "FileUtils.h"
#include "StringUtils.h"
#include <iostream>
#include <vector>
// Simple utility for creating zip files from the
// contents of a directory
//
// The advantage of this over the 'zip' tool on Linux/Mac is consistent
// behavior across platforms and support for Windows.
//
// Usage: zip-tool <archive name> <dir>
// scan a directory and record paths to files that are found
void scanDir(std::vector<std::string>& filesFound, const std::string& path)
{
DirIterator iter(path.c_str());
while (iter.next())
{
if (iter.isDir())
{
if (iter.fileName() == "." || iter.fileName() == "..")
{
continue;
}
scanDir(filesFound, iter.filePath());
}
else
{
filesFound.push_back(iter.filePath());
}
}
}
int main(int argc, char** argv)
{
if (argc < 3)
{
return 1;
}
std::string archivePath(argv[1]);
std::string inputDir(argv[2]);
try
{
std::vector<std::string> paths;
scanDir(paths, inputDir);
for (std::vector<std::string>::const_iterator iter = paths.begin();
iter != paths.end();
++iter)
{
std::string path = iter->substr(inputDir.size()+1);
std::string content = FileUtils::readFile(iter->c_str());
LOG(Info, "Adding " + path + " to archive " + archivePath);
FileUtils::addToZip(archivePath.c_str(), path.c_str(), content.data(), content.length());
}
}
catch (const std::exception& ex)
{
std::cerr << "Creating zip file failed: " << ex.what() << std::endl;
}
return 0;
}