Skip to content

Commit

Permalink
[vcpkg manifests] fix some issues (microsoft#12227)
Browse files Browse the repository at this point in the history
  • Loading branch information
strega-nil committed Jul 9, 2020
1 parent 3de0ebe commit e308846
Show file tree
Hide file tree
Showing 14 changed files with 187 additions and 63 deletions.
3 changes: 3 additions & 0 deletions include/vcpkg/base/files.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ namespace vcpkg::Files
virtual void current_path(const fs::path& path, std::error_code&) = 0;
void current_path(const fs::path& path, LineInfo li);

// waits forever for the file lock
virtual fs::SystemHandle take_exclusive_file_lock(const fs::path& path, std::error_code&) = 0;
// waits, at most, 1.5 seconds, for the file lock
virtual fs::SystemHandle try_take_exclusive_file_lock(const fs::path& path, std::error_code&) = 0;
virtual void unlock_file_lock(fs::SystemHandle handle, std::error_code&) = 0;

Expand Down
4 changes: 4 additions & 0 deletions include/vcpkg/vcpkgcmdarguments.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ namespace vcpkg
constexpr static StringLiteral PRINT_METRICS_SWITCH = "printmetrics";
Optional<bool> print_metrics = nullopt;

constexpr static StringLiteral WAIT_FOR_LOCK_SWITCH = "x-wait-for-lock";
Optional<bool> wait_for_lock = nullopt;

// feature flags
constexpr static StringLiteral FEATURE_FLAGS_ENV = "VCPKG_FEATURE_FLAGS";
constexpr static StringLiteral FEATURE_FLAGS_ARG = "feature-flags";
Expand All @@ -175,6 +178,7 @@ namespace vcpkg

void check_feature_flag_consistency() const;

void debug_print_feature_flags() const;
void track_feature_flag_metrics() const;

private:
Expand Down
13 changes: 7 additions & 6 deletions include/vcpkg/versiont.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@ namespace vcpkg
struct VersionT
{
VersionT() noexcept;
VersionT(std::string&& value);
VersionT(const std::string& value);
VersionT(std::string&& value, int port_version);
VersionT(const std::string& value, int port_version);

const std::string& to_string() const;
std::string to_string() const;

friend bool operator==(const VersionT& left, const VersionT& right);
friend bool operator!=(const VersionT& left, const VersionT& right);

private:
std::string value;
int port_version;
};

bool operator==(const VersionT& left, const VersionT& right);
bool operator!=(const VersionT& left, const VersionT& right);

struct VersionDiff
{
VersionT left;
Expand Down
1 change: 1 addition & 0 deletions src/vcpkg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ int main(const int argc, const char* const* const argv)
"Warning: passed either --printmetrics or --no-printmetrics, but metrics are disabled.\n");
}

args.debug_print_feature_flags();
args.track_feature_flag_metrics();

if (Debug::g_debugging)
Expand Down
97 changes: 74 additions & 23 deletions src/vcpkg/base/files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -874,15 +874,22 @@ namespace vcpkg::Files
fs::stdfs::current_path(path, ec);
}

