winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }