From 6dfe1be6fa865be127756db039d1bd79e30fd7cc Mon Sep 17 00:00:00 2001 From: ras0219 <533828+ras0219@users.noreply.github.com> Date: Sun, 6 Dec 2020 15:26:58 -0800 Subject: [PATCH] [vcpkg] Add --nuget-description option for `vcpkg export` (#14953) --- toolsrc/include/vcpkg/base/xmlserializer.h | 31 +++++ toolsrc/include/vcpkg/binarycaching.private.h | 23 ---- toolsrc/src/vcpkg-test/binarycaching.cpp | 1 + toolsrc/src/vcpkg/base/xmlserializer.cpp | 113 ++++++++++++++++++ toolsrc/src/vcpkg/binarycaching.cpp | 108 +---------------- toolsrc/src/vcpkg/export.cpp | 83 ++++++++----- toolsrc/windows-bootstrap/vcpkg.vcxproj | 2 + 7 files changed, 198 insertions(+), 163 deletions(-) create mode 100644 toolsrc/include/vcpkg/base/xmlserializer.h create mode 100644 toolsrc/src/vcpkg/base/xmlserializer.cpp diff --git a/toolsrc/include/vcpkg/base/xmlserializer.h b/toolsrc/include/vcpkg/base/xmlserializer.h new file mode 100644 index 0000000000..33b7c0811f --- /dev/null +++ b/toolsrc/include/vcpkg/base/xmlserializer.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +#include + +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; + }; +} diff --git a/toolsrc/include/vcpkg/binarycaching.private.h b/toolsrc/include/vcpkg/binarycaching.private.h index 209807ccc5..2ac4467929 100644 --- a/toolsrc/include/vcpkg/binarycaching.private.h +++ b/toolsrc/include/vcpkg/binarycaching.private.h @@ -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; - }; - } diff --git a/toolsrc/src/vcpkg-test/binarycaching.cpp b/toolsrc/src/vcpkg-test/binarycaching.cpp index eefe2a9c1c..3cede064c5 100644 --- a/toolsrc/src/vcpkg-test/binarycaching.cpp +++ b/toolsrc/src/vcpkg-test/binarycaching.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include diff --git a/toolsrc/src/vcpkg/base/xmlserializer.cpp b/toolsrc/src/vcpkg/base/xmlserializer.cpp new file mode 100644 index 0000000000..535a0a92b3 --- /dev/null +++ b/toolsrc/src/vcpkg/base/xmlserializer.cpp @@ -0,0 +1,113 @@ +#include +#include + +namespace vcpkg +{ + XmlSerializer& XmlSerializer::emit_declaration() + { + buf.append(R"()"); + 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, "'); + return *this; + } + XmlSerializer& XmlSerializer::text(StringView sv) + { + emit_pending_indent(); + for (auto ch : sv) + { + if (ch == '&') + { + buf.append("&"); + } + else if (ch == '<') + { + buf.append("<"); + } + else if (ch == '>') + { + buf.append(">"); + } + else if (ch == '"') + { + buf.append("""); + } + else if (ch == '\'') + { + buf.append("'"); + } + 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; + } + +} diff --git a/toolsrc/src/vcpkg/binarycaching.cpp b/toolsrc/src/vcpkg/binarycaching.cpp index 4e21fc62a9..966c2e77b7 100644 --- a/toolsrc/src/vcpkg/binarycaching.cpp +++ b/toolsrc/src/vcpkg/binarycaching.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -699,113 +700,6 @@ namespace vcpkg }; } -XmlSerializer& XmlSerializer::emit_declaration() -{ - buf.append(R"()"); - 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, "'); - return *this; -} -XmlSerializer& XmlSerializer::text(StringView sv) -{ - emit_pending_indent(); - for (auto ch : sv) - { - if (ch == '&') - { - buf.append("&"); - } - else if (ch == '<') - { - buf.append("<"); - } - else if (ch == '>') - { - buf.append(">"); - } - else if (ch == '"') - { - buf.append("""); - } - else if (ch == '\'') - { - buf.append("'"); - } - 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; diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 6d0c95aa81..b5c36ff870 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -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"( - - - @NUGET_ID@ - @VERSION@ - vcpkg - - Vcpkg NuGet export - - - - - - - - - - -)"; + 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 maybe_nuget_id; Optional maybe_nuget_version; + Optional 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 EXPORT_SETTINGS = {{ + static constexpr std::array 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"( diff --git a/toolsrc/windows-bootstrap/vcpkg.vcxproj b/toolsrc/windows-bootstrap/vcpkg.vcxproj index 16de6e9c45..b11d5540c7 100644 --- a/toolsrc/windows-bootstrap/vcpkg.vcxproj +++ b/toolsrc/windows-bootstrap/vcpkg.vcxproj @@ -205,6 +205,7 @@ + @@ -296,6 +297,7 @@ +