Introduce archives.h/cpp

This commit is contained in:
Alexander Karatarakis 2018-06-19 17:21:34 -07:00
parent 3e76baa163
commit dbae3bfe56
5 changed files with 126 additions and 101 deletions

View 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);
}

View 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());
}
}

View File

@ -1,5 +1,6 @@
#include "pch.h"
#include <vcpkg/base/archives.h>
#include <vcpkg/base/checks.h>
#include <vcpkg/base/downloads.h>
#include <vcpkg/base/sortedvector.h>
@ -236,106 +237,6 @@ namespace vcpkg::Commands::Fetch
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)
{
const std::array<int, 3>& version = tool_data.version;
@ -367,7 +268,7 @@ namespace vcpkg::Commands::Fetch
if (tool_data.is_archive)
{
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);
}
else

View File

@ -137,6 +137,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\include\pch.h" />
<ClInclude Include="..\include\vcpkg\base\archives.h" />
<ClInclude Include="..\include\vcpkg\base\checks.h" />
<ClInclude Include="..\include\vcpkg\base\chrono.h" />
<ClInclude Include="..\include\vcpkg\base\cofffilereader.h" />
@ -193,6 +194,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\src\vcpkg\base\archives.cpp" />
<ClCompile Include="..\src\vcpkg\base\checks.cpp" />
<ClCompile Include="..\src\vcpkg\base\chrono.cpp" />
<ClCompile Include="..\src\vcpkg\base\cofffilereader.cpp" />

View File

@ -204,6 +204,9 @@
<ClCompile Include="..\src\vcpkg\base\downloads.cpp">
<Filter>Source Files\vcpkg\base</Filter>
</ClCompile>
<ClCompile Include="..\src\vcpkg\base\archives.cpp">
<Filter>Source Files\vcpkg\base</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\pch.h">
@ -353,5 +356,8 @@
<ClInclude Include="..\include\vcpkg\base\downloads.h">
<Filter>Header Files\vcpkg\base</Filter>
</ClInclude>
<ClInclude Include="..\include\vcpkg\base\archives.h">
<Filter>Header Files\vcpkg\base</Filter>
</ClInclude>
</ItemGroup>
</Project>