forked from microsoft/winget-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWorkflowBase.h
More file actions
451 lines (366 loc) · 16.2 KB
/
Copy pathWorkflowBase.h
File metadata and controls
451 lines (366 loc) · 16.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include "ExecutionArgs.h"
#include "ExecutionReporter.h"
#include <winget/ExperimentalFeature.h>
#include <winget/RepositorySearch.h>
#include <winget/RepositorySource.h>
#include <winget/Authentication.h>
#include <string>
#include <string_view>
namespace AppInstaller::CLI::Execution
{
struct Context;
}
namespace AppInstaller::CLI::Workflow
{
// Values are ordered in a typical workflow stages
enum class ExecutionStage : uint32_t
{
Initial = 0,
ParseArgs = 1000,
Discovery = 2000,
Download = 3000,
PreExecution = 3500,
Execution = 4000,
PostExecution = 5000,
};
enum class OperationType
{
Completion,
Export,
Install,
List,
Pin,
Search,
Show,
Uninstall,
Upgrade,
Download,
Repair,
};
// A task in the workflow.
struct WorkflowTask
{
using Func = void (*)(Execution::Context&);
WorkflowTask(Func f) : m_isFunc(true), m_func(f) {}
WorkflowTask(std::string_view name, bool executeAlways = false) : m_name(name), m_executeAlways(executeAlways) {}
virtual ~WorkflowTask() = default;
WorkflowTask(const WorkflowTask&) = default;
WorkflowTask& operator=(const WorkflowTask&) = default;
WorkflowTask(WorkflowTask&&) = default;
WorkflowTask& operator=(WorkflowTask&&) = default;
bool operator==(const WorkflowTask& other) const;
virtual void operator()(Execution::Context& context) const;
const std::string& GetName() const { return m_name; }
bool IsFunction() const { return m_isFunc; }
Func Function() const { return m_func; }
bool ExecuteAlways() const { return m_executeAlways; }
void Log() const;
private:
bool m_isFunc = false;
Func m_func = nullptr;
std::string m_name;
bool m_executeAlways = false;
};
// Helper to determine installed source to use based on context input.
Repository::PredefinedSource DetermineInstalledSource(const Execution::Context& context);
// Helper to create authentication arguments from context input.
Authentication::AuthenticationArguments GetAuthenticationArguments(const Execution::Context& context);
// Helper to report exceptions and return the HRESULT.
HRESULT HandleException(Execution::Context& context, std::exception_ptr exception);
// Creates the source object.
// Required Args: None
// Inputs: None
// Outputs: Source
struct OpenSource : public WorkflowTask
{
OpenSource(bool forDependencies = false) : WorkflowTask("OpenSource"), m_forDependencies(forDependencies) {}
void operator()(Execution::Context& context) const override;
private:
bool m_forDependencies;
};
// Creates a source object for a source specified by name, and adds it to the list of open sources.
// Required Args: None
// Inputs: Sources?
// Outputs: Sources
struct OpenNamedSourceForSources : public WorkflowTask
{
OpenNamedSourceForSources(std::string_view sourceName) : WorkflowTask("OpenNamedSourceForSources"), m_sourceName(sourceName) {}
void operator()(Execution::Context& context) const override;
private:
Utility::LocIndView m_sourceName;
};
// Creates a source object for a predefined source.
// Required Args: None
// Inputs: None
// Outputs: Source
struct OpenPredefinedSource : public WorkflowTask
{
OpenPredefinedSource(Repository::PredefinedSource source, bool forDependencies = false) : WorkflowTask("OpenPredefinedSource"), m_predefinedSource(source), m_forDependencies(forDependencies) {}
void operator()(Execution::Context& context) const override;
private:
Repository::PredefinedSource m_predefinedSource;
bool m_forDependencies;
};
// Creates a composite source from the given predefined source and the existing source.
// Required Args: None
// Inputs: Source
// Outputs: Source
struct OpenCompositeSource : public WorkflowTask
{
OpenCompositeSource(
Repository::PredefinedSource source,
bool forDependencies = false,
Repository::CompositeSearchBehavior searchBehavior = Repository::CompositeSearchBehavior::Installed) :
WorkflowTask("OpenCompositeSource"), m_predefinedSource(source), m_forDependencies(forDependencies), m_searchBehavior(searchBehavior) {}
void operator()(Execution::Context& context) const override;
private:
Repository::PredefinedSource m_predefinedSource;
bool m_forDependencies;
Repository::CompositeSearchBehavior m_searchBehavior;
};
// Performs a search on the source.
// Required Args: None
// Inputs: Source
// Outputs: SearchResult
void SearchSourceForMany(Execution::Context& context);
// Creates a search request object with the semantics of targeting a single package.
// Required Args: None
// Inputs: Query, search filters (Id, Name, etc.)
// Outputs: SearchRequest
void GetSearchRequestForSingle(Execution::Context& context);
// Performs a search on the source with the semantics of targeting a single package.
// Required Args: None
// Inputs: Source, SearchRequest
// Outputs: SearchResult
void SearchSourceForSingle(Execution::Context& context);
// Performs a search on the source with the semantics of targeting many packages,
// but for completion purposes.
// Required Args: None
// Inputs: Source, CompletionData
// Outputs: SearchResult
void SearchSourceForManyCompletion(Execution::Context& context);
// Performs a search on the source with the semantics of targeting a single package,
// but for completion purposes.
// Required Args: None
// Inputs: Source, CompletionData
// Outputs: SearchResult
void SearchSourceForSingleCompletion(Execution::Context& context);
// Searches the source for the specific field as a completion.
// Required Args: None
// Inputs: CompletionData, Source
// Outputs: None
struct SearchSourceForCompletionField : public WorkflowTask
{
SearchSourceForCompletionField(Repository::PackageMatchField field) : WorkflowTask("SearchSourceForCompletionField"), m_field(field) {}
void operator()(Execution::Context& context) const override;
private:
Repository::PackageMatchField m_field;
};
// Outputs the search results.
// Required Args: None
// Inputs: SearchResult
// Outputs: None
void ReportSearchResult(Execution::Context& context);
// Outputs the search results as the list command would show.
// Required Args: None
// Inputs: SearchResult
// Outputs: None
struct ReportListResult : public WorkflowTask
{
ReportListResult(bool onlyShowUpgrades = false) : WorkflowTask("ReportListResult"), m_onlyShowUpgrades(onlyShowUpgrades) {}
void operator()(Execution::Context& context) const override;
private:
bool m_onlyShowUpgrades;
};
// Handles failures in the SearchResult either by warning or failing.
// Required Args: None
// Inputs: SearchResult
// Outputs: None
void HandleSearchResultFailures(Execution::Context& context);
// Outputs the search results when multiple packages found but only one expected.
// Required Args: None
// Inputs: SearchResult
// Outputs: None
void ReportMultiplePackageFoundResult(Execution::Context& context);
// Outputs the search results when multiple packages found but only one expected.
// Required Args: None
// Inputs: SearchResult
// Outputs: None
void ReportMultiplePackageFoundResultWithSource(Execution::Context& context);
// Ensures that there is at least one result in the search.
// Required Args: bool indicating if the search result is from installed source
// Inputs: SearchResult
// Outputs: None
struct EnsureMatchesFromSearchResult : public WorkflowTask
{
EnsureMatchesFromSearchResult(OperationType operation) :
WorkflowTask("EnsureMatchesFromSearchResult"), m_operationType(operation) {}
void operator()(Execution::Context& context) const override;
private:
OperationType m_operationType;
};
// Ensures that there is only one result in the search.
// Required Args: bool indicating if the search result is from installed source
// Inputs: SearchResult
// Outputs: Package
struct EnsureOneMatchFromSearchResult : public WorkflowTask
{
EnsureOneMatchFromSearchResult(OperationType operation) :
WorkflowTask("EnsureOneMatchFromSearchResult"), m_operationType(operation) {}
void operator()(Execution::Context& context) const override;
private:
OperationType m_operationType;
};
// Gets the manifest from package.
// Required Args: Version and channel; can be empty. A flag indicating whether to consider package pins
// Inputs: Package
// Outputs: Manifest, PackageVersion
struct GetManifestWithVersionFromPackage : public WorkflowTask
{
GetManifestWithVersionFromPackage(std::string_view version, std::string_view channel, bool considerPins) :
WorkflowTask("GetManifestWithVersionFromPackage"), m_version(version), m_channel(channel), m_considerPins(considerPins) {}
GetManifestWithVersionFromPackage(const Utility::VersionAndChannel& versionAndChannel, bool considerPins) :
GetManifestWithVersionFromPackage(versionAndChannel.GetVersion().ToString(), versionAndChannel.GetChannel().ToString(), considerPins) {}
void operator()(Execution::Context& context) const override;
private:
std::string_view m_version;
std::string_view m_channel;
bool m_considerPins;
};
// Gets the manifest from package.
// Required Args: A value indicating whether to consider pins
// Inputs: Package. Optionally Version and Channel
// Outputs: Manifest, PackageVersion
struct GetManifestFromPackage : public WorkflowTask
{
GetManifestFromPackage(bool considerPins) : WorkflowTask("GetManifestFromPackage"), m_considerPins(considerPins) {}
void operator()(Execution::Context& context) const override;
private:
bool m_considerPins;
};
// Ensures the file exists and is not a directory.
// Required Args: the one given
// Inputs: None
// Outputs: None
struct VerifyFile : public WorkflowTask
{
VerifyFile(Execution::Args::Type arg) : WorkflowTask("VerifyFile"), m_arg(arg) {}
void operator()(Execution::Context& context) const override;
private:
Execution::Args::Type m_arg;
};
// Ensures the path exists.
// Required Args: the one given
// Inputs: None
// Outputs: None
struct VerifyPath : public WorkflowTask
{
VerifyPath(Execution::Args::Type arg) : WorkflowTask("VerifyPath"), m_arg(arg) {}
void operator()(Execution::Context& context) const override;
private:
Execution::Args::Type m_arg;
};
// Ensures the local file exists and is not a directory. Or it's a Uri. Default only https is supported at the moment.
// Required Args: the one given
// Inputs: None
// Outputs: None
struct VerifyFileOrUri : public WorkflowTask
{
VerifyFileOrUri(Execution::Args::Type arg, std::vector<std::wstring> supportedSchemes = { L"https" }) :
WorkflowTask("VerifyFileOrUri"), m_arg(arg), m_supportedSchemes(std::move(supportedSchemes)) {}
void operator()(Execution::Context& context) const override;
private:
Execution::Args::Type m_arg;
std::vector<std::wstring> m_supportedSchemes;
};
// Opens the manifest file provided on the command line.
// Required Args: Manifest
// Inputs: None
// Outputs: Manifest
void GetManifestFromArg(Execution::Context& context);
// Reports the search result's package identity.
// Required Args: None
// Inputs: Package
// Outputs: None
void ReportPackageIdentity(Execution::Context& context);
// Reports the installed package version identity.
// Required Args: None
// Inputs: InstalledPackageVersion
// Outputs: None
void ReportInstalledPackageVersionIdentity(Execution::Context& context);
// Reports the manifest's identity.
// Required Args: None
// Inputs: Manifest
// Outputs: None
void ReportManifestIdentity(Execution::Context& context);
// Reports the manifest's identity with version.
// Required Args: None
// Inputs: Manifest
// Outputs: None
struct ReportManifestIdentityWithVersion : public WorkflowTask
{
ReportManifestIdentityWithVersion(Utility::LocIndView prefix, Execution::Reporter::Level level = Execution::Reporter::Level::Info) :
WorkflowTask("ReportManifestIdentityWithVersion"), m_prefix(prefix), m_level(level) {}
ReportManifestIdentityWithVersion(Resource::StringId label = Resource::String::ReportIdentityFound, Execution::Reporter::Level level = Execution::Reporter::Level::Info) :
WorkflowTask("ReportManifestIdentityWithVersion"), m_label(label), m_level(level) {}
void operator()(Execution::Context& context) const override;
private:
Utility::LocIndView m_prefix;
std::optional<Resource::StringId> m_label;
Execution::Reporter::Level m_level;
};
// Selects the installer from the manifest, if one is applicable.
// Required Args: None
// Inputs: Manifest
// Outputs: Installer
void SelectInstaller(Execution::Context& context);
// Ensures that the process is running as admin.
// Required Args: None
// Inputs: None
// Outputs: None
void EnsureRunningAsAdmin(Execution::Context& context);
// Ensures that the feature is enabled.
// Required Args: the desired feature
// Inputs: None
// Outputs: None
struct EnsureFeatureEnabled : public WorkflowTask
{
EnsureFeatureEnabled(Settings::ExperimentalFeature::Feature feature) : WorkflowTask("EnsureFeatureEnabled"), m_feature(feature) {}
void operator()(Execution::Context& context) const override;
private:
Settings::ExperimentalFeature::Feature m_feature;
};
// Performs a search on the source with the semantics of targeting packages matching input manifest
// Required Args: None
// Inputs: Source, Manifest
// Outputs: SearchResult
void SearchSourceUsingManifest(Execution::Context& context);
// Gets the installed package version
// Required Args: None
// Inputs: Package
// Outputs: InstalledPackageVersion
void GetInstalledPackageVersion(Execution::Context& context);
// Shows all versions for an application.
// Required Args: None
// Inputs: SearchResult [only operates on first match]
// Outputs: None
void ShowAppVersions(Execution::Context& context);
// Reports execution stage in a workflow
// Required Args: ExecutionStage
// Inputs: ExecutionStage?
// Outputs: ExecutionStage
struct ReportExecutionStage : public WorkflowTask
{
ReportExecutionStage(ExecutionStage stage) : WorkflowTask("ReportExecutionStage"), m_stage(stage) {}
void operator()(Execution::Context& context) const override;
private:
ExecutionStage m_stage;
};
}
// Passes the context to the function if it has not been terminated; returns the context.
AppInstaller::CLI::Execution::Context& operator<<(AppInstaller::CLI::Execution::Context& context, AppInstaller::CLI::Workflow::WorkflowTask::Func f);
// Passes the context to the task if it has not been terminated; returns the context.
AppInstaller::CLI::Execution::Context& operator<<(AppInstaller::CLI::Execution::Context& context, const AppInstaller::CLI::Workflow::WorkflowTask& task);