SQLiteIndexSourceV1.cpp (9775B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "Microsoft/SQLiteIndexSourceV1.h" 5 #include <winget/ManifestYamlParser.h> 6 7 using namespace AppInstaller::Utility; 8 9 10 namespace AppInstaller::Repository::Microsoft::details::V1 11 { 12 // The IPackageVersion implementation for V1 index. 13 struct PackageVersion : public SourceReference, public IPackageVersion 14 { 15 PackageVersion(const std::shared_ptr<SQLiteIndexSource>& source, SQLiteIndex::IdType manifestId, const std::shared_ptr<Caching::FileCache>& manifestCache) : 16 SourceReference(source), m_manifestId(manifestId), m_manifestCache(manifestCache) {} 17 18 // Inherited via IPackageVersion 19 LocIndString GetProperty(PackageVersionProperty property) const override 20 { 21 switch (property) 22 { 23 case PackageVersionProperty::SourceIdentifier: 24 return LocIndString{ GetReferenceSource()->GetIdentifier() }; 25 case PackageVersionProperty::SourceName: 26 return LocIndString{ GetReferenceSource()->GetDetails().Name }; 27 default: 28 // Values coming from the index will always be localized/independent. 29 std::optional<std::string> optValue = GetReferenceSource()->GetIndex().GetPropertyByPrimaryId(m_manifestId, property); 30 return LocIndString{ optValue ? optValue.value() : std::string{} }; 31 } 32 } 33 34 std::vector<LocIndString> GetMultiProperty(PackageVersionMultiProperty property) const override 35 { 36 std::vector<LocIndString> result; 37 38 for (auto&& value : GetReferenceSource()->GetIndex().GetMultiPropertyByPrimaryId(m_manifestId, property)) 39 { 40 // Values coming from the index will always be localized/independent. 41 result.emplace_back(std::move(value)); 42 } 43 44 return result; 45 } 46 47 Manifest::Manifest GetManifest() override 48 { 49 std::shared_ptr<SQLiteIndexSource> source = GetReferenceSource(); 50 51 std::optional<std::string> relativePathOpt = source->GetIndex().GetPropertyByPrimaryId(m_manifestId, PackageVersionProperty::RelativePath); 52 THROW_HR_IF(E_NOT_SET, !relativePathOpt); 53 54 std::optional<std::string> manifestHashString = source->GetIndex().GetPropertyByPrimaryId(m_manifestId, PackageVersionProperty::ManifestSHA256Hash); 55 THROW_HR_IF(APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE, source->RequireManifestHash() && !manifestHashString); 56 57 SHA256::HashBuffer manifestSHA256; 58 if (manifestHashString) 59 { 60 manifestSHA256 = SHA256::ConvertToBytes(manifestHashString.value()); 61 } 62 63 std::unique_ptr<std::istream> manifestStream = m_manifestCache->GetFile(ConvertToUTF16(relativePathOpt.value()), manifestSHA256); 64 return Manifest::YamlParser::Create(ReadEntireStream(*manifestStream)); 65 } 66 67 Source GetSource() const override 68 { 69 return Source{ GetReferenceSource() }; 70 } 71 72 IPackageVersion::Metadata GetMetadata() const override 73 { 74 auto metadata = GetReferenceSource()->GetIndex().GetMetadataByManifestId(m_manifestId); 75 76 IPackageVersion::Metadata result; 77 for (auto&& data : metadata) 78 { 79 result.emplace(std::move(data)); 80 } 81 82 return result; 83 } 84 85 private: 86 SQLiteIndex::IdType m_manifestId; 87 std::shared_ptr<Caching::FileCache> m_manifestCache; 88 }; 89 90 SQLitePackage::SQLitePackage(const std::shared_ptr<SQLiteIndexSource>& source, SQLiteIndex::IdType idId, const std::shared_ptr<Caching::FileCache>& manifestCache, bool isInstalled) : 91 SourceReference(source), m_idId(idId), m_manifestCache(manifestCache), m_isInstalled(isInstalled) {} 92 93 LocIndString SQLitePackage::GetProperty(PackageProperty property) const 94 { 95 LocIndString result; 96 97 std::shared_ptr<IPackageVersion> truth = GetLatestVersion(); 98 if (truth) 99 { 100 switch (property) 101 { 102 case PackageProperty::Id: 103 return truth->GetProperty(PackageVersionProperty::Id); 104 case PackageProperty::Name: 105 return truth->GetProperty(PackageVersionProperty::Name); 106 default: 107 THROW_HR(E_UNEXPECTED); 108 } 109 } 110 else 111 { 112 AICLI_LOG(Repo, Verbose, << "SQLitePackage: No manifest was found for the package with id# '" << m_idId << "'"); 113 } 114 115 return result; 116 } 117 118 std::vector<Utility::LocIndString> SQLitePackage::GetMultiProperty(PackageMultiProperty property) const 119 { 120 std::shared_ptr<SQLiteIndexSource> source = GetReferenceSource(); 121 std::vector<Utility::LocIndString> result; 122 PackageVersionMultiProperty mappedProperty = PackageMultiPropertyToPackageVersionMultiProperty(property); 123 124 for (const auto& version : source->GetIndex().GetVersionKeysById(m_idId)) 125 { 126 for (auto&& string : source->GetIndex().GetMultiPropertyByPrimaryId(version.ManifestId, mappedProperty)) 127 { 128 auto itr = std::lower_bound(result.begin(), result.end(), string); 129 130 if (itr == result.end() || itr->get() != string) 131 { 132 result.emplace(itr, std::move(string)); 133 } 134 } 135 } 136 137 return result; 138 } 139 140 std::vector<PackageVersionKey> SQLitePackage::GetVersionKeys() const 141 { 142 std::shared_ptr<SQLiteIndexSource> source = GetReferenceSource(); 143 144 { 145 auto sharedLock = m_versionKeysLock.lock_shared(); 146 147 if (!m_versionKeys.empty()) 148 { 149 return m_versionKeys; 150 } 151 } 152 153 auto exclusiveLock = m_versionKeysLock.lock_exclusive(); 154 155 if (!m_versionKeys.empty()) 156 { 157 return m_versionKeys; 158 } 159 160 std::vector<SQLiteIndex::VersionKey> versions = source->GetIndex().GetVersionKeysById(m_idId); 161 162 for (const auto& vk : versions) 163 { 164 std::string version = vk.VersionAndChannel.GetVersion().ToString(); 165 std::string channel = vk.VersionAndChannel.GetChannel().ToString(); 166 m_versionKeys.emplace_back(source->GetIdentifier(), version, channel); 167 m_versionKeysMap.emplace(MapKey{ std::move(version), std::move(channel) }, vk.ManifestId); 168 } 169 170 return m_versionKeys; 171 } 172 173 std::shared_ptr<IPackageVersion> SQLitePackage::GetLatestVersion() const 174 { 175 std::shared_ptr<SQLiteIndexSource> source = GetReferenceSource(); 176 std::optional<SQLiteIndex::IdType> manifestId = source->GetIndex().GetManifestIdByKey(m_idId, {}, {}); 177 178 if (manifestId) 179 { 180 return std::make_shared<PackageVersion>(source, manifestId.value(), m_manifestCache); 181 } 182 183 return {}; 184 } 185 186 std::shared_ptr<IPackageVersion> SQLitePackage::GetVersion(const PackageVersionKey& versionKey) const 187 { 188 std::shared_ptr<SQLiteIndexSource> source = GetReferenceSource(); 189 190 // Ensure that this key targets this (or any) source 191 if (!versionKey.SourceId.empty() && versionKey.SourceId != source->GetIdentifier()) 192 { 193 return {}; 194 } 195 196 std::optional<SQLiteIndex::IdType> manifestId; 197 198 { 199 MapKey requested{ versionKey.Version, versionKey.Channel }; 200 auto sharedLock = m_versionKeysLock.lock_shared(); 201 202 auto itr = m_versionKeysMap.find(requested); 203 if (itr != m_versionKeysMap.end()) 204 { 205 manifestId = itr->second; 206 } 207 } 208 209 if (!manifestId) 210 { 211 manifestId = source->GetIndex().GetManifestIdByKey(m_idId, versionKey.Version, versionKey.Channel); 212 } 213 214 if (manifestId) 215 { 216 return std::make_shared<PackageVersion>(source, manifestId.value(), m_manifestCache); 217 } 218 219 return {}; 220 } 221 222 Source SQLitePackage::GetSource() const 223 { 224 return Source{ GetReferenceSource() }; 225 } 226 227 bool SQLitePackage::IsSame(const IPackage* other) const 228 { 229 const SQLitePackage* otherSQLite = PackageCast<const SQLitePackage*>(other); 230 231 if (otherSQLite) 232 { 233 return GetReferenceSource()->IsSame(otherSQLite->GetReferenceSource().get()) && m_idId == otherSQLite->m_idId; 234 } 235 236 return false; 237 } 238 239 const void* SQLitePackage::CastTo(IPackageType type) const 240 { 241 if (type == PackageType) 242 { 243 return this; 244 } 245 246 return nullptr; 247 } 248 249 std::shared_ptr<IPackage> SQLitePackage::GetInstalled() 250 { 251 return m_isInstalled ? shared_from_this() : std::shared_ptr<IPackage>{}; 252 } 253 254 std::vector<std::shared_ptr<IPackage>> SQLitePackage::GetAvailable() 255 { 256 return m_isInstalled ? std::vector<std::shared_ptr<IPackage>>{} : std::vector<std::shared_ptr<IPackage>>{ shared_from_this() }; 257 } 258 259 bool SQLitePackage::MapKey::operator<(const MapKey& other) const 260 { 261 if (Version < other.Version) 262 { 263 return true; 264 } 265 else if (Version == other.Version) 266 { 267 return Channel < other.Channel; 268 } 269 else 270 { 271 return false; 272 } 273 } 274 }