mirror of
https://github.com/microsoft/vcpkg.git
synced 2024-12-29 20:23:41 +08:00
Introduce archives.h/cpp
This commit is contained in:
parent
3e76baa163
commit
dbae3bfe56
9
toolsrc/include/vcpkg/base/archives.h
Normal file
9
toolsrc/include/vcpkg/base/archives.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vcpkg/base/files.h>
|
||||||
|
#include <vcpkg/vcpkgpaths.h>
|
||||||
|
|
||||||
|
namespace vcpkg::Archives
|
||||||
|
{
|
||||||
|
void extract_archive(const VcpkgPaths& paths, const fs::path& archive, const fs::path& to_path);
|
||||||
|
}
|
107
toolsrc/src/vcpkg/base/archives.cpp
Normal file
107
toolsrc/src/vcpkg/base/archives.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include <vcpkg/base/archives.h>
|
||||||
|
#include <vcpkg/commands.h>
|
||||||
|
|
||||||
|
namespace vcpkg::Archives
|
||||||
|
{
|
||||||
|
void extract_archive(const VcpkgPaths& paths, const fs::path& archive, const fs::path& to_path)
|
||||||
|
{
|
||||||
|
Files::Filesystem& fs = paths.get_filesystem();
|
||||||
|
const fs::path to_path_partial = to_path.u8string() + ".partial";
|
||||||
|
|
||||||
|
std::error_code ec;
|
||||||
|
fs.remove_all(to_path, ec);
|
||||||
|
fs.remove_all(to_path_partial, ec);
|
||||||
|
fs.create_directories(to_path_partial, ec);
|
||||||
|
const auto ext = archive.extension();
|
||||||
|
#if defined(_WIN32)
|
||||||
|
if (ext == ".nupkg")
|
||||||
|
{
|
||||||
|
static bool recursion_limiter_sevenzip_old = false;
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO, !recursion_limiter_sevenzip_old);
|
||||||
|
recursion_limiter_sevenzip_old = true;
|
||||||
|
const auto nuget_exe = Commands::Fetch::get_tool_path(paths, Tools::NUGET);
|
||||||
|
|
||||||
|
const std::string stem = archive.stem().u8string();
|
||||||
|
// assuming format of [name].[version in the form d.d.d]
|
||||||
|
// This assumption may not always hold
|
||||||
|
std::smatch match;
|
||||||
|
const bool has_match = std::regex_match(stem, match, std::regex{R"###(^(.+)\.(\d+\.\d+\.\d+)$)###"});
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
|
has_match,
|
||||||
|
"Could not deduce nuget id and version from filename: %s",
|
||||||
|
archive.u8string());
|
||||||
|
|
||||||
|
const std::string nugetid = match[1];
|
||||||
|
const std::string version = match[2];
|
||||||
|
|
||||||
|
const auto code_and_output = System::cmd_execute_and_capture_output(Strings::format(
|
||||||
|
R"("%s" install %s -Version %s -OutputDirectory "%s" -Source "%s" -nocache -DirectDownload -NonInteractive -ForceEnglishOutput -PackageSaveMode nuspec)",
|
||||||
|
nuget_exe.u8string(),
|
||||||
|
nugetid,
|
||||||
|
version,
|
||||||
|
to_path_partial.u8string(),
|
||||||
|
paths.downloads.u8string()));
|
||||||
|
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
|
code_and_output.exit_code == 0,
|
||||||
|
"Failed to extract '%s' with message:\n%s",
|
||||||
|
archive.u8string(),
|
||||||
|
code_and_output.output);
|
||||||
|
recursion_limiter_sevenzip_old = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static bool recursion_limiter_sevenzip = false;
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO, !recursion_limiter_sevenzip);
|
||||||
|
recursion_limiter_sevenzip = true;
|
||||||
|
const auto seven_zip = Commands::Fetch::get_tool_path(paths, Tools::SEVEN_ZIP);
|
||||||
|
const auto code_and_output = System::cmd_execute_and_capture_output(Strings::format(
|
||||||
|
R"("%s" x "%s" -o"%s" -y)", seven_zip.u8string(), archive.u8string(), to_path_partial.u8string()));
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
|
code_and_output.exit_code == 0,
|
||||||
|
"7zip failed while extracting '%s' with message:\n%s",
|
||||||
|
archive.u8string(),
|
||||||
|
code_and_output.output);
|
||||||
|
recursion_limiter_sevenzip = false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (ext == ".gz" && ext.extension() != ".tar")
|
||||||
|
{
|
||||||
|
const auto code = System::cmd_execute(
|
||||||
|
Strings::format(R"(cd '%s' && tar xzf '%s')", to_path_partial.u8string(), archive.u8string()));
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO, code == 0, "tar failed while extracting %s", archive.u8string());
|
||||||
|
}
|
||||||
|
else if (ext == ".zip")
|
||||||
|
{
|
||||||
|
const auto code = System::cmd_execute(
|
||||||
|
Strings::format(R"(cd '%s' && unzip -qqo '%s')", to_path_partial.u8string(), archive.u8string()));
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO, code == 0, "unzip failed while extracting %s", archive.u8string());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Checks::exit_with_message(VCPKG_LINE_INFO, "Unexpected archive extension: %s", ext.u8string());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fs.rename(to_path_partial, to_path, ec);
|
||||||
|
|
||||||
|
for (int i = 0; i < 5 && ec; i++)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
std::this_thread::sleep_for(i * 100ms);
|
||||||
|
fs.rename(to_path_partial, to_path, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
Checks::check_exit(VCPKG_LINE_INFO,
|
||||||
|
!ec,
|
||||||
|
"Failed to do post-extract rename-in-place.\n"
|
||||||
|
"fs.rename(%s, %s, %s)",
|
||||||
|
to_path_partial.u8string(),
|
||||||
|
to_path.u8string(),
|
||||||
|
ec.message());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include <vcpkg/base/archives.h>
|
||||||
#include <vcpkg/base/checks.h>
|
#include <vcpkg/base/checks.h>
|
||||||
#include <vcpkg/base/downloads.h>
|
#include <vcpkg/base/downloads.h>
|
||||||
#include <vcpkg/base/sortedvector.h>
|
#include <vcpkg/base/sortedvector.h>
|
||||||
@ -236,106 +237,6 @@ namespace vcpkg::Commands::Fetch
|
|||||||
|
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void extract_archive(const VcpkgPaths& paths, const fs::path& archive, const fs::path& to_path)
|
|
||||||
{
|
|
||||||
Files::Filesystem& fs = paths.get_filesystem();
|
|
||||||
const fs::path to_path_partial = to_path.u8string() + ".partial";
|
|
||||||
|
|
||||||
std::error_code ec;
|
|
||||||
fs.remove_all(to_path, ec);
|
|
||||||
fs.remove_all(to_path_partial, ec);
|
|
||||||
fs.create_directories(to_path_partial, ec);
|
|
||||||
const auto ext = archive.extension();
|
|
||||||
#if defined(_WIN32)
|
|
||||||
if (ext == ".nupkg")
|
|
||||||
{
|
|
||||||
static bool recursion_limiter_sevenzip_old = false;
|
|
||||||
Checks::check_exit(VCPKG_LINE_INFO, !recursion_limiter_sevenzip_old);
|
|
||||||
recursion_limiter_sevenzip_old = true;
|
|
||||||
const auto nuget_exe = get_tool_path(paths, Tools::NUGET);
|
|
||||||
|
|
||||||
const std::string stem = archive.stem().u8string();
|
|
||||||
// assuming format of [name].[version in the form d.d.d]
|
|
||||||
// This assumption may not always hold
|
|
||||||
std::smatch match;
|
|
||||||
const bool has_match = std::regex_match(stem, match, std::regex{R"###(^(.+)\.(\d+\.\d+\.\d+)$)###"});
|
|
||||||
Checks::check_exit(VCPKG_LINE_INFO,
|
|
||||||
has_match,
|
|
||||||
"Could not deduce nuget id and version from filename: %s",
|
|
||||||
archive.u8string());
|
|
||||||
|
|
||||||
const std::string nugetid = match[1];
|
|
||||||
const std::string version = match[2];
|
|
||||||
|
|
||||||
const auto code_and_output = System::cmd_execute_and_capture_output(Strings::format(
|
|
||||||
R"("%s" install %s -Version %s -OutputDirectory "%s" -Source "%s" -nocache -DirectDownload -NonInteractive -ForceEnglishOutput -PackageSaveMode nuspec)",
|
|
||||||
nuget_exe.u8string(),
|
|
||||||
nugetid,
|
|
||||||
version,
|
|
||||||
to_path_partial.u8string(),
|
|
||||||
paths.downloads.u8string()));
|
|
||||||
|
|
||||||
Checks::check_exit(VCPKG_LINE_INFO,
|
|
||||||
code_and_output.exit_code == 0,
|
|
||||||
"Failed to extract '%s' with message:\n%s",
|
|
||||||
archive.u8string(),
|
|
||||||
code_and_output.output);
|
|
||||||
recursion_limiter_sevenzip_old = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static bool recursion_limiter_sevenzip = false;
|
|
||||||
Checks::check_exit(VCPKG_LINE_INFO, !recursion_limiter_sevenzip);
|
|
||||||
recursion_limiter_sevenzip = true;
|
|
||||||
const auto seven_zip = get_tool_path(paths, Tools::SEVEN_ZIP);
|
|
||||||
const auto code_and_output = System::cmd_execute_and_capture_output(Strings::format(
|
|
||||||
R"("%s" x "%s" -o"%s" -y)", seven_zip.u8string(), archive.u8string(), to_path_partial.u8string()));
|
|
||||||
Checks::check_exit(VCPKG_LINE_INFO,
|
|
||||||
code_and_output.exit_code == 0,
|
|
||||||
"7zip failed while extracting '%s' with message:\n%s",
|
|
||||||
archive.u8string(),
|
|
||||||
code_and_output.output);
|
|
||||||
recursion_limiter_sevenzip = false;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (ext == ".gz" && ext.extension() != ".tar")
|
|
||||||
{
|
|
||||||
const auto code = System::cmd_execute(
|
|
||||||
Strings::format(R"(cd '%s' && tar xzf '%s')", to_path_partial.u8string(), archive.u8string()));
|
|
||||||
Checks::check_exit(VCPKG_LINE_INFO, code == 0, "tar failed while extracting %s", archive.u8string());
|
|
||||||
}
|
|
||||||
else if (ext == ".zip")
|
|
||||||
{
|
|
||||||
const auto code = System::cmd_execute(
|
|
||||||
Strings::format(R"(cd '%s' && unzip -qqo '%s')", to_path_partial.u8string(), archive.u8string()));
|
|
||||||
Checks::check_exit(VCPKG_LINE_INFO, code == 0, "unzip failed while extracting %s", archive.u8string());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Checks::exit_with_message(VCPKG_LINE_INFO, "Unexpected archive extension: %s", ext.u8string());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fs.rename(to_path_partial, to_path, ec);
|
|
||||||
|
|
||||||
for (int i = 0; i < 5 && ec; i++)
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
using namespace std::chrono_literals;
|
|
||||||
std::this_thread::sleep_for(i * 100ms);
|
|
||||||
fs.rename(to_path_partial, to_path, ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
Checks::check_exit(VCPKG_LINE_INFO,
|
|
||||||
!ec,
|
|
||||||
"Failed to do post-extract rename-in-place.\n"
|
|
||||||
"fs.rename(%s, %s, %s)",
|
|
||||||
to_path_partial.u8string(),
|
|
||||||
to_path.u8string(),
|
|
||||||
ec.message());
|
|
||||||
}
|
|
||||||
|
|
||||||
static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data)
|
static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data)
|
||||||
{
|
{
|
||||||
const std::array<int, 3>& version = tool_data.version;
|
const std::array<int, 3>& version = tool_data.version;
|
||||||
@ -367,7 +268,7 @@ namespace vcpkg::Commands::Fetch
|
|||||||
if (tool_data.is_archive)
|
if (tool_data.is_archive)
|
||||||
{
|
{
|
||||||
System::println("Extracting %s...", tool_name);
|
System::println("Extracting %s...", tool_name);
|
||||||
extract_archive(paths, tool_data.download_path, tool_data.tool_dir_path);
|
Archives::extract_archive(paths, tool_data.download_path, tool_data.tool_dir_path);
|
||||||
System::println("Extracting %s... done.", tool_name);
|
System::println("Extracting %s... done.", tool_name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -137,6 +137,7 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\include\pch.h" />
|
<ClInclude Include="..\include\pch.h" />
|
||||||
|
<ClInclude Include="..\include\vcpkg\base\archives.h" />
|
||||||
<ClInclude Include="..\include\vcpkg\base\checks.h" />
|
<ClInclude Include="..\include\vcpkg\base\checks.h" />
|
||||||
<ClInclude Include="..\include\vcpkg\base\chrono.h" />
|
<ClInclude Include="..\include\vcpkg\base\chrono.h" />
|
||||||
<ClInclude Include="..\include\vcpkg\base\cofffilereader.h" />
|
<ClInclude Include="..\include\vcpkg\base\cofffilereader.h" />
|
||||||
@ -193,6 +194,7 @@
|
|||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\vcpkg\base\archives.cpp" />
|
||||||
<ClCompile Include="..\src\vcpkg\base\checks.cpp" />
|
<ClCompile Include="..\src\vcpkg\base\checks.cpp" />
|
||||||
<ClCompile Include="..\src\vcpkg\base\chrono.cpp" />
|
<ClCompile Include="..\src\vcpkg\base\chrono.cpp" />
|
||||||
<ClCompile Include="..\src\vcpkg\base\cofffilereader.cpp" />
|
<ClCompile Include="..\src\vcpkg\base\cofffilereader.cpp" />
|
||||||
|
@ -204,6 +204,9 @@
|
|||||||
<ClCompile Include="..\src\vcpkg\base\downloads.cpp">
|
<ClCompile Include="..\src\vcpkg\base\downloads.cpp">
|
||||||
<Filter>Source Files\vcpkg\base</Filter>
|
<Filter>Source Files\vcpkg\base</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\vcpkg\base\archives.cpp">
|
||||||
|
<Filter>Source Files\vcpkg\base</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\include\pch.h">
|
<ClInclude Include="..\include\pch.h">
|
||||||
@ -353,5 +356,8 @@
|
|||||||
<ClInclude Include="..\include\vcpkg\base\downloads.h">
|
<ClInclude Include="..\include\vcpkg\base\downloads.h">
|
||||||
<Filter>Header Files\vcpkg\base</Filter>
|
<Filter>Header Files\vcpkg\base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\include\vcpkg\base\archives.h">
|
||||||
|
<Filter>Header Files\vcpkg\base</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
x
Reference in New Issue
Block a user