Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
28 changes: 17 additions & 11 deletions include/vcpkg/archives.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,36 @@ namespace vcpkg
};

// Extract `archive` to `to_path` using `tar_tool`.
void extract_tar(const Path& tar_tool, const Path& archive, const Path& to_path);
bool extract_tar(DiagnosticContext& context, const Path& tar_tool, const Path& archive, const Path& to_path);
// Extract `archive` to `to_path` using `cmake_tool`. (CMake's built in tar)
void extract_tar_cmake(const Path& cmake_tool, const Path& archive, const Path& to_path);
void extract_archive(const Filesystem& fs,
bool extract_tar_cmake(DiagnosticContext& context,
const Path& cmake_tool,
const Path& archive,
const Path& to_path);
bool extract_archive(DiagnosticContext& context,
const Filesystem& fs,
const ToolCache& tools,
MessageSink& status_sink,
const Path& archive,
const Path& to_path);
// extract `archive` to a sibling temporary subdirectory of `to_path` and returns that path
Path extract_archive_to_temp_subdirectory(const Filesystem& fs,
const ToolCache& tools,
MessageSink& status_sink,
const Path& archive,
const Path& to_path);
Optional<Path> extract_archive_to_temp_subdirectory(DiagnosticContext& context,
const Filesystem& fs,
const ToolCache& tools,
const Path& archive,
const Path& to_path);

ExtractionType guess_extraction_type(const Path& archive);
#ifdef _WIN32
// Extract the 7z archive part of a self extracting 7z installer
void win32_extract_self_extracting_7z(const Filesystem& fs, const Path& archive, const Path& to_path);
bool win32_extract_self_extracting_7z(DiagnosticContext& context,
const Filesystem& fs,
const Path& archive,
const Path& to_path);
#endif

struct ZipTool
{
void setup(const ToolCache& tools, MessageSink& status_sink);
bool setup(DiagnosticContext& context, const Filesystem& fs, const ToolCache& tools);

// Compress the source directory into the destination file.
bool compress_directory_to_zip(DiagnosticContext& context,
Expand Down
95 changes: 72 additions & 23 deletions include/vcpkg/base/diagnostics.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

struct DiagnosticLine
{
template<class MessageLike, std::enable_if_t<std::is_convertible_v<MessageLike, LocalizedString>, int> = 0>

Check failure on line 26 in include/vcpkg/base/diagnostics.h

View workflow job for this annotation

GitHub Actions / builds / build (ubuntu-24.04-arm, linux-arm64-ci)

no type named ‘type’ in ‘struct std::enable_if<false, int>’

Check failure on line 26 in include/vcpkg/base/diagnostics.h

View workflow job for this annotation

GitHub Actions / builds / build (ubuntu-22.04, linux-ci)

no type named ‘type’ in ‘struct std::enable_if<false, int>’
DiagnosticLine(DiagKind kind, MessageLike&& message)
: m_kind(kind), m_origin(), m_position(), m_message(std::forward<MessageLike>(message))
{
Expand Down Expand Up @@ -151,20 +151,13 @@
MessageSink& sink;
};

// Stores all diagnostics into a vector, while passing through status lines to an underlying MessageSink.
struct BufferedDiagnosticContext final : DiagnosticContext
struct BasicBufferedDiagnosticContext : DiagnosticContext
{
BufferedDiagnosticContext(MessageSink& status_sink) : status_sink(status_sink) { }

virtual void report(const DiagnosticLine& line) override;
virtual void report(DiagnosticLine&& line) override;

virtual void statusln(const LocalizedString& message) override;
virtual void statusln(LocalizedString&& message) override;
virtual void statusln(const MessageLine& message) override;
virtual void statusln(MessageLine&& message) override;
// statusln intentionally unimplemented

MessageSink& status_sink;
std::vector<DiagnosticLine> lines;

// Prints all diagnostics to the supplied sink.
Expand All @@ -178,6 +171,62 @@
bool empty() const noexcept;
};

// Stores all diagnostics into a vector, while passing through status lines to an underlying MessageSink.
struct SinkBufferedDiagnosticContext final : BasicBufferedDiagnosticContext
{
SinkBufferedDiagnosticContext(MessageSink& status_sink) : status_sink(status_sink) { }

virtual void statusln(const LocalizedString& message) override;
virtual void statusln(LocalizedString&& message) override;
virtual void statusln(const MessageLine& message) override;
virtual void statusln(MessageLine&& message) override;

MessageSink& status_sink;
};

struct ContextBufferedDiagnosticContext final : BasicBufferedDiagnosticContext
{
ContextBufferedDiagnosticContext(DiagnosticContext& status_context) : status_context(status_context) { }

virtual void statusln(const LocalizedString& message) override;
virtual void statusln(LocalizedString&& message) override;
virtual void statusln(const MessageLine& message) override;
virtual void statusln(MessageLine&& message) override;

DiagnosticContext& status_context;
};

struct FullyBufferedDiagnosticContext;

struct DiagnosticOrMessageLine
{
DiagnosticOrMessageLine(const DiagnosticLine& dl);
DiagnosticOrMessageLine(DiagnosticLine&& dl);
DiagnosticOrMessageLine(const MessageLine& ml);
DiagnosticOrMessageLine(MessageLine&& ml);

DiagnosticOrMessageLine(const DiagnosticOrMessageLine& other);
DiagnosticOrMessageLine(DiagnosticOrMessageLine&& other);

DiagnosticOrMessageLine& operator=(const DiagnosticOrMessageLine&) = delete;

~DiagnosticOrMessageLine();

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

private:
friend FullyBufferedDiagnosticContext;

union
{
DiagnosticLine dl;
MessageLine ml;
};

bool is_diagnostic;
};

// Stores all diagnostics and status messages into a vector. This is generally used for background thread or similar
// scenarios where even status messages can't be immediately printed.
struct FullyBufferedDiagnosticContext final : DiagnosticContext
Expand All @@ -190,28 +239,29 @@
virtual void statusln(const MessageLine& message) override;
virtual void statusln(MessageLine&& message) override;

std::vector<MessageLine> lines;

// Prints all diagnostics to the supplied sink.
void print_to(MessageSink& sink) const;
// Converts this message into a string
// Prefer print() if possible because it applies color
std::string to_string() const;
void to_string(std::string& target) const;
// Emits all status messages and reports all diagnostics to the supplied context
void report_to(DiagnosticContext& context) const&;
void report_to(DiagnosticContext& context) &&;

bool empty() const noexcept;

private:
std::vector<DiagnosticOrMessageLine> lines;
};

// DiagnosticContext for attempted operations that may be recovered.
// Stores all diagnostics and passes through all status messages. Afterwards, call commit() to report all
// diagnostics to the outer DiagnosticContext, or handle() to forget them.
struct AttemptDiagnosticContext final : DiagnosticContext
struct AttemptDiagnosticContext final : BasicBufferedDiagnosticContext
{
AttemptDiagnosticContext(DiagnosticContext& inner_context) : inner_context(inner_context) { }

virtual void report(const DiagnosticLine& line) override;
virtual void report(DiagnosticLine&& line) override;

virtual void statusln(const LocalizedString& message) override;
virtual void statusln(LocalizedString&& message) override;
virtual void statusln(const MessageLine& message) override;
Expand All @@ -223,7 +273,6 @@
~AttemptDiagnosticContext();

DiagnosticContext& inner_context;
std::vector<DiagnosticLine> lines;
};

// Wraps another DiagnosticContext and reduces the severity of any reported diagnostics to warning from error.
Expand Down Expand Up @@ -312,11 +361,11 @@
// The overload for functors that return Optional<T>
template<class Fn, class... Args>
auto adapt_context_to_expected(Fn functor, Args&&... args) -> ExpectedL<
typename AdaptContextUnwrapOptional<std::invoke_result_t<Fn, BufferedDiagnosticContext&, Args...>>::type>
typename AdaptContextUnwrapOptional<std::invoke_result_t<Fn, SinkBufferedDiagnosticContext&, Args...>>::type>
{
using Unwrapper = AdaptContextUnwrapOptional<std::invoke_result_t<Fn, BufferedDiagnosticContext&, Args...>>;
using Unwrapper = AdaptContextUnwrapOptional<std::invoke_result_t<Fn, SinkBufferedDiagnosticContext&, Args...>>;
using ReturnType = ExpectedL<typename Unwrapper::type>;
BufferedDiagnosticContext bdc{out_sink};
SinkBufferedDiagnosticContext bdc{out_sink};
decltype(auto) maybe_result = functor(bdc, std::forward<Args>(args)...);
if (auto result = maybe_result.get())
{
Expand Down Expand Up @@ -381,11 +430,11 @@
// The overload for functors that return std::unique_ptr<T>
template<class Fn, class... Args>
auto adapt_context_to_expected(Fn functor, Args&&... args) -> ExpectedL<
typename AdaptContextDetectUniquePtr<std::invoke_result_t<Fn, BufferedDiagnosticContext&, Args...>>::type>
typename AdaptContextDetectUniquePtr<std::invoke_result_t<Fn, SinkBufferedDiagnosticContext&, Args...>>::type>
{
using ReturnType = ExpectedL<
typename AdaptContextDetectUniquePtr<std::invoke_result_t<Fn, BufferedDiagnosticContext&, Args...>>::type>;
BufferedDiagnosticContext bdc{out_sink};
using ReturnType = ExpectedL<typename AdaptContextDetectUniquePtr<
std::invoke_result_t<Fn, SinkBufferedDiagnosticContext&, Args...>>::type>;
SinkBufferedDiagnosticContext bdc{out_sink};
decltype(auto) maybe_result = functor(bdc, std::forward<Args>(args)...);
if (maybe_result)
{
Expand Down
24 changes: 12 additions & 12 deletions include/vcpkg/base/files.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ namespace vcpkg
std::string read_contents(const Path& file_path, LineInfo li) const;

ExpectedL<FileContents> try_read_contents(const Path& file_path) const;
Optional<FileContents> try_read_contents(DiagnosticContext& context, const Path& file_path) const;

// Tries to read `file_path`, and if the file starts with a shebang sequence #!, returns the contents of the
// file. If an I/O error occurs or the file does not start with a shebang sequence, returns an empty string.
Expand All @@ -163,6 +164,7 @@ namespace vcpkg
virtual std::vector<Path> get_files_non_recursive(const Path& dir, std::error_code& ec) const = 0;
std::vector<Path> get_files_non_recursive(const Path& dir, LineInfo li) const;
ExpectedL<std::vector<Path>> try_get_files_non_recursive(const Path& dir) const;
Optional<std::vector<Path>> try_get_files_non_recursive(DiagnosticContext& context, const Path& dir) const;

virtual std::vector<Path> get_directories_recursive(const Path& dir, std::error_code& ec) const = 0;
std::vector<Path> get_directories_recursive(const Path& dir, LineInfo li) const;
Expand All @@ -176,6 +178,8 @@ namespace vcpkg
virtual std::vector<Path> get_directories_non_recursive(const Path& dir, std::error_code& ec) const = 0;
std::vector<Path> get_directories_non_recursive(const Path& dir, LineInfo li) const;
ExpectedL<std::vector<Path>> try_get_directories_non_recursive(const Path& dir) const;
Optional<std::vector<Path>> try_get_directories_non_recursive(DiagnosticContext& context,
const Path& dir) const;

virtual std::vector<Path> get_regular_files_recursive(const Path& dir, std::error_code& ec) const = 0;
std::vector<Path> get_regular_files_recursive(const Path& dir, LineInfo li) const;
Expand Down Expand Up @@ -243,13 +247,15 @@ namespace vcpkg

virtual void write_contents(const Path& file_path, StringView data, std::error_code& ec) const = 0;
void write_contents(const Path& file_path, StringView data, LineInfo li) const;
bool write_contents(DiagnosticContext& context, const Path& file_path, StringView data) const;

void write_rename_contents(const Path& file_path, const Path& temp_name, StringView data, LineInfo li) const;
void write_contents_and_dirs(const Path& file_path, StringView data, LineInfo li) const;
virtual void write_contents_and_dirs(const Path& file_path, StringView data, std::error_code& ec) const = 0;

virtual void rename(const Path& old_path, const Path& new_path, std::error_code& ec) const = 0;
void rename(const Path& old_path, const Path& new_path, LineInfo li) const;
bool rename(DiagnosticContext& context, const Path& old_path, const Path& new_path) const;

void rename_with_retry(const Path& old_path, const Path& new_path, std::error_code& ec) const;
void rename_with_retry(const Path& old_path, const Path& new_path, LineInfo li) const;
Expand All @@ -268,6 +274,7 @@ namespace vcpkg

virtual bool remove(const Path& target, std::error_code& ec) const = 0;
bool remove(const Path& target, LineInfo li) const;
Optional<bool> remove(DiagnosticContext& context, const Path& target) const;

virtual void remove_all(const Path& base, std::error_code& ec, Path& failure_point) const = 0;
void remove_all(const Path& base, std::error_code& ec) const;
Expand Down Expand Up @@ -338,20 +345,12 @@ namespace vcpkg
// however, if `/a/b` doesn't exist, then the functions will fail.

// waits forever for the file lock
virtual std::unique_ptr<IExclusiveFileLock> take_exclusive_file_lock(const Path& lockfile,
MessageSink& status_sink,
std::error_code&) const = 0;
std::unique_ptr<IExclusiveFileLock> take_exclusive_file_lock(const Path& lockfile,
MessageSink& status_sink,
LineInfo li) const;
virtual std::unique_ptr<IExclusiveFileLock> take_exclusive_file_lock(DiagnosticContext& context,
const Path& lockfile) const = 0;

// waits, at most, 1.5 seconds, for the file lock
virtual std::unique_ptr<IExclusiveFileLock> try_take_exclusive_file_lock(const Path& lockfile,
MessageSink& status_sink,
std::error_code&) const = 0;
std::unique_ptr<IExclusiveFileLock> try_take_exclusive_file_lock(const Path& lockfile,
MessageSink& status_sink,
LineInfo li) const;
virtual Optional<std::unique_ptr<IExclusiveFileLock>> try_take_exclusive_file_lock(
DiagnosticContext& context, const Path& lockfile) const = 0;

virtual WriteFilePointer open_for_write(const Path& file_path, Append append, std::error_code& ec) const = 0;
WriteFilePointer open_for_write(const Path& file_path, Append append, LineInfo li) const;
Expand All @@ -360,6 +359,7 @@ namespace vcpkg
};

extern const Filesystem& real_filesystem;
extern const Filesystem& always_failing_filesystem;

extern const StringLiteral FILESYSTEM_INVALID_CHARACTERS;

Expand Down
5 changes: 3 additions & 2 deletions include/vcpkg/base/fwd/diagnostics.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ namespace vcpkg
struct DiagnosticLine;
struct DiagnosticContext;
struct PrintingDiagnosticContext;
struct BufferedDiagnosticContext;
struct SinkBufferedDiagnosticContext;
struct FullyBufferedDiagnosticContext;
struct AttemptDiagnosticContext;
struct WarningDiagnosticContext;

extern DiagnosticContext& null_diagnostic_context;
extern DiagnosticContext& console_diagnostic_context;
extern DiagnosticContext& stderr_diagnostic_context;
extern DiagnosticContext& status_only_diagnostic_context;
extern DiagnosticContext& null_diagnostic_context;
}
2 changes: 2 additions & 0 deletions include/vcpkg/base/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,8 +336,10 @@ namespace vcpkg::Json
};

ExpectedL<ParsedJson> parse(StringView text, StringView origin);
Optional<ParsedJson> parse(DiagnosticContext& context, StringView text, StringView origin);
ParsedJson parse_file(LineInfo li, const ReadOnlyFilesystem&, const Path&);
ExpectedL<Json::Object> parse_object(StringView text, StringView origin);
Optional<Json::Object> parse_object(DiagnosticContext& context, StringView text, StringView origin);

std::string stringify(const Value&);
std::string stringify(const Value&, JsonStyle style);
Expand Down
15 changes: 7 additions & 8 deletions include/vcpkg/base/lazy.h
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
#pragma once

#include <vcpkg/base/optional.h>

namespace vcpkg
{
template<class T>
struct Lazy
{
Lazy() : value(T()), initialized(false) { }

template<class F>
T const& get_lazy(const F& f) const
{
if (!initialized)
if (auto existing = value.get())
{
value = f();
initialized = true;
return *existing;
}
return value;

return value.emplace(f());
}

private:
mutable T value;
mutable bool initialized;
mutable Optional<T> value;
};
}
Loading
Loading