Various updater fixes

Updater tests for path utils
The updater now doesn't use splitpath on Windows (fixes problems with Windows XP)
Fix up paths for the OSX updater - should now install the updates into the right place
Fix translations install path - translation isntall and deploy should be fixed
This commit is contained in:
Petr Mrázek 2013-12-28 02:03:53 +01:00
parent 30d4f5981d
commit 7652b3d64a
10 changed files with 171 additions and 59 deletions

View File

@ -662,8 +662,12 @@ ELSE()
ENDIF() ENDIF()
add_custom_target (translations DEPENDS ${QM_FILES}) add_custom_target (translations DEPENDS ${QM_FILES})
IF(APPLE AND UNIX) ## OSX
install(FILES ${QM_FILES} DESTINATION MultiMC.app/Contents/MacOS/translations)
ELSE()
install(FILES ${QM_FILES} DESTINATION translations)
ENDIF()
install(FILES ${QM_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/translations)
# Tests # Tests
add_subdirectory(tests) add_subdirectory(tests)

View File

@ -66,7 +66,7 @@ void DownloadUpdateTask::processChannels()
if (channel.id == channelId) if (channel.id == channelId)
{ {
QLOG_INFO() << "Found matching channel."; QLOG_INFO() << "Found matching channel.";
m_cRepoUrl = preparePath(channel.url); m_cRepoUrl = fixPathForTests(channel.url);
break; break;
} }
} }
@ -207,8 +207,17 @@ bool DownloadUpdateTask::parseVersionInfo(const QByteArray &data, VersionFileLis
{ {
QJsonObject fileObj = fileValue.toObject(); QJsonObject fileObj = fileValue.toObject();
QString file_path = fileObj.value("Path").toString();
#ifdef Q_OS_MAC
// On OSX, the paths for the updater need to be fixed.
// basically, anything that isn't in the .app folder is ignored.
// everything else is changed so the code that processes the files actually finds
// them and puts the replacements in the right spots.
if(!fixPathForOSX(file_path))
continue;
#endif
VersionFileEntry file{ VersionFileEntry file{
fileObj.value("Path").toString(), fileObj.value("Perms").toVariant().toInt(), file_path , fileObj.value("Perms").toVariant().toInt(),
FileSourceList(), fileObj.value("MD5").toString(), }; FileSourceList(), fileObj.value("MD5").toString(), };
QLOG_DEBUG() << "File" << file.path << "with perms" << file.mode; QLOG_DEBUG() << "File" << file.path << "with perms" << file.mode;
@ -221,12 +230,12 @@ bool DownloadUpdateTask::parseVersionInfo(const QByteArray &data, VersionFileLis
if (type == "http") if (type == "http")
{ {
file.sources.append( file.sources.append(
FileSource("http", preparePath(sourceObj.value("Url").toString()))); FileSource("http", fixPathForTests(sourceObj.value("Url").toString())));
} }
else if (type == "httpc") else if (type == "httpc")
{ {
file.sources.append(FileSource("httpc", file.sources.append(FileSource("httpc",
preparePath(sourceObj.value("Url").toString()), fixPathForTests(sourceObj.value("Url").toString()),
sourceObj.value("CompressionType").toString())); sourceObj.value("CompressionType").toString()));
} }
else else
@ -491,7 +500,7 @@ bool DownloadUpdateTask::writeInstallScript(UpdateOperationList &opsList, QStrin
return true; return true;
} }
QString DownloadUpdateTask::preparePath(const QString &path) QString DownloadUpdateTask::fixPathForTests(const QString &path)
{ {
if(path.startsWith("$PWD")) if(path.startsWith("$PWD"))
{ {
@ -502,6 +511,23 @@ QString DownloadUpdateTask::preparePath(const QString &path)
return path; return path;
} }
bool DownloadUpdateTask::fixPathForOSX(QString &path)
{
if(path.startsWith("MultiMC.app/"))
{
// remove the prefix and add a new, more appropriate one.
path.remove(0,12);
path = QString("../../") + path;
return true;
}
else
{
QLOG_ERROR() << "Update path not within .app: " << path;
return false;
}
}
void DownloadUpdateTask::fileDownloadFinished() void DownloadUpdateTask::fileDownloadFinished()
{ {
emitSucceeded(); emitSucceeded();

View File

@ -198,7 +198,21 @@ protected:
* Filters paths * Filters paths
* Path of the format $PWD/path, it is converted to a file:///$PWD/ URL * Path of the format $PWD/path, it is converted to a file:///$PWD/ URL
*/ */
static QString preparePath(const QString &path); static QString fixPathForTests(const QString &path);
/*!
* Filters paths
* This fixes destination paths for OSX.
* The updater runs in MultiMC.app/Contents/MacOs by default
* The destination paths are such as this: MultiMC.app/blah/blah
*
* Therefore we chop off the 'MultiMC.app' prefix and prepend ../..
*
* Returns false if the path couldn't be fixed (is invalid)
*
* Has no effect on systems that aren't OSX
*/
static bool fixPathForOSX(QString &path);
protected slots: protected slots:
void vinfoDownloadFinished(); void vinfoDownloadFinished();

View File

@ -10,6 +10,8 @@
#include <string.h> #include <string.h>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
// this actually works with mingw32, which we use.
#include <libgen.h>
#ifdef PLATFORM_UNIX #ifdef PLATFORM_UNIX
#include <unistd.h> #include <unistd.h>
@ -19,7 +21,6 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <libgen.h>
#endif #endif
FileUtils::IOException::IOException(const std::string& error) FileUtils::IOException::IOException(const std::string& error)
@ -249,59 +250,18 @@ void FileUtils::removeFile(const char* src) throw (IOException)
std::string FileUtils::fileName(const char* path) std::string FileUtils::fileName(const char* path)
{ {
#ifdef PLATFORM_UNIX
char* pathCopy = strdup(path); char* pathCopy = strdup(path);
std::string basename = ::basename(pathCopy); std::string basename = ::basename(pathCopy);
free(pathCopy); free(pathCopy);
return basename; return basename;
#else
char baseName[MAX_PATH];
char extension[MAX_PATH];
_splitpath_s(path,
0, /* drive */
0, /* drive length */
0, /* dir */
0, /* dir length */
baseName,
MAX_PATH, /* baseName length */
extension,
MAX_PATH /* extension length */
);
return std::string(baseName) + std::string(extension);
#endif
} }
std::string FileUtils::dirname(const char* path) std::string FileUtils::dirname(const char* path)
{ {
#ifdef PLATFORM_UNIX
char* pathCopy = strdup(path); char* pathCopy = strdup(path);
std::string dirname = ::dirname(pathCopy); std::string dirname = ::dirname(pathCopy);
free(pathCopy); free(pathCopy);
return dirname; return dirname;
#else
char drive[3];
char dir[MAX_PATH];
_splitpath_s(path,
drive, /* drive */
3, /* drive length */
dir,
MAX_PATH, /* dir length */
0, /* filename */
0, /* filename length */
0, /* extension */
0 /* extension length */
);
std::string result;
if (drive[0])
{
result += std::string(drive);
}
result += dir;
return result;
#endif
} }
void FileUtils::touch(const char* path) throw (IOException) void FileUtils::touch(const char* path) throw (IOException)

View File

@ -30,7 +30,12 @@ endforeach()
# Add unit test binaries # Add unit test binaries
macro(ADD_UPDATER_TEST CLASS) macro(ADD_UPDATER_TEST CLASS)
set(TEST_TARGET updater_${CLASS}) set(TEST_TARGET updater_${CLASS})
add_executable(${TEST_TARGET} ${CLASS}.cpp) unset(srcs)
list(APPEND srcs ${CLASS}.cpp)
if (WIN32)
list(APPEND srcs ${CMAKE_CURRENT_SOURCE_DIR}/test.rc)
endif()
add_executable(${TEST_TARGET} ${srcs})
target_link_libraries(${TEST_TARGET} updatershared) target_link_libraries(${TEST_TARGET} updatershared)
add_test(NAME ${TEST_TARGET} COMMAND ${TEST_TARGET}) add_test(NAME ${TEST_TARGET} COMMAND ${TEST_TARGET})
if (APPLE) if (APPLE)

View File

@ -5,10 +5,39 @@
void TestFileUtils::testDirName() void TestFileUtils::testDirName()
{ {
std::string dirName;
std::string fileName;
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
std::string dirName = FileUtils::dirname("E:/Some Dir/App.exe"); // absolute paths
TEST_COMPARE(dirName,"E:/Some Dir/"); dirName = FileUtils::dirname("E:/Some Dir/App.exe");
TEST_COMPARE(dirName,"E:/Some Dir");
fileName = FileUtils::fileName("E:/Some Dir/App.exe");
TEST_COMPARE(fileName,"App.exe");
dirName = FileUtils::dirname("C:/Users/kitteh/AppData/Local/Temp/MultiMC5-yidaaa/MultiMC.exe");
TEST_COMPARE(dirName,"C:/Users/kitteh/AppData/Local/Temp/MultiMC5-yidaaa");
fileName = FileUtils::fileName("C:/Users/kitteh/AppData/Local/Temp/MultiMC5-yidaaa/MultiMC.exe");
TEST_COMPARE(fileName,"MultiMC.exe");
#else
// absolute paths
dirName = FileUtils::dirname("/home/tester/foo bar/baz");
TEST_COMPARE(dirName,"/home/tester/foo bar");
fileName = FileUtils::fileName("/home/tester/foo bar/baz");
TEST_COMPARE(fileName,"baz");
#endif #endif
// current directory
dirName = FileUtils::dirname("App.exe");
TEST_COMPARE(dirName,".");
fileName = FileUtils::fileName("App.exe");
TEST_COMPARE(fileName,"App.exe");
// relative paths
dirName = FileUtils::dirname("Foo/App.exe");
TEST_COMPARE(dirName,"Foo");
fileName = FileUtils::fileName("Foo/App.exe");
TEST_COMPARE(fileName,"App.exe");
} }
void TestFileUtils::testIsRelative() void TestFileUtils::testIsRelative()

View File

@ -10,7 +10,7 @@ void TestParseScript::testParse()
{ {
UpdateScript script; UpdateScript script;
script.parse("file_list.xml"); script.parse("mmc_updater/src/tests/file_list.xml");
TEST_COMPARE(script.isValid(),true); TEST_COMPARE(script.isValid(),true);
} }

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity name="MultiMC.Test.0" type="win32" version="5.0.0.0" />
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
<description>Custom Minecraft launcher for managing multiple installs.</description>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--The ID below indicates app support for Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!--The ID below indicates app support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!--The ID below indicates app support for Windows Developer Preview / Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
</application>
</compatibility>
</assembly>

View File

@ -0,0 +1,28 @@
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
1 RT_MANIFEST "test.manifest"
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_APP
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "CompanyName", "MultiMC Contributors"
VALUE "FileDescription", "Testcase"
VALUE "FileVersion", "1.0.0.0"
VALUE "ProductName", "MultiMC Testcase"
VALUE "ProductVersion", "5"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0000, 0x04b0 // Unicode
END
END

View File

@ -245,6 +245,25 @@ slots:
QVERIFY(succeededSpy.wait()); QVERIFY(succeededSpy.wait());
} }
void test_OSXPathFixup()
{
QString path, pathOrig;
bool result;
// Proper OSX path
pathOrig = path = "MultiMC.app/Foo/Bar/Baz";
qDebug() << "Proper OSX path: " << path;
result = DownloadUpdateTask::fixPathForOSX(path);
QCOMPARE(path, QString("../../Foo/Bar/Baz"));
QCOMPARE(result, true);
// Bad OSX path
pathOrig = path = "translations/klingon.lol";
qDebug() << "Bad OSX path: " << path;
result = DownloadUpdateTask::fixPathForOSX(path);
QCOMPARE(path, pathOrig);
QCOMPARE(result, false);
}
}; };
QTEST_GUILESS_MAIN_MULTIMC(DownloadUpdateTaskTest) QTEST_GUILESS_MAIN_MULTIMC(DownloadUpdateTaskTest)