react-native-update 10.38.3 → 10.38.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/harmony/pushy/src/main/cpp/CMakeLists.txt +70 -0
- package/harmony/pushy/src/main/cpp/PushyPackage.h +55 -0
- package/harmony/pushy/src/main/cpp/PushyTurboModule.cpp +142 -0
- package/harmony/pushy/src/main/cpp/PushyTurboModule.h +38 -0
- package/harmony/pushy/src/main/cpp/pushy.c +117 -0
- package/harmony/pushy/src/main/cpp/pushy.cpp +856 -0
- package/harmony/pushy/src/main/cpp/pushy.h +8 -0
- package/harmony/pushy/src/main/ets/DownloadTask.ts +610 -0
- package/harmony/pushy/src/main/ets/DownloadTaskParams.ts +19 -0
- package/harmony/pushy/src/main/ets/EventHub.ts +39 -0
- package/harmony/pushy/src/main/ets/Logger.ts +52 -0
- package/harmony/pushy/src/main/ets/NativePatchCore.ts +87 -0
- package/harmony/pushy/src/main/ets/PushyFileJSBundleProvider.ets +50 -0
- package/harmony/pushy/src/main/ets/PushyPackage.ts +22 -0
- package/harmony/pushy/src/main/ets/PushyTurboModule.ts +139 -0
- package/harmony/pushy/src/main/ets/SaveFile.ts +34 -0
- package/harmony/pushy/src/main/ets/UpdateContext.ts +346 -0
- package/harmony/pushy/src/main/ets/UpdateModuleImpl.ts +123 -0
- package/harmony/pushy/src/main/module.json5 +7 -0
- package/harmony/pushy/src/main/resources/base/element/string.json +8 -0
- package/harmony/pushy/src/main/resources/en_US/element/string.json +8 -0
- package/harmony/pushy/src/main/resources/zh_CN/element/string.json +8 -0
- package/harmony/pushy.har +0 -0
- package/package.json +1 -1
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
#include <napi/native_api.h>
|
|
2
|
+
#include <js_native_api.h>
|
|
3
|
+
#include <js_native_api_types.h>
|
|
4
|
+
|
|
5
|
+
#include <string>
|
|
6
|
+
#include <vector>
|
|
7
|
+
|
|
8
|
+
#include "archive_patch_core.h"
|
|
9
|
+
#include "patch_core.h"
|
|
10
|
+
#include "state_core.h"
|
|
11
|
+
|
|
12
|
+
extern "C" {
|
|
13
|
+
#include "hpatch.h"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
namespace {
|
|
17
|
+
|
|
18
|
+
enum class StateOperation {
|
|
19
|
+
kSwitchVersion = 1,
|
|
20
|
+
kMarkSuccess = 2,
|
|
21
|
+
kRollback = 3,
|
|
22
|
+
kClearFirstTime = 4,
|
|
23
|
+
kClearRollbackMark = 5,
|
|
24
|
+
kResolveLaunch = 6,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
constexpr const char* kDefaultBundlePatchEntryName = "index.bundlejs.patch";
|
|
28
|
+
|
|
29
|
+
void ThrowError(napi_env env, const std::string& message) {
|
|
30
|
+
napi_throw_error(env, nullptr, message.c_str());
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
bool GetArgCount(
|
|
34
|
+
napi_env env,
|
|
35
|
+
napi_callback_info info,
|
|
36
|
+
size_t* argc,
|
|
37
|
+
napi_value* args) {
|
|
38
|
+
return napi_get_cb_info(env, info, argc, args, nullptr, nullptr) == napi_ok;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
bool GetValueType(
|
|
42
|
+
napi_env env,
|
|
43
|
+
napi_value value,
|
|
44
|
+
napi_valuetype* out_type) {
|
|
45
|
+
return napi_typeof(env, value, out_type) == napi_ok;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
bool IsNullOrUndefined(napi_env env, napi_value value) {
|
|
49
|
+
napi_valuetype type = napi_undefined;
|
|
50
|
+
if (!GetValueType(env, value, &type)) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return type == napi_undefined || type == napi_null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
std::string GetString(napi_env env, napi_value value, bool* ok) {
|
|
57
|
+
if (ok != nullptr) {
|
|
58
|
+
*ok = false;
|
|
59
|
+
}
|
|
60
|
+
if (value == nullptr || IsNullOrUndefined(env, value)) {
|
|
61
|
+
if (ok != nullptr) {
|
|
62
|
+
*ok = true;
|
|
63
|
+
}
|
|
64
|
+
return std::string();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
napi_valuetype type = napi_undefined;
|
|
68
|
+
if (!GetValueType(env, value, &type) || type != napi_string) {
|
|
69
|
+
ThrowError(env, "Expected string");
|
|
70
|
+
return std::string();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
size_t length = 0;
|
|
74
|
+
if (napi_get_value_string_utf8(env, value, nullptr, 0, &length) != napi_ok) {
|
|
75
|
+
ThrowError(env, "Failed to read string");
|
|
76
|
+
return std::string();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
std::string result(length, '\0');
|
|
80
|
+
size_t written = 0;
|
|
81
|
+
if (napi_get_value_string_utf8(
|
|
82
|
+
env, value, result.data(), length + 1, &written) != napi_ok) {
|
|
83
|
+
ThrowError(env, "Failed to read string");
|
|
84
|
+
return std::string();
|
|
85
|
+
}
|
|
86
|
+
result.resize(written);
|
|
87
|
+
if (ok != nullptr) {
|
|
88
|
+
*ok = true;
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
bool GetInt32(napi_env env, napi_value value, int32_t* out_value) {
|
|
94
|
+
if (value == nullptr || out_value == nullptr) {
|
|
95
|
+
ThrowError(env, "Expected number");
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
napi_valuetype type = napi_undefined;
|
|
99
|
+
if (!GetValueType(env, value, &type) || type != napi_number) {
|
|
100
|
+
ThrowError(env, "Expected number");
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
if (napi_get_value_int32(env, value, out_value) != napi_ok) {
|
|
104
|
+
ThrowError(env, "Failed to read number");
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
bool GetBoolean(napi_env env, napi_value value, bool* out_value) {
|
|
111
|
+
if (out_value == nullptr) {
|
|
112
|
+
ThrowError(env, "Expected boolean");
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
if (value == nullptr || IsNullOrUndefined(env, value)) {
|
|
116
|
+
*out_value = false;
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
napi_valuetype type = napi_undefined;
|
|
120
|
+
if (!GetValueType(env, value, &type) || type != napi_boolean) {
|
|
121
|
+
ThrowError(env, "Expected boolean");
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
bool result = false;
|
|
125
|
+
if (napi_get_value_bool(env, value, &result) != napi_ok) {
|
|
126
|
+
ThrowError(env, "Failed to read boolean");
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
*out_value = result;
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
bool HasNamedProperty(napi_env env, napi_value object, const char* name, bool* out_has) {
|
|
134
|
+
if (out_has == nullptr) {
|
|
135
|
+
ThrowError(env, "Internal error");
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
bool has = false;
|
|
139
|
+
if (napi_has_named_property(env, object, name, &has) != napi_ok) {
|
|
140
|
+
ThrowError(env, std::string("Failed to read property ") + name);
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
*out_has = has;
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
bool GetNamedProperty(
|
|
148
|
+
napi_env env,
|
|
149
|
+
napi_value object,
|
|
150
|
+
const char* name,
|
|
151
|
+
napi_value* out_value) {
|
|
152
|
+
if (out_value == nullptr) {
|
|
153
|
+
ThrowError(env, "Internal error");
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
if (napi_get_named_property(env, object, name, out_value) != napi_ok) {
|
|
157
|
+
ThrowError(env, std::string("Failed to read property ") + name);
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
bool GetOptionalStringProperty(
|
|
164
|
+
napi_env env,
|
|
165
|
+
napi_value object,
|
|
166
|
+
const char* name,
|
|
167
|
+
std::string* out_value) {
|
|
168
|
+
bool has = false;
|
|
169
|
+
if (!HasNamedProperty(env, object, name, &has)) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
if (!has) {
|
|
173
|
+
out_value->clear();
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
napi_value property = nullptr;
|
|
178
|
+
if (!GetNamedProperty(env, object, name, &property)) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
bool ok = false;
|
|
183
|
+
*out_value = GetString(env, property, &ok);
|
|
184
|
+
return ok;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
bool GetOptionalBoolProperty(
|
|
188
|
+
napi_env env,
|
|
189
|
+
napi_value object,
|
|
190
|
+
const char* name,
|
|
191
|
+
bool default_value,
|
|
192
|
+
bool* out_value) {
|
|
193
|
+
bool has = false;
|
|
194
|
+
if (!HasNamedProperty(env, object, name, &has)) {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
if (!has) {
|
|
198
|
+
*out_value = default_value;
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
napi_value property = nullptr;
|
|
203
|
+
if (!GetNamedProperty(env, object, name, &property)) {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
return GetBoolean(env, property, out_value);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
bool GetStringArray(
|
|
210
|
+
napi_env env,
|
|
211
|
+
napi_value value,
|
|
212
|
+
std::vector<std::string>* out_values) {
|
|
213
|
+
out_values->clear();
|
|
214
|
+
if (value == nullptr || IsNullOrUndefined(env, value)) {
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
bool is_array = false;
|
|
219
|
+
if (napi_is_array(env, value, &is_array) != napi_ok || !is_array) {
|
|
220
|
+
ThrowError(env, "Expected string array");
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
uint32_t length = 0;
|
|
225
|
+
if (napi_get_array_length(env, value, &length) != napi_ok) {
|
|
226
|
+
ThrowError(env, "Failed to read array length");
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
out_values->reserve(length);
|
|
231
|
+
for (uint32_t index = 0; index < length; ++index) {
|
|
232
|
+
napi_value item = nullptr;
|
|
233
|
+
if (napi_get_element(env, value, index, &item) != napi_ok) {
|
|
234
|
+
ThrowError(env, "Failed to read array item");
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
bool ok = false;
|
|
238
|
+
out_values->push_back(GetString(env, item, &ok));
|
|
239
|
+
if (!ok) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
bool GetOptionalStringArrayProperty(
|
|
247
|
+
napi_env env,
|
|
248
|
+
napi_value object,
|
|
249
|
+
const char* name,
|
|
250
|
+
std::vector<std::string>* out_values) {
|
|
251
|
+
bool has = false;
|
|
252
|
+
if (!HasNamedProperty(env, object, name, &has)) {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
if (!has) {
|
|
256
|
+
out_values->clear();
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
napi_value property = nullptr;
|
|
261
|
+
if (!GetNamedProperty(env, object, name, &property)) {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
return GetStringArray(env, property, out_values);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
bool GetObject(napi_env env, napi_value value) {
|
|
268
|
+
if (value == nullptr || IsNullOrUndefined(env, value)) {
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
napi_valuetype type = napi_undefined;
|
|
272
|
+
if (!GetValueType(env, value, &type) || type != napi_object) {
|
|
273
|
+
ThrowError(env, "Expected object");
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
pushy::state::State ReadState(napi_env env, napi_value value, bool* ok) {
|
|
280
|
+
if (ok != nullptr) {
|
|
281
|
+
*ok = false;
|
|
282
|
+
}
|
|
283
|
+
pushy::state::State state;
|
|
284
|
+
if (value == nullptr || IsNullOrUndefined(env, value)) {
|
|
285
|
+
if (ok != nullptr) {
|
|
286
|
+
*ok = true;
|
|
287
|
+
}
|
|
288
|
+
return state;
|
|
289
|
+
}
|
|
290
|
+
if (!GetObject(env, value)) {
|
|
291
|
+
return state;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (!GetOptionalStringProperty(env, value, "packageVersion", &state.package_version) ||
|
|
295
|
+
!GetOptionalStringProperty(env, value, "buildTime", &state.build_time) ||
|
|
296
|
+
!GetOptionalStringProperty(env, value, "currentVersion", &state.current_version) ||
|
|
297
|
+
!GetOptionalStringProperty(env, value, "lastVersion", &state.last_version) ||
|
|
298
|
+
!GetOptionalBoolProperty(env, value, "firstTime", false, &state.first_time) ||
|
|
299
|
+
!GetOptionalBoolProperty(env, value, "firstTimeOk", true, &state.first_time_ok) ||
|
|
300
|
+
!GetOptionalStringProperty(env, value, "rolledBackVersion", &state.rolled_back_version)) {
|
|
301
|
+
return state;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (ok != nullptr) {
|
|
305
|
+
*ok = true;
|
|
306
|
+
}
|
|
307
|
+
return state;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
napi_value NewBoolean(napi_env env, bool value) {
|
|
311
|
+
napi_value result = nullptr;
|
|
312
|
+
napi_get_boolean(env, value, &result);
|
|
313
|
+
return result;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
napi_value NewString(napi_env env, const std::string& value) {
|
|
317
|
+
napi_value result = nullptr;
|
|
318
|
+
napi_create_string_utf8(env, value.c_str(), value.size(), &result);
|
|
319
|
+
return result;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
void SetStringProperty(
|
|
323
|
+
napi_env env,
|
|
324
|
+
napi_value object,
|
|
325
|
+
const char* name,
|
|
326
|
+
const std::string& value) {
|
|
327
|
+
if (value.empty()) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
napi_set_named_property(env, object, name, NewString(env, value));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
void SetBoolProperty(
|
|
334
|
+
napi_env env,
|
|
335
|
+
napi_value object,
|
|
336
|
+
const char* name,
|
|
337
|
+
bool value) {
|
|
338
|
+
napi_set_named_property(env, object, name, NewBoolean(env, value));
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
napi_value NewStateResult(
|
|
342
|
+
napi_env env,
|
|
343
|
+
const pushy::state::State& state,
|
|
344
|
+
bool changed,
|
|
345
|
+
const std::string& stale_version_to_delete,
|
|
346
|
+
const std::string& load_version,
|
|
347
|
+
bool did_rollback,
|
|
348
|
+
bool consumed_first_time) {
|
|
349
|
+
napi_value result = nullptr;
|
|
350
|
+
napi_create_object(env, &result);
|
|
351
|
+
|
|
352
|
+
SetStringProperty(env, result, "packageVersion", state.package_version);
|
|
353
|
+
SetStringProperty(env, result, "buildTime", state.build_time);
|
|
354
|
+
SetStringProperty(env, result, "currentVersion", state.current_version);
|
|
355
|
+
SetStringProperty(env, result, "lastVersion", state.last_version);
|
|
356
|
+
SetBoolProperty(env, result, "firstTime", state.first_time);
|
|
357
|
+
SetBoolProperty(env, result, "firstTimeOk", state.first_time_ok);
|
|
358
|
+
SetStringProperty(env, result, "rolledBackVersion", state.rolled_back_version);
|
|
359
|
+
SetBoolProperty(env, result, "changed", changed);
|
|
360
|
+
SetStringProperty(env, result, "staleVersionToDelete", stale_version_to_delete);
|
|
361
|
+
SetStringProperty(env, result, "loadVersion", load_version);
|
|
362
|
+
SetBoolProperty(env, result, "didRollback", did_rollback);
|
|
363
|
+
SetBoolProperty(env, result, "consumedFirstTime", consumed_first_time);
|
|
364
|
+
return result;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
napi_value NewArchivePatchPlanResult(
|
|
368
|
+
napi_env env,
|
|
369
|
+
const pushy::archive_patch::ArchivePatchPlan& plan) {
|
|
370
|
+
napi_value result = nullptr;
|
|
371
|
+
napi_create_object(env, &result);
|
|
372
|
+
SetStringProperty(env, result, "mergeSourceSubdir", plan.merge_source_subdir);
|
|
373
|
+
SetBoolProperty(env, result, "enableMerge", plan.enable_merge);
|
|
374
|
+
return result;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
napi_value NewCopyGroupArray(
|
|
378
|
+
napi_env env,
|
|
379
|
+
const std::vector<pushy::archive_patch::CopyGroup>& groups) {
|
|
380
|
+
napi_value result = nullptr;
|
|
381
|
+
napi_create_array_with_length(env, groups.size(), &result);
|
|
382
|
+
for (size_t index = 0; index < groups.size(); ++index) {
|
|
383
|
+
napi_value group = nullptr;
|
|
384
|
+
napi_create_object(env, &group);
|
|
385
|
+
SetStringProperty(env, group, "from", groups[index].from);
|
|
386
|
+
|
|
387
|
+
napi_value to_paths = nullptr;
|
|
388
|
+
napi_create_array_with_length(env, groups[index].to_paths.size(), &to_paths);
|
|
389
|
+
for (size_t target_index = 0; target_index < groups[index].to_paths.size();
|
|
390
|
+
++target_index) {
|
|
391
|
+
napi_set_element(
|
|
392
|
+
env,
|
|
393
|
+
to_paths,
|
|
394
|
+
target_index,
|
|
395
|
+
NewString(env, groups[index].to_paths[target_index]));
|
|
396
|
+
}
|
|
397
|
+
napi_set_named_property(env, group, "toPaths", to_paths);
|
|
398
|
+
napi_set_element(env, result, index, group);
|
|
399
|
+
}
|
|
400
|
+
return result;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
pushy::patch::PatchManifest BuildManifest(
|
|
404
|
+
const std::vector<std::string>& copy_froms,
|
|
405
|
+
const std::vector<std::string>& copy_tos,
|
|
406
|
+
const std::vector<std::string>& deletes) {
|
|
407
|
+
pushy::patch::PatchManifest manifest;
|
|
408
|
+
for (size_t index = 0; index < copy_froms.size(); ++index) {
|
|
409
|
+
manifest.copies.push_back(
|
|
410
|
+
pushy::patch::CopyOperation{copy_froms[index], copy_tos[index]});
|
|
411
|
+
}
|
|
412
|
+
manifest.deletes = deletes;
|
|
413
|
+
return manifest;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
napi_value HdiffPatch(napi_env env, napi_callback_info info) {
|
|
417
|
+
napi_value args[2] = {nullptr, nullptr};
|
|
418
|
+
size_t argc = 2;
|
|
419
|
+
if (!GetArgCount(env, info, &argc, args) || argc < 2) {
|
|
420
|
+
ThrowError(env, "Wrong number of arguments");
|
|
421
|
+
return nullptr;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
bool is_typed_array = false;
|
|
425
|
+
if (napi_is_typedarray(env, args[0], &is_typed_array) != napi_ok || !is_typed_array) {
|
|
426
|
+
ThrowError(env, "First argument must be a TypedArray");
|
|
427
|
+
return nullptr;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
uint8_t* origin_ptr = nullptr;
|
|
431
|
+
size_t origin_length = 0;
|
|
432
|
+
if (napi_get_typedarray_info(
|
|
433
|
+
env,
|
|
434
|
+
args[0],
|
|
435
|
+
nullptr,
|
|
436
|
+
&origin_length,
|
|
437
|
+
reinterpret_cast<void**>(&origin_ptr),
|
|
438
|
+
nullptr,
|
|
439
|
+
nullptr) != napi_ok) {
|
|
440
|
+
ThrowError(env, "Failed to get origin buffer");
|
|
441
|
+
return nullptr;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
if (napi_is_typedarray(env, args[1], &is_typed_array) != napi_ok || !is_typed_array) {
|
|
445
|
+
ThrowError(env, "Second argument must be a TypedArray");
|
|
446
|
+
return nullptr;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
uint8_t* patch_ptr = nullptr;
|
|
450
|
+
size_t patch_length = 0;
|
|
451
|
+
if (napi_get_typedarray_info(
|
|
452
|
+
env,
|
|
453
|
+
args[1],
|
|
454
|
+
nullptr,
|
|
455
|
+
&patch_length,
|
|
456
|
+
reinterpret_cast<void**>(&patch_ptr),
|
|
457
|
+
nullptr,
|
|
458
|
+
nullptr) != napi_ok) {
|
|
459
|
+
ThrowError(env, "Failed to get patch buffer");
|
|
460
|
+
return nullptr;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
hpatch_singleCompressedDiffInfo patch_info;
|
|
464
|
+
if (!((origin_length == 0) || origin_ptr) || !patch_ptr || patch_length == 0) {
|
|
465
|
+
ThrowError(env, "Corrupt patch");
|
|
466
|
+
return nullptr;
|
|
467
|
+
}
|
|
468
|
+
if (kHPatch_ok != hpatch_getInfo_by_mem(&patch_info, patch_ptr, patch_length)) {
|
|
469
|
+
ThrowError(env, "Error info in hpatch");
|
|
470
|
+
return nullptr;
|
|
471
|
+
}
|
|
472
|
+
if (origin_length != patch_info.oldDataSize) {
|
|
473
|
+
ThrowError(env, "Error oldDataSize in hpatch");
|
|
474
|
+
return nullptr;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
size_t new_size = static_cast<size_t>(patch_info.newDataSize);
|
|
478
|
+
if (sizeof(size_t) != sizeof(hpatch_StreamPos_t) &&
|
|
479
|
+
new_size != patch_info.newDataSize) {
|
|
480
|
+
ThrowError(env, "Error newDataSize in hpatch");
|
|
481
|
+
return nullptr;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
void* output_data = nullptr;
|
|
485
|
+
napi_value result = nullptr;
|
|
486
|
+
if (napi_create_arraybuffer(env, new_size, &output_data, &result) != napi_ok) {
|
|
487
|
+
ThrowError(env, "Failed to create result buffer");
|
|
488
|
+
return nullptr;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
if (kHPatch_ok != hpatch_by_mem(
|
|
492
|
+
origin_ptr,
|
|
493
|
+
origin_length,
|
|
494
|
+
static_cast<uint8_t*>(output_data),
|
|
495
|
+
new_size,
|
|
496
|
+
patch_ptr,
|
|
497
|
+
patch_length,
|
|
498
|
+
&patch_info)) {
|
|
499
|
+
ThrowError(env, "hpatch");
|
|
500
|
+
return nullptr;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
return result;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
napi_value SyncStateWithBinaryVersion(napi_env env, napi_callback_info info) {
|
|
507
|
+
napi_value args[3] = {nullptr, nullptr, nullptr};
|
|
508
|
+
size_t argc = 3;
|
|
509
|
+
if (!GetArgCount(env, info, &argc, args) || argc < 3) {
|
|
510
|
+
ThrowError(env, "Wrong number of arguments");
|
|
511
|
+
return nullptr;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
bool ok = false;
|
|
515
|
+
const std::string package_version = GetString(env, args[0], &ok);
|
|
516
|
+
if (!ok) {
|
|
517
|
+
return nullptr;
|
|
518
|
+
}
|
|
519
|
+
const std::string build_time = GetString(env, args[1], &ok);
|
|
520
|
+
if (!ok) {
|
|
521
|
+
return nullptr;
|
|
522
|
+
}
|
|
523
|
+
const pushy::state::State state = ReadState(env, args[2], &ok);
|
|
524
|
+
if (!ok) {
|
|
525
|
+
return nullptr;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const pushy::state::BinaryVersionSyncResult result =
|
|
529
|
+
pushy::state::SyncBinaryVersion(state, package_version, build_time);
|
|
530
|
+
return NewStateResult(env, result.state, result.changed, std::string(), std::string(), false, false);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
napi_value RunStateCore(napi_env env, napi_callback_info info) {
|
|
534
|
+
napi_value args[5] = {nullptr, nullptr, nullptr, nullptr, nullptr};
|
|
535
|
+
size_t argc = 5;
|
|
536
|
+
if (!GetArgCount(env, info, &argc, args) || argc < 2) {
|
|
537
|
+
ThrowError(env, "Wrong number of arguments");
|
|
538
|
+
return nullptr;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
int32_t operation = 0;
|
|
542
|
+
if (!GetInt32(env, args[0], &operation)) {
|
|
543
|
+
return nullptr;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
bool ok = false;
|
|
547
|
+
const pushy::state::State state = ReadState(env, args[1], &ok);
|
|
548
|
+
if (!ok) {
|
|
549
|
+
return nullptr;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
std::string string_arg;
|
|
553
|
+
if (argc >= 3) {
|
|
554
|
+
string_arg = GetString(env, args[2], &ok);
|
|
555
|
+
if (!ok) {
|
|
556
|
+
return nullptr;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
bool flag_a = false;
|
|
561
|
+
bool flag_b = false;
|
|
562
|
+
if (argc >= 4 && !GetBoolean(env, args[3], &flag_a)) {
|
|
563
|
+
return nullptr;
|
|
564
|
+
}
|
|
565
|
+
if (argc >= 5 && !GetBoolean(env, args[4], &flag_b)) {
|
|
566
|
+
return nullptr;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
switch (static_cast<StateOperation>(operation)) {
|
|
570
|
+
case StateOperation::kSwitchVersion:
|
|
571
|
+
return NewStateResult(
|
|
572
|
+
env,
|
|
573
|
+
pushy::state::SwitchVersion(state, string_arg),
|
|
574
|
+
false,
|
|
575
|
+
std::string(),
|
|
576
|
+
std::string(),
|
|
577
|
+
false,
|
|
578
|
+
false);
|
|
579
|
+
case StateOperation::kMarkSuccess: {
|
|
580
|
+
const pushy::state::MarkSuccessResult result = pushy::state::MarkSuccess(state);
|
|
581
|
+
return NewStateResult(
|
|
582
|
+
env,
|
|
583
|
+
result.state,
|
|
584
|
+
false,
|
|
585
|
+
result.stale_version_to_delete,
|
|
586
|
+
std::string(),
|
|
587
|
+
false,
|
|
588
|
+
false);
|
|
589
|
+
}
|
|
590
|
+
case StateOperation::kRollback: {
|
|
591
|
+
const pushy::state::State next = pushy::state::Rollback(state);
|
|
592
|
+
return NewStateResult(
|
|
593
|
+
env, next, false, std::string(), next.current_version, true, false);
|
|
594
|
+
}
|
|
595
|
+
case StateOperation::kClearFirstTime:
|
|
596
|
+
return NewStateResult(
|
|
597
|
+
env,
|
|
598
|
+
pushy::state::ClearFirstTime(state),
|
|
599
|
+
false,
|
|
600
|
+
std::string(),
|
|
601
|
+
std::string(),
|
|
602
|
+
false,
|
|
603
|
+
false);
|
|
604
|
+
case StateOperation::kClearRollbackMark:
|
|
605
|
+
return NewStateResult(
|
|
606
|
+
env,
|
|
607
|
+
pushy::state::ClearRollbackMark(state),
|
|
608
|
+
false,
|
|
609
|
+
std::string(),
|
|
610
|
+
std::string(),
|
|
611
|
+
false,
|
|
612
|
+
false);
|
|
613
|
+
case StateOperation::kResolveLaunch: {
|
|
614
|
+
const pushy::state::LaunchDecision decision =
|
|
615
|
+
pushy::state::ResolveLaunchState(state, flag_a, flag_b);
|
|
616
|
+
return NewStateResult(
|
|
617
|
+
env,
|
|
618
|
+
decision.state,
|
|
619
|
+
false,
|
|
620
|
+
std::string(),
|
|
621
|
+
decision.load_version,
|
|
622
|
+
decision.did_rollback,
|
|
623
|
+
decision.consumed_first_time);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
ThrowError(env, "Unknown state operation");
|
|
628
|
+
return nullptr;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
napi_value BuildArchivePatchPlan(napi_env env, napi_callback_info info) {
|
|
632
|
+
napi_value args[6] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
|
|
633
|
+
size_t argc = 6;
|
|
634
|
+
if (!GetArgCount(env, info, &argc, args) || argc < 5) {
|
|
635
|
+
ThrowError(env, "Wrong number of arguments");
|
|
636
|
+
return nullptr;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
int32_t patch_type = 0;
|
|
640
|
+
if (!GetInt32(env, args[0], &patch_type)) {
|
|
641
|
+
return nullptr;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
std::vector<std::string> entry_names;
|
|
645
|
+
std::vector<std::string> copy_froms;
|
|
646
|
+
std::vector<std::string> copy_tos;
|
|
647
|
+
std::vector<std::string> deletes;
|
|
648
|
+
if (!GetStringArray(env, args[1], &entry_names) ||
|
|
649
|
+
!GetStringArray(env, args[2], ©_froms) ||
|
|
650
|
+
!GetStringArray(env, args[3], ©_tos) ||
|
|
651
|
+
!GetStringArray(env, args[4], &deletes)) {
|
|
652
|
+
return nullptr;
|
|
653
|
+
}
|
|
654
|
+
if (copy_froms.size() != copy_tos.size()) {
|
|
655
|
+
ThrowError(env, "copyFroms and copyTos length mismatch");
|
|
656
|
+
return nullptr;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
std::string bundle_patch_entry_name = kDefaultBundlePatchEntryName;
|
|
660
|
+
if (argc >= 6) {
|
|
661
|
+
bool ok = false;
|
|
662
|
+
const std::string candidate = GetString(env, args[5], &ok);
|
|
663
|
+
if (!ok) {
|
|
664
|
+
return nullptr;
|
|
665
|
+
}
|
|
666
|
+
if (!candidate.empty()) {
|
|
667
|
+
bundle_patch_entry_name = candidate;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
const pushy::patch::PatchManifest manifest =
|
|
672
|
+
BuildManifest(copy_froms, copy_tos, deletes);
|
|
673
|
+
pushy::archive_patch::ArchivePatchPlan plan;
|
|
674
|
+
const pushy::patch::Status status = pushy::archive_patch::BuildArchivePatchPlan(
|
|
675
|
+
static_cast<pushy::archive_patch::ArchivePatchType>(patch_type),
|
|
676
|
+
manifest,
|
|
677
|
+
entry_names,
|
|
678
|
+
&plan,
|
|
679
|
+
bundle_patch_entry_name);
|
|
680
|
+
if (!status.ok) {
|
|
681
|
+
ThrowError(env, status.message);
|
|
682
|
+
return nullptr;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
return NewArchivePatchPlanResult(env, plan);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
napi_value BuildCopyGroups(napi_env env, napi_callback_info info) {
|
|
689
|
+
napi_value args[2] = {nullptr, nullptr};
|
|
690
|
+
size_t argc = 2;
|
|
691
|
+
if (!GetArgCount(env, info, &argc, args) || argc < 2) {
|
|
692
|
+
ThrowError(env, "Wrong number of arguments");
|
|
693
|
+
return nullptr;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
std::vector<std::string> copy_froms;
|
|
697
|
+
std::vector<std::string> copy_tos;
|
|
698
|
+
if (!GetStringArray(env, args[0], ©_froms) ||
|
|
699
|
+
!GetStringArray(env, args[1], ©_tos)) {
|
|
700
|
+
return nullptr;
|
|
701
|
+
}
|
|
702
|
+
if (copy_froms.size() != copy_tos.size()) {
|
|
703
|
+
ThrowError(env, "copyFroms and copyTos length mismatch");
|
|
704
|
+
return nullptr;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
const pushy::patch::PatchManifest manifest =
|
|
708
|
+
BuildManifest(copy_froms, copy_tos, std::vector<std::string>());
|
|
709
|
+
std::vector<pushy::archive_patch::CopyGroup> groups;
|
|
710
|
+
const pushy::patch::Status status =
|
|
711
|
+
pushy::archive_patch::BuildCopyGroups(manifest, &groups);
|
|
712
|
+
if (!status.ok) {
|
|
713
|
+
ThrowError(env, status.message);
|
|
714
|
+
return nullptr;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
return NewCopyGroupArray(env, groups);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
napi_value ApplyPatchFromFileSource(napi_env env, napi_callback_info info) {
|
|
721
|
+
napi_value args[1] = {nullptr};
|
|
722
|
+
size_t argc = 1;
|
|
723
|
+
if (!GetArgCount(env, info, &argc, args) || argc < 1) {
|
|
724
|
+
ThrowError(env, "Wrong number of arguments");
|
|
725
|
+
return nullptr;
|
|
726
|
+
}
|
|
727
|
+
if (!GetObject(env, args[0])) {
|
|
728
|
+
return nullptr;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
std::vector<std::string> copy_froms;
|
|
732
|
+
std::vector<std::string> copy_tos;
|
|
733
|
+
std::vector<std::string> deletes;
|
|
734
|
+
std::string source_root;
|
|
735
|
+
std::string target_root;
|
|
736
|
+
std::string origin_bundle_path;
|
|
737
|
+
std::string bundle_patch_path;
|
|
738
|
+
std::string bundle_output_path;
|
|
739
|
+
std::string merge_source_subdir;
|
|
740
|
+
bool enable_merge = true;
|
|
741
|
+
|
|
742
|
+
if (!GetOptionalStringArrayProperty(env, args[0], "copyFroms", ©_froms) ||
|
|
743
|
+
!GetOptionalStringArrayProperty(env, args[0], "copyTos", ©_tos) ||
|
|
744
|
+
!GetOptionalStringArrayProperty(env, args[0], "deletes", &deletes) ||
|
|
745
|
+
!GetOptionalStringProperty(env, args[0], "sourceRoot", &source_root) ||
|
|
746
|
+
!GetOptionalStringProperty(env, args[0], "targetRoot", &target_root) ||
|
|
747
|
+
!GetOptionalStringProperty(env, args[0], "originBundlePath", &origin_bundle_path) ||
|
|
748
|
+
!GetOptionalStringProperty(env, args[0], "bundlePatchPath", &bundle_patch_path) ||
|
|
749
|
+
!GetOptionalStringProperty(env, args[0], "bundleOutputPath", &bundle_output_path) ||
|
|
750
|
+
!GetOptionalStringProperty(env, args[0], "mergeSourceSubdir", &merge_source_subdir) ||
|
|
751
|
+
!GetOptionalBoolProperty(env, args[0], "enableMerge", true, &enable_merge)) {
|
|
752
|
+
return nullptr;
|
|
753
|
+
}
|
|
754
|
+
if (copy_froms.size() != copy_tos.size()) {
|
|
755
|
+
ThrowError(env, "copyFroms and copyTos length mismatch");
|
|
756
|
+
return nullptr;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
pushy::patch::FileSourcePatchOptions options;
|
|
760
|
+
options.manifest = BuildManifest(copy_froms, copy_tos, deletes);
|
|
761
|
+
options.source_root = source_root;
|
|
762
|
+
options.target_root = target_root;
|
|
763
|
+
options.origin_bundle_path = origin_bundle_path;
|
|
764
|
+
options.bundle_patch_path = bundle_patch_path;
|
|
765
|
+
options.bundle_output_path = bundle_output_path;
|
|
766
|
+
options.merge_source_subdir = merge_source_subdir;
|
|
767
|
+
options.enable_merge = enable_merge;
|
|
768
|
+
|
|
769
|
+
const pushy::patch::Status status =
|
|
770
|
+
pushy::patch::ApplyPatchFromFileSource(options);
|
|
771
|
+
if (!status.ok) {
|
|
772
|
+
ThrowError(env, status.message);
|
|
773
|
+
return nullptr;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
napi_value undefined_value = nullptr;
|
|
777
|
+
napi_get_undefined(env, &undefined_value);
|
|
778
|
+
return undefined_value;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
napi_value CleanupOldEntries(napi_env env, napi_callback_info info) {
|
|
782
|
+
napi_value args[4] = {nullptr, nullptr, nullptr, nullptr};
|
|
783
|
+
size_t argc = 4;
|
|
784
|
+
if (!GetArgCount(env, info, &argc, args) || argc < 4) {
|
|
785
|
+
ThrowError(env, "Wrong number of arguments");
|
|
786
|
+
return nullptr;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
bool ok = false;
|
|
790
|
+
const std::string root_dir = GetString(env, args[0], &ok);
|
|
791
|
+
if (!ok) {
|
|
792
|
+
return nullptr;
|
|
793
|
+
}
|
|
794
|
+
const std::string keep_current = GetString(env, args[1], &ok);
|
|
795
|
+
if (!ok) {
|
|
796
|
+
return nullptr;
|
|
797
|
+
}
|
|
798
|
+
const std::string keep_previous = GetString(env, args[2], &ok);
|
|
799
|
+
if (!ok) {
|
|
800
|
+
return nullptr;
|
|
801
|
+
}
|
|
802
|
+
int32_t max_age_days = 0;
|
|
803
|
+
if (!GetInt32(env, args[3], &max_age_days)) {
|
|
804
|
+
return nullptr;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
const pushy::patch::Status status = pushy::patch::CleanupOldEntries(
|
|
808
|
+
root_dir,
|
|
809
|
+
keep_current,
|
|
810
|
+
keep_previous,
|
|
811
|
+
max_age_days);
|
|
812
|
+
if (!status.ok) {
|
|
813
|
+
ThrowError(env, status.message);
|
|
814
|
+
return nullptr;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
napi_value undefined_value = nullptr;
|
|
818
|
+
napi_get_undefined(env, &undefined_value);
|
|
819
|
+
return undefined_value;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
bool ExportFunction(
|
|
823
|
+
napi_env env,
|
|
824
|
+
napi_value exports,
|
|
825
|
+
const char* name,
|
|
826
|
+
napi_callback callback) {
|
|
827
|
+
napi_value fn = nullptr;
|
|
828
|
+
if (napi_create_function(env, name, NAPI_AUTO_LENGTH, callback, nullptr, &fn) !=
|
|
829
|
+
napi_ok) {
|
|
830
|
+
ThrowError(env, std::string("Unable to create function ") + name);
|
|
831
|
+
return false;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
if (napi_set_named_property(env, exports, name, fn) != napi_ok) {
|
|
835
|
+
ThrowError(env, std::string("Unable to export function ") + name);
|
|
836
|
+
return false;
|
|
837
|
+
}
|
|
838
|
+
return true;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
} // namespace
|
|
842
|
+
|
|
843
|
+
napi_value Init(napi_env env, napi_value exports) {
|
|
844
|
+
if (!ExportFunction(env, exports, "hdiffPatch", HdiffPatch) ||
|
|
845
|
+
!ExportFunction(env, exports, "syncStateWithBinaryVersion", SyncStateWithBinaryVersion) ||
|
|
846
|
+
!ExportFunction(env, exports, "runStateCore", RunStateCore) ||
|
|
847
|
+
!ExportFunction(env, exports, "buildArchivePatchPlan", BuildArchivePatchPlan) ||
|
|
848
|
+
!ExportFunction(env, exports, "buildCopyGroups", BuildCopyGroups) ||
|
|
849
|
+
!ExportFunction(env, exports, "applyPatchFromFileSource", ApplyPatchFromFileSource) ||
|
|
850
|
+
!ExportFunction(env, exports, "cleanupOldEntries", CleanupOldEntries)) {
|
|
851
|
+
return nullptr;
|
|
852
|
+
}
|
|
853
|
+
return exports;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
|