virtual fs::SystemHandle try_take_exclusive_file_lock(const fs::path& path, std::error_code& ec) override
struct TakeExclusiveFileLockHelper
{
fs::SystemHandle res;
fs::SystemHandle& res;
const fs::path::string_type& native;
TakeExclusiveFileLockHelper(fs::SystemHandle& res, const fs::path::string_type& native)
: res(res), native(native)
{
}

const auto system_file_name = path.native();
#if defined(WIN32)
constexpr static auto busy_error = ERROR_BUSY;
const auto system_try_take_file_lock = [&] {
auto handle = CreateFileW(system_file_name.c_str(),
void assign_busy_error(std::error_code& ec) { ec.assign(ERROR_BUSY, std::system_category()); }

bool operator()(std::error_code& ec)
{
ec.clear();
auto handle = CreateFileW(native.c_str(),
GENERIC_READ,
0 /* no sharing */,
nullptr /* no security attributes */,
Expand All @@ -901,31 +908,77 @@ namespace vcpkg::Files

res.system_handle = reinterpret_cast<intptr_t>(handle);
return true;
};
}
#else // ^^^ WIN32 / !WIN32 vvv
constexpr static auto busy_error = EBUSY;
int fd = open(system_file_name.c_str(), 0);
if (fd < 0)
int fd = -1;

void assign_busy_error(std::error_code& ec) { ec.assign(EBUSY, std::generic_category()); }

bool operator()(std::error_code& ec)
{
ec.assign(errno, std::system_category());
return res;
}
const auto system_try_take_file_lock = [&] {
if (flock(fd, LOCK_EX | LOCK_NB) != 0)
ec.clear();
if (fd == -1)
{
fd = ::open(native.c_str(), 0);
if (fd < 0)
{
ec.assign(errno, std::generic_category());
return false;
}
}

if (::flock(fd, LOCK_EX | LOCK_NB) != 0)
{
if (errno != EWOULDBLOCK)
{
ec.assign(errno, std::system_category());
ec.assign(errno, std::generic_category());
}
return false;
}

res.system_handle = fd;
fd = -1;
return true;
};

~TakeExclusiveFileLockHelper()
{
if (fd != -1)
{
::close(fd);
}
}
#endif
};

if (system_try_take_file_lock() || ec)
virtual fs::SystemHandle take_exclusive_file_lock(const fs::path& path, std::error_code& ec) override
{
fs::SystemHandle res;
TakeExclusiveFileLockHelper helper(res, path.native());

if (helper(ec) || ec)
{
return res;
}

System::printf("Waiting to take filesystem lock on %s...\n", path.u8string());
const auto wait = std::chrono::milliseconds(1000);
for (;;)
{
std::this_thread::sleep_for(wait);
if (helper(ec) || ec)
{
return res;
}
}
}

virtual fs::SystemHandle try_take_exclusive_file_lock(const fs::path& path, std::error_code& ec) override
{
fs::SystemHandle res;
TakeExclusiveFileLockHelper helper(res, path.native());

if (helper(ec) || ec)
{
return res;
}
Expand All @@ -936,19 +989,17 @@ namespace vcpkg::Files
while (wait < std::chrono::milliseconds(1000))
{
std::this_thread::sleep_for(wait);
if (system_try_take_file_lock() || ec)
if (helper(ec) || ec)
{
return res;
}
wait *= 2;
}

#if !defined(WIN32)
close(fd);
#endif
ec.assign(busy_error, std::system_category());
helper.assign_busy_error(ec);
return res;
}

virtual void unlock_file_lock(fs::SystemHandle handle, std::error_code& ec) override
{
#if defined(WIN32)
Expand All @@ -959,7 +1010,7 @@ namespace vcpkg::Files
#else
if (flock(handle.system_handle, LOCK_UN) != 0 || close(handle.system_handle) != 0)
{
ec.assign(errno, std::system_category());
ec.assign(errno, std::generic_category());
}
#endif
}
Expand Down
6 changes: 4 additions & 2 deletions src/vcpkg/commands.list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <vcpkg/commands.h>
#include <vcpkg/help.h>
#include <vcpkg/vcpkglib.h>
#include <vcpkg/versiont.h>

namespace vcpkg::Commands::List
{
Expand All @@ -12,11 +13,12 @@ namespace vcpkg::Commands::List

static void do_print(const StatusParagraph& pgh, const bool full_desc)
{
auto full_version = VersionT(pgh.package.version, pgh.package.port_version).to_string();
if (full_desc)
{
System::printf("%-50s %-16s %s\n",
pgh.package.displayname(),
pgh.package.version,
full_version,
Strings::join("\n ", pgh.package.description));
}
else
Expand All @@ -28,7 +30,7 @@ namespace vcpkg::Commands::List
}
System::printf("%-50s %-16s %s\n",
vcpkg::shorten_text(pgh.package.displayname(), 50),
vcpkg::shorten_text(pgh.package.version, 16),
vcpkg::shorten_text(full_version, 16),
vcpkg::shorten_text(description, 51));
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/vcpkg/commands.porthistory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,14 @@ namespace vcpkg::Commands::PortHistory
const std::string cmd = Strings::format(R"(show %s:ports/%s/CONTROL)", commit_id, port_name);
auto output = run_git_command(paths, cmd);

const auto version = Strings::find_at_most_one_enclosed(output.output, "Version: ", "\n");
const auto version = Strings::find_at_most_one_enclosed(output.output, "\nVersion: ", "\n");
const auto port_version = Strings::find_at_most_one_enclosed(output.output, "\nPort-Version: ", "\n");
Checks::check_exit(VCPKG_LINE_INFO, version.has_value(), "CONTROL file does not have a 'Version' field");
if (auto pv = port_version.get())
{
return Strings::format("%s#%s", version.get()->to_string(), pv->to_string());
}

return version.get()->to_string();
}

Expand Down
5 changes: 4 additions & 1 deletion src/vcpkg/commands.portsdiff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,10 @@ namespace vcpkg::Commands::PortsDiff
Paragraphs::load_all_ports(paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string);
std::map<std::string, VersionT> names_and_versions;
for (auto&& port : all_ports)
names_and_versions.emplace(port->core_paragraph->name, port->core_paragraph->version);
{
const auto& core_pgh = *port->core_paragraph;
names_and_versions.emplace(port->core_paragraph->name, VersionT(core_pgh.version, core_pgh.port_version));
}
fs.remove_all(temp_checkout_path, VCPKG_LINE_INFO);
return names_and_versions;
}
Expand Down
6 changes: 4 additions & 2 deletions src/vcpkg/commands.search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <vcpkg/paragraphs.h>
#include <vcpkg/sourceparagraph.h>
#include <vcpkg/vcpkglib.h>
#include <vcpkg/versiont.h>

using vcpkg::PortFileProvider::PathsPortFileProvider;

Expand All @@ -18,11 +19,12 @@ namespace vcpkg::Commands::Search

static void do_print(const SourceParagraph& source_paragraph, bool full_desc)
{
auto full_version = VersionT(source_paragraph.version, source_paragraph.port_version).to_string();
if (full_desc)
{
System::printf("%-20s %-16s %s\n",
source_paragraph.name,
source_paragraph.version,
full_version,
Strings::join("\n ", source_paragraph.description));
}
else
Expand All @@ -34,7 +36,7 @@ namespace vcpkg::Commands::Search
}
System::printf("%-20s %-16s %s\n",
vcpkg::shorten_text(source_paragraph.name, 20),
vcpkg::shorten_text(source_paragraph.version, 16),
vcpkg::shorten_text(full_version, 16),
vcpkg::shorten_text(description, 81));
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/vcpkg/install.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,8 +726,10 @@ namespace vcpkg::Install
{
for (auto& dep : (*val)->core_paragraph->dependencies)
{
specs.push_back(Input::check_and_get_full_package_spec(
std::move(dep.name), default_triplet, COMMAND_STRUCTURE.example_text));
specs.push_back(FullPackageSpec{
{std::move(dep.name), default_triplet},
std::move(dep.features),
});
}
}
else
Expand Down
10 changes: 6 additions & 4 deletions src/vcpkg/update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ namespace vcpkg::Update
auto maybe_scfl = provider.get_control_file(pgh->package.spec.name());
if (auto p_scfl = maybe_scfl.get())
{
auto&& port_version = p_scfl->source_control_file->core_paragraph->version;
auto&& installed_version = pgh->package.version;
if (installed_version != port_version)
const auto& latest_pgh = *p_scfl->source_control_file->core_paragraph;
auto latest_version = VersionT(latest_pgh.version, latest_pgh.port_version);
auto installed_version = VersionT(pgh->package.version, pgh->package.port_version);
if (latest_version != installed_version)
{
output.push_back({pgh->package.spec, VersionDiff(installed_version, port_version)});
output.push_back(
{pgh->package.spec, VersionDiff(std::move(installed_version), std::move(latest_version))});
}
}
else
Expand Down
31 changes: 30 additions & 1 deletion src/vcpkg/vcpkgcmdarguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ namespace vcpkg
{PRINT_METRICS_SWITCH, &VcpkgCmdArguments::print_metrics},
{FEATURE_PACKAGES_SWITCH, &VcpkgCmdArguments::feature_packages},
{BINARY_CACHING_SWITCH, &VcpkgCmdArguments::binary_caching},
{WAIT_FOR_LOCK_SWITCH, &VcpkgCmdArguments::wait_for_lock},
};

bool found = false;
Expand Down Expand Up @@ -677,13 +678,41 @@ namespace vcpkg
}
}

void VcpkgCmdArguments::debug_print_feature_flags() const
{
struct
{
StringView name;
Optional<bool> flag;
} flags[] = {
{BINARY_CACHING_FEATURE, binary_caching},
{MANIFEST_MODE_FEATURE, manifest_mode},
{COMPILER_TRACKING_FEATURE, compiler_tracking},
};

for (const auto& flag : flags)
{
if (auto r = flag.flag.get())
{
Debug::print("Feature flag '", flag.name, "' = ", *r ? "on" : "off", "\n");
}
else
{
Debug::print("Feature flag '", flag.name, "' unset\n");
}
}
}

void VcpkgCmdArguments::track_feature_flag_metrics() const
{
struct
{
StringView flag;
bool enabled;
} flags[] = {{BINARY_CACHING_FEATURE, binary_caching_enabled()}};
} flags[] = {
{BINARY_CACHING_FEATURE, binary_caching_enabled()},
{COMPILER_TRACKING_FEATURE, compiler_tracking_enabled()},
};

for (const auto& flag : flags)
{
Expand Down
Loading

0 comments on commit e308846

Please sign in to comment.