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 }