[x-update-baseline] Initial implementation (#341)

* start working

* update vcpkgpaths to better support what I want

* optional: make certain `get()` is only called when
  it won't result in a dangling pointer
* vcpkgpaths: remove JsonStyle support as it isn't used
* vcpkgpaths: switch from two functions returning
  Optional<Manifest> + Optional<Path>,
  to one function returning Optional<ManifestAndLocation>
* vcpkgpaths: add `get_configuration_and_location`

* rename get_*_and_location -> get_*

* lots of CRs

* get_latest_baseline -> configuration.cpp
* format
* optional - add see-through operator==
* add `--add-initial-baseline` option
* more correct if-elses

* add messages!

```
PS /../nimazzuc/projects/testproj> ../vcpkg-tool/build/vcpkg x-update-baseline --dry-run
registry 'https://github.com/microsoft/vcpkg' already up to date: 89295c9fe22e97ca9e380a6c771ccf2ff09dca95
registry '/a/b' not updated: default
registry 'https://foobar' not updated: default
warning: git failed to fetch remote repository https://foobar
Error: Failed to fetch ref HEAD from repository https://foobar.
fatal: unable to access 'https://foobar/': Could not resolve host: foobar
```

* update - hopefully fix Billy's CRs

* fix formatting

* (optional::operator==) add tests, add opt<T> == opt<U>

* rename things

* registry_location -> pretty_location
* ManifestAndLocation -> ManifestAndPath
* ConfigurationAndLocation -> ConfigurationAndSource

* minor other CRs

* forgot to to_string

* format

* I think this is what robert wants?

* format
This commit is contained in:
nicole mazzuca 2022-04-19 13:04:52 -07:00 коммит произвёл GitHub
Родитель 48006ab73a
Коммит 1cf1f7f126
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
18 изменённых файлов: 535 добавлений и 75 удалений

Просмотреть файл

@ -106,6 +106,9 @@ namespace vcpkg
return lhs.data() >= rhs.data();
}
bool empty() { return m_data.empty(); }
void clear() { m_data.clear(); }
private:
std::string m_data;
@ -244,6 +247,8 @@ namespace vcpkg::msg
DECLARE_MSG_ARG(expected, "");
DECLARE_MSG_ARG(actual, "");
DECLARE_MSG_ARG(list, "");
DECLARE_MSG_ARG(old_value, "");
DECLARE_MSG_ARG(new_value, "");
DECLARE_MSG_ARG(actual_version, "1.3.8");
DECLARE_MSG_ARG(arch, "x64");
@ -317,10 +322,10 @@ namespace vcpkg::msg
inline void print_warning(const LocalizedString& s)
{
print(Color::warning, format(msgErrorMessage).append(s).appendnl());
print(Color::warning, format(msgWarningMessage).append(s).appendnl());
}
template<class Message, class... Ts>
void print_warning(Message m, Ts... args)
typename Message::is_message_type print_warning(Message m, Ts... args)
{
print(Color::warning, format(msgWarningMessage).append(format(m, args...).appendnl()));
}
@ -330,7 +335,7 @@ namespace vcpkg::msg
print(Color::error, format(msgErrorMessage).append(s).appendnl());
}
template<class Message, class... Ts>
void print_error(Message m, Ts... args)
typename Message::is_message_type print_error(Message m, Ts... args)
{
print(Color::error, format(msgErrorMessage).append(format(m, args...).appendnl()));
}

Просмотреть файл

