Commit f1d1e853 authored by Andrew Knight's avatar Andrew Knight
Browse files

winrtrunner: Add an inherited method for creating packages


This method can be used by AppxEngine subclasses for creating package
(*.appx) files.

Change-Id: I7aab9bced144353c3c9e8cf6fbb914bd2f5b7fbb
Reviewed-by: default avatarOliver Wolff <oliver.wolff@digia.com>
Showing with 93 additions and 0 deletions
...@@ -343,3 +343,95 @@ bool AppxEngine::installDependencies() ...@@ -343,3 +343,95 @@ bool AppxEngine::installDependencies()
return true; return true;
} }
bool AppxEngine::createPackage(const QString &packageFileName)
{
Q_D(AppxEngine);
static QHash<QString, QString> contentTypes;
if (contentTypes.isEmpty()) {
contentTypes.insert(QStringLiteral("dll"), QStringLiteral("application/x-msdownload"));
contentTypes.insert(QStringLiteral("exe"), QStringLiteral("application/x-msdownload"));
contentTypes.insert(QStringLiteral("png"), QStringLiteral("image/png"));
contentTypes.insert(QStringLiteral("xml"), QStringLiteral("vnd.ms-appx.manifest+xml"));
}
// Check for package map, or create one if needed
QDir base = QFileInfo(d->manifest).absoluteDir();
QFile packageFile(packageFileName);
QHash<QString, QString> files;
QFile mappingFile(base.absoluteFilePath(QStringLiteral("AppxManifest.map")));
if (mappingFile.exists()) {
qCWarning(lcWinRtRunner) << "Creating package from mapping file:" << mappingFile.fileName();
if (!mappingFile.open(QFile::ReadOnly)) {
qCWarning(lcWinRtRunner) << "Unable to read mapping file:" << mappingFile.errorString();
return false;
}
QRegExp pattern(QStringLiteral("^\"([^\"]*)\"\\s*\"([^\"]*)\"$"));
bool inFileSection = false;
while (!mappingFile.atEnd()) {
const QString line = QString::fromUtf8(mappingFile.readLine()).trimmed();
if (line.startsWith(QLatin1Char('['))) {
inFileSection = line == QStringLiteral("[Files]");
continue;
}
if (pattern.cap(2).compare(QStringLiteral("AppxManifest.xml"), Qt::CaseInsensitive) == 0)
continue;
if (inFileSection && pattern.indexIn(line) >= 0 && pattern.captureCount() == 2) {
QString inputFile = pattern.cap(1);
if (!QFile::exists(inputFile))
inputFile = base.absoluteFilePath(inputFile);
files.insert(QDir::toNativeSeparators(inputFile), QDir::toNativeSeparators(pattern.cap(2)));
}
}
} else {
qCWarning(lcWinRtRunner) << "No mapping file exists. Only recognized files will be packaged.";
// Add executable
files.insert(QDir::toNativeSeparators(d->executable), QFileInfo(d->executable).fileName());
// Add potential Qt files
const QStringList fileTypes = QStringList()
<< QStringLiteral("*.dll") << QStringLiteral("*.png") << QStringLiteral("*.qm")
<< QStringLiteral("*.qml") << QStringLiteral("*.qmldir");
QDirIterator dirIterator(base.absolutePath(), fileTypes, QDir::Files, QDirIterator::Subdirectories);
while (dirIterator.hasNext()) {
const QString filePath = dirIterator.next();
files.insert(QDir::toNativeSeparators(filePath), QDir::toNativeSeparators(base.relativeFilePath(filePath)));
}
}
ComPtr<IStream> outputStream;
HRESULT hr = SHCreateStreamOnFile(wchar(packageFile.fileName()), STGM_WRITE|STGM_CREATE, &outputStream);
RETURN_FALSE_IF_FAILED("Failed to create package file output stream");
ComPtr<IUri> hashMethod;
hr = CreateUri(L"http://www.w3.org/2001/04/xmlenc#sha512", Uri_CREATE_CANONICALIZE, 0, &hashMethod);
RETURN_FALSE_IF_FAILED("Failed to create the has method URI");
APPX_PACKAGE_SETTINGS packageSettings = { FALSE, hashMethod.Get() };
ComPtr<IAppxPackageWriter> packageWriter;
hr = d->packageFactory->CreatePackageWriter(outputStream.Get(), &packageSettings, &packageWriter);
RETURN_FALSE_IF_FAILED("Failed to create package writer");
for (QHash<QString, QString>::const_iterator i = files.begin(); i != files.end(); ++i) {
qCDebug(lcWinRtRunner) << "Packaging" << i.key() << i.value();
ComPtr<IStream> inputStream;
hr = SHCreateStreamOnFile(wchar(i.key()), STGM_READ, &inputStream);
RETURN_FALSE_IF_FAILED("Failed to open file");
const QString contentType = contentTypes.value(QFileInfo(i.key()).suffix().toLower(),
QStringLiteral("application/octet-stream"));
hr = packageWriter->AddPayloadFile(wchar(i.value()), wchar(contentType),
APPX_COMPRESSION_OPTION_NORMAL, inputStream.Get());
RETURN_FALSE_IF_FAILED("Failed to add payload file");
}
// Write out the manifest
ComPtr<IStream> manifestStream;
hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream);
RETURN_FALSE_IF_FAILED("Failed to open manifest for packaging");
hr = packageWriter->Close(manifestStream.Get());
RETURN_FALSE_IF_FAILED("Failed to finalize package.");
return true;
}
...@@ -67,6 +67,7 @@ protected: ...@@ -67,6 +67,7 @@ protected:
virtual bool installPackage(IAppxManifestReader *reader, const QString &filePath) = 0; virtual bool installPackage(IAppxManifestReader *reader, const QString &filePath) = 0;
bool installDependencies(); bool installDependencies();
bool createPackage(const QString &packageFileName);
static bool getManifestFile(const QString &fileName, QString *manifest = 0); static bool getManifestFile(const QString &fileName, QString *manifest = 0);
QScopedPointer<AppxEnginePrivate> d_ptr; QScopedPointer<AppxEnginePrivate> d_ptr;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment