Skip to content

Commit 486fbf9

Browse files
committed
Plumb DiagnosticContext into ToolCache / download / caching infrastructure.
Unblocks microsoft/vcpkg#43309 by making --x-stderr-status actually work to `vcpkg fetch`
1 parent 4819c23 commit 486fbf9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2632
-1340
lines changed

include/vcpkg/archives.h

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,30 +28,36 @@ namespace vcpkg
2828
};
2929

3030
// Extract `archive` to `to_path` using `tar_tool`.
31-
void extract_tar(const Path& tar_tool, const Path& archive, const Path& to_path);
31+
bool extract_tar(DiagnosticContext& context, const Path& tar_tool, const Path& archive, const Path& to_path);
3232
// Extract `archive` to `to_path` using `cmake_tool`. (CMake's built in tar)
33-
void extract_tar_cmake(const Path& cmake_tool, const Path& archive, const Path& to_path);
34-
void extract_archive(const Filesystem& fs,
33+
bool extract_tar_cmake(DiagnosticContext& context,
34+
const Path& cmake_tool,
35+
const Path& archive,
36+
const Path& to_path);
37+
bool extract_archive(DiagnosticContext& context,
38+
const Filesystem& fs,
3539
const ToolCache& tools,
36-
MessageSink& status_sink,
3740
const Path& archive,
3841
const Path& to_path);
3942
// extract `archive` to a sibling temporary subdirectory of `to_path` and returns that path
40-
Path extract_archive_to_temp_subdirectory(const Filesystem& fs,
41-
const ToolCache& tools,
42-
MessageSink& status_sink,
43-
const Path& archive,
44-
const Path& to_path);
43+
Optional<Path> extract_archive_to_temp_subdirectory(DiagnosticContext& context,
44+
const Filesystem& fs,
45+
const ToolCache& tools,
46+
const Path& archive,
47+
const Path& to_path);
4548

4649
ExtractionType guess_extraction_type(const Path& archive);
4750
#ifdef _WIN32
4851
// Extract the 7z archive part of a self extracting 7z installer
49-
void win32_extract_self_extracting_7z(const Filesystem& fs, const Path& archive, const Path& to_path);
52+
bool win32_extract_self_extracting_7z(DiagnosticContext& context,
53+
const Filesystem& fs,
54+
const Path& archive,
55+
const Path& to_path);
5056
#endif
5157

5258
struct ZipTool
5359
{
54-
void setup(const ToolCache& tools, MessageSink& status_sink);
60+
bool setup(DiagnosticContext& context, const Filesystem& fs, const ToolCache& tools);
5561

5662
// Compress the source directory into the destination file.
5763
bool compress_directory_to_zip(DiagnosticContext& context,

include/vcpkg/base/diagnostics.h

Lines changed: 72 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -151,20 +151,13 @@ namespace vcpkg
151151
MessageSink& sink;
152152
};
153153

154-
// Stores all diagnostics into a vector, while passing through status lines to an underlying MessageSink.
155-
struct BufferedDiagnosticContext final : DiagnosticContext
154+
struct BasicBufferedDiagnosticContext : DiagnosticContext
156155
{
157-
BufferedDiagnosticContext(MessageSink& status_sink) : status_sink(status_sink) { }
158-
159156
virtual void report(const DiagnosticLine& line) override;
160157
virtual void report(DiagnosticLine&& line) override;
161158

162-
virtual void statusln(const LocalizedString& message) override;
163-
virtual void statusln(LocalizedString&& message) override;
164-
virtual void statusln(const MessageLine& message) override;
165-
virtual void statusln(MessageLine&& message) override;
159+
// statusln intentionally unimplemented
166160

167-
MessageSink& status_sink;
168161
std::vector<DiagnosticLine> lines;
169162

170163
// Prints all diagnostics to the supplied sink.
@@ -178,6 +171,62 @@ namespace vcpkg
178171
bool empty() const noexcept;
179172
};
180173

174+
// Stores all diagnostics into a vector, while passing through status lines to an underlying MessageSink.
175+
struct SinkBufferedDiagnosticContext final : BasicBufferedDiagnosticContext
176+
{
177+
SinkBufferedDiagnosticContext(MessageSink& status_sink) : status_sink(status_sink) { }
178+
179+
virtual void statusln(const LocalizedString& message) override;
180+
virtual void statusln(LocalizedString&& message) override;
181+
virtual void statusln(const MessageLine& message) override;
182+
virtual void statusln(MessageLine&& message) override;
183+
184+
MessageSink& status_sink;
185+
};
186+
187+
struct ContextBufferedDiagnosticContext final : BasicBufferedDiagnosticContext
188+
{
189+
ContextBufferedDiagnosticContext(DiagnosticContext& status_context) : status_context(status_context) { }
190+
191+
virtual void statusln(const LocalizedString& message) override;
192+
virtual void statusln(LocalizedString&& message) override;
193+
virtual void statusln(const MessageLine& message) override;
194+
virtual void statusln(MessageLine&& message) override;
195+
196+
DiagnosticContext& status_context;
197+
};
198+
199+
struct FullyBufferedDiagnosticContext;
200+
201+
struct DiagnosticOrMessageLine
202+
{
203+
DiagnosticOrMessageLine(const DiagnosticLine& dl);
204+
DiagnosticOrMessageLine(DiagnosticLine&& dl);
205+
DiagnosticOrMessageLine(const MessageLine& ml);
206+
DiagnosticOrMessageLine(MessageLine&& ml);
207+
208+
DiagnosticOrMessageLine(const DiagnosticOrMessageLine& other);
209+
DiagnosticOrMessageLine(DiagnosticOrMessageLine&& other);
210+
211+
DiagnosticOrMessageLine& operator=(const DiagnosticOrMessageLine&) = delete;
212+
213+
~DiagnosticOrMessageLine();
214+
215+
std::string to_string() const;
216+
void to_string(std::string& target) const;
217+
218+
private:
219+
friend FullyBufferedDiagnosticContext;
220+
221+
union
222+
{
223+
DiagnosticLine dl;
224+
MessageLine ml;
225+
};
226+
227+
bool is_diagnostic;
228+
};
229+
181230
// Stores all diagnostics and status messages into a vector. This is generally used for background thread or similar
182231
// scenarios where even status messages can't be immediately printed.
183232
struct FullyBufferedDiagnosticContext final : DiagnosticContext
@@ -190,28 +239,29 @@ namespace vcpkg
190239
virtual void statusln(const MessageLine& message) override;
191240
virtual void statusln(MessageLine&& message) override;
192241

193-
std::vector<MessageLine> lines;
194-
195242
// Prints all diagnostics to the supplied sink.
196243
void print_to(MessageSink& sink) const;
197244
// Converts this message into a string
198245
// Prefer print() if possible because it applies color
199246
std::string to_string() const;
200247
void to_string(std::string& target) const;
248+
// Emits all status messages and reports all diagnostics to the supplied context
249+
void report_to(DiagnosticContext& context) const&;
250+
void report_to(DiagnosticContext& context) &&;
201251

202252
bool empty() const noexcept;
253+
254+
private:
255+
std::vector<DiagnosticOrMessageLine> lines;
203256
};
204257

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

212-
virtual void report(const DiagnosticLine& line) override;
213-
virtual void report(DiagnosticLine&& line) override;
214-
215265
virtual void statusln(const LocalizedString& message) override;
216266
virtual void statusln(LocalizedString&& message) override;
217267
virtual void statusln(const MessageLine& message) override;
@@ -223,7 +273,6 @@ namespace vcpkg
223273
~AttemptDiagnosticContext();
224274

225275
DiagnosticContext& inner_context;
226-
std::vector<DiagnosticLine> lines;
227276
};
228277

