diff options
author | Eike Ziller <eike.ziller@qt.io> | 2020-05-27 16:32:31 +0200 |
---|---|---|
committer | Eike Ziller <eike.ziller@qt.io> | 2020-05-29 13:17:02 +0000 |
commit | 26c26c0dada6b057804dd15f1cc0c057e0d794a8 (patch) | |
tree | 915c65229c97e488cde82aee9bf1d78d7df2bddd | |
parent | f75d1ae61a26cd51c9b0a73a66dbf336eb61551b (diff) | |
download | qt-creator-26c26c0dada6b057804dd15f1cc0c057e0d794a8.tar.gz |
Support more file formats for unarchiving plugins
Use tar, or cmake -E tar, for .tar, .tar.gz, tar.xz, tar.bz2.
Use 7zip for 7zip.
Zip is supported by unzip, 7zip, tar, and cmake.
Change-Id: I799c3211325398add150644b57c32b7ad5bb8903
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
-rw-r--r-- | src/libs/utils/archive.cpp | 83 |
1 files changed, 63 insertions, 20 deletions
diff --git a/src/libs/utils/archive.cpp b/src/libs/utils/archive.cpp index daab53451f..0ea6a920f2 100644 --- a/src/libs/utils/archive.cpp +++ b/src/libs/utils/archive.cpp @@ -39,27 +39,69 @@ namespace { struct Tool { - Utils::FilePath executable; + QString executable; QStringList arguments; + QStringList supportedMimeTypes; }; -Utils::optional<Tool> unzipTool(const Utils::FilePath &src, const Utils::FilePath &dest) +const QVector<Tool> sTools = { + {"unzip", {"-o", "%{src}", "-d", "%{dest}"}, {"application/zip"}}, + {"7z", {"x", "-o%{dest}", "-y", "%{src}"}, {"application/zip", "application/x-7z-compressed"}}, + {"tar", + {"xvf", "%{src}"}, + {"application/zip", "application/x-tar", "application/x-7z-compressed"}}, + {"tar", {"xvzf", "%{src}"}, {"application/x-compressed-tar"}}, + {"tar", {"xvJf", "%{src}"}, {"application/x-xz-compressed-tar"}}, + {"tar", {"xvjf", "%{src}"}, {"application/x-bzip-compressed-tar"}}, + {"cmake", + {"-E", "tar", "xvf", "%{src}"}, + {"application/zip", "application/x-tar", "application/x-7z-compressed"}}, + {"cmake", {"-E", "tar", "xvzf", "%{src}"}, {"application/x-compressed-tar"}}, + {"cmake", {"-E", "tar", "xvJf", "%{src}"}, {"application/x-xz-compressed-tar"}}, + {"cmake", {"-E", "tar", "xvjf", "%{src}"}, {"application/x-bzip-compressed-tar"}}, +}; + +static QVector<Tool> toolsForMimeType(const Utils::MimeType &mimeType) { - const Utils::FilePath unzip = Utils::Environment::systemEnvironment().searchInPath( - Utils::HostOsInfo::withExecutableSuffix("unzip")); - if (!unzip.isEmpty()) - return Tool{unzip, {"-o", src.toString(), "-d", dest.toString()}}; + return Utils::filtered(sTools, [mimeType](const Tool &tool) { + return Utils::anyOf(tool.supportedMimeTypes, + [mimeType](const QString &mt) { return mimeType.inherits(mt); }); + }); +} - const Utils::FilePath sevenzip = Utils::Environment::systemEnvironment().searchInPath( - Utils::HostOsInfo::withExecutableSuffix("7z")); - if (!sevenzip.isEmpty()) - return Tool{sevenzip, {"x", QString("-o") + dest.toString(), "-y", src.toString()}}; +static QVector<Tool> toolsForFilePath(const Utils::FilePath &fp) +{ + return toolsForMimeType(Utils::mimeTypeForFile(fp.toString())); +} - const Utils::FilePath cmake = Utils::Environment::systemEnvironment().searchInPath( - Utils::HostOsInfo::withExecutableSuffix("cmake")); - if (!cmake.isEmpty()) - return Tool{cmake, {"-E", "tar", "xvf", src.toString()}}; +static Utils::optional<Tool> resolveTool(const Tool &tool) +{ + const QString executable = Utils::Environment::systemEnvironment() + .searchInPath( + Utils::HostOsInfo::withExecutableSuffix(tool.executable)) + .toString(); + Tool resolvedTool = tool; + resolvedTool.executable = executable; + return executable.isEmpty() ? Utils::nullopt : Utils::make_optional(resolvedTool); +} +Utils::optional<Tool> unzipTool(const Utils::FilePath &src, const Utils::FilePath &dest) +{ + const QVector<Tool> tools = toolsForFilePath(src); + for (const Tool &tool : tools) { + const Utils::optional<Tool> resolvedTool = resolveTool(tool); + if (resolvedTool) { + Tool result = *resolvedTool; + const QString srcStr = src.toString(); + const QString destStr = dest.toString(); + result.arguments + = Utils::transform(result.arguments, [srcStr, destStr](const QString &a) { + QString val = a; + return val.replace("%{src}", srcStr).replace("%{dest}", destStr); + }); + return result; + } + } return {}; } @@ -69,15 +111,16 @@ namespace Utils { bool Archive::supportsFile(const FilePath &filePath, QString *reason) { - const QList<MimeType> mimeType = mimeTypesForFileName(filePath.toString()); - if (!anyOf(mimeType, [](const MimeType &mt) { return mt.inherits("application/zip"); })) { + const QVector<Tool> tools = toolsForFilePath(filePath); + if (tools.isEmpty()) { if (reason) *reason = tr("File format not supported."); return false; } - if (!unzipTool({}, {})) { + if (!anyOf(tools, [](const Tool &t) { return resolveTool(t); })) { if (reason) - *reason = tr("Could not find unzip, 7z, or cmake executable in PATH."); + *reason = tr("Could not find any unarchiving executable in PATH (%1).") + .arg(transform<QStringList>(tools, &Tool::executable).join(", ")); return false; } return true; @@ -91,7 +134,7 @@ bool Archive::unarchive(const FilePath &src, const FilePath &dest, QWidget *pare QDir(workingDirectory).mkpath("."); CheckableMessageBox box(parent); box.setIcon(QMessageBox::Information); - box.setWindowTitle(tr("Unzipping File")); + box.setWindowTitle(tr("Unarchiving File")); box.setText(tr("Unzipping \"%1\" to \"%2\".").arg(src.toUserOutput(), dest.toUserOutput())); box.setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); box.button(QDialogButtonBox::Ok)->setEnabled(false); @@ -113,7 +156,7 @@ bool Archive::unarchive(const FilePath &src, const FilePath &dest, QWidget *pare QObject::connect(&box, &QMessageBox::rejected, &process, [&process] { SynchronousProcess::stopProcess(process); }); - process.setProgram(tool->executable.toString()); + process.setProgram(tool->executable); process.setArguments(tool->arguments); process.setWorkingDirectory(workingDirectory); process.start(QProcess::ReadOnly); |