@ -107,6 +107,11 @@ namespace vcpkg
const T& value() const { return this->m_t; }
T& value() { return this->m_t; }
const T* get() const& { return m_is_present ? &m_t : nullptr; }
T* get() & { return m_is_present ? &m_t : nullptr; }
const T* get() const&& = delete;
T* get() && = delete;
void destroy()
{
m_is_present = false;
@ -180,6 +185,11 @@ namespace vcpkg
const T& value() const { return this->m_t; }
T& value() { return this->m_t; }
const T* get() const& { return m_is_present ? &m_t : nullptr; }
T* get() & { return m_is_present ? &m_t : nullptr; }
const T* get() const&& = delete;
T* get() && = delete;
template<class... Args>
T& emplace(Args&&... args)
{
@ -228,6 +238,8 @@ namespace vcpkg
return *m_t;
}
T* get() const { return m_t; }
private:
T* m_t;
};
@ -246,6 +258,8 @@ namespace vcpkg
const T& value() const { return *this->m_t; }
const T* get() const { return m_t; }
const T& emplace(const T& t)
{
m_t = &t;
@ -260,6 +274,10 @@ namespace vcpkg
template<class T>
struct Optional
{
private:
details::OptionalStorage<T> m_base;
public:
constexpr Optional() noexcept { }
// Constructors are intentionally implicit
@ -320,12 +338,11 @@ namespace vcpkg
return this->m_base.has_value() ? std::move(this->m_base.value()) : static_cast<T&&>(default_value);
}
typename std::add_pointer<const T>::type get() const
{
return this->m_base.has_value() ? &this->m_base.value() : nullptr;
}
typename std::add_pointer<T>::type get() { return this->m_base.has_value() ? &this->m_base.value() : nullptr; }
// this allows us to error out when `.get()` would return a pointer to a temporary
decltype(auto) get() const& { return this->m_base.get(); }
decltype(auto) get() & { return this->m_base.get(); }
decltype(auto) get() const&& { return std::move(this->m_base).get(); }
decltype(auto) get() && { return std::move(this->m_base).get(); }
template<class F>
using map_t = decltype(std::declval<F&>()(std::declval<const T&>()));
@ -396,9 +413,6 @@ namespace vcpkg
return !rhs.m_base.has_value();
}
friend bool operator!=(const Optional& lhs, const Optional& rhs) noexcept { return !(lhs == rhs); }
private:
details::OptionalStorage<T> m_base;
};
template<class U>
@ -407,28 +421,44 @@ namespace vcpkg
return Optional<std::decay_t<U>>(std::forward<U>(u));
}
template<class T>
bool operator==(const Optional<T>& o, const T& t)
// these cannot be hidden friends, unfortunately
template<class T, class U>
auto operator==(const Optional<T>& lhs, const Optional<U>& rhs) -> decltype(*lhs.get() == *rhs.get())
{
if (auto p = o.get()) return *p == t;
return false;
if (lhs.has_value() && rhs.has_value())
{
return *lhs.get() == *rhs.get();
}
return lhs.has_value() == rhs.has_value();
}
template<class T>
bool operator==(const T& t, const Optional<T>& o)
template<class T, class U>
auto operator==(const Optional<T>& lhs, const U& rhs) -> decltype(*lhs.get() == rhs)
{
if (auto p = o.get()) return t == *p;
return false;
return lhs.has_value() ? *lhs.get() == rhs : false;
}
template<class T>
bool operator!=(const Optional<T>& o, const T& t)
template<class T, class U>
auto operator==(const T& lhs, const Optional<U>& rhs) -> decltype(lhs == *rhs.get())
{
if (auto p = o.get()) return *p != t;
return true;
return rhs.has_value() ? lhs == *rhs.get() : false;
}
template<class T>
bool operator!=(const T& t, const Optional<T>& o)
template<class T, class U>
auto operator!=(const Optional<T>& lhs, const Optional<U>& rhs) -> decltype(*lhs.get() != *rhs.get())
{
if (auto p = o.get()) return t != *p;
return true;
if (lhs.has_value() && rhs.has_value())
{
return *lhs.get() != *rhs.get();
}
return lhs.has_value() != rhs.has_value();
}
template<class T, class U>
auto operator!=(const Optional<T>& lhs, const U& rhs) -> decltype(*lhs.get() != rhs)
{
return lhs.has_value() ? *lhs.get() != rhs : true;
}
template<class T, class U>
auto operator!=(const T& lhs, const Optional<U>& rhs) -> decltype(lhs != *rhs.get())
{
return rhs.has_value() ? lhs != *rhs.get() : true;
}
}

Просмотреть файл

@ -0,0 +1,11 @@
#pragma once
#include <vcpkg/commands.interface.h>
namespace vcpkg::Commands
{
struct UpdateBaselineCommand : PathsCommand
{
virtual void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const override;
};
}

Просмотреть файл

