Skip to content

Commit

Permalink
manifest install: Add option to check stamp file
Browse files Browse the repository at this point in the history
  • Loading branch information
autoantwort committed Feb 18, 2022
1 parent f21b866 commit 372a6f7
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 39 deletions.
1 change: 1 addition & 0 deletions include/vcpkg/base/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace vcpkg::Hash

struct Hasher
{
void add_bytes(StringView data);
virtual void add_bytes(const void* start, const void* end) noexcept = 0;

// one may only call this once before calling `clear()` or the dtor
Expand Down
18 changes: 9 additions & 9 deletions include/vcpkg/commands.setinstalled.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
namespace vcpkg::Commands::SetInstalled
{
extern const CommandStructure COMMAND_STRUCTURE;
void perform_and_exit_ex(const VcpkgCmdArguments& args,
const VcpkgPaths& paths,
const PortFileProvider::PathsPortFileProvider& provider,
BinaryCache& binary_cache,
const CMakeVars::CMakeVarProvider& cmake_vars,
Dependencies::ActionPlan action_plan,
DryRun dry_run,
const Optional<Path>& pkgsconfig_path,
Triplet host_triplet);
void perform_ex(const VcpkgCmdArguments& args,
const VcpkgPaths& paths,
const PortFileProvider::PathsPortFileProvider& provider,
BinaryCache& binary_cache,
const CMakeVars::CMakeVarProvider& cmake_vars,
Dependencies::ActionPlan action_plan,
DryRun dry_run,
const Optional<Path>& pkgsconfig_path,
Triplet host_triplet);
void perform_and_exit(const VcpkgCmdArguments& args,
const VcpkgPaths& paths,
Triplet default_triplet,
Expand Down
1 change: 1 addition & 0 deletions include/vcpkg/installedpaths.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace vcpkg
Path vcpkg_dir_info() const { return vcpkg_dir() / "info"; }
Path vcpkg_dir_updates() const { return vcpkg_dir() / "updates"; }
Path lockfile_path() const { return vcpkg_dir() / "vcpkg-lock.json"; }
Path hashfile_path() const { return vcpkg_dir() / "hash.txt"; }
Path triplet_dir(Triplet t) const { return m_root / t.canonical_name(); }
Path share_dir(const PackageSpec& p) const { return triplet_dir(p.triplet()) / "share" / p.name(); }
Path usage_file(const PackageSpec& p) const { return share_dir(p) / "usage"; }
Expand Down
1 change: 1 addition & 0 deletions include/vcpkg/vcpkgpaths.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ namespace vcpkg
const std::string& get_triplet_info(const Build::AbiInfo& abi_info) const;
const Build::CompilerInfo& get_compiler_info(const Build::AbiInfo& abi_info) const;
bool manifest_mode_enabled() const { return get_manifest().has_value(); }
std::string get_configuration_hash() const;

const FeatureFlagSettings& get_feature_flags() const;
void track_feature_flag_metrics() const;
Expand Down
1 change: 1 addition & 0 deletions locales/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"ProcessorArchitectureMissing": "The required environment variable %PROCESSOR_ARCHITECTURE% is missing.",
"ProcessorArchitectureW6432Malformed": "Failed to parse %PROCESSOR_ARCHITEW6432% ({value}) as a valid CPU architecture. Falling back to %PROCESSOR_ARCHITECTURE%.",
"SeeURL": "See {url} for more information.",
"StampNotChanged": "Installation skipped. Everything seems to be installed. To disable this check, don't pass the option `--{value}` to vcpkg.",
"UnsupportedSystemName": "Error: Could not map VCPKG_CMAKE_SYSTEM_NAME '{value}' 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 {value}\n The selected Visual Studio instance is at {path}\n The available toolchain combinations are {list}\n",
"UsingManifestAt": "Using manifest file at {path}.",
Expand Down
2 changes: 2 additions & 0 deletions src/vcpkg/base/hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ namespace vcpkg::Hash
}
}

void Hasher::add_bytes(StringView data) { add_bytes(data.data(), data.data() + data.size()); }

template<class UIntTy>
auto top_bits(UIntTy x) -> std::enable_if_t<std::is_unsigned<UIntTy>::value, uchar>
{
Expand Down
39 changes: 19 additions & 20 deletions src/vcpkg/commands.setinstalled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ namespace vcpkg::Commands::SetInstalled
nullptr,
};

void perform_and_exit_ex(const VcpkgCmdArguments& args,
const VcpkgPaths& paths,
const PortFileProvider::PathsPortFileProvider& provider,
BinaryCache& binary_cache,
const CMakeVars::CMakeVarProvider& cmake_vars,
Dependencies::ActionPlan action_plan,
DryRun dry_run,
const Optional<Path>& maybe_pkgsconfig,
Triplet host_triplet)
void perform_ex(const VcpkgCmdArguments& args,
const VcpkgPaths& paths,
const PortFileProvider::PathsPortFileProvider& provider,
BinaryCache& binary_cache,
const CMakeVars::CMakeVarProvider& cmake_vars,
Dependencies::ActionPlan action_plan,
DryRun dry_run,
const Optional<Path>& maybe_pkgsconfig,
Triplet host_triplet)
{
auto& fs = paths.get_filesystem();

Expand Down Expand Up @@ -136,8 +136,6 @@ namespace vcpkg::Commands::SetInstalled
Install::print_usage_information(it->get()->package, printed_usages, fs, paths.installed());
}
}