229278
// Wraps another DiagnosticContext and reduces the severity of any reported diagnostics to warning from error.
@@ -312,11 +361,11 @@ namespace vcpkg
312361
// The overload for functors that return Optional<T>
313362
template<class Fn, class... Args>
314363
auto adapt_context_to_expected(Fn functor, Args&&... args) -> ExpectedL<
315-
typename AdaptContextUnwrapOptional<std::invoke_result_t<Fn, BufferedDiagnosticContext&, Args...>>::type>
364+
typename AdaptContextUnwrapOptional<std::invoke_result_t<Fn, SinkBufferedDiagnosticContext&, Args...>>::type>
316365
{
317-
using Unwrapper = AdaptContextUnwrapOptional<std::invoke_result_t<Fn, BufferedDiagnosticContext&, Args...>>;
366+
using Unwrapper = AdaptContextUnwrapOptional<std::invoke_result_t<Fn, SinkBufferedDiagnosticContext&, Args...>>;
318367
using ReturnType = ExpectedL<typename Unwrapper::type>;
319-
BufferedDiagnosticContext bdc{out_sink};
368+
SinkBufferedDiagnosticContext bdc{out_sink};
320369
decltype(auto) maybe_result = functor(bdc, std::forward<Args>(args)...);
321370
if (auto result = maybe_result.get())
322371
{
@@ -381,11 +430,11 @@ namespace vcpkg
381430
// The overload for functors that return std::unique_ptr<T>
382431
template<class Fn, class... Args>
383432
auto adapt_context_to_expected(Fn functor, Args&&... args) -> ExpectedL<
384-
typename AdaptContextDetectUniquePtr<std::invoke_result_t<Fn, BufferedDiagnosticContext&, Args...>>::type>
433+
typename AdaptContextDetectUniquePtr<std::invoke_result_t<Fn, SinkBufferedDiagnosticContext&, Args...>>::type>
385434
{
386-
using ReturnType = ExpectedL<
387-
typename AdaptContextDetectUniquePtr<std::invoke_result_t<Fn, BufferedDiagnosticContext&, Args...>>::type>;
388-
BufferedDiagnosticContext bdc{out_sink};
435+
using ReturnType = ExpectedL<typename AdaptContextDetectUniquePtr<
436+
std::invoke_result_t<Fn, SinkBufferedDiagnosticContext&, Args...>>::type>;
437+
SinkBufferedDiagnosticContext bdc{out_sink};
389438
decltype(auto) maybe_result = functor(bdc, std::forward<Args>(args)...);
390439
if (maybe_result)
391440
{

include/vcpkg/base/files.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ namespace vcpkg
140140
std::string read_contents(const Path& file_path, LineInfo li) const;
141141

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

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

167169
virtual std::vector<Path> get_directories_recursive(const Path& dir, std::error_code& ec) const = 0;
168170
std::vector<Path> get_directories_recursive(const Path& dir, LineInfo li) const;
@@ -176,6 +178,8 @@ namespace vcpkg
176178
virtual std::vector<Path> get_directories_non_recursive(const Path& dir, std::error_code& ec) const = 0;
177179
std::vector<Path> get_directories_non_recursive(const Path& dir, LineInfo li) const;
178180
ExpectedL<std::vector<Path>> try_get_directories_non_recursive(const Path& dir) const;
181+
Optional<std::vector<Path>> try_get_directories_non_recursive(DiagnosticContext& context,
182+
const Path& dir) const;
179183

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

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

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

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

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

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

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

340347
// waits forever for the file lock
341-
virtual std::unique_ptr<IExclusiveFileLock> take_exclusive_file_lock(const Path& lockfile,
342-
MessageSink& status_sink,
343-
std::error_code&) const = 0;
344-
std::unique_ptr<IExclusiveFileLock> take_exclusive_file_lock(const Path& lockfile,
345-
MessageSink& status_sink,
346-
LineInfo li) const;
348+
virtual std::unique_ptr<IExclusiveFileLock> take_exclusive_file_lock(DiagnosticContext& context,
349+
const Path& lockfile) const = 0;
347350

348351
// waits, at most, 1.5 seconds, for the file lock
349-
virtual std::unique_ptr<IExclusiveFileLock> try_take_exclusive_file_lock(const Path& lockfile,
350-
MessageSink& status_sink,
351-
std::error_code&) const = 0;
352-
std::unique_ptr<IExclusiveFileLock> try_take_exclusive_file_lock(const Path& lockfile,
353-
MessageSink& status_sink,
354-
LineInfo li) const;
352+
virtual Optional<std::unique_ptr<IExclusiveFileLock>> try_take_exclusive_file_lock(
353+
DiagnosticContext& context, const Path& lockfile) const = 0;
355354

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

362361
extern const Filesystem& real_filesystem;
362+
extern const Filesystem& always_failing_filesystem;
363363

364364
extern const StringLiteral FILESYSTEM_INVALID_CHARACTERS;
365365

include/vcpkg/base/fwd/diagnostics.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ namespace vcpkg
1616
struct DiagnosticLine;
1717
struct DiagnosticContext;
1818
struct PrintingDiagnosticContext;
19-
struct BufferedDiagnosticContext;
19+
struct SinkBufferedDiagnosticContext;
2020
struct FullyBufferedDiagnosticContext;
2121
struct AttemptDiagnosticContext;
2222
struct WarningDiagnosticContext;
2323

24+
extern DiagnosticContext& null_diagnostic_context;
2425
extern DiagnosticContext& console_diagnostic_context;
26+
extern DiagnosticContext& stderr_diagnostic_context;
2527
extern DiagnosticContext& status_only_diagnostic_context;
26-
extern DiagnosticContext& null_diagnostic_context;
2728
}

include/vcpkg/base/json.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,8 +336,10 @@ namespace vcpkg::Json
336336
};
337337

338338
ExpectedL<ParsedJson> parse(StringView text, StringView origin);
339+
Optional<ParsedJson> parse(DiagnosticContext& context, StringView text, StringView origin);
339340
ParsedJson parse_file(LineInfo li, const ReadOnlyFilesystem&, const Path&);
340341
ExpectedL<Json::Object> parse_object(StringView text, StringView origin);
342+
Optional<Json::Object> parse_object(DiagnosticContext& context, StringView text, StringView origin);
341343

342344
std::string stringify(const Value&);
343345
std::string stringify(const Value&, JsonStyle style);

include/vcpkg/base/lazy.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
11
#pragma once
22

3+
#include <vcpkg/base/optional.h>
4+
35
namespace vcpkg
46
{
57
template<class T>
68
struct Lazy
79
{
8-
Lazy() : value(T()), initialized(false) { }
9-
1010
template<class F>
1111
T const& get_lazy(const F& f) const
1212
{
13-
if (!initialized)
13+
if (auto existing = value.get())
1414
{
15-
value = f();
16-
initialized = true;
15+
return *existing;
1716
}
18-
return value;
17+
18+
return value.emplace(f());
1919
}
2020

2121
private:
22-
mutable T value;
23-
mutable bool initialized;
22+
mutable Optional<T> value;
2423
};
2524
}

0 commit comments

Comments
 (0)