-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
PackageVersionSelection.cpp
157 lines (132 loc) · 6.48 KB
/
PackageVersionSelection.cpp
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
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "pch.h"
#include "Public/winget/PackageVersionSelection.h"
#include "Public/winget/RepositorySource.h"
namespace AppInstaller::Repository
{
namespace
{
std::shared_ptr<IPackage> GetAvailablePackageFromSource(const std::vector<std::shared_ptr<IPackage>>& packages, const std::string_view sourceIdentifier)
{
for (const std::shared_ptr<IPackage>& package : packages)
{
if (sourceIdentifier == package->GetSource().GetIdentifier())
{
return package;
}
}
return {};
}
struct AvailablePackageVersionCollection : public IPackageVersionCollection
{
AvailablePackageVersionCollection(const std::shared_ptr<ICompositePackage>& composite, const std::shared_ptr<IPackageVersion>& installedVersion) :
m_packages(composite->GetAvailable())
{
if (!installedVersion)
{
return;
}
m_channel = installedVersion->GetProperty(PackageVersionProperty::Channel);
// Remove the packages that are not from the installed source.
Source installedVersionSource = installedVersion->GetSource();
if (installedVersionSource && installedVersionSource.ContainsAvailablePackages())
{
m_packages.erase(std::remove_if(m_packages.begin(), m_packages.end(), [&](const std::shared_ptr<IPackage>& p) { return installedVersionSource != p->GetSource(); }), m_packages.end());
}
}
std::vector<PackageVersionKey> GetVersionKeys() const override
{
std::vector<PackageVersionKey> result;
for (const std::shared_ptr<IPackage>& package : m_packages)
{
std::vector<PackageVersionKey> versionKeys = package->GetVersionKeys();
std::copy(versionKeys.begin(), versionKeys.end(), std::back_inserter(result));
}
// Remove all elements whose channel does not match the installed package.
if (m_channel)
{
result.erase(
std::remove_if(result.begin(), result.end(), [&](const PackageVersionKey& pvk) { return !Utility::ICUCaseInsensitiveEquals(pvk.Channel, m_channel.value()); }),
result.end());
}
// Put latest versions at the front; for versions available from multiple sources maintain the order they were added in
std::stable_sort(result.begin(), result.end());
return result;
}
std::shared_ptr<IPackageVersion> GetVersion(const PackageVersionKey& versionKey) const override
{
// If there is a specific source, just use that package's result
std::shared_ptr<IPackage> package;
if (!versionKey.SourceId.empty())
{
package = GetAvailablePackageFromSource(m_packages, versionKey.SourceId);
}
else if (m_packages.size() == 1)
{
package = m_packages[0];
}
else if (versionKey.IsDefaultLatest())
{
std::shared_ptr<IPackageVersion> result;
Utility::Version resultVersion;
for (const auto& p : m_packages)
{
std::shared_ptr<IPackageVersion> latest = p->GetLatestVersion();
Utility::Version version { latest->GetProperty(PackageVersionProperty::Version) };
if (!result || resultVersion < version)
{
result = std::move(latest);
resultVersion = std::move(version);
}
}
return result;
}
else
{
// Otherwise, find the first version that matches
std::vector<PackageVersionKey> versions = GetVersionKeys();
for (const PackageVersionKey& key : versions)
{
if (key.IsMatch(versionKey))
{
package = GetAvailablePackageFromSource(m_packages, key.SourceId);
break;
}
}
}
return package ? package->GetVersion(versionKey) : nullptr;
}
std::shared_ptr<IPackageVersion> GetLatestVersion() const override
{
return GetVersion({ "", "", m_channel.value_or("") });
}
private:
std::optional<std::string> m_channel;
std::vector<std::shared_ptr<IPackage>> m_packages;
};
}
std::shared_ptr<IPackageVersionCollection> GetAvailableVersionsForInstalledVersion(const std::shared_ptr<ICompositePackage>& composite)
{
return std::make_shared<AvailablePackageVersionCollection>(composite, GetInstalledVersion(composite));
}
std::shared_ptr<IPackageVersionCollection> GetAvailableVersionsForInstalledVersion(
const std::shared_ptr<ICompositePackage>& composite,
const std::shared_ptr<IPackageVersion>& installedVersion)
{
return std::make_shared<AvailablePackageVersionCollection>(composite, installedVersion);
}
std::shared_ptr<IPackageVersionCollection> GetAllAvailableVersions(const std::shared_ptr<ICompositePackage>& composite)
{
return GetAvailableVersionsForInstalledVersion(composite, nullptr);
}
std::shared_ptr<IPackageVersion> GetInstalledVersion(const std::shared_ptr<ICompositePackage>& composite)
{
auto installedPackage = composite->GetInstalled();
return installedPackage ? installedPackage->GetLatestVersion() : nullptr;
}
std::shared_ptr<IPackage> GetAvailablePackageFromSource(const std::shared_ptr<ICompositePackage>& composite, const std::string_view sourceIdentifier)
{
return GetAvailablePackageFromSource(composite->GetAvailable(), sourceIdentifier);
}
}