Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions toolsrc/include/vcpkg/fwd/vcpkgcmdarguments.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ namespace vcpkg
struct CommandStructure;
struct HelpTableFormatter;
struct VcpkgCmdArguments;
struct FeatureFlagSettings;
}
24 changes: 13 additions & 11 deletions toolsrc/include/vcpkg/sourceparagraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <vcpkg/packagespec.h>
#include <vcpkg/paragraphparser.h>
#include <vcpkg/platform-expression.h>
#include <vcpkg/versions.h>

namespace vcpkg
{
Expand Down Expand Up @@ -54,6 +55,7 @@ namespace vcpkg
struct SourceParagraph
{
std::string name;
Versions::Scheme version_scheme = Versions::Scheme::String;
std::string version;
int port_version = 0;
std::vector<std::string> description;
Expand All @@ -78,14 +80,15 @@ namespace vcpkg
/// </summary>
struct SourceControlFile
{
SourceControlFile() = default;
SourceControlFile(const SourceControlFile& scf)
: core_paragraph(std::make_unique<SourceParagraph>(*scf.core_paragraph))
SourceControlFile clone() const
{
for (const auto& feat_ptr : scf.feature_paragraphs)
SourceControlFile ret;
ret.core_paragraph = std::make_unique<SourceParagraph>(*core_paragraph);
for (const auto& feat_ptr : feature_paragraphs)
{
feature_paragraphs.push_back(std::make_unique<FeatureParagraph>(*feat_ptr));
ret.feature_paragraphs.push_back(std::make_unique<FeatureParagraph>(*feat_ptr));
}
return ret;
}

static Parse::ParseExpected<SourceControlFile> parse_manifest_file(const fs::path& path_to_manifest,
Expand Down Expand Up @@ -114,12 +117,6 @@ namespace vcpkg
/// </summary>
struct SourceControlFileLocation
{
SourceControlFileLocation(const SourceControlFileLocation& scfl)
: source_control_file(std::make_unique<SourceControlFile>(*scfl.source_control_file))
, source_location(scfl.source_location)
{
}

SourceControlFileLocation(std::unique_ptr<SourceControlFile>&& scf, fs::path&& source)
: source_control_file(std::move(scf)), source_location(std::move(source))
{
Expand All @@ -130,6 +127,11 @@ namespace vcpkg
{
}

SourceControlFileLocation clone() const
{
return {std::make_unique<SourceControlFile>(source_control_file->clone()), source_location};
}

std::unique_ptr<SourceControlFile> source_control_file;
fs::path source_location;
};
Expand Down
21 changes: 21 additions & 0 deletions toolsrc/include/vcpkg/vcpkgcmdarguments.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ namespace vcpkg
std::string m_str;
};

struct FeatureFlagSettings
{
bool registries;
bool compiler_tracking;
bool binary_caching;
bool versions;
};

struct VcpkgCmdArguments
{
static VcpkgCmdArguments create_from_command_line(const Files::Filesystem& fs,
Expand Down Expand Up @@ -173,12 +181,25 @@ namespace vcpkg
Optional<bool> manifest_mode = nullopt;
constexpr static StringLiteral REGISTRIES_FEATURE = "registries";
Optional<bool> registries_feature = nullopt;
constexpr static StringLiteral VERSIONS_FEATURE = "versions";
Optional<bool> versions_feature = nullopt;

constexpr static StringLiteral RECURSIVE_DATA_ENV = "VCPKG_X_RECURSIVE_DATA";

bool binary_caching_enabled() const { return binary_caching.value_or(true); }
bool compiler_tracking_enabled() const { return compiler_tracking.value_or(true); }
bool registries_enabled() const { return registries_feature.value_or(false); }
bool versions_enabled() const { return versions_feature.value_or(false); }
FeatureFlagSettings feature_flag_settings() const
{
FeatureFlagSettings f;
f.binary_caching = binary_caching_enabled();
f.compiler_tracking = compiler_tracking_enabled();
f.registries = registries_enabled();
f.versions = versions_enabled();
return f;
}

bool output_json() const { return json.value_or(false); }
bool is_recursive_invocation() const { return m_is_recursive_invocation; }

Expand Down
1 change: 1 addition & 0 deletions toolsrc/include/vcpkg/vcpkgpaths.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ namespace vcpkg
const Build::CompilerInfo& get_compiler_info(const Build::AbiInfo& abi_info) const;
bool manifest_mode_enabled() const { return get_manifest().has_value(); }

const FeatureFlagSettings& get_feature_flags() const;
void track_feature_flag_metrics() const;

private:
Expand Down
14 changes: 14 additions & 0 deletions toolsrc/include/vcpkg/versions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include <vcpkg/fwd/vcpkgpaths.h>

namespace vcpkg::Versions
{
enum class Scheme
{
String,
Relaxed,
Semver,
Date
};
}
52 changes: 52 additions & 0 deletions toolsrc/src/vcpkg-test/manifests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ static Parse::ParseExpected<SourceControlFile> test_parse_manifest(StringView sv
{
print_error_message(res.error());
}
REQUIRE(res.has_value() == !expect_fail);
return res;
}

Expand All @@ -59,6 +60,57 @@ TEST_CASE ("manifest construct minimum", "[manifests]")
REQUIRE(pgh.core_paragraph->dependencies.empty());
}

TEST_CASE ("manifest versioning", "[manifests]")
{
std::tuple<StringLiteral, Versions::Scheme, StringLiteral> data[] = {
{R"json({
"name": "zlib",
"version-string": "abcd"
}
)json",
Versions::Scheme::String,
"abcd"},
{R"json({
"name": "zlib",
"version-date": "2020-01-01"
}
)json",
Versions::Scheme::Date,
"2020-01-01"},
{R"json({
"name": "zlib",
"version": "1.2.3.4.5"
}
)json",
Versions::Scheme::Relaxed,
"1.2.3.4.5"},
{R"json({
"name": "zlib",
"version-semver": "1.2.3-rc3"
}
)json",
Versions::Scheme::Semver,
"1.2.3-rc3"},
};
for (auto v : data)
{
auto m_pgh = test_parse_manifest(std::get<0>(v));

REQUIRE(m_pgh.has_value());
auto& pgh = **m_pgh.get();
REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == std::get<0>(v));
REQUIRE(pgh.core_paragraph->version_scheme == std::get<1>(v));
REQUIRE(pgh.core_paragraph->version == std::get<2>(v));
}

test_parse_manifest(R"json({
"name": "zlib",
"version-string": "abcd",
"version-semver": "1.2.3-rc3"
})json",
true);
}

TEST_CASE ("manifest construct maximum", "[manifests]")
{
auto m_pgh = test_parse_manifest(R"json({
Expand Down
6 changes: 3 additions & 3 deletions toolsrc/src/vcpkg-test/plan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,9 +389,9 @@ TEST_CASE ("basic feature test 8", "[plan]")
auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}};

spec_map.triplet = Test::X86_WINDOWS;
auto spec_a_86 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}};
auto spec_b_86 = FullPackageSpec{spec_map.emplace("b")};
auto spec_c_86 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}};
auto spec_a_86 = FullPackageSpec{PackageSpec{"a", Test::X86_WINDOWS}};
auto spec_b_86 = FullPackageSpec{PackageSpec{"b", Test::X86_WINDOWS}};
auto spec_c_86 = FullPackageSpec{PackageSpec{"c", Test::X86_WINDOWS}};

PortFileProvider::MapPortFileProvider map_port{spec_map.map};
MockCMakeVarProvider var_provider;
Expand Down
6 changes: 4 additions & 2 deletions toolsrc/src/vcpkg-test/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,10 @@ namespace vcpkg::Test

PackageSpec PackageSpecMap::emplace(vcpkg::SourceControlFileLocation&& scfl)
{
map.emplace(scfl.source_control_file->core_paragraph->name, std::move(scfl));
return {scfl.source_control_file->core_paragraph->name, triplet};
const auto& name = scfl.source_control_file->core_paragraph->name;
REQUIRE(map.find(name) == map.end());
map.emplace(name, std::move(scfl));
return {name, triplet};
}