Checks::exit_success(VCPKG_LINE_INFO);
}

void perform_and_exit(const VcpkgCmdArguments& args,
Expand Down Expand Up @@ -178,15 +176,16 @@ namespace vcpkg::Commands::SetInstalled
action.build_options = Build::default_build_package_options;
}

perform_and_exit_ex(args,
paths,
provider,
binary_cache,
*cmake_vars,
std::move(action_plan),
dry_run ? DryRun::Yes : DryRun::No,
pkgsconfig,
host_triplet);
perform_ex(args,
paths,
provider,
binary_cache,
*cmake_vars,
std::move(action_plan),
dry_run ? DryRun::Yes : DryRun::No,
pkgsconfig,
host_triplet);
Checks::exit_success(VCPKG_LINE_INFO);
}

void SetInstalledCommand::perform_and_exit(const VcpkgCmdArguments& args,
Expand Down
86 changes: 76 additions & 10 deletions src/vcpkg/install.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ namespace vcpkg::Install
static constexpr StringLiteral OPTION_RECURSE = "recurse";
static constexpr StringLiteral OPTION_KEEP_GOING = "keep-going";
static constexpr StringLiteral OPTION_EDITABLE = "editable";
static constexpr StringLiteral OPTION_CHECK_STAMP = "check-stamp";
static constexpr StringLiteral OPTION_XUNIT = "x-xunit";
static constexpr StringLiteral OPTION_USE_ARIA2 = "x-use-aria2";
static constexpr StringLiteral OPTION_CLEAN_AFTER_BUILD = "clean-after-build";
Expand All @@ -523,7 +524,7 @@ namespace vcpkg::Install
static constexpr StringLiteral OPTION_ENFORCE_PORT_CHECKS = "enforce-port-checks";
static constexpr StringLiteral OPTION_ALLOW_UNSUPPORTED_PORT = "allow-unsupported";

static constexpr std::array<CommandSwitch, 17> INSTALL_SWITCHES = {{
static constexpr std::array<CommandSwitch, 18> INSTALL_SWITCHES = {{
{OPTION_DRY_RUN, "Do not actually build or install"},
{OPTION_USE_HEAD_VERSION,
"Install the libraries on the command line using the latest upstream sources (classic mode)"},
Expand All @@ -534,6 +535,9 @@ namespace vcpkg::Install
{OPTION_KEEP_GOING, "Continue installing packages on failure"},
{OPTION_EDITABLE,
"Disable source re-extraction and binary caching for libraries on the command line (classic mode)"},
{OPTION_CHECK_STAMP,
"If the configuration (triplets, manifest file, registries, selected features) is the same as the last time "
"install is skipped. Local port modifications are not detected anymore."},

{OPTION_USE_ARIA2, "Use aria2 to perform download tasks"},
{OPTION_CLEAN_AFTER_BUILD, "Clean buildtrees, packages and downloads after building each package"},
Expand Down Expand Up @@ -795,6 +799,12 @@ namespace vcpkg::Install
"",
"Error: The option {value} is not supported in manifest mode.");

DECLARE_AND_REGISTER_MESSAGE(StampNotChanged,
(msg::value),
"",
"Installation skipped. Everything seems to be installed. To disable this check, don't "
"pass the option `--{value}` to vcpkg.");

void perform_and_exit(const VcpkgCmdArguments& args,
const VcpkgPaths& paths,
Triplet default_triplet,
Expand All @@ -810,6 +820,7 @@ namespace vcpkg::Install
const bool no_build_missing = Util::Sets::contains(options.switches, OPTION_ONLY_BINARYCACHING);
const bool is_recursive = Util::Sets::contains(options.switches, (OPTION_RECURSE));
const bool is_editable = Util::Sets::contains(options.switches, (OPTION_EDITABLE)) || !args.cmake_args.empty();
const bool check_stamp = Util::Sets::contains(options.switches, (OPTION_CHECK_STAMP));
const bool use_aria2 = Util::Sets::contains(options.switches, (OPTION_USE_ARIA2));
const bool clean_after_build = Util::Sets::contains(options.switches, (OPTION_CLEAN_AFTER_BUILD));
const bool clean_buildtrees_after_build =
Expand Down Expand Up @@ -873,6 +884,13 @@ namespace vcpkg::Install
msg::value = Strings::concat("--", OPTION_MANIFEST_NO_DEFAULT_FEATURES));
failure = true;
}
if (Util::Sets::contains(options.switches, OPTION_CHECK_STAMP))
{
msg::println(Color::error,
msgErrorInvalidClassicModeOption,
msg::value = Strings::concat("--", OPTION_CHECK_STAMP));
failure = true;
}
if (Util::Sets::contains(options.multisettings, OPTION_MANIFEST_FEATURE))
{
msg::println(Color::error,
Expand Down Expand Up @@ -1009,6 +1027,50 @@ namespace vcpkg::Install
{
extended_overlay_ports.push_back(paths.builtin_ports_directory().native());
}

std::string hash;
{
auto timer = ElapsedTimer::create_started();
auto hasher = Hash::get_hasher_for(Hash::Algorithm::Sha256);
for (auto&& path : args.overlay_ports)
{
for (auto&& file : fs.get_regular_files_recursive(path, VCPKG_LINE_INFO))
{
hasher->add_bytes(fs.read_contents(file, VCPKG_LINE_INFO));
}
}
hasher->add_bytes(paths.get_configuration_hash());
hasher->add_bytes(Json::stringify(*manifest, Json::JsonStyle{}.with_spaces(0)));
hasher->add_bytes(default_triplet.to_string());
hasher->add_bytes(host_triplet.to_string());
hasher->add_bytes(fs.read_contents(paths.get_triplet_file_path(default_triplet), VCPKG_LINE_INFO));
hasher->add_bytes(fs.read_contents(paths.get_triplet_file_path(host_triplet), VCPKG_LINE_INFO));
hasher->add_bytes(fs.read_contents(paths.get_triplet_file_path(host_triplet), VCPKG_LINE_INFO));
for (const auto& feature : features)
{
hasher->add_bytes(feature);
}
if (paths.get_registry_set().is_default_builtin_registry())
{
auto maybe_git_sha = paths.get_current_git_sha();
if (maybe_git_sha)
{
hasher->add_bytes(maybe_git_sha.value_or_exit(VCPKG_LINE_INFO));
}
}
Debug::print("Time needed to compute hash for stamp: ", timer.elapsed().to_string(), "\n");
hash = hasher->get_hash();
if (fs.exists(paths.installed().hashfile_path(), VCPKG_LINE_INFO))
{
if (check_stamp && fs.read_contents(paths.installed().hashfile_path(), VCPKG_LINE_INFO) == hash)
{
msg::println(msgStampNotChanged, msg::value = OPTION_CHECK_STAMP);
Checks::exit_success(VCPKG_LINE_INFO);
}
fs.remove(paths.installed().hashfile_path(), VCPKG_LINE_INFO);
}
}

auto oprovider = PortFileProvider::make_overlay_provider(paths, extended_overlay_ports);
PackageSpec toplevel{manifest_scf.core_paragraph->name, default_triplet};
auto install_plan = Dependencies::create_versioned_install_plan(*verprovider,
Expand All @@ -1021,6 +1083,7 @@ namespace vcpkg::Install
host_triplet,
unsupported_port_action)
.value_or_exit(VCPKG_LINE_INFO);

for (const auto& warning : install_plan.warnings)
{
print2(Color::warning, warning, '\n');
Expand All @@ -1038,15 +1101,18 @@ namespace vcpkg::Install

PortFileProvider::PathsPortFileProvider provider(paths, extended_overlay_ports);

Commands::SetInstalled::perform_and_exit_ex(args,
paths,
provider,
binary_cache,
var_provider,
std::move(install_plan),
dry_run ? Commands::DryRun::Yes : Commands::DryRun::No,
pkgsconfig,
host_triplet);
Commands::SetInstalled::perform_ex(args,
paths,
provider,
binary_cache,
var_provider,
std::move(install_plan),
dry_run ? Commands::DryRun::Yes : Commands::DryRun::No,
pkgsconfig,
host_triplet);

fs.write_contents_and_dirs(paths.installed().hashfile_path(), hash, VCPKG_LINE_INFO);
Checks::exit_success(VCPKG_LINE_INFO);
}

PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
Expand Down
6 changes: 6 additions & 0 deletions src/vcpkg/vcpkgpaths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1440,6 +1440,12 @@ namespace vcpkg
return m_pimpl->m_env_cache.get_compiler_info(*this, abi_info);
}
std::string VcpkgPaths::get_configuration_hash() const
{
return Hash::get_string_hash(Json::stringify(m_pimpl->m_config.serialize(), Json::JsonStyle{}.with_spaces(0)),
Hash::Algorithm::Sha512);
}
Filesystem& VcpkgPaths::get_filesystem() const { return m_pimpl->m_fs; }
bool VcpkgPaths::use_git_default_registry() const { return m_pimpl->m_bundle.m_usegitregistry; }
Expand Down

0 comments on commit 372a6f7

Please sign in to comment.