@ -23,6 +23,9 @@ namespace vcpkg
Optional<std::vector<std::string>> packages;
Json::Value serialize() const;
ExpectedL<Optional<std::string>> get_latest_baseline(const VcpkgPaths& paths) const;
StringView pretty_location() const;
};
struct Configuration
@ -42,6 +45,25 @@ namespace vcpkg
static View<StringView> known_fields();
};
enum class ConfigurationSource
{
None,
VcpkgConfigurationFile,
ManifestFile,
};
struct ConfigurationAndSource
{
Configuration config;
Path directory;
ConfigurationSource source = ConfigurationSource::None;
std::unique_ptr<RegistrySet> instantiate_registry_set(const VcpkgPaths& paths) const
{
return config.instantiate_registry_set(paths, directory);
}
};
struct ManifestConfiguration
{
Optional<std::string> builtin_baseline;

Просмотреть файл

@ -3,6 +3,7 @@
namespace vcpkg
{
struct Configuration;
struct ConfigurationAndSource;
struct RegistryConfig;
struct ManifestConfiguration;
}

Просмотреть файл

@ -20,6 +20,8 @@
namespace vcpkg
{
constexpr StringLiteral builtin_registry_git_url() { return "https://github.com/microsoft/vcpkg"; }
struct LockFile
{
struct EntryData

Просмотреть файл

@ -58,6 +58,12 @@ namespace vcpkg
struct PackageSpec;
struct Triplet;
struct ManifestAndPath
{
Json::Object manifest;
Path path;
};
struct VcpkgPaths
{
struct TripletFile
@ -147,8 +153,8 @@ namespace vcpkg
const Path& relative_path_to_file) const;
ExpectedS<Path> git_checkout_object_from_remote_registry(StringView tree) const;
Optional<const Json::Object&> get_manifest() const;
Optional<const Path&> get_manifest_path() const;
Optional<const ManifestAndPath&> get_manifest() const;
const ConfigurationAndSource& get_configuration() const;
const RegistrySet& get_registry_set() const;
// Retrieve a toolset matching the requirements in prebuildinfo

Просмотреть файл

@ -132,6 +132,13 @@
"UnknownBinaryProviderType": "unknown binary provider type: valid providers are 'clear', 'default', 'nuget', 'nugetconfig', 'interactive', and 'files'",
"UnsupportedSystemName": "Error: Could not map VCPKG_CMAKE_SYSTEM_NAME '{system_name}' to a vcvarsall platform. Supported system names are '', 'Windows' and 'WindowsStore'.",
"UnsupportedToolchain": "Error: in triplet {triplet}: Unable to find a valid toolchain combination.\n The requested target architecture was {arch}\n The selected Visual Studio instance is at {path}\n The available toolchain combinations are {list}\n",
"UpdateBaselineAddBaselineNoManifest": "the --{option} switch was passed, but there is no manifest file to add a `builtin-baseline` field to.",
"UpdateBaselineLocalGitError": "git failed to parse HEAD for the local vcpkg registry at '{path}'",
"UpdateBaselineNoConfiguration": "neither `vcpkg.json` nor `vcpkg-configuration.json` exist to update.",
"UpdateBaselineNoExistingBuiltinBaseline": "the manifest file currently does not contain a `builtin-baseline` field; in order to add one, pass the --{option} switch.",
"UpdateBaselineNoUpdate": "registry '{url}' not updated: '{value}'",
"UpdateBaselineRemoteGitError": "git failed to fetch remote repository '{url}'",
"UpdateBaselineUpdatedBaseline": "updated registry '{url}': baseline '{old_value}' -> '{new_value}'",
"UploadedPackagesToVendor": "Uploaded {count} package(s) to {vendor} in {elapsed}",
"UsingManifestAt": "Using manifest file at {path}.",
"Utf8DecoderDereferencedAtEof": "dereferenced Utf8Decoder at the end of a string.",

Просмотреть файл

@ -228,6 +228,19 @@
"_UnsupportedSystemName.comment": "example of {system_name} is 'Darwin'.\n",
"UnsupportedToolchain": "Error: in triplet {triplet}: Unable to find a valid toolchain combination.\n The requested target architecture was {arch}\n The selected Visual Studio instance is at {path}\n The available toolchain combinations are {list}\n",
"_UnsupportedToolchain.comment": "example for {list} is 'x86, arm64'\nexample of {triplet} is 'x64-windows'.\nexample of {arch} is 'x64'.\nexample of {path} is '/foo/bar'.\n",
"UpdateBaselineAddBaselineNoManifest": "the --{option} switch was passed, but there is no manifest file to add a `builtin-baseline` field to.",
"_UpdateBaselineAddBaselineNoManifest.comment": "example of {option} is 'editable'.\n",
"UpdateBaselineLocalGitError": "git failed to parse HEAD for the local vcpkg registry at '{path}'",
"_UpdateBaselineLocalGitError.comment": "example of {path} is '/foo/bar'.\n",
"UpdateBaselineNoConfiguration": "neither `vcpkg.json` nor `vcpkg-configuration.json` exist to update.",
"UpdateBaselineNoExistingBuiltinBaseline": "the manifest file currently does not contain a `builtin-baseline` field; in order to add one, pass the --{option} switch.",
"_UpdateBaselineNoExistingBuiltinBaseline.comment": "example of {option} is 'editable'.\n",
"UpdateBaselineNoUpdate": "registry '{url}' not updated: '{value}'",
"_UpdateBaselineNoUpdate.comment": "example of {value} is '5507daa796359fe8d45418e694328e878ac2b82f'\nexample of {url} is 'https://github.com/microsoft/vcpkg'.\n",
"UpdateBaselineRemoteGitError": "git failed to fetch remote repository '{url}'",
"_UpdateBaselineRemoteGitError.comment": "example of {url} is 'https://github.com/microsoft/vcpkg'.\n",
"UpdateBaselineUpdatedBaseline": "updated registry '{url}': baseline '{old_value}' -> '{new_value}'",
"_UpdateBaselineUpdatedBaseline.comment": "example of {old_value}, {new_value} is '5507daa796359fe8d45418e694328e878ac2b82f'\nexample of {url} is 'https://github.com/microsoft/vcpkg'.\n",
"UploadedPackagesToVendor": "Uploaded {count} package(s) to {vendor} in {elapsed}",
"_UploadedPackagesToVendor.comment": "example of {count} is '42'.\nexample of {elapsed} is '3.532 min'.\nexample of {vendor} is 'Azure'.\n",
"UsingManifestAt": "Using manifest file at {path}.",

Просмотреть файл

@ -63,6 +63,7 @@ TEST_CASE ("list of commands is correct", "[commands]")
"remove",
"search",
"update",
"x-update-baseline",
"upgrade",
"use",
"version",

Просмотреть файл

@ -119,3 +119,127 @@ TEST_CASE ("common_projection", "[optional]")
input.push_back(1729);
CHECK(!common_projection(input, identity_projection{}).has_value());
}
TEST_CASE ("operator==/operator!=", "[optional]")
{
using vcpkg::Optional;
using vcpkg::StringLiteral;
SECTION ("same type - opt == opt")
{
Optional<std::string> s1;
Optional<std::string> s2;
// none == none
CHECK(s1 == s2);
CHECK_FALSE(s1 != s2);
CHECK(s2 == s1);
CHECK_FALSE(s2 != s1);
// some("") != none
s1 = "";
CHECK_FALSE(s1 == s2);
CHECK(s1 != s2);
CHECK_FALSE(s2 == s1);
CHECK(s2 != s1);
// some("") == some("")
s2 = "";
CHECK(s1 == s2);
CHECK_FALSE(s1 != s2);
CHECK(s2 == s1);
CHECK_FALSE(s2 != s1);
// some("hi") != some("")
s1 = "hi";
CHECK_FALSE(s1 == s2);
CHECK(s1 != s2);
CHECK_FALSE(s2 == s1);
CHECK(s2 != s1);
};
SECTION ("same type - opt == raw")
{
Optional<std::string> opt_string;
std::string string;
// none != ""
CHECK_FALSE(opt_string == string);
CHECK(opt_string != string);
CHECK_FALSE(string == opt_string);
CHECK(string != opt_string);
// some("") == ""
opt_string = "";
CHECK(opt_string == string);
CHECK_FALSE(opt_string != string);
CHECK(string == opt_string);
CHECK_FALSE(string != opt_string);
// some("hi") != ""
opt_string = "hi";
CHECK_FALSE(opt_string == string);
CHECK(opt_string != string);
CHECK_FALSE(string == opt_string);
CHECK(string != opt_string);
};
SECTION ("different types - opt == opt")
{
Optional<std::string> opt_string;
Optional<StringLiteral> opt_literal;
// none == none
CHECK(opt_string == opt_literal);
CHECK_FALSE(opt_string != opt_literal);
CHECK(opt_literal == opt_string);
CHECK_FALSE(opt_literal != opt_string);
// some("") != none
opt_string = "";
CHECK_FALSE(opt_string == opt_literal);
CHECK(opt_string != opt_literal);
CHECK_FALSE(opt_literal == opt_string);
CHECK(opt_literal != opt_string);
// some("") == some("")
opt_literal = "";
CHECK(opt_string == opt_literal);
CHECK_FALSE(opt_string != opt_literal);
CHECK(opt_literal == opt_string);
CHECK_FALSE(opt_literal != opt_string);
// some("hi") != some("")
opt_string = "hi";
CHECK_FALSE(opt_string == opt_literal);
CHECK(opt_string != opt_literal);
CHECK_FALSE(opt_literal == opt_string);
CHECK(opt_literal != opt_string);
};
SECTION ("different types - opt == raw")
{
Optional<std::string> opt_string;
StringLiteral literal = "";
// none != ""
CHECK_FALSE(opt_string == literal);
CHECK(opt_string != literal);
CHECK_FALSE(literal == opt_string);
CHECK(literal != opt_string);
// some("") == ""
opt_string = "";
CHECK(opt_string == literal);
CHECK_FALSE(opt_string != literal);
CHECK(literal == opt_string);
CHECK_FALSE(literal != opt_string);
// some("hi") != ""
opt_string = "hi";
CHECK_FALSE(opt_string == literal);
CHECK(opt_string != literal);
CHECK_FALSE(literal == opt_string);
CHECK(literal != opt_string);
};
}

Просмотреть файл

@ -99,8 +99,7 @@ namespace vcpkg::Commands
specs.push_back(std::move(value));
}
const auto& manifest_path = paths.get_manifest_path().value_or_exit(VCPKG_LINE_INFO);
auto maybe_manifest_scf = SourceControlFile::parse_manifest_object(manifest_path, *manifest);
auto maybe_manifest_scf = SourceControlFile::parse_manifest_object(manifest->path, manifest->manifest);
if (!maybe_manifest_scf)
{
print_error_message(maybe_manifest_scf.error());
@ -133,7 +132,7 @@ namespace vcpkg::Commands
}
paths.get_filesystem().write_contents(
manifest_path, Json::stringify(serialize_manifest(manifest_scf), {}), VCPKG_LINE_INFO);
manifest->path, Json::stringify(serialize_manifest(manifest_scf), {}), VCPKG_LINE_INFO);
msg::println(msgAddPortSucceded);
auto metrics = LockGuardPtr<Metrics>(g_metrics);

