[vcpkg] Add --nuget-description option for vcpkg export (#14953)

This commit is contained in:
ras0219 2020-12-06 15:26:58 -08:00 committed by GitHub
parent 5e7794f3f2
commit 6dfe1be6fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 198 additions and 163 deletions

View File

@ -0,0 +1,31 @@
#pragma once
#include <vcpkg/base/stringliteral.h>
#include <vcpkg/base/stringview.h>
#include <string>
namespace vcpkg
{
struct XmlSerializer
{
XmlSerializer& emit_declaration();
XmlSerializer& open_tag(StringLiteral sl);
XmlSerializer& start_complex_open_tag(StringLiteral sl);
XmlSerializer& text_attr(StringLiteral name, StringView content);
XmlSerializer& finish_complex_open_tag();
XmlSerializer& finish_self_closing_complex_tag();
XmlSerializer& close_tag(StringLiteral sl);
XmlSerializer& text(StringView sv);
XmlSerializer& simple_tag(StringLiteral tag, StringView content);
XmlSerializer& line_break();
std::string buf;
private:
XmlSerializer& emit_pending_indent();
int m_indent = 0;
bool m_pending_indent = false;
};
}

View File

@ -48,27 +48,4 @@ namespace vcpkg
const Dependencies::InstallPlanAction& action,
const NugetReference& ref,
details::NuGetRepoInfo rinfo = details::get_nuget_repo_info_from_env());
struct XmlSerializer
{
XmlSerializer& emit_declaration();
XmlSerializer& open_tag(StringLiteral sl);
XmlSerializer& start_complex_open_tag(StringLiteral sl);
XmlSerializer& text_attr(StringLiteral name, StringView content);
XmlSerializer& finish_complex_open_tag();
XmlSerializer& finish_self_closing_complex_tag();
XmlSerializer& close_tag(StringLiteral sl);
XmlSerializer& text(StringView sv);
XmlSerializer& simple_tag(StringLiteral tag, StringView content);
XmlSerializer& line_break();
std::string buf;
private:
XmlSerializer& emit_pending_indent();
int m_indent = 0;
bool m_pending_indent = false;
};
}

View File

@ -1,6 +1,7 @@
#include <catch2/catch.hpp>
#include <vcpkg/base/files.h>
#include <vcpkg/base/xmlserializer.h>
#include <vcpkg/binarycaching.h>
#include <vcpkg/binarycaching.private.h>

View File

@ -0,0 +1,113 @@
#include <vcpkg/base/strings.h>
#include <vcpkg/base/xmlserializer.h>
namespace vcpkg
{
XmlSerializer& XmlSerializer::emit_declaration()
{
buf.append(R"(<?xml version="1.0" encoding="utf-8"?>)");
return *this;
}
XmlSerializer& XmlSerializer::open_tag(StringLiteral sl)
{
emit_pending_indent();
Strings::append(buf, '<', sl, '>');
m_indent += 2;
return *this;
}
XmlSerializer& XmlSerializer::start_complex_open_tag(StringLiteral sl)
{
emit_pending_indent();
Strings::append(buf, '<', sl);
m_indent += 2;
return *this;
}
XmlSerializer& XmlSerializer::text_attr(StringLiteral name, StringView content)
{
if (m_pending_indent)
{
m_pending_indent = false;
buf.append(m_indent, ' ');
}
else
{
buf.push_back(' ');
}
Strings::append(buf, name, "=\"");
text(content);
Strings::append(buf, '"');
return *this;
}
XmlSerializer& XmlSerializer::finish_complex_open_tag()
{
emit_pending_indent();
Strings::append(buf, '>');
return *this;
}
XmlSerializer& XmlSerializer::finish_self_closing_complex_tag()
{
emit_pending_indent();
Strings::append(buf, "/>");
m_indent -= 2;
return *this;
}
XmlSerializer& XmlSerializer::close_tag(StringLiteral sl)
{
m_indent -= 2;
emit_pending_indent();
Strings::append(buf, "</", sl, '>');
return *this;
}
XmlSerializer& XmlSerializer::text(StringView sv)
{
emit_pending_indent();
for (auto ch : sv)
{
if (ch == '&')
{
buf.append("&amp;");
}
else if (ch == '<')
{
buf.append("&lt;");
}
else if (ch == '>')
{
buf.append("&gt;");
}
else if (ch == '"')
{
buf.append("&quot;");
}
else if (ch == '\'')
{
buf.append("&apos;");
}
else
{
buf.push_back(ch);
}
}
return *this;
}
XmlSerializer& XmlSerializer::simple_tag(StringLiteral tag, StringView content)
{
return emit_pending_indent().open_tag(tag).text(content).close_tag(tag);
}
XmlSerializer& XmlSerializer::line_break()
{
buf.push_back('\n');
m_pending_indent = true;
return *this;
}
XmlSerializer& XmlSerializer::emit_pending_indent()
{
if (m_pending_indent)
{
m_pending_indent = false;
buf.append(m_indent, ' ');
}
return *this;
}
}

