aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src
diff options
context:
space:
mode:
authorras0219 <533828+ras0219@users.noreply.github.com>2021-01-15 12:35:48 -0800
committerGitHub <noreply@github.com>2021-01-15 12:35:48 -0800
commit4f8fb510ba03f195a49f6353b97fabf5bb20d450 (patch)
tree7564b1db60e1086ce5cf587846ea28d628735d05 /toolsrc/src
parenta8e97d4a4b22d489123dc6d673ceee2c203dc046 (diff)
downloadvcpkg-4f8fb510ba03f195a49f6353b97fabf5bb20d450.tar.gz
vcpkg-4f8fb510ba03f195a49f6353b97fabf5bb20d450.zip
[vcpkg] Add initial versioning documentation (#15565)
* [vcpkg] Improve efficiency and tests of versioning * [vcpkg] Add initial versioning documentation and rename x-default-baseline to builtin-baseline * [vcpkg] Enable metrics for builtin-baseline & overrides * [vcpkg] Address PR comments * [vcpkg] Add support for syntax in version>= * [vcpkg] Remove port-version from dependency syntax * [vcpkg] Address CR comment * [vcpkg] Minor docs fixup
Diffstat (limited to 'toolsrc/src')
-rw-r--r--toolsrc/src/vcpkg-test/dependencies.cpp27
-rw-r--r--toolsrc/src/vcpkg-test/manifests.cpp108
-rw-r--r--toolsrc/src/vcpkg/base/json.cpp5
-rw-r--r--toolsrc/src/vcpkg/commands.civerifyversions.cpp2
-rw-r--r--toolsrc/src/vcpkg/help.cpp65
-rw-r--r--toolsrc/src/vcpkg/install.cpp22
-rw-r--r--toolsrc/src/vcpkg/paragraphs.cpp9
-rw-r--r--toolsrc/src/vcpkg/registries.cpp63
-rw-r--r--toolsrc/src/vcpkg/sourceparagraph.cpp125
-rw-r--r--toolsrc/src/vcpkg/vcpkgpaths.cpp232
10 files changed, 441 insertions, 217 deletions
diff --git a/toolsrc/src/vcpkg-test/dependencies.cpp b/toolsrc/src/vcpkg-test/dependencies.cpp
index 2831ea5a1..8f936abc3 100644
--- a/toolsrc/src/vcpkg-test/dependencies.cpp
+++ b/toolsrc/src/vcpkg-test/dependencies.cpp
@@ -196,7 +196,7 @@ private:
static const MockOverlayProvider s_empty_mock_overlay;
-ExpectedS<Dependencies::ActionPlan> create_versioned_install_plan(
+static ExpectedS<Dependencies::ActionPlan> create_versioned_install_plan(
const PortFileProvider::IVersionedPortfileProvider& provider,
const PortFileProvider::IBaselineProvider& bprovider,
const CMakeVars::CMakeVarProvider& var_provider,
@@ -335,7 +335,7 @@ TEST_CASE ("basic version install scheme baseline missing success", "[versionpla
bp,
var_provider,
{
- Dependency{"a", {}, {}, {Constraint::Type::Exact, "2"}},
+ Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2"}},
},
{},
toplevel_spec()));
@@ -375,7 +375,7 @@ TEST_CASE ("version string baseline agree", "[versionplan]")
MockCMakeVarProvider var_provider;
auto install_plan = create_versioned_install_plan(
- vp, bp, var_provider, {Dependency{"a", {}, {}, {Constraint::Type::Exact, "2"}}}, {}, toplevel_spec());
+ vp, bp, var_provider, {Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2"}}}, {}, toplevel_spec());
REQUIRE(install_plan.has_value());
}
@@ -396,7 +396,7 @@ TEST_CASE ("version install scheme baseline conflict", "[versionplan]")
bp,
var_provider,
{
- Dependency{"a", {}, {}, {Constraint::Type::Exact, "3"}},
+ Dependency{"a", {}, {}, {Constraint::Type::Minimum, "3"}},
},
{},
toplevel_spec());
@@ -421,7 +421,7 @@ TEST_CASE ("version install string port version", "[versionplan]")
bp,
var_provider,
{
- Dependency{"a", {}, {}, {Constraint::Type::Exact, "2", 1}},
+ Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2", 1}},
},
{},
toplevel_spec()));
@@ -447,7 +447,7 @@ TEST_CASE ("version install string port version 2", "[versionplan]")
bp,
var_provider,
{
- Dependency{"a", {}, {}, {Constraint::Type::Exact, "2", 0}},
+ Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2", 0}},
},
{},
toplevel_spec()));
@@ -463,10 +463,10 @@ TEST_CASE ("version install transitive string", "[versionplan]")
MockVersionedPortfileProvider vp;
vp.emplace("a", {"2", 0}).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Exact, "1"}},
+ Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "1"}},
};
vp.emplace("a", {"2", 1}).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Exact, "2"}},
+ Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "2"}},
};
vp.emplace("b", {"1", 0});
vp.emplace("b", {"2", 0});
@@ -478,7 +478,7 @@ TEST_CASE ("version install transitive string", "[versionplan]")
bp,
var_provider,
{
- Dependency{"a", {}, {}, {Constraint::Type::Exact, "2", 1}},
+ Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2", 1}},
},
{},
toplevel_spec()));
@@ -1006,7 +1006,7 @@ TEST_CASE ("version install scheme change in port version", "[versionplan]")
{
MockVersionedPortfileProvider vp;
vp.emplace("a", {"2", 0}).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Exact, "1"}},
+ Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "1"}},
};
vp.emplace("a", {"2", 1}).source_control_file->core_paragraph->dependencies = {
Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "1", 1}},
@@ -1026,7 +1026,7 @@ TEST_CASE ("version install scheme change in port version", "[versionplan]")
bp,
var_provider,
{
- Dependency{"a", {}, {}, {Constraint::Type::Exact, "2", 1}},
+ Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2", 1}},
},
{},
toplevel_spec()));
@@ -1045,7 +1045,7 @@ TEST_CASE ("version install scheme change in port version", "[versionplan]")
bp,
var_provider,
{
- Dependency{"a", {}, {}, {Constraint::Type::Exact, "2", 0}},
+ Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2", 0}},
},
{},
toplevel_spec()));
@@ -1305,7 +1305,8 @@ TEST_CASE ("version install transitive overrides", "[versionplan]")
MockVersionedPortfileProvider vp;
vp.emplace("b", {"1", 0}, Scheme::Relaxed)
- .source_control_file->core_paragraph->dependencies.push_back({"c", {}, {}, {Constraint::Type::Exact, "2", 1}});
+ .source_control_file->core_paragraph->dependencies.push_back(
+ {"c", {}, {}, {Constraint::Type::Minimum, "2", 1}});
vp.emplace("b", {"2", 0}, Scheme::Relaxed);
vp.emplace("c", {"1", 0}, Scheme::String);
vp.emplace("c", {"2", 1}, Scheme::String);
diff --git a/toolsrc/src/vcpkg-test/manifests.cpp b/toolsrc/src/vcpkg-test/manifests.cpp
index 39e470075..0af9f4f96 100644
--- a/toolsrc/src/vcpkg-test/manifests.cpp
+++ b/toolsrc/src/vcpkg-test/manifests.cpp
@@ -62,6 +62,7 @@ TEST_CASE ("manifest construct minimum", "[manifests]")
REQUIRE(pgh.core_paragraph->maintainers.empty());
REQUIRE(pgh.core_paragraph->description.empty());
REQUIRE(pgh.core_paragraph->dependencies.empty());
+ REQUIRE(!pgh.core_paragraph->builtin_baseline.has_value());
REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning));
}
@@ -157,19 +158,31 @@ TEST_CASE ("manifest versioning", "[manifests]")
}
}
-TEST_CASE ("manifest constraints error hash", "[manifests]")
+TEST_CASE ("manifest constraints hash", "[manifests]")
{
+ auto p = unwrap(test_parse_manifest(R"json({
+ "name": "zlib",
+ "version-string": "abcd",
+ "dependencies": [
+ {
+ "name": "d",
+ "version>=": "2018-09-01#1"
+ }
+ ]
+})json"));
+ REQUIRE(p->core_paragraph->dependencies.at(0).constraint.value == "2018-09-01");
+ REQUIRE(p->core_paragraph->dependencies.at(0).constraint.port_version == 1);
+
test_parse_manifest(R"json({
"name": "zlib",
"version-string": "abcd",
"dependencies": [
{
- "name": "b",
- "version=": "5#1"
+ "name": "d",
+ "version>=": "2018-09-01#0"
}
]
-}
-)json",
+})json",
true);
test_parse_manifest(R"json({
@@ -178,7 +191,20 @@ TEST_CASE ("manifest constraints error hash", "[manifests]")
"dependencies": [
{
"name": "d",
- "version>=": "2018-09-01#1"
+ "version>=": "2018-09-01#-1"
+ }
+ ]
+})json",
+ true);
+
+ test_parse_manifest(R"json({
+ "name": "zlib",
+ "version-string": "abcd",
+ "dependencies": [
+ {
+ "name": "d",
+ "version>=": "2018-09-01",
+ "port-version": 1
}
]
})json",
@@ -238,14 +264,10 @@ TEST_CASE ("manifest constraints", "[manifests]")
std::string raw = R"json({
"name": "zlib",
"version-string": "abcd",
+ "builtin-baseline": "089fa4de7dca22c67dcab631f618d5cd0697c8d4",
"dependencies": [
"a",
{
- "name": "b",
- "port-version": 12,
- "version=": "5"
- },
- {
"$extra": null,
"name": "c"
},
@@ -263,32 +285,17 @@ TEST_CASE ("manifest constraints", "[manifests]")
REQUIRE(pgh.check_against_feature_flags({}, feature_flags_without_versioning));
REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_with_versioning));
REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == raw);
- REQUIRE(pgh.core_paragraph->dependencies.size() == 4);
+ REQUIRE(pgh.core_paragraph->dependencies.size() == 3);
REQUIRE(pgh.core_paragraph->dependencies[0].name == "a");
REQUIRE(pgh.core_paragraph->dependencies[0].constraint ==
DependencyConstraint{Versions::Constraint::Type::None, "", 0});
- REQUIRE(pgh.core_paragraph->dependencies[1].name == "b");
+ REQUIRE(pgh.core_paragraph->dependencies[1].name == "c");
REQUIRE(pgh.core_paragraph->dependencies[1].constraint ==
- DependencyConstraint{Versions::Constraint::Type::Exact, "5", 12});
- REQUIRE(pgh.core_paragraph->dependencies[2].name == "c");
- REQUIRE(pgh.core_paragraph->dependencies[2].constraint ==
DependencyConstraint{Versions::Constraint::Type::None, "", 0});
- REQUIRE(pgh.core_paragraph->dependencies[3].name == "d");
- REQUIRE(pgh.core_paragraph->dependencies[3].constraint ==
+ REQUIRE(pgh.core_paragraph->dependencies[2].name == "d");
+ REQUIRE(pgh.core_paragraph->dependencies[2].constraint ==
DependencyConstraint{Versions::Constraint::Type::Minimum, "2018-09-01", 0});
-
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "abcd",
- "dependencies": [
- {
- "name": "d",
- "version=": "2018-09-01",
- "version>=": "2018-09-01"
- }
- ]
- })json",
- true);
+ REQUIRE(pgh.core_paragraph->builtin_baseline == "089fa4de7dca22c67dcab631f618d5cd0697c8d4");
test_parse_manifest(R"json({
"name": "zlib",
@@ -303,6 +310,45 @@ TEST_CASE ("manifest constraints", "[manifests]")
true);
}
+TEST_CASE ("manifest builtin-baseline", "[manifests]")
+{
+ SECTION ("valid baseline")
+ {
+ std::string raw = R"json({
+ "name": "zlib",
+ "version-string": "abcd",
+ "builtin-baseline": "089fa4de7dca22c67dcab631f618d5cd0697c8d4"
+}
+)json";
+ auto m_pgh = test_parse_manifest(raw);
+
+ REQUIRE(m_pgh.has_value());
+ auto& pgh = **m_pgh.get();
+ REQUIRE(pgh.check_against_feature_flags({}, feature_flags_without_versioning));
+ REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_with_versioning));
+ REQUIRE(pgh.core_paragraph->builtin_baseline.value_or("does not have a value") ==
+ "089fa4de7dca22c67dcab631f618d5cd0697c8d4");
+ }
+
+ SECTION ("empty baseline")
+ {
+ std::string raw = R"json({
+ "name": "zlib",
+ "version-string": "abcd",
+ "builtin-baseline": ""
+}
+)json";
+
+ auto m_pgh = test_parse_manifest(raw);
+
+ REQUIRE(m_pgh.has_value());
+ auto& pgh = **m_pgh.get();
+ REQUIRE(pgh.check_against_feature_flags({}, feature_flags_without_versioning));
+ REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_with_versioning));
+ REQUIRE(pgh.core_paragraph->builtin_baseline.value_or("does not have a value") == "");
+ }
+}
+
TEST_CASE ("manifest overrides", "[manifests]")
{
std::tuple<StringLiteral, Versions::Scheme, StringLiteral> data[] = {
diff --git a/toolsrc/src/vcpkg/base/json.cpp b/toolsrc/src/vcpkg/base/json.cpp
index 4a784235e..d99fa7392 100644
--- a/toolsrc/src/vcpkg/base/json.cpp
+++ b/toolsrc/src/vcpkg/base/json.cpp
@@ -1064,6 +1064,11 @@ namespace vcpkg::Json
{
return Parser::parse(json, fs::generic_u8string(filepath));
}
+ ExpectedT<std::pair<Value, JsonStyle>, std::unique_ptr<Parse::IParseError>> parse(StringView json,
+ StringView origin) noexcept
+ {
+ return Parser::parse(json, origin);
+ }
// } auto parse()
namespace
diff --git a/toolsrc/src/vcpkg/commands.civerifyversions.cpp b/toolsrc/src/vcpkg/commands.civerifyversions.cpp
index 84aab9c01..71ced9f76 100644
--- a/toolsrc/src/vcpkg/commands.civerifyversions.cpp
+++ b/toolsrc/src/vcpkg/commands.civerifyversions.cpp
@@ -404,7 +404,7 @@ namespace vcpkg::Commands::CIVerifyVersions
System::printf(System::Color::error, "%s\n", error);
}
System::print2(System::Color::error,
- "\nTo attempt to resolve all erros at once, run:\n\n"
+ "\nTo attempt to resolve all errors at once, run:\n\n"
" vcpkg x-add-version --all\n\n");
Checks::exit_fail(VCPKG_LINE_INFO);
}
diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp
index ded6592fb..0556b4fa0 100644
--- a/toolsrc/src/vcpkg/help.cpp
+++ b/toolsrc/src/vcpkg/help.cpp
@@ -47,7 +47,69 @@ namespace vcpkg::Help
nullptr,
};
- static constexpr std::array<Topic, 15> topics = {{
+ static void help_topic_versioning(const VcpkgPaths&)
+ {
+ HelpTableFormatter tbl;
+ tbl.text("Versioning allows you to deterministically control the precise revisions of dependencies used by "
+ "your project from within your manifest file.");
+ tbl.blank();
+ tbl.blank();
+ tbl.text("** This feature is experimental and requires `--feature-flags=versions` **");
+ tbl.blank();
+ tbl.blank();
+ tbl.header("Versions in vcpkg come in four primary flavors");
+ tbl.format("version", "A dot-separated sequence of numbers (1.2.3.4)");
+ tbl.format("version-date", "A date (2021-01-01.5)");
+ tbl.format("version-semver", "A Semantic Version 2.0 (2.1.0-rc2)");
+ tbl.format("version-string", "An exact, incomparable version (Vista)");
+ tbl.blank();
+ tbl.text("Each version additionally has a \"port-version\" which is a nonnegative integer. When rendered as "
+ "text, the port version (if nonzero) is added as a suffix to the primary version text separated by a "
+ "hash (#). Port-versions are sorted lexographically after the primary version text, for example:");
+ tbl.blank();
+ tbl.blank();
+ tbl.text(" 1.0.0 < 1.0.0#1 < 1.0.1 < 1.0.1#5 < 2.0.0");
+ tbl.blank();
+ tbl.blank();
+ tbl.header("Manifests can place three kinds of constraints upon the versions used");
+ tbl.format("builtin-baseline",
+ "The baseline references a commit within the vcpkg repository that establishes a minimum version on "
+ "every dependency in the graph. If no other constraints are specified (directly or transitively), "
+ "then the version from the baseline of the top level manifest will be used. Baselines of transitive "
+ "dependencies are ignored.");
+ tbl.blank();
+ tbl.format("version>=",
+ "Within the \"dependencies\" field, each dependency can have a minimum constraint listed. These "
+ "minimum constraints will be used when transitively depending upon this library. A minimum "
+ "port-version can additionally be specified with a '#' suffix.");
+ tbl.blank();
+ tbl.format(
+ "overrides",
+ "When used as the top-level manifest (such as when running `vcpkg install` in the directory), overrides "
+ "allow a manifest to short-circuit dependency resolution and specify exactly the version to use. These can "
+ "be used to handle version conflicts, such as with `version-string` dependencies. They will not be "
+ "considered when transitively depended upon.");
+ tbl.blank();
+ tbl.text("Example manifest:");
+ tbl.blank();
+ tbl.text(R"({
+ "name": "example",
+ "version": "1.0",
+ "builtin-baseline": "a14a6bcb27287e3ec138dba1b948a0cdbc337a3a",
+ "dependencies": [
+ { "name": "zlib", "version>=": "1.2.11#8" },
+ "rapidjson"
+ ],
+ "overrides": [
+ { "name": "rapidjson", "version": "2020-09-14" }
+ ]
+})");
+ System::print2(tbl.m_str,
+ "\nExtended documentation is available at "
+ "https://github.com/Microsoft/vcpkg/tree/master/docs/users/versioning.md\n");
+ }
+
+ static constexpr std::array<Topic, 16> topics = {{
{"binarycaching", help_topic_binary_caching},
{"create", command_topic_fn<Commands::Create::COMMAND_STRUCTURE>},
{"depend-info", command_topic_fn<Commands::DependInfo::COMMAND_STRUCTURE>},
@@ -63,6 +125,7 @@ namespace vcpkg::Help
{"search", command_topic_fn<Commands::Search::COMMAND_STRUCTURE>},
{"topics", help_topics},
{"triplet", help_topic_valid_triplet},
+ {"versioning", help_topic_versioning},
}};
static void help_topics(const VcpkgPaths&)
diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp
index 80b4eae3a..e86a78a76 100644
--- a/toolsrc/src/vcpkg/install.cpp
+++ b/toolsrc/src/vcpkg/install.cpp
@@ -17,6 +17,7 @@
#include <vcpkg/metrics.h>
#include <vcpkg/paragraphs.h>
#include <vcpkg/remove.h>
+#include <vcpkg/tools.h>
#include <vcpkg/vcpkglib.h>
#include <vcpkg/vcpkgpaths.h>
@@ -847,10 +848,25 @@ namespace vcpkg::Install
if (args.versions_enabled() || args.registries_enabled())
{
- if (auto p_baseline = manifest_scf.core_paragraph->extra_info.get("$x-default-baseline"))
+ if (!manifest_scf.core_paragraph->overrides.empty())
{
- paths.get_configuration().registry_set.experimental_set_builtin_registry_baseline(
- p_baseline->string());
+ Metrics::g_metrics.lock()->track_property("manifest_overrides", "defined");
+ }
+ if (auto p_baseline = manifest_scf.core_paragraph->builtin_baseline.get())
+ {
+ Metrics::g_metrics.lock()->track_property("manifest_baseline", "defined");
+ if (p_baseline->size() != 40 || !std::all_of(p_baseline->begin(), p_baseline->end(), [](char ch) {
+ return (ch >= 'a' || ch <= 'f') || Parse::ParserBase::is_ascii_digit(ch);
+ }))
+ {
+ Checks::exit_with_message(
+ VCPKG_LINE_INFO,
+ "Error: the top-level builtin-baseline (%s) was not a valid commit sha: "
+ "expected 40 lowercase hexadecimal characters.\n%s\n",
+ *p_baseline,
+ paths.get_current_git_sha_message());
+ }
+ paths.get_configuration().registry_set.experimental_set_builtin_registry_baseline(*p_baseline);
}
}
if (args.versions_enabled())
diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp
index 32103c76b..2d28c49d7 100644
--- a/toolsrc/src/vcpkg/paragraphs.cpp
+++ b/toolsrc/src/vcpkg/paragraphs.cpp
@@ -373,7 +373,14 @@ namespace vcpkg::Paragraphs
auto error_info = std::make_unique<ParseControlErrorInfo>();
error_info->name = fs::u8string(path.filename());
- error_info->error = "Failed to find either a CONTROL file or vcpkg.json file.";
+ if (fs.exists(path))
+ {
+ error_info->error = "Failed to find either a CONTROL file or vcpkg.json file.";
+ }
+ else
+ {
+ error_info->error = "The port directory (" + fs::u8string(path) + ") does not exist";
+ }
return error_info;
}
diff --git a/toolsrc/src/vcpkg/registries.cpp b/toolsrc/src/vcpkg/registries.cpp
index b9afa089b..934e6537a 100644
--- a/toolsrc/src/vcpkg/registries.cpp
+++ b/toolsrc/src/vcpkg/registries.cpp
@@ -186,17 +186,6 @@ namespace
DelayedInit<Baseline> m_baseline;
};
- ExpectedS<fs::path> get_git_baseline_json_path(const VcpkgPaths& paths, StringView baseline_commit_sha)
- {
- auto baseline_path = paths.git_checkout_baseline(paths.get_filesystem(), baseline_commit_sha);
- if (paths.get_filesystem().exists(baseline_path))
- {
- return std::move(baseline_path);
- }
- return {Strings::concat("Error: Baseline database file does not exist: ", fs::u8string(baseline_path)),
- expected_right_tag};
- }
-
struct VersionDbEntry
{
VersionT version;
@@ -224,7 +213,7 @@ namespace
// returns nullopt if the baseline is valid, but doesn't contain the specified baseline,
// or (equivalently) if the baseline does not exist.
- ExpectedS<Optional<Baseline>> parse_baseline_versions(StringView contents, StringView baseline);
+ ExpectedS<Optional<Baseline>> parse_baseline_versions(StringView contents, StringView baseline, StringView origin);
ExpectedS<Optional<Baseline>> load_baseline_versions(const VcpkgPaths& paths,
const fs::path& path_to_baseline,
StringView identifier = {});
@@ -327,18 +316,20 @@ namespace
if (baseline_identifier == "default")
{
- return Strings::format("Couldn't find explicitly specified baseline `\"default\"` in baseline file: %s",
- fs::u8string(path_to_baseline));
+ return Strings::format(
+ "Error: Couldn't find explicitly specified baseline `\"default\"` in baseline file: %s",
+ fs::u8string(path_to_baseline));
}
// attempt to check out the baseline:
- auto maybe_path = get_git_baseline_json_path(paths, baseline_identifier);
+ auto maybe_path = paths.git_checkout_baseline(baseline_identifier);
if (!maybe_path.has_value())
{
- return Strings::format("Couldn't find explicitly specified baseline `\"%s\"` in the baseline file, "
- "and there was no baseline at that commit or the commit didn't exist.\n%s",
+ return Strings::format("Error: Couldn't find explicitly specified baseline `\"%s\"` in the baseline file, "
+ "and there was no baseline at that commit or the commit didn't exist.\n%s\n%s",
baseline_identifier,
- maybe_path.error());
+ maybe_path.error(),
+ paths.get_current_git_sha_message());
}
res_baseline = load_baseline_versions(paths, *maybe_path.get());
@@ -352,7 +343,7 @@ namespace
return std::move(*p);
}
- return Strings::format("Couldn't find explicitly specified baseline `\"%s\"` in the baseline "
+ return Strings::format("Error: Couldn't find explicitly specified baseline `\"%s\"` in the baseline "
"file, and the `\"default\"` baseline does not exist at that commit.",
baseline_identifier);
}
@@ -549,7 +540,7 @@ namespace
}
auto contents = maybe_contents.get();
- res_baseline = parse_baseline_versions(*contents, {});
+ res_baseline = parse_baseline_versions(*contents, "default", fs::u8string(path_to_baseline));
if (!res_baseline.has_value())
{
Checks::exit_with_message(VCPKG_LINE_INFO, res_baseline.error());
@@ -599,12 +590,22 @@ namespace
auto it = std::find(git_entry->port_versions.begin(), git_entry->port_versions.end(), version);
if (it == git_entry->port_versions.end())
{
- return Strings::concat(
- "Error: No version entry for ", git_entry->port_name, " at version ", version, ".");
+ return {
+ Strings::concat("Error: No version entry for ",
+ git_entry->port_name,
+ " at version ",
+ version,
+ ". This may be fixed by updating vcpkg to the latest master via `git "
+ "pull`.\nAvailable versions:\n",
+ Strings::join("",
+ git_entry->port_versions,
+ [](const VersionT& v) { return Strings::concat(" ", v, "\n"); }),
+ "\nSee `vcpkg help versioning` for more information."),
+ expected_right_tag};
}
const auto& git_tree = git_entry->git_trees[it - git_entry->port_versions.begin()];
- return paths.git_checkout_port(paths.get_filesystem(), git_entry->port_name, git_tree);
+ return paths.git_checkout_port(git_entry->port_name, git_tree, paths.root / fs::u8path(".git"));
}
if (scfl_version == version)
@@ -1014,19 +1015,20 @@ namespace
return db_entries;
}
- ExpectedS<Optional<Baseline>> parse_baseline_versions(StringView contents, StringView baseline)
+ ExpectedS<Optional<Baseline>> parse_baseline_versions(StringView contents, StringView baseline, StringView origin)
{
- auto maybe_value = Json::parse(contents);
+ auto maybe_value = Json::parse(contents, origin);
if (!maybe_value.has_value())
{
- return Strings::format("Error: failed to parse baseline file: %s", maybe_value.error()->format());
+ return Strings::format(
+ "Error: failed to parse baseline file: %s\n%s", origin, maybe_value.error()->format());
}
auto& value = *maybe_value.get();
if (!value.first.is_object())
{
- return std::string("Error: baseline does not have a top-level object.");
+ return Strings::concat("Error: baseline does not have a top-level object: ", origin);
}
auto real_baseline = baseline.size() == 0 ? "default" : baseline;
@@ -1047,8 +1049,7 @@ namespace
}
else
{
- Checks::exit_with_message(
- VCPKG_LINE_INFO, "Error: failed to parse baseline:\n%s", Strings::join("\n", r.errors()));
+ return Strings::format("Error: failed to parse baseline: %s\n%s", origin, Strings::join("\n", r.errors()));
}
}
@@ -1059,7 +1060,7 @@ namespace
auto maybe_contents = paths.get_filesystem().read_contents(path_to_baseline);
if (auto contents = maybe_contents.get())
{
- return parse_baseline_versions(*contents, baseline);
+ return parse_baseline_versions(*contents, baseline, fs::u8string(path_to_baseline));
}
else if (maybe_contents.error() == std::errc::no_such_file_or_directory)
{
@@ -1143,7 +1144,7 @@ namespace vcpkg
if (!default_registry_is_builtin || registries_.size() != 0)
{
System::print2(System::Color::warning,
- "Warning: when using the registries feature, one should not use `\"$x-default-baseline\"` "
+ "Warning: when using the registries feature, one should not use `\"builtin-baseline\"` "
"to set the baseline.\n",
" Instead, use the \"baseline\" field of the registry.\n");
}
diff --git a/toolsrc/src/vcpkg/sourceparagraph.cpp b/toolsrc/src/vcpkg/sourceparagraph.cpp
index c4ae3e855..61cc7f826 100644
--- a/toolsrc/src/vcpkg/sourceparagraph.cpp
+++ b/toolsrc/src/vcpkg/sourceparagraph.cpp
@@ -430,8 +430,6 @@ namespace vcpkg
constexpr static StringLiteral FEATURES = "features";
constexpr static StringLiteral DEFAULT_FEATURES = "default-features";
constexpr static StringLiteral PLATFORM = "platform";
- constexpr static StringLiteral PORT_VERSION = "port-version";
- constexpr static StringLiteral VERSION_EQ = "version=";
constexpr static StringLiteral VERSION_GE = "version>=";
virtual Span<const StringView> valid_fields() const override
@@ -441,8 +439,6 @@ namespace vcpkg
FEATURES,
DEFAULT_FEATURES,
PLATFORM,
- PORT_VERSION,
- VERSION_EQ,
VERSION_GE,
};
@@ -488,33 +484,34 @@ namespace vcpkg
r.optional_object_field(obj, PLATFORM, dep.platform, PlatformExprDeserializer::instance);
- static auto version_deserializer = make_version_deserializer("a version");
+ static Json::StringDeserializer version_deserializer("a version");
- auto has_eq_constraint =
- r.optional_object_field(obj, VERSION_EQ, dep.constraint.value, *version_deserializer);
auto has_ge_constraint =
- r.optional_object_field(obj, VERSION_GE, dep.constraint.value, *version_deserializer);
- auto has_port_ver = r.optional_object_field(
- obj, PORT_VERSION, dep.constraint.port_version, Json::NaturalNumberDeserializer::instance);
+ r.optional_object_field(obj, VERSION_GE, dep.constraint.value, version_deserializer);
- if (has_eq_constraint)
+ if (has_ge_constraint)
{
- dep.constraint.type = Versions::Constraint::Type::Exact;
- if (has_ge_constraint)
+ dep.constraint.type = Versions::Constraint::Type::Minimum;
+ auto h = dep.constraint.value.find('#');
+ if (h != std::string::npos)
{
- r.add_generic_error(type_name(), "cannot have both exact and minimum constraints simultaneously");
+ auto opt = Strings::strto<int>(dep.constraint.value.c_str() + h + 1);
+ auto v = opt.get();
+ if (v && *v > 0)
+ {
+ dep.constraint.port_version = *v;
+ }
+ else
+ {
+ r.add_generic_error(type_name(),
+ "embedded port-version ('#') in the primary "
+ "constraint (\"",
+ VERSION_GE,
+ "\") must be a positive integer");
+ }
+ dep.constraint.value.erase(h);
}
}
- else if (has_ge_constraint)
- {
- dep.constraint.type = Versions::Constraint::Type::Minimum;
- }
- else if (has_port_ver) // does not have a primary constraint
- {
- r.add_generic_error(
- type_name(),
- "\"port-version\" cannot be used without a primary constraint (\"version=\" or \"version>=\")");
- }
return dep;
}
@@ -540,9 +537,7 @@ namespace vcpkg
constexpr StringLiteral DependencyDeserializer::FEATURES;
constexpr StringLiteral DependencyDeserializer::DEFAULT_FEATURES;
constexpr StringLiteral DependencyDeserializer::PLATFORM;
- constexpr StringLiteral DependencyDeserializer::VERSION_EQ;
constexpr StringLiteral DependencyDeserializer::VERSION_GE;
- constexpr StringLiteral DependencyDeserializer::PORT_VERSION;
struct DependencyOverrideDeserializer : Json::IDeserializer<DependencyOverride>
{
@@ -860,6 +855,21 @@ namespace vcpkg
};
LicenseExpressionDeserializer LicenseExpressionDeserializer::instance;
+ struct BaselineCommitDeserializer final : Json::IDeserializer<std::string>
+ {
+ virtual StringView type_name() const override { return "a vcpkg repository commit"; }
+
+ virtual Optional<std::string> visit_string(Json::Reader&, StringView s) override
+ {
+ // We allow non-sha strings here to allow the core vcpkg code to provide better error
+ // messages including the current git commit
+ return s.to_string();
+ }
+
+ static BaselineCommitDeserializer instance;
+ };
+ BaselineCommitDeserializer BaselineCommitDeserializer::instance;
+
struct ManifestDeserializer : Json::IDeserializer<std::unique_ptr<SourceControlFile>>
{
virtual StringView type_name() const override { return "a manifest"; }
@@ -876,6 +886,7 @@ namespace vcpkg
constexpr static StringLiteral DEFAULT_FEATURES = "default-features";
constexpr static StringLiteral SUPPORTS = "supports";
constexpr static StringLiteral OVERRIDES = "overrides";
+ constexpr static StringLiteral BUILTIN_BASELINE = "builtin-baseline";
virtual Span<const StringView> valid_fields() const override
{
@@ -892,6 +903,7 @@ namespace vcpkg
DEFAULT_FEATURES,
SUPPORTS,
OVERRIDES,
+ BUILTIN_BASELINE,
};
static const auto t = Util::Vectors::concat<StringView>(schemed_deserializer_fields(), u);
@@ -917,9 +929,9 @@ namespace vcpkg
static Json::StringDeserializer url_deserializer{"a url"};
- constexpr static StringView type_name = "vcpkg.json";
+ constexpr static StringView inner_type_name = "vcpkg.json";
DependencyOverrideDeserializer::visit_impl(
- type_name, r, obj, spgh->name, spgh->version, spgh->version_scheme, spgh->port_version);
+ inner_type_name, r, obj, spgh->name, spgh->version, spgh->version_scheme, spgh->port_version);
r.optional_object_field(obj, MAINTAINERS, spgh->maintainers, Json::ParagraphDeserializer::instance);
r.optional_object_field(obj, DESCRIPTION, spgh->description, Json::ParagraphDeserializer::instance);
@@ -933,8 +945,12 @@ namespace vcpkg
if (obj.contains(DEV_DEPENDENCIES))
{
- System::print2(System::Color::error, DEV_DEPENDENCIES, " are not yet supported");
- Checks::exit_fail(VCPKG_LINE_INFO);
+ r.add_generic_error(type_name(), DEV_DEPENDENCIES, " are not yet supported");
+ }
+ std::string baseline;
+ if (r.optional_object_field(obj, BUILTIN_BASELINE, baseline, BaselineCommitDeserializer::instance))
+ {
+ spgh->builtin_baseline = std::move(baseline);
}
r.optional_object_field(obj, SUPPORTS, spgh->supports_expression, PlatformExprDeserializer::instance);
@@ -1007,6 +1023,7 @@ namespace vcpkg
Optional<std::string> SourceControlFile::check_against_feature_flags(const fs::path& origin,
const FeatureFlagSettings& flags) const
{
+ static constexpr StringLiteral s_extended_help = "See `vcpkg help versioning` for more information.";
if (!flags.versions)
{
auto check_deps = [&](View<Dependency> deps) -> Optional<std::string> {
@@ -1014,11 +1031,12 @@ namespace vcpkg
{
if (dep.constraint.type != Versions::Constraint::Type::None)
{
- return Strings::concat(fs::u8string(origin),
- " was rejected because it uses constraints and the `",
- VcpkgCmdArguments::VERSIONS_FEATURE,
- "` feature flag is disabled.\nThis can be fixed by removing uses of "
- "\"version>=\" and \"version=\".");
+ return Strings::concat(
+ fs::u8string(origin),
+ " was rejected because it uses constraints and the `",
+ VcpkgCmdArguments::VERSIONS_FEATURE,
+ "` feature flag is disabled.\nThis can be fixed by removing uses of \"version>=\".\n",
+ s_extended_help);
}
}
return nullopt;
@@ -1036,7 +1054,18 @@ namespace vcpkg
return Strings::concat(fs::u8string(origin),
" was rejected because it uses overrides and the `",
VcpkgCmdArguments::VERSIONS_FEATURE,
- "` feature flag is disabled.\nThis can be fixed by removing \"overrides\".");
+ "` feature flag is disabled.\nThis can be fixed by removing \"overrides\".\n",
+ s_extended_help);
+ }
+
+ if (core_paragraph->builtin_baseline.has_value())
+ {
+ return Strings::concat(
+ fs::u8string(origin),
+ " was rejected because it uses builtin-baseline and the `",
+ VcpkgCmdArguments::VERSIONS_FEATURE,
+ "` feature flag is disabled.\nThis can be fixed by removing \"builtin-baseline\".\n",
+ s_extended_help);
}
}
return nullopt;
@@ -1242,19 +1271,14 @@ namespace vcpkg
serialize_optional_array(dep_obj, DependencyDeserializer::FEATURES, features_copy);
serialize_optional_string(dep_obj, DependencyDeserializer::PLATFORM, to_string(dep.platform));
- if (dep.constraint.port_version != 0)
- {
- dep_obj.insert(DependencyDeserializer::PORT_VERSION,
- Json::Value::integer(dep.constraint.port_version));
- }
-
- if (dep.constraint.type == Versions::Constraint::Type::Exact)
- {
- dep_obj.insert(DependencyDeserializer::VERSION_EQ, Json::Value::string(dep.constraint.value));
- }
- else if (dep.constraint.type == Versions::Constraint::Type::Minimum)
+ if (dep.constraint.type == Versions::Constraint::Type::Minimum)
{
- dep_obj.insert(DependencyDeserializer::VERSION_GE, Json::Value::string(dep.constraint.value));
+ auto s = dep.constraint.value;
+ if (dep.constraint.port_version != 0)
+ {
+ Strings::append(s, '#', dep.constraint.port_version);
+ }
+ dep_obj.insert(DependencyDeserializer::VERSION_GE, Json::Value::string(std::move(s)));
}
}
};
@@ -1294,6 +1318,11 @@ namespace vcpkg
serialize_optional_string(obj, ManifestDeserializer::LICENSE, scf.core_paragraph->license);
serialize_optional_string(
obj, ManifestDeserializer::SUPPORTS, to_string(scf.core_paragraph->supports_expression));
+ if (scf.core_paragraph->builtin_baseline.has_value())
+ {
+ obj.insert(ManifestDeserializer::BUILTIN_BASELINE,
+ Json::Value::string(scf.core_paragraph->builtin_baseline.value_or_exit(VCPKG_LINE_INFO)));
+ }
if (!scf.core_paragraph->dependencies.empty() || debug)
{
diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp
index afd724765..7926e7a5f 100644
--- a/toolsrc/src/vcpkg/vcpkgpaths.cpp
+++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp
@@ -554,6 +554,33 @@ If you wish to silence this error and use classic mode, you can:
}
}
+ ExpectedS<std::string> VcpkgPaths::get_current_git_sha() const
+ {
+ auto cmd = git_cmd_builder(*this, this->root / fs::u8path(".git"), this->root);
+ cmd.string_arg("rev-parse").string_arg("HEAD");
+ auto output = System::cmd_execute_and_capture_output(cmd);
+ if (output.exit_code != 0)
+ {
+ return {std::move(output.output), expected_right_tag};
+ }
+ else
+ {
+ return {Strings::trim(std::move(output.output)), expected_left_tag};
+ }
+ }
+ std::string VcpkgPaths::get_current_git_sha_message() const
+ {
+ auto maybe_cur_sha = get_current_git_sha();
+ if (auto p_sha = maybe_cur_sha.get())
+ {
+ return Strings::concat("The current commit is \"", *p_sha, '"');
+ }
+ else
+ {
+ return Strings::concat("Failed to determine the current commit:\n", maybe_cur_sha.error());
+ }
+ }
+
ExpectedS<std::string> VcpkgPaths::git_show(const std::string& treeish, const fs::path& dot_git_dir) const
{
// All git commands are run with: --git-dir={dot_git_dir} --work-tree={work_tree_temp}
@@ -620,119 +647,148 @@ If you wish to silence this error and use classic mode, you can:
return ret;
}
- void VcpkgPaths::git_checkout_object(const VcpkgPaths& paths,
- StringView git_object,
- const fs::path& local_repo,
- const fs::path& destination,
- const fs::path& dot_git_dir,
- const fs::path& work_tree)
- {
- Files::Filesystem& fs = paths.get_filesystem();
- fs.remove_all(work_tree, VCPKG_LINE_INFO);
- fs.remove_all(destination, VCPKG_LINE_INFO);
-
- if (!fs.exists(dot_git_dir))
- {
- // All git commands are run with: --git-dir={dot_git_dir} --work-tree={work_tree_temp}
- // git clone --no-checkout --local {vcpkg_root} {dot_git_dir}
- System::CmdLineBuilder clone_cmd_builder = git_cmd_builder(paths, dot_git_dir, work_tree)
- .string_arg("clone")
- .string_arg("--no-checkout")
- .string_arg("--local")
- .string_arg("--no-hardlinks")
- .path_arg(local_repo)
- .path_arg(dot_git_dir);
- const auto clone_output = System::cmd_execute_and_capture_output(clone_cmd_builder);
- Checks::check_exit(VCPKG_LINE_INFO,
- clone_output.exit_code == 0,
- "Failed to clone temporary vcpkg instance.\n%s\n",
- clone_output.output);
- }
- else
- {
- System::CmdLineBuilder fetch_cmd_builder =
- git_cmd_builder(paths, dot_git_dir, work_tree).string_arg("fetch");
- const auto fetch_output = System::cmd_execute_and_capture_output(fetch_cmd_builder);
- Checks::check_exit(VCPKG_LINE_INFO,
- fetch_output.exit_code == 0,
- "Failed to update refs on temporary vcpkg repository.\n%s\n",
- fetch_output.output);
- }
-
- if (!fs.exists(work_tree))
- {
- fs.create_directories(work_tree, VCPKG_LINE_INFO);
- }
-
- // git checkout {tree_object} .
- System::CmdLineBuilder checkout_cmd_builder = git_cmd_builder(paths, dot_git_dir, work_tree)
- .string_arg("checkout")
- .string_arg(git_object)
- .string_arg(".");
- const auto checkout_output = System::cmd_execute_and_capture_output(checkout_cmd_builder);
- Checks::check_exit(VCPKG_LINE_INFO, checkout_output.exit_code == 0, "Failed to checkout %s", git_object);
-
- const auto& containing_folder = destination.parent_path();
- if (!fs.exists(containing_folder))
- {
- fs.create_directories(containing_folder, VCPKG_LINE_INFO);
- }
-
- std::error_code ec;
- fs.rename_or_copy(work_tree, destination, ".tmp", ec);
- fs.remove_all(work_tree, VCPKG_LINE_INFO);
- if (ec)
- {
- System::printf(System::Color::error,
- "Error: Couldn't move checked out files from %s to destination %s",
- fs::u8string(work_tree),
- fs::u8string(destination));
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- }
-
- fs::path VcpkgPaths::git_checkout_baseline(Files::Filesystem& fs, StringView commit_sha) const
+ ExpectedS<fs::path> VcpkgPaths::git_checkout_baseline(StringView commit_sha) const
{
+ Files::Filesystem& fs = get_filesystem();
const fs::path destination_parent = this->baselines_output / fs::u8path(commit_sha);
- const fs::path destination = destination_parent / fs::u8path("baseline.json");
+ fs::path destination = destination_parent / fs::u8path("baseline.json");
if (!fs.exists(destination))
{
+ const fs::path destination_tmp = destination_parent / fs::u8path("baseline.json.tmp");
auto treeish = Strings::concat(commit_sha, ":port_versions/baseline.json");
auto maybe_contents = git_show(treeish, this->root / fs::u8path(".git"));
if (auto contents = maybe_contents.get())
{
- fs.create_directories(destination_parent, VCPKG_LINE_INFO);
- fs.write_contents(destination, *contents, VCPKG_LINE_INFO);
+ std::error_code ec;
+ fs.create_directories(destination_parent, ec);
+ if (ec)
+ {
+ return {Strings::format(
+ "Error: while checking out baseline %s\nError: while creating directories %s: %s",
+ commit_sha,
+ fs::u8string(destination_parent),
+ ec.message()),
+ expected_right_tag};
+ }
+ fs.write_contents(destination_tmp, *contents, ec);
+ if (ec)
+ {
+ return {Strings::format("Error: while checking out baseline %s\nError: while writing %s: %s",
+ commit_sha,
+ fs::u8string(destination_tmp),
+ ec.message()),
+ expected_right_tag};
+ }
+ fs.rename(destination_tmp, destination, ec);
+ if (ec)
+ {
+ return {Strings::format("Error: while checking out baseline %s\nError: while renaming %s to %s: %s",
+ commit_sha,
+ fs::u8string(destination_tmp),
+ fs::u8string(destination),
+ ec.message()),
+ expected_right_tag};
+ }
}
else
{
- Checks::exit_with_message(
- VCPKG_LINE_INFO, "Error: while checking out baseline '%s':\n%s", treeish, maybe_contents.error());
+ return {Strings::format("Error: while checking out baseline '%s':\n%s\nThis may be fixed by updating "
+ "vcpkg to the latest master via `git pull`.",
+ treeish,
+ maybe_contents.error()),
+ expected_right_tag};
}
}
return destination;
}
- fs::path VcpkgPaths::git_checkout_port(Files::Filesystem& fs, StringView port_name, StringView git_tree) const
+ ExpectedS<fs::path> VcpkgPaths::git_checkout_port(StringView port_name,
+ StringView git_tree,
+ const fs::path& dot_git_dir) const
{
- /* Clone a new vcpkg repository instance using the local instance as base.
- *
- * The `--git-dir` directory will store all the Git metadata files,
- * and the `--work-tree` is the directory where files will be checked out.
+ /* Check out a git tree into the versioned port recipes folder
*
* Since we are checking a git tree object, all files will be checked out to the root of `work-tree`.
* Because of that, it makes sense to use the git hash as the name for the directory.
*/
- const fs::path& local_repo = this->root;
- fs::path destination = this->versions_output / fs::u8path(git_tree) / fs::u8path(port_name);
+ Files::Filesystem& fs = get_filesystem();
+ fs::path destination = this->versions_output / fs::u8path(port_name) / fs::u8path(git_tree);
+ if (fs.exists(destination))
+ {
+ return destination;
+ }
- if (!fs.exists(destination / "CONTROL") && !fs.exists(destination / "vcpkg.json"))
+ const fs::path destination_tmp =
+ this->versions_output / fs::u8path(port_name) / fs::u8path(Strings::concat(git_tree, ".tmp"));
+ const fs::path destination_tar =
+ this->versions_output / fs::u8path(port_name) / fs::u8path(Strings::concat(git_tree, ".tar"));
+#define PRELUDE "Error: while checking out port ", port_name, " with git tree ", git_tree, "\n"
+ std::error_code ec;
+ fs::path failure_point;
+ fs.remove_all(destination_tmp, ec, failure_point);
+ if (ec)
{
- git_checkout_object(
- *this, git_tree, local_repo, destination, this->versions_dot_git_dir, this->versions_work_tree);
+ return {Strings::concat(PRELUDE, "Error: while removing ", fs::u8string(failure_point), ": ", ec.message()),
+ expected_right_tag};
}
+ fs.create_directories(destination_tmp, ec);
+ if (ec)
+ {
+ return {
+ Strings::concat(
+ PRELUDE, "Error: while creating directories ", fs::u8string(destination_tmp), ": ", ec.message()),
+ expected_right_tag};
+ }
+
+ System::CmdLineBuilder tar_cmd_builder = git_cmd_builder(*this, dot_git_dir, dot_git_dir)
+ .string_arg("archive")
+ .string_arg(git_tree)
+ .string_arg("-o")
+ .path_arg(destination_tar);
+ const auto tar_output = System::cmd_execute_and_capture_output(tar_cmd_builder);
+ if (tar_output.exit_code != 0)
+ {
+ return {Strings::concat(PRELUDE, "Error: Failed to tar port directory\n", tar_output.output),
+ expected_right_tag};
+ }
+
+ System::CmdLineBuilder extract_cmd_builder;
+ extract_cmd_builder.path_arg(this->get_tool_exe(Tools::CMAKE))
+ .string_arg("-E")
+ .string_arg("tar")
+ .string_arg("xf")
+ .path_arg(destination_tar);
+
+ const auto extract_output =
+ System::cmd_execute_and_capture_output(extract_cmd_builder, System::InWorkingDirectory{destination_tmp});
+ if (extract_output.exit_code != 0)
+ {
+ return {Strings::concat(PRELUDE, "Error: Failed to extract port directory\n", extract_output.output),
+ expected_right_tag};
+ }
+ fs.remove(destination_tar, ec);
+ if (ec)
+ {
+ return {
+ Strings::concat(PRELUDE, "Error: while removing ", fs::u8string(destination_tar), ": ", ec.message()),
+ expected_right_tag};
+ }
+ fs.rename(destination_tmp, destination, ec);
+ if (ec)
+ {
+ return {Strings::concat(PRELUDE,
+ "Error: while renaming ",
+ fs::u8string(destination_tmp),
+ " to ",
+ fs::u8string(destination),
+ ": ",
+ ec.message()),
+ expected_right_tag};
+ }
+
return destination;
+#undef PRELUDE
}
ExpectedS<std::string> VcpkgPaths::git_fetch_from_remote_registry(StringView repo, StringView treeish) const
@@ -757,7 +813,7 @@ If you wish to silence this error and use classic mode, you can:
auto lock_file = work_tree / fs::u8path(".vcpkg-lock");
std::error_code ec;
- auto guard = Files::ExclusiveFileLock(Files::ExclusiveFileLock::Wait::Yes, fs, lock_file, ec);
+ Files::ExclusiveFileLock guard(Files::ExclusiveFileLock::Wait::Yes, fs, lock_file, ec);
System::CmdLineBuilder fetch_git_ref =
git_cmd_builder(*this, dot_git_dir, work_tree).string_arg("fetch").string_arg("--").string_arg(repo);