Просмотреть файл

@ -33,6 +33,7 @@
#include <vcpkg/commands.regenerate.h>
#include <vcpkg/commands.search.h>
#include <vcpkg/commands.setinstalled.h>
#include <vcpkg/commands.update-baseline.h>
#include <vcpkg/commands.upgrade.h>
#include <vcpkg/commands.upload-metrics.h>
#include <vcpkg/commands.use.h>
@ -103,6 +104,7 @@ namespace vcpkg::Commands
static const RegenerateCommand regenerate{};
static const SearchCommand search{};
static const Update::UpdateCommand update{};
static const UpdateBaselineCommand update_baseline{};
static const UseCommand use{};
static const X_VSInstances::VSInstancesCommand vsinstances{};
static const ZCeCommand ce{};
@ -126,6 +128,7 @@ namespace vcpkg::Commands
{"portsdiff", &portsdiff},
{"search", &search},
{"update", &update},
{"x-update-baseline", &update_baseline},
{"use", &use},
{"x-add-version", &add_version},
{"x-ci-clean", &ciclean},

Просмотреть файл

@ -0,0 +1,167 @@
#include <vcpkg/base/files.h>
#include <vcpkg/base/messages.h>
#include <vcpkg/commands.update-baseline.h>
#include <vcpkg/configuration.h>
#include <vcpkg/vcpkgcmdarguments.h>
#include <vcpkg/vcpkgpaths.h>
namespace
{
using namespace vcpkg;
DECLARE_AND_REGISTER_MESSAGE(UpdateBaselineNoConfiguration,
(),
"",
"neither `vcpkg.json` nor `vcpkg-configuration.json` exist to update.");
DECLARE_AND_REGISTER_MESSAGE(UpdateBaselineNoExistingBuiltinBaseline,
(msg::option),
"",
"the manifest file currently does not contain a `builtin-baseline` field; in order to "
"add one, pass the --{option} switch.");
DECLARE_AND_REGISTER_MESSAGE(
UpdateBaselineAddBaselineNoManifest,
(msg::option),
"",
"the --{option} switch was passed, but there is no manifest file to add a `builtin-baseline` field to.");
DECLARE_AND_REGISTER_MESSAGE(UpdateBaselineUpdatedBaseline,
(msg::url, msg::old_value, msg::new_value),
"example of {old_value}, {new_value} is '5507daa796359fe8d45418e694328e878ac2b82f'",
"updated registry '{url}': baseline '{old_value}' -> '{new_value}'");
DECLARE_AND_REGISTER_MESSAGE(UpdateBaselineNoUpdate,
(msg::url, msg::value),
"example of {value} is '5507daa796359fe8d45418e694328e878ac2b82f'",
"registry '{url}' not updated: '{value}'");
}
namespace vcpkg::Commands
{
static constexpr StringLiteral OPTION_ADD_INITIAL_BASELINE = "add-initial-baseline";
static constexpr StringLiteral OPTION_DRY_RUN = "dry-run";
static constexpr CommandSwitch switches[] = {
{OPTION_ADD_INITIAL_BASELINE, "add a `builtin-baseline` to a vcpkg.json that doesn't already have it"},
{OPTION_DRY_RUN, "Print out plan without execution"},
};
static const CommandStructure COMMAND_STRUCTURE{
create_example_string("x-update-baseline"),
0,
0,
{switches},
};
static void update_baseline_in_config(const VcpkgPaths& paths, RegistryConfig& reg)
{
auto url = reg.pretty_location();
auto new_baseline_res = reg.get_latest_baseline(paths);
if (auto new_baseline = new_baseline_res.get())
{
if (*new_baseline != reg.baseline)
{
msg::println(msgUpdateBaselineUpdatedBaseline,
msg::url = url,
msg::old_value = reg.baseline.value_or(""),
msg::new_value = new_baseline->value_or(""));
reg.baseline = std::move(*new_baseline);
}
// new_baseline == reg.baseline
else
{
msg::println(msgUpdateBaselineNoUpdate, msg::url = url, msg::value = reg.baseline.value_or(""));
}
return;
}
// this isn't an error, since we want to continue attempting to update baselines
msg::print_warning(
msg::format(msgUpdateBaselineNoUpdate, msg::url = url, msg::value = reg.baseline.value_or(""))
.appendnl()
.append(new_baseline_res.error()));
}
void UpdateBaselineCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
{
auto options = args.parse_arguments(COMMAND_STRUCTURE);
const bool add_builtin_baseline = Util::Sets::contains(options.switches, OPTION_ADD_INITIAL_BASELINE);
const bool dry_run = Util::Sets::contains(options.switches, OPTION_DRY_RUN);
auto configuration = paths.get_configuration();
const bool has_manifest = paths.get_manifest().has_value();
auto manifest = has_manifest ? *paths.get_manifest().get() : ManifestAndPath{};
if (configuration.source == ConfigurationSource::None && !has_manifest)
{
msg::print_warning(msgUpdateBaselineNoConfiguration);
Checks::exit_success(VCPKG_LINE_INFO);
}
bool has_builtin_baseline = manifest.manifest.contains("builtin-baseline");
if (add_builtin_baseline && !has_manifest)
{
Checks::msg_exit_with_error(
VCPKG_LINE_INFO, msgUpdateBaselineAddBaselineNoManifest, msg::option = OPTION_ADD_INITIAL_BASELINE);
}
if (!has_builtin_baseline && !add_builtin_baseline && configuration.source == ConfigurationSource::None)
{
msg::print_warning(msgUpdateBaselineNoExistingBuiltinBaseline, msg::option = OPTION_ADD_INITIAL_BASELINE);
Checks::exit_success(VCPKG_LINE_INFO);
}
if (has_builtin_baseline || add_builtin_baseline)
{
// remove default_reg, since that's filled in with the builtin-baseline
configuration.config.default_reg = nullopt;
RegistryConfig synthesized_registry;
synthesized_registry.kind = "builtin";
if (auto p = manifest.manifest.get("builtin-baseline"))
{
synthesized_registry.baseline = p->string().to_string();
}
update_baseline_in_config(paths, synthesized_registry);
if (auto p = synthesized_registry.baseline.get())
{
manifest.manifest.insert_or_replace("builtin-baseline", std::move(*p));
}
}
if (auto default_reg = configuration.config.default_reg.get())
{
update_baseline_in_config(paths, *default_reg);
}
for (auto& reg : configuration.config.registries)
{
update_baseline_in_config(paths, reg);
}
if (configuration.source == ConfigurationSource::ManifestFile)
{
manifest.manifest.insert_or_replace("vcpkg-configuration", configuration.config.serialize());
}
if (!dry_run && configuration.source == ConfigurationSource::VcpkgConfigurationFile)
{
paths.get_filesystem().write_contents(configuration.directory / "vcpkg-configuration.json",
Json::stringify(configuration.config.serialize(), {}),
VCPKG_LINE_INFO);
}
if (!dry_run && has_manifest)
{
paths.get_filesystem().write_contents(
manifest.path, Json::stringify(manifest.manifest, {}), VCPKG_LINE_INFO);
}
Checks::exit_success(VCPKG_LINE_INFO);
}
}

