winget-cli

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

PortableIndex.cpp (5356B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "Public/winget/PortableIndex.h"
      5 #include "Microsoft/Schema/IPortableIndex.h"
      6 #include "Microsoft/Schema/Portable_1_0/PortableTable.h"
      7 #include <winget/SQLiteStorageBase.h>
      8 #include "Schema/Portable_1_0/PortableIndexInterface.h"
      9 #include <winget/Filesystem.h>
     10 
     11 namespace AppInstaller::Repository::Microsoft
     12 {
     13     PortableIndex::PortableIndex(PortableIndex&&) = default;
     14     PortableIndex& PortableIndex::operator=(PortableIndex&&) = default;
     15 
     16     PortableIndex::~PortableIndex() = default;
     17 
     18     PortableIndex PortableIndex::CreateNew(const std::string& filePath, SQLite::Version version)
     19     {
     20         AICLI_LOG(Repo, Info, << "Creating new Portable Index with version [" << version << "] at '" << filePath << "'");
     21         PortableIndex result{ filePath, version };
     22 
     23         SQLite::Savepoint savepoint = SQLite::Savepoint::Create(result.m_dbconn, "portableindex_createnew");
     24 
     25         // Use calculated version, as incoming version could be 'latest'
     26         result.m_version.SetSchemaVersion(result.m_dbconn);
     27 
     28         result.m_interface->CreateTable(result.m_dbconn);
     29 
     30         const auto& filePathUTF16 = Utility::ConvertToUTF16(filePath);
     31         SetFileAttributes(filePathUTF16.c_str(), GetFileAttributes(filePathUTF16.c_str()) | FILE_ATTRIBUTE_HIDDEN);
     32 
     33         result.SetLastWriteTime();
     34 
     35         savepoint.Commit();
     36 
     37         return result;
     38     }
     39 
     40     PortableIndex PortableIndex::Open(const std::string& filePath, OpenDisposition disposition, Utility::ManagedFile&& indexFile)
     41     {
     42         return { filePath, disposition, std::move(indexFile) };
     43     }
     44 
     45     PortableIndex::IdType PortableIndex::AddPortableFile(const Portable::PortableFileEntry& file)
     46     {
     47         std::lock_guard<std::mutex> lockInterface{ *m_interfaceLock };
     48         AICLI_LOG(Repo, Verbose, << "Adding portable file for [" << file.GetFilePath() << "]");
     49 
     50         SQLite::Savepoint savepoint = SQLite::Savepoint::Create(m_dbconn, "portableindex_addfile");
     51 
     52         IdType result = m_interface->AddPortableFile(m_dbconn, file);
     53 
     54         SetLastWriteTime();
     55 
     56         savepoint.Commit();
     57 
     58         return result;
     59     }
     60 
     61     void PortableIndex::RemovePortableFile(const Portable::PortableFileEntry& file)
     62     {
     63         AICLI_LOG(Repo, Verbose, << "Removing portable file [" << file.GetFilePath() << "]");
     64         std::lock_guard<std::mutex> lockInterface{ *m_interfaceLock };
     65 
     66         SQLite::Savepoint savepoint = SQLite::Savepoint::Create(m_dbconn, "portableindex_removefile");
     67 
     68         m_interface->RemovePortableFile(m_dbconn, file);
     69 
     70         SetLastWriteTime();
     71 
     72         savepoint.Commit();
     73     }
     74 
     75     bool PortableIndex::UpdatePortableFile(const Portable::PortableFileEntry& file)
     76     {
     77         AICLI_LOG(Repo, Verbose, << "Updating portable file [" << file.GetFilePath() << "]");
     78         std::lock_guard<std::mutex> lockInterface{ *m_interfaceLock };
     79 
     80         SQLite::Savepoint savepoint = SQLite::Savepoint::Create(m_dbconn, "portableindex_updatefile");
     81 
     82         bool result = m_interface->UpdatePortableFile(m_dbconn, file).first;
     83         
     84         if (result)
     85         {
     86             SetLastWriteTime();
     87             savepoint.Commit();
     88         }
     89 
     90         return result;
     91     }
     92 
     93     bool PortableIndex::Exists(const Portable::PortableFileEntry& file)
     94     {
     95         AICLI_LOG(Repo, Verbose, << "Checking if portable file exists [" << file.GetFilePath() << "]");
     96         return m_interface->Exists(m_dbconn, file);
     97     }
     98 
     99     bool PortableIndex::IsEmpty()
    100     {
    101         return m_interface->IsEmpty(m_dbconn);
    102     }
    103 
    104     void PortableIndex::AddOrUpdatePortableFile(const Portable::PortableFileEntry& file)
    105     {
    106         if (Exists(file))
    107         {
    108             UpdatePortableFile(file);
    109         }
    110         else
    111         {
    112             AddPortableFile(file);
    113         }
    114     }
    115 
    116     std::vector<Portable::PortableFileEntry> PortableIndex::GetAllPortableFiles()
    117     {
    118         return m_interface->GetAllPortableFiles(m_dbconn);
    119     }
    120 
    121     std::unique_ptr<Schema::IPortableIndex> PortableIndex::CreateIPortableIndex() const
    122     {
    123         if (m_version == SQLite::Version{ 1, 0 } ||
    124             m_version.MajorVersion == 1 ||
    125             m_version.IsLatest())
    126         {
    127             return std::make_unique<Schema::Portable_V1_0::PortableIndexInterface>();
    128         }
    129 
    130         THROW_HR(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED));
    131     }
    132 
    133     PortableIndex::PortableIndex(const std::string& target, SQLiteStorageBase::OpenDisposition disposition, Utility::ManagedFile&& indexFile) :
    134         SQLiteStorageBase(target, disposition, std::move(indexFile))
    135     {
    136         AICLI_LOG(Repo, Info, << "Opened Portable Index with version [" << m_version << "], last write [" << GetLastWriteTime() << "]");
    137         m_interface = CreateIPortableIndex();
    138         THROW_HR_IF(APPINSTALLER_CLI_ERROR_CANNOT_WRITE_TO_UPLEVEL_INDEX, disposition == SQLiteStorageBase::OpenDisposition::ReadWrite && m_version != m_interface->GetVersion());
    139     }
    140 
    141     PortableIndex::PortableIndex(const std::string& target, SQLite::Version version) : SQLiteStorageBase(target, version)
    142     {
    143         m_interface = CreateIPortableIndex();
    144         m_version = m_interface->GetVersion();
    145     }
    146 }