1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.createTempUpdateFile = exports.DownloadedUpdateHelper = void 0;
|
4 | const crypto_1 = require("crypto");
|
5 | const fs_1 = require("fs");
|
6 |
|
7 | const isEqual = require("lodash.isequal");
|
8 | const fs_extra_1 = require("fs-extra");
|
9 | const path = require("path");
|
10 |
|
11 | class DownloadedUpdateHelper {
|
12 | constructor(cacheDir) {
|
13 | this.cacheDir = cacheDir;
|
14 | this._file = null;
|
15 | this._packageFile = null;
|
16 | this.versionInfo = null;
|
17 | this.fileInfo = null;
|
18 | this._downloadedFileInfo = null;
|
19 | }
|
20 | get downloadedFileInfo() {
|
21 | return this._downloadedFileInfo;
|
22 | }
|
23 | get file() {
|
24 | return this._file;
|
25 | }
|
26 | get packageFile() {
|
27 | return this._packageFile;
|
28 | }
|
29 | get cacheDirForPendingUpdate() {
|
30 | return path.join(this.cacheDir, "pending");
|
31 | }
|
32 | async validateDownloadedPath(updateFile, updateInfo, fileInfo, logger) {
|
33 | if (this.versionInfo != null && this.file === updateFile && this.fileInfo != null) {
|
34 |
|
35 |
|
36 | if (isEqual(this.versionInfo, updateInfo) && isEqual(this.fileInfo.info, fileInfo.info) && (await fs_extra_1.pathExists(updateFile))) {
|
37 | return updateFile;
|
38 | }
|
39 | else {
|
40 | return null;
|
41 | }
|
42 | }
|
43 |
|
44 | const cachedUpdateFile = await this.getValidCachedUpdateFile(fileInfo, logger);
|
45 | if (cachedUpdateFile === null) {
|
46 | return null;
|
47 | }
|
48 | logger.info(`Update has already been downloaded to ${updateFile}).`);
|
49 | this._file = cachedUpdateFile;
|
50 | return cachedUpdateFile;
|
51 | }
|
52 | async setDownloadedFile(downloadedFile, packageFile, versionInfo, fileInfo, updateFileName, isSaveCache) {
|
53 | this._file = downloadedFile;
|
54 | this._packageFile = packageFile;
|
55 | this.versionInfo = versionInfo;
|
56 | this.fileInfo = fileInfo;
|
57 | this._downloadedFileInfo = {
|
58 | fileName: updateFileName,
|
59 | sha512: fileInfo.info.sha512,
|
60 | isAdminRightsRequired: fileInfo.info.isAdminRightsRequired === true,
|
61 | };
|
62 | if (isSaveCache) {
|
63 | await fs_extra_1.outputJson(this.getUpdateInfoFile(), this._downloadedFileInfo);
|
64 | }
|
65 | }
|
66 | async clear() {
|
67 | this._file = null;
|
68 | this._packageFile = null;
|
69 | this.versionInfo = null;
|
70 | this.fileInfo = null;
|
71 | await this.cleanCacheDirForPendingUpdate();
|
72 | }
|
73 | async cleanCacheDirForPendingUpdate() {
|
74 | try {
|
75 |
|
76 | await fs_extra_1.emptyDir(this.cacheDirForPendingUpdate);
|
77 | }
|
78 | catch (ignore) {
|
79 |
|
80 | }
|
81 | }
|
82 | |
83 |
|
84 |
|
85 |
|
86 |
|
87 | async getValidCachedUpdateFile(fileInfo, logger) {
|
88 | var _a;
|
89 | const updateInfoFilePath = this.getUpdateInfoFile();
|
90 | const doesUpdateInfoFileExist = await fs_extra_1.pathExists(updateInfoFilePath);
|
91 | if (!doesUpdateInfoFileExist) {
|
92 | return null;
|
93 | }
|
94 | let cachedInfo;
|
95 | try {
|
96 | cachedInfo = await fs_extra_1.readJson(updateInfoFilePath);
|
97 | }
|
98 | catch (error) {
|
99 | let message = `No cached update info available`;
|
100 | if (error.code !== "ENOENT") {
|
101 | await this.cleanCacheDirForPendingUpdate();
|
102 | message += ` (error on read: ${error.message})`;
|
103 | }
|
104 | logger.info(message);
|
105 | return null;
|
106 | }
|
107 | const isCachedInfoFileNameValid = (_a = (cachedInfo === null || cachedInfo === void 0 ? void 0 : cachedInfo.fileName) !== null) !== null && _a !== void 0 ? _a : false;
|
108 | if (!isCachedInfoFileNameValid) {
|
109 | logger.warn(`Cached update info is corrupted: no fileName, directory for cached update will be cleaned`);
|
110 | await this.cleanCacheDirForPendingUpdate();
|
111 | return null;
|
112 | }
|
113 | if (fileInfo.info.sha512 !== cachedInfo.sha512) {
|
114 | logger.info(`Cached update sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${cachedInfo.sha512}, expected: ${fileInfo.info.sha512}. Directory for cached update will be cleaned`);
|
115 | await this.cleanCacheDirForPendingUpdate();
|
116 | return null;
|
117 | }
|
118 | const updateFile = path.join(this.cacheDirForPendingUpdate, cachedInfo.fileName);
|
119 | if (!(await fs_extra_1.pathExists(updateFile))) {
|
120 | logger.info("Cached update file doesn't exist");
|
121 | return null;
|
122 | }
|
123 | const sha512 = await hashFile(updateFile);
|
124 | if (fileInfo.info.sha512 !== sha512) {
|
125 | logger.warn(`Sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${sha512}, expected: ${fileInfo.info.sha512}`);
|
126 | await this.cleanCacheDirForPendingUpdate();
|
127 | return null;
|
128 | }
|
129 | this._downloadedFileInfo = cachedInfo;
|
130 | return updateFile;
|
131 | }
|
132 | getUpdateInfoFile() {
|
133 | return path.join(this.cacheDirForPendingUpdate, "update-info.json");
|
134 | }
|
135 | }
|
136 | exports.DownloadedUpdateHelper = DownloadedUpdateHelper;
|
137 | function hashFile(file, algorithm = "sha512", encoding = "base64", options) {
|
138 | return new Promise((resolve, reject) => {
|
139 | const hash = crypto_1.createHash(algorithm);
|
140 | hash.on("error", reject).setEncoding(encoding);
|
141 | fs_1.createReadStream(file, { ...options, highWaterMark: 1024 * 1024 })
|
142 | .on("error", reject)
|
143 | .on("end", () => {
|
144 | hash.end();
|
145 | resolve(hash.read());
|
146 | })
|
147 | .pipe(hash, { end: false });
|
148 | });
|
149 | }
|
150 | async function createTempUpdateFile(name, cacheDir, log) {
|
151 |
|
152 | let nameCounter = 0;
|
153 | let result = path.join(cacheDir, name);
|
154 | for (let i = 0; i < 3; i++) {
|
155 | try {
|
156 | await fs_extra_1.unlink(result);
|
157 | return result;
|
158 | }
|
159 | catch (e) {
|
160 | if (e.code === "ENOENT") {
|
161 | return result;
|
162 | }
|
163 | log.warn(`Error on remove temp update file: ${e}`);
|
164 | result = path.join(cacheDir, `${nameCounter++}-${name}`);
|
165 | }
|
166 | }
|
167 | return result;
|
168 | }
|
169 | exports.createTempUpdateFile = createTempUpdateFile;
|
170 |
|
\ | No newline at end of file |