View File

@ -5,6 +5,7 @@
#include <vcpkg/base/system.debug.h>
#include <vcpkg/base/system.print.h>
#include <vcpkg/base/system.process.h>
#include <vcpkg/base/xmlserializer.h>
#include <vcpkg/binarycaching.h>
#include <vcpkg/binarycaching.private.h>
@ -699,113 +700,6 @@ namespace vcpkg
};
}
XmlSerializer& XmlSerializer::emit_declaration()
{
buf.append(R"(<?xml version="1.0" encoding="utf-8"?>)");
return *this;
}
XmlSerializer& XmlSerializer::open_tag(StringLiteral sl)
{
emit_pending_indent();
Strings::append(buf, '<', sl, '>');
m_indent += 2;
return *this;
}
XmlSerializer& XmlSerializer::start_complex_open_tag(StringLiteral sl)
{
emit_pending_indent();
Strings::append(buf, '<', sl);
m_indent += 2;
return *this;
}
XmlSerializer& XmlSerializer::text_attr(StringLiteral name, StringView content)
{
if (m_pending_indent)
{
m_pending_indent = false;
buf.append(m_indent, ' ');
}
else
{
buf.push_back(' ');
}
Strings::append(buf, name, "=\"");
text(content);
Strings::append(buf, '"');
return *this;
}
XmlSerializer& XmlSerializer::finish_complex_open_tag()
{
emit_pending_indent();
Strings::append(buf, '>');
return *this;
}
XmlSerializer& XmlSerializer::finish_self_closing_complex_tag()
{
emit_pending_indent();
Strings::append(buf, "/>");
m_indent -= 2;
return *this;
}
XmlSerializer& XmlSerializer::close_tag(StringLiteral sl)
{
m_indent -= 2;
emit_pending_indent();
Strings::append(buf, "</", sl, '>');
return *this;
}
XmlSerializer& XmlSerializer::text(StringView sv)
{
emit_pending_indent();
for (auto ch : sv)
{
if (ch == '&')
{
buf.append("&amp;");
}
else if (ch == '<')
{
buf.append("&lt;");
}
else if (ch == '>')
{
buf.append("&gt;");
}
else if (ch == '"')
{
buf.append("&quot;");
}
else if (ch == '\'')
{
buf.append("&apos;");
}
else
{
buf.push_back(ch);
}
}
return *this;
}
XmlSerializer& XmlSerializer::simple_tag(StringLiteral tag, StringView content)
{
return emit_pending_indent().open_tag(tag).text(content).close_tag(tag);
}
XmlSerializer& XmlSerializer::line_break()
{
buf.push_back('\n');
m_pending_indent = true;
return *this;
}
XmlSerializer& XmlSerializer::emit_pending_indent()
{
if (m_pending_indent)
{
m_pending_indent = false;
buf.append(m_indent, ' ');
}
return *this;
}
IBinaryProvider& vcpkg::null_binary_provider()
{
static NullBinaryProvider p;

View File

@ -2,6 +2,7 @@
#include <vcpkg/base/system.print.h>
#include <vcpkg/base/system.process.h>
#include <vcpkg/base/util.h>
#include <vcpkg/base/xmlserializer.h>
#include <vcpkg/commands.h>
#include <vcpkg/dependencies.h>
@ -28,37 +29,47 @@ namespace vcpkg::Export
const fs::path& targets_redirect_path,
const fs::path& props_redirect_path,
const std::string& nuget_id,
const std::string& nupkg_version)
const std::string& nupkg_version,
const std::string& nuget_description)
{
static constexpr auto CONTENT_TEMPLATE = R"(
<package>
<metadata>
<id>@NUGET_ID@</id>
<version>@VERSION@</version>
<authors>vcpkg</authors>
<description>
Vcpkg NuGet export
</description>
</metadata>
<files>
<file src="@RAW_EXPORTED_DIR@\installed\**" target="installed" />
<file src="@RAW_EXPORTED_DIR@\scripts\**" target="scripts" />
<file src="@RAW_EXPORTED_DIR@\.vcpkg-root" target="" />
<file src="@TARGETS_REDIRECT_PATH@" target="build\native\@NUGET_ID@.targets" />
<file src="@PROPS_REDIRECT_PATH@" target="build\native\@NUGET_ID@.props" />
</files>
</package>
)";
XmlSerializer xml;
xml.open_tag("package").line_break();
xml.open_tag("metadata").line_break();
xml.simple_tag("id", nuget_id).line_break();
xml.simple_tag("version", nupkg_version).line_break();
xml.simple_tag("authors", "vcpkg").line_break();
xml.simple_tag("description", nuget_description).line_break();
xml.close_tag("metadata").line_break();
xml.open_tag("files").line_break();
xml.start_complex_open_tag("file")
.text_attr("src", raw_exported_dir + "\\installed\\**")
.text_attr("target", "installed")
.finish_self_closing_complex_tag();
std::string nuspec_file_content = Strings::replace_all(CONTENT_TEMPLATE, "@NUGET_ID@", nuget_id);
nuspec_file_content = Strings::replace_all(std::move(nuspec_file_content), "@VERSION@", nupkg_version);
nuspec_file_content =
Strings::replace_all(std::move(nuspec_file_content), "@RAW_EXPORTED_DIR@", raw_exported_dir);
nuspec_file_content = Strings::replace_all(
std::move(nuspec_file_content), "@TARGETS_REDIRECT_PATH@", fs::u8string(targets_redirect_path));
nuspec_file_content = Strings::replace_all(
std::move(nuspec_file_content), "@PROPS_REDIRECT_PATH@", fs::u8string(props_redirect_path));
return nuspec_file_content;
xml.start_complex_open_tag("file")
.text_attr("src", raw_exported_dir + "\\scripts\\**")
.text_attr("target", "scripts")
.finish_self_closing_complex_tag();
xml.start_complex_open_tag("file")
.text_attr("src", raw_exported_dir + "\\.vcpkg-root")
.text_attr("target", "")
.finish_self_closing_complex_tag();
xml.start_complex_open_tag("file")
.text_attr("src", fs::u8string(targets_redirect_path))
.text_attr("target", Strings::concat("build\\native\\", nuget_id, ".targets"))
.finish_self_closing_complex_tag();
xml.start_complex_open_tag("file")
.text_attr("src", fs::u8string(props_redirect_path))
.text_attr("target", Strings::concat("build\\native\\", nuget_id, ".props"))
.finish_self_closing_complex_tag();
xml.close_tag("files").line_break();
xml.close_tag("package").line_break();
return std::move(xml.buf);
}
static std::string create_targets_redirect(const std::string& target_path) noexcept
@ -123,6 +134,7 @@ namespace vcpkg::Export
static fs::path do_nuget_export(const VcpkgPaths& paths,
const std::string& nuget_id,
const std::string& nuget_version,
const std::string& nuget_description,
const fs::path& raw_exported_dir,
const fs::path& output_dir)
{
@ -145,7 +157,7 @@ namespace vcpkg::Export
fs.write_contents(props_redirect, props_redirect_content, VCPKG_LINE_INFO);
const std::string nuspec_file_content = create_nuspec_file_contents(
raw_exported_dir.string(), targets_redirect, props_redirect, nuget_id, nuget_version);
raw_exported_dir.string(), targets_redirect, props_redirect, nuget_id, nuget_version, nuget_description);
const fs::path nuspec_file_path = paths.buildsystems / "tmp" / "vcpkg.export.nuspec";
fs.write_contents(nuspec_file_path, nuspec_file_content, VCPKG_LINE_INFO);
@ -284,6 +296,7 @@ namespace vcpkg::Export
Optional<std::string> maybe_nuget_id;
Optional<std::string> maybe_nuget_version;
Optional<std::string> maybe_nuget_description;
IFW::Options ifw_options;
Prefab::Options prefab_options;
@ -300,6 +313,7 @@ namespace vcpkg::Export
static constexpr StringLiteral OPTION_ZIP = "zip";
static constexpr StringLiteral OPTION_SEVEN_ZIP = "7zip";
static constexpr StringLiteral OPTION_NUGET_ID = "nuget-id";
static constexpr StringLiteral OPTION_NUGET_DESCRIPTION = "nuget-description";
static constexpr StringLiteral OPTION_NUGET_VERSION = "nuget-version";
static constexpr StringLiteral OPTION_IFW_REPOSITORY_URL = "ifw-repository-url";
static constexpr StringLiteral OPTION_IFW_PACKAGES_DIR_PATH = "ifw-packages-directory-path";
@ -334,10 +348,11 @@ namespace vcpkg::Export
{OPTION_ALL_INSTALLED, "Export all installed packages"},
}};
static constexpr std::array<CommandSetting, 16> EXPORT_SETTINGS = {{
static constexpr std::array<CommandSetting, 17> EXPORT_SETTINGS = {{
{OPTION_OUTPUT, "Specify the output name (used to construct filename)"},
{OPTION_OUTPUT_DIR, "Specify the output directory for produced artifacts"},
{OPTION_NUGET_ID, "Specify the id for the exported NuGet package (overrides --output)"},
{OPTION_NUGET_DESCRIPTION, "Specify a description for the exported NuGet package"},
{OPTION_NUGET_VERSION, "Specify the version for the exported NuGet package"},
{OPTION_IFW_REPOSITORY_URL, "Specify the remote repository URL for the online installer"},
{OPTION_IFW_PACKAGES_DIR_PATH, "Specify the temporary directory path for the repacked packages"},
@ -456,6 +471,7 @@ namespace vcpkg::Export
{
{OPTION_NUGET_ID, ret.maybe_nuget_id},
{OPTION_NUGET_VERSION, ret.maybe_nuget_version},
{OPTION_NUGET_DESCRIPTION, ret.maybe_nuget_description},
});
options_implies(OPTION_IFW,
@ -567,8 +583,9 @@ namespace vcpkg::Export
const std::string nuget_id = opts.maybe_nuget_id.value_or(raw_exported_dir_path.filename().string());
const std::string nuget_version = opts.maybe_nuget_version.value_or("1.0.0");
const fs::path output_path =
do_nuget_export(paths, nuget_id, nuget_version, raw_exported_dir_path, opts.output_dir);
const std::string nuget_description = opts.maybe_nuget_description.value_or("Vcpkg NuGet export");
const fs::path output_path = do_nuget_export(
paths, nuget_id, nuget_version, nuget_description, raw_exported_dir_path, opts.output_dir);
System::print2(System::Color::success, "NuGet package exported at: ", fs::u8string(output_path), "\n");
System::printf(R"(

View File

@ -205,6 +205,7 @@
<ClInclude Include="..\include\vcpkg\base\unicode.h" />
<ClInclude Include="..\include\vcpkg\base\util.h" />
<ClInclude Include="..\include\vcpkg\base\view.h" />
<ClInclude Include="..\include\vcpkg\base\xmlserializer.h" />
<ClInclude Include="..\include\vcpkg\base\zstringview.h" />
<ClInclude Include="..\include\vcpkg\binarycaching.h" />
<ClInclude Include="..\include\vcpkg\binaryparagraph.h" />
@ -296,6 +297,7 @@
<ClCompile Include="..\src\vcpkg\base\system.print.cpp" />
<ClCompile Include="..\src\vcpkg\base\system.process.cpp" />
<ClCompile Include="..\src\vcpkg\base\unicode.cpp" />
<ClCompile Include="..\src\vcpkg\base\xmlserializer.cpp" />
<ClCompile Include="..\src\vcpkg\binarycaching.cpp" />
<ClCompile Include="..\src\vcpkg\binaryparagraph.cpp" />
<ClCompile Include="..\src\vcpkg\build.cpp" />