MiKTeX 23.10-next
A scalable TeX distribution
Loading...
Searching...
No Matches
PackageInstallerImpl.h
Go to the documentation of this file.
1
14#pragma once
15
16#include <memory>
17#include <mutex>
18#include <set>
19#include <thread>
20#include <vector>
21
22#include <miktex/Core/Cfg>
23#include <miktex/Core/Session>
24#include <miktex/Core/TemporaryFile>
25#include <miktex/Extractor/Extractor>
26#include <miktex/Trace/Trace>
27
28#include "PackageManagerImpl.h"
29#include "RepositoryManifest.h"
30
31#if defined(MIKTEX_WINDOWS)
32#include <miktex/Core/win/COMInitializer>
33#endif
34
35#if defined(MIKTEX_WINDOWS) && USE_LOCAL_SERVER
36#include "COM/com-internal.h"
37#endif
38
39MPM_INTERNAL_BEGIN_NAMESPACE;
40
42#if defined(MIKTEX_WINDOWS) && USE_LOCAL_SERVER
43 public MiKTeXPackageManagerLib::IPackageInstallerCallback,
44#endif
45 public IProgressNotify_,
50{
51
52public:
53
54 PackageInstallerImpl(std::shared_ptr<MiKTeX::Packages::D6AAD62216146D44B580E92711724B78::PackageManagerImpl> manager, const InitInfo& initInfo);
55 MIKTEXTHISCALL ~PackageInstallerImpl() override;
56
57 void MIKTEXTHISCALL Dispose() override;
58 void MIKTEXTHISCALL Download() override;
59 void MIKTEXTHISCALL DownloadAsync() override;
60 void MIKTEXTHISCALL FindUpdatesAsync() override;
61 void MIKTEXTHISCALL FindUpgradesAsync(PackageLevel packageLevel) override;
62 void MIKTEXTHISCALL InstallRemove(Role role) override;
63 void MIKTEXTHISCALL InstallRemoveAsync(Role role) override;
64 void MIKTEXTHISCALL OnBeginFileExtraction(const std::string& fileName, std::size_t uncompressedSize) override;
65 void MIKTEXTHISCALL OnEndFileExtraction(const std::string& fileName, std::size_t uncompressedSize) override;
66 bool MIKTEXTHISCALL OnError(const std::string& message) override;
67 bool MIKTEXTHISCALL OnProcessOutput(const void* pOutput, std::size_t n) override;
68 void OnProgress() override;
69 void MIKTEXTHISCALL RegisterComponents(bool doRegister) override;
70 void MIKTEXTHISCALL SetCallback(PackageInstallerCallback* callback) override;
71 void MIKTEXTHISCALL UpdateDbAsync() override;
72 void MIKTEXTHISCALL WaitForCompletion() override;
73
74#if defined(MIKTEX_WINDOWS) && USE_LOCAL_SERVER
75 STDMETHOD_(ULONG, AddRef)();
76 HRESULT __stdcall OnProgress(LONG nf, VARIANT_BOOL* pDoContinue) override;
77 HRESULT __stdcall OnRetryableError(BSTR message, VARIANT_BOOL* pDoContinue) override;
78 STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObj);
79 STDMETHOD_(ULONG, Release)();
80 HRESULT __stdcall ReportLine(BSTR line) override;
81#endif
82
83 void MIKTEXTHISCALL FindUpdates() override
84 {
85 MPM_LOCK_BEGIN(this->packageManager)
86 {
87 FindUpdatesNoLock();
88 }
89 MPM_LOCK_END();
90 }
91
92 void MIKTEXTHISCALL FindUpgrades(PackageLevel packageLevel) override
93 {
94 // TODO: locking
95 FindUpgradesNoLock(packageLevel);
96 }
97
98 ProgressInfo MIKTEXTHISCALL GetProgressInfo() override
99 {
100 std::lock_guard<std::mutex> lockGuard(progressIndicatorMutex);
101 if (progressInfo.numErrors > 0)
102 {
103 throw threadMiKTeXException;
104 }
105 return progressInfo;
106 }
107
108 std::vector<UpdateInfo> MIKTEXTHISCALL GetUpdates() override
109 {
110 return updates;
111 }
112
113 std::vector<UpgradeInfo> MIKTEXTHISCALL GetUpgrades() override
114 {
115 return upgrades;
116 }
117
118 bool MIKTEXTHISCALL IsRunning() const override
119 {
120 if (!workerThread.joinable())
121 {
122 return false;
123 }
124 return !progressInfo.ready;
125 }
126
127 void MIKTEXTHISCALL SetDownloadDirectory(const MiKTeX::Util::PathName& directory) override
128 {
129 this->downloadDirectory = directory;
130 }
131
132 void MIKTEXTHISCALL SetFileList(const std::vector<std::string>& tbi) override
133 {
134 SetFileLists(tbi, std::vector<std::string>());
135 }
136
137 void MIKTEXTHISCALL SetFileLists(const std::vector<std::string>& tbi, const std::vector<std::string>& tbr) override
138 {
139 this->toBeInstalled = tbi;
140 this->toBeRemoved = tbr;
141 }
142
143 void MIKTEXTHISCALL SetPackageLevel(PackageLevel packageLevel) override
144 {
145 taskPackageLevel = packageLevel;
146 }
147
148 void MIKTEXTHISCALL SetRepository(const std::string& repository) override
149 {
150 repositoryType = PackageRepositoryDataStore::DetermineRepositoryType(repository);
151 this->repository = repository;
152 }
153
154 void MIKTEXTHISCALL UpdateDb(UpdateDbOptionSet options) override
155 {
156 MPM_LOCK_BEGIN(this->packageManager)
157 {
158 UpdateDbNoLock(options);
159 }
160 MPM_LOCK_END();
161 }
162
163private:
164
165 enum ErrorCode
166 {
167 ERROR_CANNOT_DELETE,
168 ERROR_CORRUPTED_PACKAGE,
169 ERROR_MISSING_PACKAGE,
170 ERROR_SIZE_MISMATCH,
171 ERROR_SOURCE_FILE_NOT_FOUND,
172 };
173
174 void CalculateExpenditure(bool downloadOnly = false);
175 bool CheckArchiveFile(const std::string& packageId, const MiKTeX::Util::PathName& archiveFileName, bool mustBeOk);
176 void CheckDependencies(std::set<std::string>& packages, const std::string& packageId, bool force, int level);
177 void CleanUpUserDatabase();
178 void CopyFiles(const MiKTeX::Util::PathName& pathSourceRoot, const std::vector<std::string>& fileList);
179 void CopyPackage(const MiKTeX::Util::PathName& pathSourceRoot, const std::string& packageId);
180 void Download(const MiKTeX::Util::PathName& fileName, std::size_t expectedSize = 0);
181 void Download(const std::string& url, const MiKTeX::Util::PathName& dest, std::size_t expectedSize = 0);
182 void DownloadPackage(const std::string& packageId);
183 void DownloadThread();
184 void ExtractFiles(const MiKTeX::Util::PathName& archiveFileName, MiKTeX::Extractor::ArchiveFileType archiveFileType);
185 std::string FatalError(ErrorCode error);
186 void FindUpdatesNoLock();
187 void FindUpdatesThread();
188 void FindUpgradesNoLock(PackageLevel packageLevel);
189 void FindUpgradesThread();
190 void InstallPackage(const std::string& packageId, MiKTeX::Core::Cfg& packageManifests);
191 void HandleObsoletePackageManifests(MiKTeX::Core::Cfg& cfgExisting, const MiKTeX::Core::Cfg& cfgNew);
192 void InstallRemoveThread();
193 void InstallRepositoryManifest(bool fromCache);
194 void LoadRepositoryManifest(bool download);
195 std::string MakeUrl(const std::string& relPath);
196 void MyCopyFile(const MiKTeX::Util::PathName& source, const MiKTeX::Util::PathName& dest, std::size_t& size);
197 void NeedRepository();
198 bool MIKTEXTHISCALL OnProgress(unsigned level, const MiKTeX::Util::PathName& directory) override;
199 bool MIKTEXTHISCALL ReadDirectory(const MiKTeX::Util::PathName& path, std::vector<std::string>& subDirNames, std::vector<std::string>& fileNames, std::vector<std::string>& fileNameInfos) override;
200 void RegisterComponents(bool doRegister, const std::vector<std::string>& packages);
201 void RemoveFiles(const std::vector<std::string>& toBeRemoved, bool silently = false);
202 void RemovePackage(const std::string& packageId, MiKTeX::Core::Cfg& packageManifests);
203 void ReportLine(const std::string& s);
204 void RunOneMiKTeXUtility(const std::vector<std::string>& arguments);
205 void StartWorkerThread(void (PackageInstallerImpl::* method)());
206 void UpdateDbNoLock(UpdateDbOptionSet options);
207 void UpdateDbThread();
208 void UpdateFndb(const std::unordered_set<MiKTeX::Util::PathName>& installedFiles, const std::unordered_set<MiKTeX::Util::PathName>& removedFiles, const std::string& packageId);
209
210#if defined(MIKTEX_WINDOWS)
211 void RegisterComponent(bool doRegister, const MiKTeX::Util::PathName& path, bool mustSucceed);
212#endif
213
214#if defined(MIKTEX_WINDOWS) && USE_LOCAL_SERVER
215 bool UseLocalServer();
216 void ConnectToServer();
217#endif
218
219 bool AbortOrRetry(const std::string& message)
220 {
221 return callback == nullptr || !callback->OnRetryableError(message);
222 }
223
224 void Notify(MiKTeX::Packages::Notification nf = MiKTeX::Packages::Notification::None)
225 {
226 if (callback != nullptr && !callback->OnProgress(nf))
227 {
228 trace_mpm->WriteLine(TRACE_FACILITY, T_("client wants to cancel"));
229 trace_mpm->WriteLine(TRACE_FACILITY, T_("throwing OperationCancelledException"));
230 throw MiKTeX::Core::OperationCancelledException();
231 }
232 }
233
234 void RegisterComponents(bool doRegister, const std::vector<std::string>& packages, const std::vector<std::string>& packages2)
235 {
236 RegisterComponents(doRegister, packages);
237 RegisterComponents(doRegister, packages2);
238 }
239
241 Role currentRole;
242 MiKTeX::Util::PathName downloadDirectory;
243 bool enablePostProcessing = true;
244 std::unordered_set<MiKTeX::Util::PathName> installedFiles;
245 PackageDataStore* packageDataStore = nullptr;
246 std::shared_ptr<PackageManagerImpl> packageManager;
247 std::mutex progressIndicatorMutex;
248 ProgressInfo progressInfo;
249 std::unordered_set<MiKTeX::Util::PathName> removedFiles;
250 std::string repository;
251 RepositoryManifest repositoryManifest;
252 MiKTeX::Packages::RepositoryReleaseState repositoryReleaseState = MiKTeX::Packages::RepositoryReleaseState::Unknown;
253 MiKTeX::Packages::RepositoryType repositoryType = MiKTeX::Packages::RepositoryType::Unknown;
254 std::shared_ptr<MiKTeX::Core::Session> session;
255 MiKTeX::Packages::PackageLevel taskPackageLevel = MiKTeX::Packages::PackageLevel::None;
256 MiKTeX::Core::MiKTeXException threadMiKTeXException;
257 clock_t timeStarted;
258 std::vector<std::string> toBeInstalled;
259 std::vector<std::string> toBeRemoved;
260 std::mutex thisMutex;
261 std::unique_ptr<MiKTeX::Trace::TraceStream> trace_error;
262 std::unique_ptr<MiKTeX::Trace::TraceStream> trace_mpm;
263 std::unique_ptr<MiKTeX::Trace::TraceStream> trace_stopwatch;
264 std::vector<UpdateInfo> updates;
265 PackageLevel upgradeLevel = PackageLevel::None;
266 std::vector<UpgradeInfo> upgrades;
267 std::thread workerThread;
268
269#if defined(MIKTEX_WINDOWS) && USE_LOCAL_SERVER
270 struct LocalServer :
271 public MiKTeX::Core::COMInitializer
272 {
273 ATL::CComPtr<MiKTeXPackageManagerLib::IPackageInstaller> pInstaller;
274 ATL::CComQIPtr<MiKTeXPackageManagerLib::IPackageManager> pManager;
275 };
276 std::unique_ptr<LocalServer> localServer;
277#endif
278};
279
280MPM_INTERNAL_END_NAMESPACE;
PackageManager implementation.
INI container.
Definition: Cfg.h:60
Run process callback interface.
Definition: Process.h:47
Definition: Extractor.h:52
Callback interface.
Definition: PackageInstaller.h:79
virtual bool OnRetryableError(const std::string &message)=0
virtual bool OnProgress(Notification nf)=0
Definition: PackageInstaller.h:103
Role
Installation role.
Definition: PackageInstaller.h:214
Definition: PackageInstallerImpl.h:50
void UpdateDb(UpdateDbOptionSet options) override
Synchronizes the package database.
Definition: PackageInstallerImpl.h:154
void FindUpdates() override
Checks for updates.
Definition: PackageInstallerImpl.h:83
std::vector< UpgradeInfo > GetUpgrades() override
Definition: PackageInstallerImpl.h:113
void SetPackageLevel(PackageLevel packageLevel) override
Definition: PackageInstallerImpl.h:143
void SetRepository(const std::string &repository) override
Definition: PackageInstallerImpl.h:148
ProgressInfo GetProgressInfo() override
Definition: PackageInstallerImpl.h:98
void FindUpgrades(PackageLevel packageLevel) override
Definition: PackageInstallerImpl.h:92
void SetFileList(const std::vector< std::string > &tbi) override
Definition: PackageInstallerImpl.h:132
std::vector< UpdateInfo > GetUpdates() override
Definition: PackageInstallerImpl.h:108
void SetDownloadDirectory(const MiKTeX::Util::PathName &directory) override
Definition: PackageInstallerImpl.h:127
void SetFileLists(const std::vector< std::string > &tbi, const std::vector< std::string > &tbr) override
Definition: PackageInstallerImpl.h:137
bool IsRunning() const override
Definition: PackageInstallerImpl.h:118
Definition: OptionSet.h:37
Instances of this class can be used to store path names.
Definition: PathName.h:73
Notification
Installer notifications.
Definition: PackageInstaller.h:53
PackageLevel
Package level.
Definition: RepositoryInfo.h:40
RepositoryReleaseState
Repository release state.
Definition: RepositoryInfo.h:174
RepositoryType
Repository type.
Definition: RepositoryInfo.h:78
Initialization options.
Definition: PackageInstaller.h:373
Progress information.
Definition: PackageInstaller.h:254