Просмотреть файл

@ -10,6 +10,15 @@ namespace
{
using namespace vcpkg;
DECLARE_AND_REGISTER_MESSAGE(UpdateBaselineRemoteGitError,
(msg::url),
"",
"git failed to fetch remote repository '{url}'");
DECLARE_AND_REGISTER_MESSAGE(UpdateBaselineLocalGitError,
(msg::path),
"",
"git failed to parse HEAD for the local vcpkg registry at '{path}'");
struct RegistryConfigDeserializer : Json::IDeserializer<RegistryConfig>
{
constexpr static StringLiteral KIND = "kind";
@ -535,6 +544,77 @@ namespace
namespace vcpkg
{
static ExpectedL<Optional<std::string>> get_baseline_from_git_repo(const VcpkgPaths& paths, StringView url)
{
auto res = paths.git_fetch_from_remote_registry(url, "HEAD");
if (auto p = res.get())
{
return Optional<std::string>(std::move(*p));
}
else
{
return msg::format(msgUpdateBaselineRemoteGitError, msg::url = url)
.appendnl()
.append_raw(Strings::trim(res.error()));
}
}
ExpectedL<Optional<std::string>> RegistryConfig::get_latest_baseline(const VcpkgPaths& paths) const
{
if (kind == RegistryConfigDeserializer::KIND_GIT)
{
return get_baseline_from_git_repo(paths, repo.value_or_exit(VCPKG_LINE_INFO));
}
else if (kind == RegistryConfigDeserializer::KIND_BUILTIN)
{
if (paths.use_git_default_registry())
{
return get_baseline_from_git_repo(paths, builtin_registry_git_url());
}
else
{
// use the vcpkg git repository sha from the user's machine
auto res = paths.get_current_git_sha();
if (auto p = res.get())
{
return Optional<std::string>(std::move(*p));
}
else
{
return msg::format(msgUpdateBaselineLocalGitError, msg::path = paths.root)
.appendnl()
.append_raw(Strings::trim(res.error()));
}
}
}
else
{
return baseline;
}
}
StringView RegistryConfig::pretty_location() const
{
if (kind == RegistryConfigDeserializer::KIND_BUILTIN)
{
return builtin_registry_git_url();
}
if (kind == RegistryConfigDeserializer::KIND_FILESYSTEM)
{
return path.value_or_exit(VCPKG_LINE_INFO);
}
if (kind == RegistryConfigDeserializer::KIND_GIT)
{
return repo.value_or_exit(VCPKG_LINE_INFO);
}
if (kind == RegistryConfigDeserializer::KIND_ARTIFACT)
{
return location.value_or_exit(VCPKG_LINE_INFO);
}
Checks::unreachable(VCPKG_LINE_INFO);
}
View<StringView> Configuration::known_fields()
{
static constexpr StringView known_fields[]{

Просмотреть файл

@ -927,7 +927,7 @@ namespace vcpkg::Install
LockGuardPtr<Metrics>(g_metrics)->track_property("install_manifest_mode", paths.manifest_mode_enabled());
if (paths.manifest_mode_enabled())
if (auto p = paths.get_manifest().get())
{
bool failure = false;
if (!args.command_arguments.empty())
@ -948,7 +948,7 @@ namespace vcpkg::Install
}
if (failure)
{
msg::println(msgUsingManifestAt, msg::path = paths.get_manifest_path().value_or_exit(VCPKG_LINE_INFO));
msg::println(msgUsingManifestAt, msg::path = p->path);
print2("\n");
print_usage(MANIFEST_COMMAND_STRUCTURE);
Checks::exit_fail(VCPKG_LINE_INFO);
@ -1018,8 +1018,7 @@ namespace vcpkg::Install
LockGuardPtr<Metrics>(g_metrics)->track_property("x-write-nuget-packages-config", "defined");
pkgsconfig = Path(it_pkgsconfig->second);
}
const auto& manifest_path = paths.get_manifest_path().value_or_exit(VCPKG_LINE_INFO);
auto maybe_manifest_scf = SourceControlFile::parse_manifest_object(manifest_path, *manifest);
auto maybe_manifest_scf = SourceControlFile::parse_manifest_object(manifest->path, manifest->manifest);
if (!maybe_manifest_scf)
{
print_error_message(maybe_manifest_scf.error());
@ -1030,7 +1029,7 @@ namespace vcpkg::Install
auto& manifest_scf = *maybe_manifest_scf.value_or_exit(VCPKG_LINE_INFO);
if (auto maybe_error = manifest_scf.check_against_feature_flags(
manifest_path, paths.get_feature_flags(), paths.get_registry_set().is_default_builtin_registry()))
manifest->path, paths.get_feature_flags(), paths.get_registry_set().is_default_builtin_registry()))
{
Checks::exit_with_message(VCPKG_LINE_INFO, maybe_error.value_or_exit(VCPKG_LINE_INFO));
}
@ -1096,7 +1095,7 @@ namespace vcpkg::Install
std::vector<std::string> extended_overlay_ports;
extended_overlay_ports.reserve(args.overlay_ports.size() + 2);
extended_overlay_ports.push_back(manifest_path.parent_path().to_string());
extended_overlay_ports.push_back(manifest->path.parent_path().to_string());
Util::Vectors::append(&extended_overlay_ports, args.overlay_ports);
if (paths.get_registry_set().is_default_builtin_registry() && !paths.use_git_default_registry())
{

Просмотреть файл

@ -1246,7 +1246,7 @@ namespace vcpkg
if (paths.use_git_default_registry())
{
return std::make_unique<GitRegistry>(
paths, "https://github.com/Microsoft/vcpkg", "HEAD", std::move(baseline));
paths, builtin_registry_git_url().to_string(), "HEAD", std::move(baseline));
}
else
{

Просмотреть файл

@ -60,7 +60,7 @@ namespace
namespace vcpkg
{
static std::pair<Json::Object, Json::JsonStyle> load_manifest(const Filesystem& fs, const Path& manifest_dir)
static ManifestAndPath load_manifest(const Filesystem& fs, const Path& manifest_dir)
{
std::error_code ec;
auto manifest_path = manifest_dir / "vcpkg.json";
@ -86,15 +86,15 @@ namespace vcpkg
": Manifest files must have a top-level object\n");
Checks::exit_fail(VCPKG_LINE_INFO);
}
return {std::move(manifest_value.first.object()), std::move(manifest_value.second)};
return {std::move(manifest_value.first.object()), std::move(manifest_path)};
}
static Optional<ManifestConfiguration> config_from_manifest(
const Path& manifest_path, const Optional<std::pair<Json::Object, Json::JsonStyle>>& manifest_doc)
static Optional<ManifestConfiguration> config_from_manifest(const Path& manifest_path,
const Optional<ManifestAndPath>& manifest_doc)
{
if (auto manifest = manifest_doc.get())
{
return parse_manifest_configuration(manifest_path, manifest->first).value_or_exit(VCPKG_LINE_INFO);
return parse_manifest_configuration(manifest_path, manifest->manifest).value_or_exit(VCPKG_LINE_INFO);
}
return nullopt;
}
@ -131,13 +131,13 @@ namespace vcpkg
return parsed_config_opt;
}
static Configuration merge_validate_configs(Optional<ManifestConfiguration>&& manifest_data,
const Path& manifest_dir,
Optional<Configuration>&& config_data,
const Path& config_dir,
const VcpkgPaths& paths)
static ConfigurationAndSource merge_validate_configs(Optional<ManifestConfiguration>&& manifest_data,
const Path& manifest_dir,
Optional<Configuration>&& config_data,
const Path& config_dir,
const VcpkgPaths& paths)
{
Configuration ret;
ConfigurationAndSource ret;
if (auto manifest = manifest_data.get())
{
@ -169,7 +169,7 @@ namespace vcpkg
Checks::exit_fail(VCPKG_LINE_INFO);
}
ret = std::move(*config);
ret = ConfigurationAndSource{std::move(*config), config_dir, ConfigurationSource::ManifestFile};
}
}
@ -177,7 +177,7 @@ namespace vcpkg
{
config->validate_as_active();
ret = std::move(*config);
ret = ConfigurationAndSource{std::move(*config), config_dir, ConfigurationSource::VcpkgConfigurationFile};
}
if (auto manifest = manifest_data.get())
@ -195,7 +195,7 @@ namespace vcpkg
paths.get_current_git_sha_baseline_message());
}
if (ret.default_reg)
if (ret.config.default_reg)
{
print2(Color::warning,
"warning: attempting to set builtin-baseline in vcpkg.json while overriding the "
@ -204,7 +204,7 @@ namespace vcpkg
}
else
{
auto& default_reg = ret.default_reg.emplace();
auto& default_reg = ret.config.default_reg.emplace();
default_reg.kind = "builtin";
default_reg.baseline = std::move(*p_baseline);
}
@ -436,6 +436,7 @@ namespace vcpkg
VcpkgPathsImpl(Filesystem& fs, const VcpkgCmdArguments& args, const Path& root, const Path& original_cwd)
: VcpkgPathsImplStage1(fs, args, root, original_cwd)
, m_config_dir(m_manifest_dir.empty() ? root : m_manifest_dir)
, m_has_configuration_file(fs.exists(m_config_dir / "vcpkg-configuration.json", VCPKG_LINE_INFO))
, m_manifest_path(m_manifest_dir.empty() ? Path{} : m_manifest_dir / "vcpkg.json")
, m_registries_work_tree_dir(m_cache_root / "git")
, m_registries_dot_git_dir(m_cache_root / "git" / ".git")
@ -501,6 +502,7 @@ namespace vcpkg
}
const Path m_config_dir;
const bool m_has_configuration_file;
const Path m_manifest_path;
const Path m_registries_work_tree_dir;
const Path m_registries_dot_git_dir;
@ -513,8 +515,8 @@ namespace vcpkg
std::unique_ptr<IExclusiveFileLock> file_lock_handle;
Optional<std::pair<Json::Object, Json::JsonStyle>> m_manifest_doc;
Configuration m_config;
Optional<ManifestAndPath> m_manifest_doc;
ConfigurationAndSource m_config;
std::unique_ptr<RegistrySet> m_registry_set;
};
}
@ -662,7 +664,7 @@ namespace vcpkg
m_pimpl->m_config_dir,
*this);
m_pimpl->m_registry_set = m_pimpl->m_config.instantiate_registry_set(*this, m_pimpl->m_config_dir);
m_pimpl->m_registry_set = m_pimpl->m_config.instantiate_registry_set(*this);
}
// metrics from configuration
@ -1275,29 +1277,17 @@ namespace vcpkg
}
}
Optional<const Json::Object&> VcpkgPaths::get_manifest() const
Optional<const ManifestAndPath&> VcpkgPaths::get_manifest() const
{
if (auto p = m_pimpl->m_manifest_doc.get())
{
return p->first;
}
else
{
return nullopt;
}
}
Optional<const Path&> VcpkgPaths::get_manifest_path() const
{
if (m_pimpl->m_manifest_doc)
{
return m_pimpl->m_manifest_path;
}
else
{
return nullopt;
return *p;
}
return nullopt;
}
const ConfigurationAndSource& VcpkgPaths::get_configuration() const { return m_pimpl->m_config; }
const RegistrySet& VcpkgPaths::get_registry_set() const
{
Checks::check_exit(VCPKG_LINE_INFO, m_pimpl->m_registry_set != nullptr);