static AllowSymlinks internal_can_create_symlinks() noexcept
Expand Down
2 changes: 1 addition & 1 deletion toolsrc/src/vcpkg/commands.ci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ namespace vcpkg::Commands::CI
ret->features.emplace(action.spec, action.feature_list);
if (auto scfl = p->source_control_file_location.get())
{
auto emp = ret->default_feature_provider.emplace(p->spec.name(), *scfl);
auto emp = ret->default_feature_provider.emplace(p->spec.name(), scfl->clone());
emp.first->second.source_control_file->core_paragraph->default_features = p->feature_list;

p->build_options = vcpkg::Build::default_build_package_options;
Expand Down
11 changes: 8 additions & 3 deletions toolsrc/src/vcpkg/dependencies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -684,10 +684,15 @@ namespace vcpkg::Dependencies
std::vector<FeatureSpec> feature_specs;
for (const FullPackageSpec& spec : specs)
{
const SourceControlFileLocation* scfl = port_provider.get_control_file(spec.package_spec.name()).get();
auto maybe_scfl = port_provider.get_control_file(spec.package_spec.name());

Checks::check_exit(
VCPKG_LINE_INFO, scfl, "Error: Cannot find definition for package `%s`.", spec.package_spec.name());
Checks::check_exit(VCPKG_LINE_INFO,
maybe_scfl.has_value(),
"Error: while loading port `%s`: %s",
spec.package_spec.name(),
maybe_scfl.error());

const SourceControlFileLocation* scfl = maybe_scfl.get();

const std::vector<std::string> all_features =
Util::fmap(scfl->source_control_file->feature_paragraphs,
Expand Down
71 changes: 49 additions & 22 deletions toolsrc/src/vcpkg/portfileprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <vcpkg/portfileprovider.h>
#include <vcpkg/registries.h>
#include <vcpkg/sourceparagraph.h>
#include <vcpkg/vcpkgcmdarguments.h>

namespace vcpkg::PortFileProvider
{
Expand Down Expand Up @@ -59,16 +60,10 @@ namespace vcpkg::PortFileProvider
}
}

ExpectedS<const SourceControlFileLocation&> PathsPortFileProvider::get_control_file(const std::string& spec) const
static Optional<SourceControlFileLocation> try_load_overlay_port(const Files::Filesystem& fs,
View<fs::path> overlay_ports,
const std::string& spec)
{
auto cache_it = cache.find(spec);
if (cache_it != cache.end())
{
return cache_it->second;
}

const auto& fs = paths.get_filesystem();

for (auto&& ports_dir : overlay_ports)
{
// Try loading individual port
Expand All @@ -79,10 +74,7 @@ namespace vcpkg::PortFileProvider
{
if (scf->get()->core_paragraph->name == spec)
{
auto it = cache.emplace(std::piecewise_construct,
std::forward_as_tuple(spec),
std::forward_as_tuple(std::move(*scf), ports_dir));
return it.first->second;
return SourceControlFileLocation{std::move(*scf), ports_dir};
}
}
else
Expand All @@ -103,10 +95,7 @@ namespace vcpkg::PortFileProvider
{
if (scf->get()->core_paragraph->name == spec)
{
auto it = cache.emplace(std::piecewise_construct,
std::forward_as_tuple(std::move(spec)),
std::forward_as_tuple(std::move(*scf), std::move(ports_spec)));
return it.first->second;
return SourceControlFileLocation{std::move(*scf), std::move(ports_spec)};
}
Checks::exit_with_message(VCPKG_LINE_INFO,
"Error: Failed to load port from %s: names did not match: '%s' != '%s'",
Expand All @@ -122,7 +111,12 @@ namespace vcpkg::PortFileProvider
}
}
}
return nullopt;
}

static Optional<SourceControlFileLocation> try_load_registry_port(const VcpkgPaths& paths, const std::string& spec)
{
const auto& fs = paths.get_filesystem();
if (auto registry = paths.get_configuration().registry_set.registry_for_port(spec))
{
auto registry_root = registry->get_registry_root(paths);
Expand All @@ -135,10 +129,7 @@ namespace vcpkg::PortFileProvider
{
if (scf->get()->core_paragraph->name == spec)
{
auto it = cache.emplace(std::piecewise_construct,
std::forward_as_tuple(spec),
std::forward_as_tuple(std::move(*scf), std::move(port_directory)));
return it.first->second;
return SourceControlFileLocation{std::move(*scf), std::move(port_directory)};
}
Checks::exit_with_message(VCPKG_LINE_INFO,
"Error: Failed to load port from %s: names did not match: '%s' != '%s'",
Expand All @@ -154,8 +145,44 @@ namespace vcpkg::PortFileProvider
}
}
}
return nullopt;
}

return std::string("Port definition not found");
ExpectedS<const SourceControlFileLocation&> PathsPortFileProvider::get_control_file(const std::string& spec) const
{
auto cache_it = cache.find(spec);
if (cache_it == cache.end())
{
const auto& fs = paths.get_filesystem();
auto maybe_port = try_load_overlay_port(fs, overlay_ports, spec);
if (!maybe_port)
{
maybe_port = try_load_registry_port(paths, spec);
}
if (auto p = maybe_port.get())
{
cache_it = cache.emplace(spec, std::move(*p)).first;
}
}

if (cache_it == cache.end())
{
return std::string("Port definition not found");
}
else
{
if (!paths.get_feature_flags().versions)
{
if (cache_it->second.source_control_file->core_paragraph->version_scheme != Versions::Scheme::String)
{
return Strings::concat(
"Port definition rejected because the `",
VcpkgCmdArguments::VERSIONS_FEATURE,
"` feature flag is disabled.\nThis can be fixed by using the \"version-string\" field.");
}
}
return cache_it->second;
}
}

std::vector<const SourceControlFileLocation*> PathsPortFileProvider::load_all_control_files() const
Expand Down
Loading