Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use 7zr to unpack 7zip #1477

Merged
merged 16 commits into from
Sep 17, 2024
3 changes: 3 additions & 0 deletions azure-pipelines/end-to-end-tests-dir/upgrade.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ try
{
$env:VCPKG_ROOT = "$TestingRoot/temp-repo"
git -C "$TestingRoot/temp-repo" switch -d e1934f4a2a0c58bb75099d89ed980832379907fa # vcpkg-cmake @ 2022-12-22
Copy-Item "$VcpkgRoot/scripts/vcpkgTools.xml" "$TestingRoot/temp-repo/scripts/vcpkgTools.xml" -Force
$output = Run-VcpkgAndCaptureOutput install vcpkg-cmake
Throw-IfFailed
if (-Not ($output -match 'vcpkg-cmake:[^ ]+@2022-12-22'))
{
throw 'Unexpected vcpkg-cmake install'
}

git -C "$TestingRoot/temp-repo" checkout -- 'scripts/vcpkgTools.xml'
git -C "$TestingRoot/temp-repo" switch -d f6a5d4e8eb7476b8d7fc12a56dff300c1c986131 # vcpkg-cmake @ 2023-05-04
Copy-Item "$VcpkgRoot/scripts/vcpkgTools.xml" "$TestingRoot/temp-repo/scripts/vcpkgTools.xml" -Force
$output = Run-VcpkgAndCaptureOutput upgrade
Throw-IfNotFailed
if (-Not ($output -match 'If you are sure you want to rebuild the above packages, run this command with the --no-dry-run option.'))
Expand Down
8 changes: 1 addition & 7 deletions include/vcpkg/archives.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace vcpkg
Unknown,
Tar,
Zip,
SevenZip,
Nupkg,
Msi,
Exe
Expand Down Expand Up @@ -48,13 +49,6 @@ namespace vcpkg
#ifdef _WIN32
// Extract the 7z archive part of a self extracting 7z installer
void win32_extract_self_extracting_7z(const Filesystem& fs, const Path& archive, const Path& to_path);
// Extract `archive` to `to_path`, deleting `to_path` first. `archive` must be a zip file.
// This function will use potentially less performant tools that are reliably available on any machine.
void win32_extract_bootstrap_zip(const Filesystem& fs,
const ToolCache& tools,
MessageSink& status_sink,
const Path& archive,
const Path& to_path);
#endif

struct ZipTool
Expand Down
3 changes: 1 addition & 2 deletions include/vcpkg/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace vcpkg
{
static constexpr StringLiteral SEVEN_ZIP = "7zip";
static constexpr StringLiteral SEVEN_ZIP_ALT = "7z";
static constexpr StringLiteral SEVEN_ZIP_R = "7zr";
static constexpr StringLiteral TAR = "tar";
static constexpr StringLiteral MAVEN = "mvn";
static constexpr StringLiteral CMAKE = "cmake";
Expand All @@ -32,8 +33,6 @@ namespace vcpkg
static constexpr StringLiteral IFW_INSTALLER_BASE = "ifw_installerbase";
// This duplicate of CMake should only be used as a fallback to unpack
static constexpr StringLiteral CMAKE_SYSTEM = "cmake_system";
// This duplicate of 7zip uses msiexec to unpack, which is a fallback for Windows 7.
static constexpr StringLiteral SEVEN_ZIP_MSI = "7zip_msi";
static constexpr StringLiteral PYTHON3 = "python3";
static constexpr StringLiteral PYTHON3_WITH_VENV = "python3_with_venv";
}
Expand Down
2 changes: 1 addition & 1 deletion src/vcpkg-test/archives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ TEST_CASE ("Testing guess_extraction_type", "[z-extract]")
REQUIRE(guess_extraction_type(Path("path/to/archive.nupkg")) == ExtractionType::Nupkg);
REQUIRE(guess_extraction_type(Path("/path/to/archive.msi")) == ExtractionType::Msi);
REQUIRE(guess_extraction_type(Path("/path/to/archive.zip")) == ExtractionType::Zip);
REQUIRE(guess_extraction_type(Path("/path/to/archive.7z")) == ExtractionType::Zip);
REQUIRE(guess_extraction_type(Path("/path/to/archive.7z")) == ExtractionType::SevenZip);
REQUIRE(guess_extraction_type(Path("/path/to/archive.gz")) == ExtractionType::Tar);
REQUIRE(guess_extraction_type(Path("/path/to/archive.bz2")) == ExtractionType::Tar);
REQUIRE(guess_extraction_type(Path("/path/to/archive.tgz")) == ExtractionType::Tar);
Expand Down
60 changes: 10 additions & 50 deletions src/vcpkg/archives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ namespace
static bool recursion_limiter_sevenzip = false;
Checks::check_exit(VCPKG_LINE_INFO, !recursion_limiter_sevenzip);
recursion_limiter_sevenzip = true;
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved

const auto maybe_output = flatten(cmd_execute_and_capture_output(Command{seven_zip}
.string_arg("x")
.string_arg(archive)
Expand Down Expand Up @@ -141,8 +142,11 @@ namespace vcpkg
{
return ExtractionType::Msi;
}
else if (Strings::case_insensitive_ascii_equals(ext, ".zip") ||
Strings::case_insensitive_ascii_equals(ext, ".7z"))
else if (Strings::case_insensitive_ascii_equals(ext, ".7z"))
{
return ExtractionType::SevenZip;
}
else if (Strings::case_insensitive_ascii_equals(ext, ".zip"))
{
return ExtractionType::Zip;
}
Expand Down Expand Up @@ -174,8 +178,11 @@ namespace vcpkg
case ExtractionType::Unknown: break;
case ExtractionType::Nupkg: win32_extract_nupkg(tools, status_sink, archive, to_path); break;
JavierMatosD marked this conversation as resolved.
Show resolved Hide resolved
case ExtractionType::Msi: win32_extract_msi(archive, to_path); break;
case ExtractionType::SevenZip:
win32_extract_with_seven_zip(tools.get_tool_path(Tools::SEVEN_ZIP_R, status_sink), archive, to_path);
break;
case ExtractionType::Zip:
extract_tar_cmake(tools.get_tool_path(Tools::CMAKE, status_sink), archive, to_path);
win32_extract_with_seven_zip(tools.get_tool_path(Tools::SEVEN_ZIP, status_sink), archive, to_path);
break;
case ExtractionType::Tar:
extract_tar(tools.get_tool_path(Tools::TAR, status_sink), archive, to_path);
Expand Down Expand Up @@ -236,7 +243,6 @@ namespace vcpkg
void win32_extract_self_extracting_7z(const Filesystem& fs, const Path& archive, const Path& to_path)
{
constexpr static const char header_7z[] = "7z\xBC\xAF\x27\x1C";

const Path stem = archive.stem();
const auto subext = stem.extension();
Checks::msg_check_exit(VCPKG_LINE_INFO,
Expand All @@ -254,52 +260,6 @@ namespace vcpkg
contents = contents.substr(pos);
fs.write_contents(to_path, contents, VCPKG_LINE_INFO);
}

// We are trying to bootstrap vcpkg's copy of CMake which comes in a zipped file.
// If this is successful, we'll use the downloaded CMake for most extractions.
// We will also extract a portable 7z (using the bootstrapped CMake) to use when performance is required.
//
// We use the following methods to attempt this bootstrap, in order:
// 1) Search for a System32/tar.exe (available on Windows 10+)
// tar.exe unpacks cmake.zip -> cmake.exe unpacks 7z.7z
// 2) Search for a user installed CMake on PATH and Program Files [(x86)]
// (user) cmake.exe unpacks cmake.zip -> (vcpkg) cmake.exe unpacks 7z.7z
// 3) As a last resource, install 7zip using a MSI installer
// msiexec installs 7zip.msi -> 7zip unpacks cmake.zip -> cmake.exe unpacks 7z.7z
void win32_extract_bootstrap_zip(const Filesystem& fs,
const ToolCache& tools,
MessageSink& status_sink,
const Path& archive,
const Path& to_path)
{
fs.remove_all(to_path, VCPKG_LINE_INFO);
Path to_path_partial = to_path + ".partial." + std::to_string(GetCurrentProcessId());

fs.remove_all(to_path_partial, VCPKG_LINE_INFO);
fs.create_directories(to_path_partial, VCPKG_LINE_INFO);
const auto tar_path = get_system32().value_or_exit(VCPKG_LINE_INFO) / "tar.exe";
if (fs.exists(tar_path, IgnoreErrors{}))
{
// On Windows 10, tar.exe is in the box.
extract_tar(tar_path, archive, to_path_partial);
}
else
{
auto maybe_cmake_tool = find_system_cmake(fs);
if (maybe_cmake_tool)
{
// If the user has a CMake version installed we can use that to unpack.
extract_tar_cmake(maybe_cmake_tool.value_or_exit(VCPKG_LINE_INFO), archive, to_path_partial);
}
else
{
// On Windows <10, we attempt to use msiexec to unpack 7zip.
win32_extract_with_seven_zip(
tools.get_tool_path(Tools::SEVEN_ZIP_MSI, status_sink), archive, to_path_partial);
}
}
fs.rename_with_retry(to_path_partial, to_path, VCPKG_LINE_INFO);
}
#endif

void extract_tar(const Path& tar_tool, const Path& archive, const Path& to_path)
Expand Down
13 changes: 1 addition & 12 deletions src/vcpkg/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -691,18 +691,7 @@ namespace vcpkg
if (tool_data.is_archive)
{
status_sink.println(Color::none, msgExtractingTool, msg::tool_name = tool_data.name);
#if defined(_WIN32)
if (tool_data.name == "cmake")
{
// We use cmake as the core extractor on Windows, so we need to perform a special dance when
// extracting it.
win32_extract_bootstrap_zip(fs, *this, status_sink, download_path, tool_dir_path);
}
else
#endif // ^^^ _WIN32
{
set_directory_to_archive_contents(fs, *this, status_sink, download_path, tool_dir_path);
}
set_directory_to_archive_contents(fs, *this, status_sink, download_path, tool_dir_path);
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion vcpkg-init/vcpkg-scripts-sha.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5c7d3a872dd861817fc812647176d5076085a7eb
9f11f2df35f60fb483e0f11667653974ddb880ee
Loading