@mnaoumov/obsidian-lib 10.3.0 → 10.4.0

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.
Files changed (49) hide show
  1. package/command-handlers/undo-bulk-operation-command-handler/package.json +6 -0
  2. package/components/bulk-operation-commit-component/package.json +6 -0
  3. package/dist/lib/cjs/__merged.cjs +42 -1
  4. package/dist/lib/cjs/__merged.d.cts +5 -0
  5. package/dist/lib/cjs/bulk-operation-progress.cjs +120 -0
  6. package/dist/lib/cjs/bulk-operation-progress.d.cts +33 -0
  7. package/dist/lib/cjs/bulk-operation.cjs +220 -0
  8. package/dist/lib/cjs/bulk-operation.d.cts +237 -0
  9. package/dist/lib/cjs/command-handlers/index.cjs +4 -1
  10. package/dist/lib/cjs/command-handlers/index.d.cts +1 -0
  11. package/dist/lib/cjs/command-handlers/undo-bulk-operation-command-handler.cjs +164 -0
  12. package/dist/lib/cjs/command-handlers/undo-bulk-operation-command-handler.d.cts +51 -0
  13. package/dist/lib/cjs/components/bulk-operation-commit-component.cjs +337 -0
  14. package/dist/lib/cjs/components/bulk-operation-commit-component.d.cts +152 -0
  15. package/dist/lib/cjs/components/index.cjs +4 -1
  16. package/dist/lib/cjs/components/index.d.cts +1 -0
  17. package/dist/lib/cjs/desktop-bulk-operation-git.cjs +534 -0
  18. package/dist/lib/cjs/desktop-bulk-operation-git.d.cts +196 -0
  19. package/dist/lib/cjs/generated-during-build.cjs +1 -1
  20. package/dist/lib/cjs/i18n/locales/en.cjs +10 -1
  21. package/dist/lib/cjs/i18n/locales/en.d.cts +9 -0
  22. package/dist/lib/cjs/i18n/locales/translations-map.d.cts +9 -0
  23. package/dist/lib/cjs/index.cjs +10 -1
  24. package/dist/lib/cjs/index.d.cts +3 -0
  25. package/dist/lib/cjs/loop.cjs +3 -1
  26. package/dist/lib/esm/__merged.d.mts +5 -0
  27. package/dist/lib/esm/__merged.mjs +43 -1
  28. package/dist/lib/esm/bulk-operation-progress.d.mts +33 -0
  29. package/dist/lib/esm/bulk-operation-progress.mjs +31 -0
  30. package/dist/lib/esm/bulk-operation.d.mts +237 -0
  31. package/dist/lib/esm/bulk-operation.mjs +125 -0
  32. package/dist/lib/esm/command-handlers/index.d.mts +1 -0
  33. package/dist/lib/esm/command-handlers/index.mjs +3 -1
  34. package/dist/lib/esm/command-handlers/undo-bulk-operation-command-handler.d.mts +51 -0
  35. package/dist/lib/esm/command-handlers/undo-bulk-operation-command-handler.mjs +76 -0
  36. package/dist/lib/esm/components/bulk-operation-commit-component.d.mts +152 -0
  37. package/dist/lib/esm/components/bulk-operation-commit-component.mjs +245 -0
  38. package/dist/lib/esm/components/index.d.mts +1 -0
  39. package/dist/lib/esm/components/index.mjs +3 -1
  40. package/dist/lib/esm/desktop-bulk-operation-git.d.mts +196 -0
  41. package/dist/lib/esm/desktop-bulk-operation-git.mjs +463 -0
  42. package/dist/lib/esm/generated-during-build.mjs +1 -1
  43. package/dist/lib/esm/i18n/locales/en.d.mts +9 -0
  44. package/dist/lib/esm/i18n/locales/en.mjs +10 -1
  45. package/dist/lib/esm/i18n/locales/translations-map.d.mts +9 -0
  46. package/dist/lib/esm/index.d.mts +3 -0
  47. package/dist/lib/esm/index.mjs +7 -1
  48. package/dist/lib/esm/loop.mjs +3 -1
  49. package/package.json +1 -1
@@ -0,0 +1,534 @@
1
+ /*
2
+ THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
3
+ if you want to view the source, please visit the github repository of this plugin
4
+ */
5
+ (function () {
6
+ function ensureBrowserProcess() {
7
+ const browserProcess = {
8
+ browser: true,
9
+ cwd() {
10
+ return "/";
11
+ },
12
+ env: {},
13
+ platform: "android"
14
+ };
15
+ const existingProcess = globalThis.process;
16
+ if (!existingProcess) {
17
+ globalThis.process = browserProcess;
18
+ return;
19
+ }
20
+ if (existingProcess.versions?.node) {
21
+ return;
22
+ }
23
+ const existingProcessRecord = existingProcess;
24
+ for (const [key, value] of Object.entries(browserProcess)) {
25
+ existingProcessRecord[key] ??= value;
26
+ }
27
+ existingProcessRecord["browser"] = true;
28
+ }
29
+
30
+ ensureBrowserProcess();
31
+ })();
32
+ (function patchObsidianRequire() {
33
+ const originalRequire = require;
34
+ if (!originalRequire || originalRequire.__isPatched) {
35
+ return;
36
+ }
37
+ require = Object.assign(
38
+ (id) => requirePatched(id),
39
+ originalRequire,
40
+ {
41
+ __isPatched: true
42
+ }
43
+ );
44
+ function extractDefault($module) {
45
+ return $module && $module.__esModule && "default" in $module ? $module.default : $module;
46
+ }
47
+ const OBSIDIAN_BUILT_IN_MODULE_NAMES = /* @__PURE__ */ new Set([
48
+ "@codemirror/autocomplete",
49
+ "@codemirror/collab",
50
+ "@codemirror/commands",
51
+ "@codemirror/language",
52
+ "@codemirror/lint",
53
+ "@codemirror/search",
54
+ "@codemirror/state",
55
+ "@codemirror/text",
56
+ "@codemirror/view",
57
+ "@lezer/common",
58
+ "@lezer/highlight",
59
+ "@lezer/lr",
60
+ "obsidian"
61
+ ]);
62
+ const DEPRECATED_OBSIDIAN_BUILT_IN_MODULE_NAMES = /* @__PURE__ */ new Set([
63
+ "@codemirror/closebrackets",
64
+ "@codemirror/comment",
65
+ "@codemirror/fold",
66
+ "@codemirror/gutter",
67
+ "@codemirror/highlight",
68
+ "@codemirror/history",
69
+ "@codemirror/matchbrackets",
70
+ "@codemirror/panel",
71
+ "@codemirror/rangeset",
72
+ "@codemirror/rectangular-selection",
73
+ "@codemirror/stream-parser",
74
+ "@codemirror/tooltip"
75
+ ]);
76
+ function requirePatched(id) {
77
+ if (OBSIDIAN_BUILT_IN_MODULE_NAMES.has(id) || DEPRECATED_OBSIDIAN_BUILT_IN_MODULE_NAMES.has(id)) {
78
+ return originalRequire?.(id);
79
+ }
80
+ const app = globalThis.app;
81
+ if (app?.isMobile) {
82
+ if (id === "process" || id === "node:process") {
83
+ console.debug(`The most likely you can safely ignore this error. Module not found: ${id}. Fake process object is returned instead.`);
84
+ return process;
85
+ }
86
+ } else {
87
+ const $module = originalRequire?.(id);
88
+ if ($module) {
89
+ return extractDefault($module);
90
+ }
91
+ }
92
+ console.debug(`The most likely you can safely ignore this error. Module not found: ${id}. Empty object is returned instead.`);
93
+ return {};
94
+ }
95
+ })();
96
+
97
+ "use strict";
98
+ var __defProp = Object.defineProperty;
99
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
100
+ var __getOwnPropNames = Object.getOwnPropertyNames;
101
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
102
+ var __export = (target, all) => {
103
+ for (var name in all)
104
+ __defProp(target, name, { get: all[name], enumerable: true });
105
+ };
106
+ var __copyProps = (to, from, except, desc) => {
107
+ if (from && typeof from === "object" || typeof from === "function") {
108
+ for (let key of __getOwnPropNames(from))
109
+ if (!__hasOwnProp.call(to, key) && key !== except)
110
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
111
+ }
112
+ return to;
113
+ };
114
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
115
+ var desktop_bulk_operation_git_exports = {};
116
+ __export(desktop_bulk_operation_git_exports, {
117
+ BulkOperationGitRepo: () => BulkOperationGitRepo,
118
+ GitCommandError: () => GitCommandError
119
+ });
120
+ module.exports = __toCommonJS(desktop_bulk_operation_git_exports);
121
+ var import_async = require('@mnaoumov/typescript-lib/async');
122
+ var import_function = require('@mnaoumov/typescript-lib/function');
123
+ var import_reg_exp = require('@mnaoumov/typescript-lib/reg-exp');
124
+ var import_type_guards = require('@mnaoumov/typescript-lib/type-guards');
125
+ var import_node_child_process = require('node:child_process');
126
+ var import_promises = require('node:fs/promises');
127
+ var import_node_os = require('node:os');
128
+ var import_node_path = require('node:path');
129
+ var import_bulk_operation_progress = require('./bulk-operation-progress.cjs');
130
+ var import_bulk_operation = require('./bulk-operation.cjs');
131
+ const DEFAULT_LOCK_WAIT_TIMEOUT_IN_MILLISECONDS = 6e5;
132
+ const HEARTBEAT_THROTTLE_IN_MILLISECONDS = 5e3;
133
+ const INDEX_LOCK_RETRY_COUNT = 20;
134
+ const INDEX_LOCK_RETRY_DELAY_IN_MILLISECONDS = 500;
135
+ const LOCK_POLL_INTERVAL_IN_MILLISECONDS = 1e3;
136
+ const MAX_BUFFER_IN_BYTES = 268435456;
137
+ const MILLISECONDS_IN_SECOND = 1e3;
138
+ const GIT_FATAL_EXIT_CODE = 128;
139
+ const REV_PARSE_OUTPUT_LINE_COUNT = 2;
140
+ const UNIT_SEPARATOR = "";
141
+ class BulkOperationGitRepo {
142
+ /**
143
+ * The absolute path of the repo's git directory.
144
+ */
145
+ gitDirectory;
146
+ /**
147
+ * The absolute path of the folder whose changes are committed.
148
+ */
149
+ workingDirectory;
150
+ lockFilePath;
151
+ lockWaitTimeoutInMilliseconds;
152
+ ownLock = null;
153
+ /**
154
+ * Creates a new instance. Use {@link BulkOperationGitRepo.open} to find the repo of a folder.
155
+ *
156
+ * @param params - The constructor parameters.
157
+ */
158
+ constructor(params) {
159
+ this.gitDirectory = params.gitDirectory;
160
+ this.workingDirectory = params.workingDirectory;
161
+ this.lockWaitTimeoutInMilliseconds = params.lockWaitTimeoutInMilliseconds ?? DEFAULT_LOCK_WAIT_TIMEOUT_IN_MILLISECONDS;
162
+ this.lockFilePath = (0, import_node_path.join)(this.gitDirectory, import_bulk_operation.BULK_OPERATION_LOCK_FILE_NAME);
163
+ }
164
+ /**
165
+ * Finds the git repo a folder belongs to.
166
+ *
167
+ * @param workingDirectory - The folder, normally the vault root.
168
+ * @returns The repo, or `null` when the folder is not inside a git work tree or `git` cannot be run.
169
+ */
170
+ static async open(workingDirectory) {
171
+ let result;
172
+ try {
173
+ result = await execGit({ cwd: workingDirectory, gitArguments: ["rev-parse", "--is-inside-work-tree", "--absolute-git-dir"] });
174
+ } catch {
175
+ return null;
176
+ }
177
+ const [isInsideWorkTree, gitDirectory] = result.stdout.split(/\r?\n/, REV_PARSE_OUTPUT_LINE_COUNT);
178
+ return result.exitCode !== 0 || isInsideWorkTree !== "true" || !gitDirectory ? null : new BulkOperationGitRepo({ gitDirectory, workingDirectory });
179
+ }
180
+ /**
181
+ * Refuses to go on when the repo routes files through git-annex but `git-annex` cannot be run, since a
182
+ * plain `git add` would then put the large files into git itself.
183
+ */
184
+ async assertCanCommitLargeFiles() {
185
+ const annexFilters = await this.runGit({ allowedExitCodes: [0, 1], gitArguments: ["config", "--get-regexp", String.raw`^filter\.annex\.`] });
186
+ if (!annexFilters.stdout.trim()) {
187
+ return;
188
+ }
189
+ const annexVersion = await this.runGit({ gitArguments: ["annex", "version", "--raw"] }).catch(() => null);
190
+ if (annexVersion === null) {
191
+ throw new Error(
192
+ "The vault repository routes files through git-annex, but git-annex is not on PATH. Bulk operation commits are refused, because they would add large files to git itself."
193
+ );
194
+ }
195
+ }
196
+ /**
197
+ * Lists the bulk-operation commits a plugin made on the current branch, newest first.
198
+ *
199
+ * @param pluginId - The plugin id.
200
+ * @returns The commits.
201
+ */
202
+ async listBulkOperationCommits(pluginId) {
203
+ const result = await this.runGit({
204
+ allowedExitCodes: [0, GIT_FATAL_EXIT_CODE],
205
+ gitArguments: [
206
+ "log",
207
+ `--format=%H${UNIT_SEPARATOR}%aI${UNIT_SEPARATOR}%s`,
208
+ "--extended-regexp",
209
+ `--grep=^${import_bulk_operation.PLUGIN_TRAILER_KEY}: ${(0, import_reg_exp.escapeRegExp)(pluginId)}$`
210
+ ]
211
+ });
212
+ if (result.exitCode !== 0) {
213
+ return [];
214
+ }
215
+ const commits = [];
216
+ for (const line of result.stdout.split(/\r?\n/)) {
217
+ const [sha = "", date = "", ...subjectParts] = line.split(UNIT_SEPARATOR);
218
+ const commit = (0, import_bulk_operation.parseBulkOperationCommit)({ date, sha, subject: subjectParts.join(UNIT_SEPARATOR) });
219
+ if (commit) {
220
+ commits.push(commit);
221
+ }
222
+ }
223
+ return commits;
224
+ }
225
+ /**
226
+ * Commits whatever a stale lock's operation left behind as `OP<n> interrupted` and removes the lock.
227
+ *
228
+ * @returns The id of the recovered operation, or `null` when there was no stale lock.
229
+ */
230
+ async recoverStaleLock() {
231
+ const lock = await this.readLock();
232
+ return !lock || !this.isStale(lock) ? null : await this.recover(lock);
233
+ }
234
+ /**
235
+ * Reverts a bulk-operation commit with `git revert --no-edit`.
236
+ *
237
+ * Whatever is pending is committed first, so the revert starts from a clean tree. A conflict is NOT aborted: the
238
+ * repo is left mid-revert for the user to resolve.
239
+ *
240
+ * @param commit - The commit to revert.
241
+ * @returns Whether the revert stopped on a conflict, and what git printed.
242
+ */
243
+ async revertBulkOperationCommit(commit) {
244
+ await this.assertCanCommitLargeFiles();
245
+ await this.acquireLock();
246
+ try {
247
+ await this.commitPending({ body: "", subject: `chore: before revert of ${commit.operationId}` });
248
+ const result = await this.runGit({ allowedExitCodes: [0, 1], gitArguments: ["revert", "--no-edit", commit.sha] });
249
+ return { isConflict: result.exitCode !== 0, output: `${result.stdout}${result.stderr}`.trim() };
250
+ } finally {
251
+ await this.releaseLock();
252
+ }
253
+ }
254
+ /**
255
+ * Runs a bulk operation between two commits.
256
+ *
257
+ * Takes the lease lock, commits whatever is pending as `chore: before OP<n>`, runs the operation, waits for its
258
+ * follow-ups to settle, commits the result as `OP<n>: <summary>` and releases the lock. An operation that throws
259
+ * still gets its partial changes committed, as `OP<n> interrupted`, before the error is rethrown.
260
+ *
261
+ * @typeParam T - The type of the operation's result.
262
+ * @param params - The parameters.
263
+ * @returns The operation's result, its id and the hash of its commit.
264
+ */
265
+ async runBulkOperation(params) {
266
+ await this.assertCanCommitLargeFiles();
267
+ await this.acquireLock();
268
+ let unregisterProgressListener = null;
269
+ try {
270
+ const operationId = await this.allocateOperationId(params.pluginId);
271
+ await this.commitPending({ body: "", subject: (0, import_bulk_operation.buildBeforeOperationCommitSubject)(operationId) });
272
+ unregisterProgressListener = (0, import_bulk_operation_progress.registerBulkOperationProgressListener)(this.createThrottledHeartbeat());
273
+ let result;
274
+ try {
275
+ result = await params.operation();
276
+ await params.settle();
277
+ } catch (error) {
278
+ await this.heartbeat();
279
+ await this.commitOperation({ isInterrupted: true, operationId, pluginId: params.pluginId });
280
+ throw error;
281
+ }
282
+ await this.heartbeat();
283
+ const commitSha = await this.commitOperation({ operationId, pluginId: params.pluginId, summary: params.summary });
284
+ return { commitSha, operationId, result };
285
+ } finally {
286
+ unregisterProgressListener?.();
287
+ await this.releaseLock();
288
+ }
289
+ }
290
+ async acquireLock() {
291
+ const deadline = Date.now() + this.lockWaitTimeoutInMilliseconds;
292
+ for (; ; ) {
293
+ if (await this.tryCreateLock()) {
294
+ return;
295
+ }
296
+ const lock = await this.readLock();
297
+ if (!lock) {
298
+ continue;
299
+ }
300
+ if (this.isStale(lock)) {
301
+ await this.recover(lock);
302
+ continue;
303
+ }
304
+ if (Date.now() >= deadline) {
305
+ throw new Error(
306
+ `Timed out waiting for ${lock.operationId || "an operation"} of ${lock.pluginId} on ${lock.host} to release the bulk operation lock ${this.lockFilePath}.`
307
+ );
308
+ }
309
+ await (0, import_async.setTimeoutAsync)(LOCK_POLL_INTERVAL_IN_MILLISECONDS);
310
+ }
311
+ }
312
+ async allocateOperationId(pluginId) {
313
+ const operationId = await this.findNextOperationId();
314
+ const ownLock = (0, import_type_guards.ensureNonNullable)(this.ownLock);
315
+ this.ownLock = { ...ownLock, heartbeatAt: Date.now(), operationId, pluginId };
316
+ await this.writeLock(this.ownLock);
317
+ return operationId;
318
+ }
319
+ async commitOperation(params) {
320
+ const changedFileCount = await this.stageAll();
321
+ if (changedFileCount === 0) {
322
+ return null;
323
+ }
324
+ const message = (0, import_bulk_operation.buildOperationCommitMessage)({ ...params, changedFileCount, timestamp: /* @__PURE__ */ new Date() });
325
+ await this.commitStaged(message);
326
+ const headResult = await this.runGit({ gitArguments: ["rev-parse", "HEAD"] });
327
+ return headResult.stdout.trim();
328
+ }
329
+ async commitPending(message) {
330
+ if (await this.stageAll() === 0) {
331
+ return;
332
+ }
333
+ await this.commitStaged(message);
334
+ }
335
+ async commitStaged(message) {
336
+ const gitArguments = ["commit", "--quiet", "-m", message.subject];
337
+ if (message.body) {
338
+ gitArguments.push("-m", message.body);
339
+ }
340
+ gitArguments.push("--", ".");
341
+ await this.runGit({ gitArguments });
342
+ }
343
+ createThrottledHeartbeat() {
344
+ let lastHeartbeatAt = Date.now();
345
+ let pendingHeartbeat = (0, import_function.noopAsync)();
346
+ return () => {
347
+ const now = Date.now();
348
+ if (now - lastHeartbeatAt < HEARTBEAT_THROTTLE_IN_MILLISECONDS) {
349
+ return;
350
+ }
351
+ lastHeartbeatAt = now;
352
+ pendingHeartbeat = pendingHeartbeat.then(() => this.heartbeat()).catch((error) => {
353
+ console.error("Failed to refresh the bulk operation lock heartbeat", error);
354
+ });
355
+ };
356
+ }
357
+ async findNextOperationId() {
358
+ const result = await this.runGit({
359
+ gitArguments: ["log", "--all", "--format=%s", "--extended-regexp", "--grep=^(chore: before )?OP[0-9]+"]
360
+ });
361
+ return (0, import_bulk_operation.getNextOperationId)(result.stdout.split(/\r?\n/));
362
+ }
363
+ async heartbeat() {
364
+ const lock = await this.readLock();
365
+ if (!lock || !this.isOwnLock(lock)) {
366
+ return;
367
+ }
368
+ await this.writeLock({ ...lock, heartbeatAt: Date.now() });
369
+ }
370
+ isOwnLock(lock) {
371
+ return this.ownLock !== null && lock.host === this.ownLock.host && lock.processId === this.ownLock.processId && lock.startedAt === this.ownLock.startedAt;
372
+ }
373
+ isStale(lock) {
374
+ return (0, import_bulk_operation.isBulkOperationLockStale)(lock, {
375
+ bootedAt: Date.now() - (0, import_node_os.uptime)() * MILLISECONDS_IN_SECOND,
376
+ host: (0, import_node_os.hostname)(),
377
+ isProcessAlive,
378
+ now: Date.now()
379
+ });
380
+ }
381
+ async readLock() {
382
+ let text;
383
+ try {
384
+ text = await (0, import_promises.readFile)(this.lockFilePath, "utf-8");
385
+ } catch (error) {
386
+ if (isErrorWithCode(error, "ENOENT")) {
387
+ return null;
388
+ }
389
+ throw error;
390
+ }
391
+ try {
392
+ const value = JSON.parse(text);
393
+ if ((0, import_bulk_operation.isBulkOperationLock)(value)) {
394
+ return value;
395
+ }
396
+ } catch {
397
+ }
398
+ const fileStats = await (0, import_promises.stat)(this.lockFilePath);
399
+ return {
400
+ heartbeatAt: fileStats.mtimeMs,
401
+ host: "",
402
+ operationId: "",
403
+ pluginId: "",
404
+ processId: 0,
405
+ processStartedAt: 0,
406
+ startedAt: 0
407
+ };
408
+ }
409
+ async recover(lock) {
410
+ const operationId = lock.operationId || await this.findNextOperationId();
411
+ await this.commitOperation({ isInterrupted: true, operationId, pluginId: lock.pluginId || "unknown" });
412
+ await (0, import_promises.unlink)(this.lockFilePath).catch((error) => {
413
+ if (!isErrorWithCode(error, "ENOENT")) {
414
+ throw error;
415
+ }
416
+ });
417
+ return operationId;
418
+ }
419
+ async releaseLock() {
420
+ const lock = await this.readLock();
421
+ const isOwnLock = lock !== null && this.isOwnLock(lock);
422
+ this.ownLock = null;
423
+ if (!isOwnLock) {
424
+ return;
425
+ }
426
+ await (0, import_promises.unlink)(this.lockFilePath).catch((error) => {
427
+ if (!isErrorWithCode(error, "ENOENT")) {
428
+ throw error;
429
+ }
430
+ });
431
+ }
432
+ async runGit(params) {
433
+ const allowedExitCodes = params.allowedExitCodes ?? [0];
434
+ for (let attempt = 1; ; attempt++) {
435
+ const result = await execGit({ cwd: this.workingDirectory, gitArguments: params.gitArguments });
436
+ if (allowedExitCodes.includes(result.exitCode)) {
437
+ return result;
438
+ }
439
+ if (attempt < INDEX_LOCK_RETRY_COUNT && result.stderr.includes("index.lock")) {
440
+ await (0, import_async.setTimeoutAsync)(INDEX_LOCK_RETRY_DELAY_IN_MILLISECONDS);
441
+ continue;
442
+ }
443
+ throw new GitCommandError(params.gitArguments, result.exitCode, result.stderr);
444
+ }
445
+ }
446
+ async stageAll() {
447
+ await this.runGit({ gitArguments: ["add", "--all", "--", "."] });
448
+ const result = await this.runGit({ gitArguments: ["diff", "--cached", "--name-only", "-z", "--", "."] });
449
+ return result.stdout.split("\0").filter(Boolean).length;
450
+ }
451
+ async tryCreateLock() {
452
+ const lock = createLockRecord();
453
+ try {
454
+ await (0, import_promises.writeFile)(this.lockFilePath, JSON.stringify(lock), { flag: "wx" });
455
+ this.ownLock = lock;
456
+ return true;
457
+ } catch (error) {
458
+ if (isErrorWithCode(error, "EEXIST")) {
459
+ return false;
460
+ }
461
+ throw error;
462
+ }
463
+ }
464
+ async writeLock(lock) {
465
+ const temporaryPath = `${this.lockFilePath}.${String(lock.processId)}.tmp`;
466
+ await (0, import_promises.writeFile)(temporaryPath, JSON.stringify(lock));
467
+ await (0, import_promises.rename)(temporaryPath, this.lockFilePath);
468
+ }
469
+ }
470
+ class GitCommandError extends Error {
471
+ /**
472
+ * Creates a new instance.
473
+ *
474
+ * @param gitArguments - The arguments `git` was run with.
475
+ * @param exitCode - The exit code.
476
+ * @param stderr - What `git` printed to stderr.
477
+ */
478
+ constructor(gitArguments, exitCode, stderr) {
479
+ super(`git ${gitArguments.join(" ")} failed with exit code ${String(exitCode)}: ${stderr.trim()}`);
480
+ this.gitArguments = gitArguments;
481
+ this.exitCode = exitCode;
482
+ this.stderr = stderr;
483
+ this.name = "GitCommandError";
484
+ }
485
+ gitArguments;
486
+ exitCode;
487
+ stderr;
488
+ }
489
+ function createLockRecord() {
490
+ const now = Date.now();
491
+ return {
492
+ heartbeatAt: now,
493
+ host: (0, import_node_os.hostname)(),
494
+ operationId: "",
495
+ pluginId: "",
496
+ processId: process.pid,
497
+ processStartedAt: getProcessStartedAt(),
498
+ startedAt: now
499
+ };
500
+ }
501
+ async function execGit(params) {
502
+ return await new Promise((resolve, reject) => {
503
+ (0, import_node_child_process.execFile)("git", [...params.gitArguments], { cwd: params.cwd, maxBuffer: MAX_BUFFER_IN_BYTES, windowsHide: true }, (error, stdout, stderr) => {
504
+ if (error && typeof error.code !== "number") {
505
+ reject(new Error(`Failed to run git ${params.gitArguments.join(" ")}`, { cause: error }));
506
+ return;
507
+ }
508
+ resolve({ exitCode: typeof error?.code === "number" ? error.code : 0, stderr, stdout });
509
+ });
510
+ });
511
+ }
512
+ function getProcessStartedAt() {
513
+ return Math.round(performance.timeOrigin);
514
+ }
515
+ function isErrorWithCode(error, code) {
516
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
517
+ }
518
+ function isProcessAlive(processId) {
519
+ if (processId <= 0) {
520
+ return false;
521
+ }
522
+ try {
523
+ process.kill(processId, 0);
524
+ return true;
525
+ } catch (error) {
526
+ return !isErrorWithCode(error, "ESRCH") && (isErrorWithCode(error, "EPERM") || null);
527
+ }
528
+ }
529
+ // Annotate the CommonJS export names for ESM import in node:
530
+ 0 && (module.exports = {
531
+ BulkOperationGitRepo,
532
+ GitCommandError
533
+ });
534
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZXNrdG9wLWJ1bGstb3BlcmF0aW9uLWdpdC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBmaWxlXG4gKlxuICogVGhlIGRlc2t0b3AgaGFsZiBvZiBidWxrLW9wZXJhdGlvbiBnaXQgY29tbWl0czogZHJpdmVzIHRoZSBzeXN0ZW0gYGdpdGAgQ0xJIHRvIHdyYXAgYSBidWxrIG9wZXJhdGlvbiBpbiBjb21taXRzLFxuICogZ3VhcmRlZCBieSBhIGxlYXNlIGxvY2sgaW4gdGhlIHJlcG8ncyBnaXQgZGlyZWN0b3J5LlxuICpcbiAqIFRoZSBzeXN0ZW0gQ0xJIGlzIHVzZWQgcmF0aGVyIHRoYW4gYSBidW5kbGVkIGltcGxlbWVudGF0aW9uIGJlY2F1c2UgaXQgaG9ub3JzIHRoZSByZXBvJ3Mgb3duIGNvbmZpZywgaG9va3NcbiAqIGFuZCBjbGVhbi9zbXVkZ2UgZmlsdGVycywgZ2l0LWFubmV4J3MgYW1vbmcgdGhlbSwgYW5kIGJlY2F1c2UgYGdpdCByZXZlcnRgIGlzIHRoZSB3aG9sZSB1bmRvIHN0b3J5LlxuICpcbiAqIEV2ZXJ5IGNvbW1hbmQgcnVucyB3aXRoIHRoZSB2YXVsdCBmb2xkZXIgYXMgaXRzIHdvcmtpbmcgZGlyZWN0b3J5IGFuZCBgLmAgYXMgaXRzIHBhdGhzcGVjLCBzbyB3aGVuIHRoZSB2YXVsdCBpcyBhXG4gKiBzdWJmb2xkZXIgb2YgYSBsYXJnZXIgcmVwbyBvbmx5IHRoZSB2YXVsdCdzIGNoYW5nZXMgYXJlIGNvbW1pdHRlZC5cbiAqXG4gKiBEZXNrdG9wLW9ubHkgKGBub2RlOmNoaWxkX3Byb2Nlc3NgLCBgbm9kZTpmc2AsIGBub2RlOm9zYCksIGJ1dCBpbmVydCB0byBpbXBvcnQgb24gbW9iaWxlOiBub3RoaW5nIGhlcmUgdG91Y2hlcyBhXG4gKiBOb2RlIGJ1aWx0aW4gdW50aWwgYSBmdW5jdGlvbiBpcyBjYWxsZWQuXG4gKi9cblxuaW1wb3J0IHsgc2V0VGltZW91dEFzeW5jIH0gZnJvbSAnQG1uYW91bW92L3R5cGVzY3JpcHQtbGliL2FzeW5jJztcbmltcG9ydCB7IG5vb3BBc3luYyB9IGZyb20gJ0BtbmFvdW1vdi90eXBlc2NyaXB0LWxpYi9mdW5jdGlvbic7XG5pbXBvcnQgeyBlc2NhcGVSZWdFeHAgfSBmcm9tICdAbW5hb3Vtb3YvdHlwZXNjcmlwdC1saWIvcmVnLWV4cCc7XG5pbXBvcnQgeyBlbnN1cmVOb25OdWxsYWJsZSB9IGZyb20gJ0BtbmFvdW1vdi90eXBlc2NyaXB0LWxpYi90eXBlLWd1YXJkcyc7XG5pbXBvcnQgeyBleGVjRmlsZSB9IGZyb20gJ25vZGU6Y2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQge1xuICByZWFkRmlsZSxcbiAgcmVuYW1lLFxuICBzdGF0LFxuICB1bmxpbmssXG4gIHdyaXRlRmlsZVxufSBmcm9tICdub2RlOmZzL3Byb21pc2VzJztcbmltcG9ydCB7XG4gIGhvc3RuYW1lLFxuICB1cHRpbWVcbn0gZnJvbSAnbm9kZTpvcyc7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSAnbm9kZTpwYXRoJztcblxuaW1wb3J0IHR5cGUge1xuICBCdWxrT3BlcmF0aW9uQ29tbWl0LFxuICBCdWxrT3BlcmF0aW9uTG9ja1xufSBmcm9tICcuL2J1bGstb3BlcmF0aW9uLnRzJztcblxuaW1wb3J0IHsgcmVnaXN0ZXJCdWxrT3BlcmF0aW9uUHJvZ3Jlc3NMaXN0ZW5lciB9IGZyb20gJy4vYnVsay1vcGVyYXRpb24tcHJvZ3Jlc3MudHMnO1xuaW1wb3J0IHtcbiAgYnVpbGRCZWZvcmVPcGVyYXRpb25Db21taXRTdWJqZWN0LFxuICBidWlsZE9wZXJhdGlvbkNvbW1pdE1lc3NhZ2UsXG4gIEJVTEtfT1BFUkFUSU9OX0xPQ0tfRklMRV9OQU1FLFxuICBnZXROZXh0T3BlcmF0aW9uSWQsXG4gIGlzQnVsa09wZXJhdGlvbkxvY2ssXG4gIGlzQnVsa09wZXJhdGlvbkxvY2tTdGFsZSxcbiAgcGFyc2VCdWxrT3BlcmF0aW9uQ29tbWl0LFxuICBQTFVHSU5fVFJBSUxFUl9LRVlcbn0gZnJvbSAnLi9idWxrLW9wZXJhdGlvbi50cyc7XG5cbi8qKlxuICogQ29uc3RydWN0b3IgcGFyYW1ldGVycyBmb3Ige0BsaW5rIEJ1bGtPcGVyYXRpb25HaXRSZXBvfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCdWxrT3BlcmF0aW9uR2l0UmVwb0NvbnN0cnVjdG9yUGFyYW1zIHtcbiAgLyoqXG4gICAqIFRoZSBhYnNvbHV0ZSBwYXRoIG9mIHRoZSByZXBvJ3MgZ2l0IGRpcmVjdG9yeSwgd2hlcmUgdGhlIGxlYXNlIGxvY2sgbGl2ZXMuXG4gICAqL1xuICByZWFkb25seSBnaXREaXJlY3Rvcnk6IHN0cmluZztcblxuICAvKipcbiAgICogSG93IGxvbmcgdG8gd2FpdCBmb3IgYW5vdGhlciBvcGVyYXRpb24ncyBsb2NrIGJlZm9yZSBnaXZpbmcgdXAuXG4gICAqXG4gICAqIEBkZWZhdWx0IGA2MDBfMDAwYFxuICAgKi9cbiAgcmVhZG9ubHkgbG9ja1dhaXRUaW1lb3V0SW5NaWxsaXNlY29uZHM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBhYnNvbHV0ZSBwYXRoIG9mIHRoZSBmb2xkZXIgd2hvc2UgY2hhbmdlcyBhcmUgY29tbWl0dGVkOiB0aGUgdmF1bHQgcm9vdC5cbiAgICovXG4gIHJlYWRvbmx5IHdvcmtpbmdEaXJlY3Rvcnk6IHN0cmluZztcbn1cblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgQnVsa09wZXJhdGlvbkdpdFJlcG8ucnVuQnVsa09wZXJhdGlvbn0uXG4gKlxuICogQHR5cGVQYXJhbSBUIC0gVGhlIHR5cGUgb2YgdGhlIG9wZXJhdGlvbidzIHJlc3VsdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCdWxrT3BlcmF0aW9uR2l0UmVwb1J1bkJ1bGtPcGVyYXRpb25QYXJhbXM8VD4ge1xuICAvKipcbiAgICogUnVucyB0aGUgYnVsayBvcGVyYXRpb24uXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSBvcGVyYXRpb24ncyByZXN1bHQuXG4gICAqL1xuICByZWFkb25seSBvcGVyYXRpb246ICgpID0+IFByb21pc2U8VD47XG5cbiAgLyoqXG4gICAqIFRoZSBpZCBvZiB0aGUgcGx1Z2luIHJ1bm5pbmcgdGhlIG9wZXJhdGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IHBsdWdpbklkOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdhaXRzIGZvciB0aGUgZm9sbG93LXVwcyB0aGUgb3BlcmF0aW9uIHNldCBvZmYgKHJlbmFtZSBoYW5kbGVycywgbGluayB1cGRhdGVzLCB0aGUgbWV0YWRhdGEgY2FjaGUpIHRvIGZpbmlzaCwgc29cbiAgICogdGhlaXIgY2hhbmdlcyBsYW5kIGluIHRoZSBvcGVyYXRpb24ncyBjb21taXQuXG4gICAqL1xuICByZWFkb25seSBzZXR0bGU6ICgpID0+IFByb21pc2U8dm9pZD47XG5cbiAgLyoqXG4gICAqIEEgb25lLWxpbmUgZGVzY3JpcHRpb24gb2YgdGhlIG9wZXJhdGlvbiwgdXNlZCBpbiB0aGUgY29tbWl0IHN1YmplY3QuXG4gICAqL1xuICByZWFkb25seSBzdW1tYXJ5OiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIHJlc3VsdCBvZiB7QGxpbmsgQnVsa09wZXJhdGlvbkdpdFJlcG8ucnVuQnVsa09wZXJhdGlvbn0uXG4gKlxuICogQHR5cGVQYXJhbSBUIC0gVGhlIHR5cGUgb2YgdGhlIG9wZXJhdGlvbidzIHJlc3VsdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHaXRCdWxrT3BlcmF0aW9uUmVzdWx0PFQ+IHtcbiAgLyoqXG4gICAqIFRoZSBoYXNoIG9mIHRoZSBjb21taXQgcmVjb3JkaW5nIHRoZSBvcGVyYXRpb24sIG9yIGBudWxsYCB3aGVuIHRoZSBvcGVyYXRpb24gY2hhbmdlZCBub3RoaW5nLlxuICAgKi9cbiAgcmVhZG9ubHkgY29tbWl0U2hhOiBudWxsIHwgc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgb3BlcmF0aW9uIGlkLCBzdWNoIGFzIGBPUDEyYC5cbiAgICovXG4gIHJlYWRvbmx5IG9wZXJhdGlvbklkOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBvcGVyYXRpb24ncyByZXN1bHQuXG4gICAqL1xuICByZWFkb25seSByZXN1bHQ6IFQ7XG59XG5cbi8qKlxuICogVGhlIHJlc3VsdCBvZiB7QGxpbmsgQnVsa09wZXJhdGlvbkdpdFJlcG8ucmV2ZXJ0QnVsa09wZXJhdGlvbkNvbW1pdH0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2l0UmV2ZXJ0UmVzdWx0IHtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIHJldmVydCBzdG9wcGVkIG9uIGEgY29uZmxpY3QsIGxlYXZpbmcgdGhlIHJlcG8gbWlkLXJldmVydCBmb3IgdGhlIHVzZXIgdG8gcmVzb2x2ZS5cbiAgICovXG4gIHJlYWRvbmx5IGlzQ29uZmxpY3Q6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoYXQgZ2l0IHByaW50ZWQuXG4gICAqL1xuICByZWFkb25seSBvdXRwdXQ6IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIEJ1bGtPcGVyYXRpb25HaXRSZXBvUnVuR2l0UGFyYW1zIHtcbiAgcmVhZG9ubHkgYWxsb3dlZEV4aXRDb2Rlcz86IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSBnaXRBcmd1bWVudHM6IHJlYWRvbmx5IHN0cmluZ1tdO1xufVxuXG5pbnRlcmZhY2UgR2l0Q29tbWFuZFJlc3VsdCB7XG4gIHJlYWRvbmx5IGV4aXRDb2RlOiBudW1iZXI7XG4gIHJlYWRvbmx5IHN0ZGVycjogc3RyaW5nO1xuICByZWFkb25seSBzdGRvdXQ6IHN0cmluZztcbn1cblxuY29uc3QgREVGQVVMVF9MT0NLX1dBSVRfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMgPSA2MDBfMDAwO1xuY29uc3QgSEVBUlRCRUFUX1RIUk9UVExFX0lOX01JTExJU0VDT05EUyA9IDUwMDA7XG5jb25zdCBJTkRFWF9MT0NLX1JFVFJZX0NPVU5UID0gMjA7XG5jb25zdCBJTkRFWF9MT0NLX1JFVFJZX0RFTEFZX0lOX01JTExJU0VDT05EUyA9IDUwMDtcbmNvbnN0IExPQ0tfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMgPSAxMDAwO1xuY29uc3QgTUFYX0JVRkZFUl9JTl9CWVRFUyA9IDI2OF80MzVfNDU2O1xuY29uc3QgTUlMTElTRUNPTkRTX0lOX1NFQ09ORCA9IDEwMDA7XG5jb25zdCBHSVRfRkFUQUxfRVhJVF9DT0RFID0gMTI4O1xuY29uc3QgUkVWX1BBUlNFX09VVFBVVF9MSU5FX0NPVU5UID0gMjtcbmNvbnN0IFVOSVRfU0VQQVJBVE9SID0gJ1xcdXsxRn0nO1xuXG5pbnRlcmZhY2UgQnVsa09wZXJhdGlvbkdpdFJlcG9Db21taXRPcGVyYXRpb25QYXJhbXMge1xuICByZWFkb25seSBpc0ludGVycnVwdGVkPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgb3BlcmF0aW9uSWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgcGx1Z2luSWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgc3VtbWFyeT86IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIENvbW1pdE1lc3NhZ2Uge1xuICByZWFkb25seSBib2R5OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHN1YmplY3Q6IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIEV4ZWNHaXRQYXJhbXMge1xuICByZWFkb25seSBjd2Q6IHN0cmluZztcbiAgcmVhZG9ubHkgZ2l0QXJndW1lbnRzOiByZWFkb25seSBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBBIGdpdCByZXBvIGhvbGRpbmcgYSB2YXVsdCwgZHJpdmVuIHRvIHdyYXAgYnVsayBvcGVyYXRpb25zIGluIGNvbW1pdHMuXG4gKi9cbmV4cG9ydCBjbGFzcyBCdWxrT3BlcmF0aW9uR2l0UmVwbyB7XG4gIC8qKlxuICAgKiBUaGUgYWJzb2x1dGUgcGF0aCBvZiB0aGUgcmVwbydzIGdpdCBkaXJlY3RvcnkuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgZ2l0RGlyZWN0b3J5OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBhYnNvbHV0ZSBwYXRoIG9mIHRoZSBmb2xkZXIgd2hvc2UgY2hhbmdlcyBhcmUgY29tbWl0dGVkLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHdvcmtpbmdEaXJlY3Rvcnk6IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IGxvY2tGaWxlUGF0aDogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGxvY2tXYWl0VGltZW91dEluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG4gIHByaXZhdGUgb3duTG9jazogQnVsa09wZXJhdGlvbkxvY2sgfCBudWxsID0gbnVsbDtcblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBpbnN0YW5jZS4gVXNlIHtAbGluayBCdWxrT3BlcmF0aW9uR2l0UmVwby5vcGVufSB0byBmaW5kIHRoZSByZXBvIG9mIGEgZm9sZGVyLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIGNvbnN0cnVjdG9yIHBhcmFtZXRlcnMuXG4gICAqL1xuICBwdWJsaWMgY29uc3RydWN0b3IocGFyYW1zOiBCdWxrT3BlcmF0aW9uR2l0UmVwb0NvbnN0cnVjdG9yUGFyYW1zKSB7XG4gICAgdGhpcy5naXREaXJlY3RvcnkgPSBwYXJhbXMuZ2l0RGlyZWN0b3J5O1xuICAgIHRoaXMud29ya2luZ0RpcmVjdG9yeSA9IHBhcmFtcy53b3JraW5nRGlyZWN0b3J5O1xuICAgIHRoaXMubG9ja1dhaXRUaW1lb3V0SW5NaWxsaXNlY29uZHMgPSBwYXJhbXMubG9ja1dhaXRUaW1lb3V0SW5NaWxsaXNlY29uZHMgPz8gREVGQVVMVF9MT0NLX1dBSVRfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFM7XG4gICAgdGhpcy5sb2NrRmlsZVBhdGggPSBqb2luKHRoaXMuZ2l0RGlyZWN0b3J5LCBCVUxLX09QRVJBVElPTl9MT0NLX0ZJTEVfTkFNRSk7XG4gIH1cblxuICAvKipcbiAgICogRmluZHMgdGhlIGdpdCByZXBvIGEgZm9sZGVyIGJlbG9uZ3MgdG8uXG4gICAqXG4gICAqIEBwYXJhbSB3b3JraW5nRGlyZWN0b3J5IC0gVGhlIGZvbGRlciwgbm9ybWFsbHkgdGhlIHZhdWx0IHJvb3QuXG4gICAqIEByZXR1cm5zIFRoZSByZXBvLCBvciBgbnVsbGAgd2hlbiB0aGUgZm9sZGVyIGlzIG5vdCBpbnNpZGUgYSBnaXQgd29yayB0cmVlIG9yIGBnaXRgIGNhbm5vdCBiZSBydW4uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFzeW5jIG9wZW4od29ya2luZ0RpcmVjdG9yeTogc3RyaW5nKTogUHJvbWlzZTxCdWxrT3BlcmF0aW9uR2l0UmVwbyB8IG51bGw+IHtcbiAgICBsZXQgcmVzdWx0OiBHaXRDb21tYW5kUmVzdWx0O1xuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCBleGVjR2l0KHsgY3dkOiB3b3JraW5nRGlyZWN0b3J5LCBnaXRBcmd1bWVudHM6IFsncmV2LXBhcnNlJywgJy0taXMtaW5zaWRlLXdvcmstdHJlZScsICctLWFic29sdXRlLWdpdC1kaXInXSB9KTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCBbaXNJbnNpZGVXb3JrVHJlZSwgZ2l0RGlyZWN0b3J5XSA9IHJlc3VsdC5zdGRvdXQuc3BsaXQoL1xccj9cXG4vLCBSRVZfUEFSU0VfT1VUUFVUX0xJTkVfQ09VTlQpO1xuICAgIHJldHVybiByZXN1bHQuZXhpdENvZGUgIT09IDAgfHwgaXNJbnNpZGVXb3JrVHJlZSAhPT0gJ3RydWUnIHx8ICFnaXREaXJlY3RvcnkgPyBudWxsIDogbmV3IEJ1bGtPcGVyYXRpb25HaXRSZXBvKHsgZ2l0RGlyZWN0b3J5LCB3b3JraW5nRGlyZWN0b3J5IH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZnVzZXMgdG8gZ28gb24gd2hlbiB0aGUgcmVwbyByb3V0ZXMgZmlsZXMgdGhyb3VnaCBnaXQtYW5uZXggYnV0IGBnaXQtYW5uZXhgIGNhbm5vdCBiZSBydW4sIHNpbmNlIGFcbiAgICogcGxhaW4gYGdpdCBhZGRgIHdvdWxkIHRoZW4gcHV0IHRoZSBsYXJnZSBmaWxlcyBpbnRvIGdpdCBpdHNlbGYuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgYXNzZXJ0Q2FuQ29tbWl0TGFyZ2VGaWxlcygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBhbm5leEZpbHRlcnMgPSBhd2FpdCB0aGlzLnJ1bkdpdCh7IGFsbG93ZWRFeGl0Q29kZXM6IFswLCAxXSwgZ2l0QXJndW1lbnRzOiBbJ2NvbmZpZycsICctLWdldC1yZWdleHAnLCBTdHJpbmcucmF3YF5maWx0ZXJcXC5hbm5leFxcLmBdIH0pO1xuICAgIGlmICghYW5uZXhGaWx0ZXJzLnN0ZG91dC50cmltKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgYW5uZXhWZXJzaW9uID0gYXdhaXQgdGhpcy5ydW5HaXQoeyBnaXRBcmd1bWVudHM6IFsnYW5uZXgnLCAndmVyc2lvbicsICctLXJhdyddIH0pLmNhdGNoKCgpID0+IG51bGwpO1xuICAgIGlmIChhbm5leFZlcnNpb24gPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ1RoZSB2YXVsdCByZXBvc2l0b3J5IHJvdXRlcyBmaWxlcyB0aHJvdWdoIGdpdC1hbm5leCwgYnV0IGdpdC1hbm5leCBpcyBub3Qgb24gUEFUSC4gQnVsayBvcGVyYXRpb24gY29tbWl0cyBhcmUgcmVmdXNlZCwgYmVjYXVzZSB0aGV5IHdvdWxkIGFkZCBsYXJnZSBmaWxlcyB0byBnaXQgaXRzZWxmLidcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIExpc3RzIHRoZSBidWxrLW9wZXJhdGlvbiBjb21taXRzIGEgcGx1Z2luIG1hZGUgb24gdGhlIGN1cnJlbnQgYnJhbmNoLCBuZXdlc3QgZmlyc3QuXG4gICAqXG4gICAqIEBwYXJhbSBwbHVnaW5JZCAtIFRoZSBwbHVnaW4gaWQuXG4gICAqIEByZXR1cm5zIFRoZSBjb21taXRzLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGxpc3RCdWxrT3BlcmF0aW9uQ29tbWl0cyhwbHVnaW5JZDogc3RyaW5nKTogUHJvbWlzZTxCdWxrT3BlcmF0aW9uQ29tbWl0W10+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnJ1bkdpdCh7XG4gICAgICBhbGxvd2VkRXhpdENvZGVzOiBbMCwgR0lUX0ZBVEFMX0VYSVRfQ09ERV0sXG4gICAgICBnaXRBcmd1bWVudHM6IFtcbiAgICAgICAgJ2xvZycsXG4gICAgICAgIGAtLWZvcm1hdD0lSCR7VU5JVF9TRVBBUkFUT1J9JWFJJHtVTklUX1NFUEFSQVRPUn0lc2AsXG4gICAgICAgICctLWV4dGVuZGVkLXJlZ2V4cCcsXG4gICAgICAgIGAtLWdyZXA9XiR7UExVR0lOX1RSQUlMRVJfS0VZfTogJHtlc2NhcGVSZWdFeHAocGx1Z2luSWQpfSRgXG4gICAgICBdXG4gICAgfSk7XG4gICAgaWYgKHJlc3VsdC5leGl0Q29kZSAhPT0gMCkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBjb25zdCBjb21taXRzOiBCdWxrT3BlcmF0aW9uQ29tbWl0W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGxpbmUgb2YgcmVzdWx0LnN0ZG91dC5zcGxpdCgvXFxyP1xcbi8pKSB7XG4gICAgICBjb25zdCBbc2hhID0gJycsIGRhdGUgPSAnJywgLi4uc3ViamVjdFBhcnRzXSA9IGxpbmUuc3BsaXQoVU5JVF9TRVBBUkFUT1IpO1xuICAgICAgY29uc3QgY29tbWl0ID0gcGFyc2VCdWxrT3BlcmF0aW9uQ29tbWl0KHsgZGF0ZSwgc2hhLCBzdWJqZWN0OiBzdWJqZWN0UGFydHMuam9pbihVTklUX1NFUEFSQVRPUikgfSk7XG4gICAgICBpZiAoY29tbWl0KSB7XG4gICAgICAgIGNvbW1pdHMucHVzaChjb21taXQpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY29tbWl0cztcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21taXRzIHdoYXRldmVyIGEgc3RhbGUgbG9jaydzIG9wZXJhdGlvbiBsZWZ0IGJlaGluZCBhcyBgT1A8bj4gaW50ZXJydXB0ZWRgIGFuZCByZW1vdmVzIHRoZSBsb2NrLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgaWQgb2YgdGhlIHJlY292ZXJlZCBvcGVyYXRpb24sIG9yIGBudWxsYCB3aGVuIHRoZXJlIHdhcyBubyBzdGFsZSBsb2NrLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHJlY292ZXJTdGFsZUxvY2soKTogUHJvbWlzZTxudWxsIHwgc3RyaW5nPiB7XG4gICAgY29uc3QgbG9jayA9IGF3YWl0IHRoaXMucmVhZExvY2soKTtcbiAgICByZXR1cm4gIWxvY2sgfHwgIXRoaXMuaXNTdGFsZShsb2NrKSA/IG51bGwgOiAoYXdhaXQgdGhpcy5yZWNvdmVyKGxvY2spKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXZlcnRzIGEgYnVsay1vcGVyYXRpb24gY29tbWl0IHdpdGggYGdpdCByZXZlcnQgLS1uby1lZGl0YC5cbiAgICpcbiAgICogV2hhdGV2ZXIgaXMgcGVuZGluZyBpcyBjb21taXR0ZWQgZmlyc3QsIHNvIHRoZSByZXZlcnQgc3RhcnRzIGZyb20gYSBjbGVhbiB0cmVlLiBBIGNvbmZsaWN0IGlzIE5PVCBhYm9ydGVkOiB0aGVcbiAgICogcmVwbyBpcyBsZWZ0IG1pZC1yZXZlcnQgZm9yIHRoZSB1c2VyIHRvIHJlc29sdmUuXG4gICAqXG4gICAqIEBwYXJhbSBjb21taXQgLSBUaGUgY29tbWl0IHRvIHJldmVydC5cbiAgICogQHJldHVybnMgV2hldGhlciB0aGUgcmV2ZXJ0IHN0b3BwZWQgb24gYSBjb25mbGljdCwgYW5kIHdoYXQgZ2l0IHByaW50ZWQuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmV2ZXJ0QnVsa09wZXJhdGlvbkNvbW1pdChjb21taXQ6IEJ1bGtPcGVyYXRpb25Db21taXQpOiBQcm9taXNlPEdpdFJldmVydFJlc3VsdD4ge1xuICAgIGF3YWl0IHRoaXMuYXNzZXJ0Q2FuQ29tbWl0TGFyZ2VGaWxlcygpO1xuICAgIGF3YWl0IHRoaXMuYWNxdWlyZUxvY2soKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5jb21taXRQZW5kaW5nKHsgYm9keTogJycsIHN1YmplY3Q6IGBjaG9yZTogYmVmb3JlIHJldmVydCBvZiAke2NvbW1pdC5vcGVyYXRpb25JZH1gIH0pO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5ydW5HaXQoeyBhbGxvd2VkRXhpdENvZGVzOiBbMCwgMV0sIGdpdEFyZ3VtZW50czogWydyZXZlcnQnLCAnLS1uby1lZGl0JywgY29tbWl0LnNoYV0gfSk7XG4gICAgICByZXR1cm4geyBpc0NvbmZsaWN0OiByZXN1bHQuZXhpdENvZGUgIT09IDAsIG91dHB1dDogYCR7cmVzdWx0LnN0ZG91dH0ke3Jlc3VsdC5zdGRlcnJ9YC50cmltKCkgfTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgdGhpcy5yZWxlYXNlTG9jaygpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGEgYnVsayBvcGVyYXRpb24gYmV0d2VlbiB0d28gY29tbWl0cy5cbiAgICpcbiAgICogVGFrZXMgdGhlIGxlYXNlIGxvY2ssIGNvbW1pdHMgd2hhdGV2ZXIgaXMgcGVuZGluZyBhcyBgY2hvcmU6IGJlZm9yZSBPUDxuPmAsIHJ1bnMgdGhlIG9wZXJhdGlvbiwgd2FpdHMgZm9yIGl0c1xuICAgKiBmb2xsb3ctdXBzIHRvIHNldHRsZSwgY29tbWl0cyB0aGUgcmVzdWx0IGFzIGBPUDxuPjogPHN1bW1hcnk+YCBhbmQgcmVsZWFzZXMgdGhlIGxvY2suIEFuIG9wZXJhdGlvbiB0aGF0IHRocm93c1xuICAgKiBzdGlsbCBnZXRzIGl0cyBwYXJ0aWFsIGNoYW5nZXMgY29tbWl0dGVkLCBhcyBgT1A8bj4gaW50ZXJydXB0ZWRgLCBiZWZvcmUgdGhlIGVycm9yIGlzIHJldGhyb3duLlxuICAgKlxuICAgKiBAdHlwZVBhcmFtIFQgLSBUaGUgdHlwZSBvZiB0aGUgb3BlcmF0aW9uJ3MgcmVzdWx0LlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBhcmFtZXRlcnMuXG4gICAqIEByZXR1cm5zIFRoZSBvcGVyYXRpb24ncyByZXN1bHQsIGl0cyBpZCBhbmQgdGhlIGhhc2ggb2YgaXRzIGNvbW1pdC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBydW5CdWxrT3BlcmF0aW9uPFQ+KHBhcmFtczogQnVsa09wZXJhdGlvbkdpdFJlcG9SdW5CdWxrT3BlcmF0aW9uUGFyYW1zPFQ+KTogUHJvbWlzZTxHaXRCdWxrT3BlcmF0aW9uUmVzdWx0PFQ+PiB7XG4gICAgYXdhaXQgdGhpcy5hc3NlcnRDYW5Db21taXRMYXJnZUZpbGVzKCk7XG4gICAgYXdhaXQgdGhpcy5hY3F1aXJlTG9jaygpO1xuICAgIGxldCB1bnJlZ2lzdGVyUHJvZ3Jlc3NMaXN0ZW5lcjogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG9wZXJhdGlvbklkID0gYXdhaXQgdGhpcy5hbGxvY2F0ZU9wZXJhdGlvbklkKHBhcmFtcy5wbHVnaW5JZCk7XG4gICAgICBhd2FpdCB0aGlzLmNvbW1pdFBlbmRpbmcoeyBib2R5OiAnJywgc3ViamVjdDogYnVpbGRCZWZvcmVPcGVyYXRpb25Db21taXRTdWJqZWN0KG9wZXJhdGlvbklkKSB9KTtcblxuICAgICAgdW5yZWdpc3RlclByb2dyZXNzTGlzdGVuZXIgPSByZWdpc3RlckJ1bGtPcGVyYXRpb25Qcm9ncmVzc0xpc3RlbmVyKHRoaXMuY3JlYXRlVGhyb3R0bGVkSGVhcnRiZWF0KCkpO1xuXG4gICAgICBsZXQgcmVzdWx0OiBUO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmVzdWx0ID0gYXdhaXQgcGFyYW1zLm9wZXJhdGlvbigpO1xuICAgICAgICBhd2FpdCBwYXJhbXMuc2V0dGxlKCk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBhd2FpdCB0aGlzLmhlYXJ0YmVhdCgpO1xuICAgICAgICBhd2FpdCB0aGlzLmNvbW1pdE9wZXJhdGlvbih7IGlzSW50ZXJydXB0ZWQ6IHRydWUsIG9wZXJhdGlvbklkLCBwbHVnaW5JZDogcGFyYW1zLnBsdWdpbklkIH0pO1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cblxuICAgICAgYXdhaXQgdGhpcy5oZWFydGJlYXQoKTtcbiAgICAgIGNvbnN0IGNvbW1pdFNoYSA9IGF3YWl0IHRoaXMuY29tbWl0T3BlcmF0aW9uKHsgb3BlcmF0aW9uSWQsIHBsdWdpbklkOiBwYXJhbXMucGx1Z2luSWQsIHN1bW1hcnk6IHBhcmFtcy5zdW1tYXJ5IH0pO1xuICAgICAgcmV0dXJuIHsgY29tbWl0U2hhLCBvcGVyYXRpb25JZCwgcmVzdWx0IH07XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHVucmVnaXN0ZXJQcm9ncmVzc0xpc3RlbmVyPy4oKTtcbiAgICAgIGF3YWl0IHRoaXMucmVsZWFzZUxvY2soKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGFjcXVpcmVMb2NrKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIHRoaXMubG9ja1dhaXRUaW1lb3V0SW5NaWxsaXNlY29uZHM7XG4gICAgZm9yICg7Oykge1xuICAgICAgaWYgKGF3YWl0IHRoaXMudHJ5Q3JlYXRlTG9jaygpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbG9jayA9IGF3YWl0IHRoaXMucmVhZExvY2soKTtcbiAgICAgIGlmICghbG9jaykge1xuICAgICAgICAvLyBSZWxlYXNlZCBiZXR3ZWVuIHRoZSB0d28gY2FsbHM6IHRyeSB0byB0YWtlIGl0IGFnYWluIGF0IG9uY2UuXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5pc1N0YWxlKGxvY2spKSB7XG4gICAgICAgIGF3YWl0IHRoaXMucmVjb3Zlcihsb2NrKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChEYXRlLm5vdygpID49IGRlYWRsaW5lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgVGltZWQgb3V0IHdhaXRpbmcgZm9yICR7bG9jay5vcGVyYXRpb25JZCB8fCAnYW4gb3BlcmF0aW9uJ30gb2YgJHtsb2NrLnBsdWdpbklkfSBvbiAke2xvY2suaG9zdH0gdG8gcmVsZWFzZSB0aGUgYnVsayBvcGVyYXRpb24gbG9jayAke3RoaXMubG9ja0ZpbGVQYXRofS5gXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IHNldFRpbWVvdXRBc3luYyhMT0NLX1BPTExfSU5URVJWQUxfSU5fTUlMTElTRUNPTkRTKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGFsbG9jYXRlT3BlcmF0aW9uSWQocGx1Z2luSWQ6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3Qgb3BlcmF0aW9uSWQgPSBhd2FpdCB0aGlzLmZpbmROZXh0T3BlcmF0aW9uSWQoKTtcbiAgICBjb25zdCBvd25Mb2NrID0gZW5zdXJlTm9uTnVsbGFibGUodGhpcy5vd25Mb2NrKTtcbiAgICB0aGlzLm93bkxvY2sgPSB7IC4uLm93bkxvY2ssIGhlYXJ0YmVhdEF0OiBEYXRlLm5vdygpLCBvcGVyYXRpb25JZCwgcGx1Z2luSWQgfTtcbiAgICBhd2FpdCB0aGlzLndyaXRlTG9jayh0aGlzLm93bkxvY2spO1xuICAgIHJldHVybiBvcGVyYXRpb25JZDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY29tbWl0T3BlcmF0aW9uKHBhcmFtczogQnVsa09wZXJhdGlvbkdpdFJlcG9Db21taXRPcGVyYXRpb25QYXJhbXMpOiBQcm9taXNlPG51bGwgfCBzdHJpbmc+IHtcbiAgICBjb25zdCBjaGFuZ2VkRmlsZUNvdW50ID0gYXdhaXQgdGhpcy5zdGFnZUFsbCgpO1xuICAgIGlmIChjaGFuZ2VkRmlsZUNvdW50ID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3QgbWVzc2FnZSA9IGJ1aWxkT3BlcmF0aW9uQ29tbWl0TWVzc2FnZSh7IC4uLnBhcmFtcywgY2hhbmdlZEZpbGVDb3VudCwgdGltZXN0YW1wOiBuZXcgRGF0ZSgpIH0pO1xuICAgIGF3YWl0IHRoaXMuY29tbWl0U3RhZ2VkKG1lc3NhZ2UpO1xuICAgIGNvbnN0IGhlYWRSZXN1bHQgPSBhd2FpdCB0aGlzLnJ1bkdpdCh7IGdpdEFyZ3VtZW50czogWydyZXYtcGFyc2UnLCAnSEVBRCddIH0pO1xuICAgIHJldHVybiBoZWFkUmVzdWx0LnN0ZG91dC50cmltKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNvbW1pdFBlbmRpbmcobWVzc2FnZTogQ29tbWl0TWVzc2FnZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChhd2FpdCB0aGlzLnN0YWdlQWxsKCkgPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYXdhaXQgdGhpcy5jb21taXRTdGFnZWQobWVzc2FnZSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNvbW1pdFN0YWdlZChtZXNzYWdlOiBDb21taXRNZXNzYWdlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgZ2l0QXJndW1lbnRzID0gWydjb21taXQnLCAnLS1xdWlldCcsICctbScsIG1lc3NhZ2Uuc3ViamVjdF07XG4gICAgaWYgKG1lc3NhZ2UuYm9keSkge1xuICAgICAgZ2l0QXJndW1lbnRzLnB1c2goJy1tJywgbWVzc2FnZS5ib2R5KTtcbiAgICB9XG4gICAgZ2l0QXJndW1lbnRzLnB1c2goJy0tJywgJy4nKTtcbiAgICBhd2FpdCB0aGlzLnJ1bkdpdCh7IGdpdEFyZ3VtZW50cyB9KTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVGhyb3R0bGVkSGVhcnRiZWF0KCk6ICgpID0+IHZvaWQge1xuICAgIGxldCBsYXN0SGVhcnRiZWF0QXQgPSBEYXRlLm5vdygpO1xuICAgIGxldCBwZW5kaW5nSGVhcnRiZWF0OiBQcm9taXNlPHZvaWQ+ID0gbm9vcEFzeW5jKCk7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICBpZiAobm93IC0gbGFzdEhlYXJ0YmVhdEF0IDwgSEVBUlRCRUFUX1RIUk9UVExFX0lOX01JTExJU0VDT05EUykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBsYXN0SGVhcnRiZWF0QXQgPSBub3c7XG4gICAgICBwZW5kaW5nSGVhcnRiZWF0ID0gcGVuZGluZ0hlYXJ0YmVhdC50aGVuKCgpID0+IHRoaXMuaGVhcnRiZWF0KCkpLmNhdGNoKChlcnJvcjogdW5rbm93bikgPT4ge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gcmVmcmVzaCB0aGUgYnVsayBvcGVyYXRpb24gbG9jayBoZWFydGJlYXQnLCBlcnJvcik7XG4gICAgICB9KTtcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmaW5kTmV4dE9wZXJhdGlvbklkKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgLy8gYC0tYWxsYCBhbHNvIHJlYWRzIGEgcmVwb3NpdG9yeSB3aXRoIG5vIGNvbW1pdCB5ZXQsIHdoZXJlIGEgcGxhaW4gYGdpdCBsb2dgIGZhaWxzLlxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMucnVuR2l0KHtcbiAgICAgIGdpdEFyZ3VtZW50czogWydsb2cnLCAnLS1hbGwnLCAnLS1mb3JtYXQ9JXMnLCAnLS1leHRlbmRlZC1yZWdleHAnLCAnLS1ncmVwPV4oY2hvcmU6IGJlZm9yZSApP09QWzAtOV0rJ11cbiAgICB9KTtcbiAgICByZXR1cm4gZ2V0TmV4dE9wZXJhdGlvbklkKHJlc3VsdC5zdGRvdXQuc3BsaXQoL1xccj9cXG4vKSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGhlYXJ0YmVhdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBsb2NrID0gYXdhaXQgdGhpcy5yZWFkTG9jaygpO1xuICAgIGlmICghbG9jayB8fCAhdGhpcy5pc093bkxvY2sobG9jaykpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYXdhaXQgdGhpcy53cml0ZUxvY2soeyAuLi5sb2NrLCBoZWFydGJlYXRBdDogRGF0ZS5ub3coKSB9KTtcbiAgfVxuXG4gIHByaXZhdGUgaXNPd25Mb2NrKGxvY2s6IEJ1bGtPcGVyYXRpb25Mb2NrKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMub3duTG9jayAhPT0gbnVsbFxuICAgICAgJiYgbG9jay5ob3N0ID09PSB0aGlzLm93bkxvY2suaG9zdFxuICAgICAgJiYgbG9jay5wcm9jZXNzSWQgPT09IHRoaXMub3duTG9jay5wcm9jZXNzSWRcbiAgICAgICYmIGxvY2suc3RhcnRlZEF0ID09PSB0aGlzLm93bkxvY2suc3RhcnRlZEF0O1xuICB9XG5cbiAgcHJpdmF0ZSBpc1N0YWxlKGxvY2s6IEJ1bGtPcGVyYXRpb25Mb2NrKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGlzQnVsa09wZXJhdGlvbkxvY2tTdGFsZShsb2NrLCB7XG4gICAgICBib290ZWRBdDogRGF0ZS5ub3coKSAtIHVwdGltZSgpICogTUlMTElTRUNPTkRTX0lOX1NFQ09ORCxcbiAgICAgIGhvc3Q6IGhvc3RuYW1lKCksXG4gICAgICBpc1Byb2Nlc3NBbGl2ZSxcbiAgICAgIG5vdzogRGF0ZS5ub3coKVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWFkTG9jaygpOiBQcm9taXNlPEJ1bGtPcGVyYXRpb25Mb2NrIHwgbnVsbD4ge1xuICAgIGxldCB0ZXh0OiBzdHJpbmc7XG4gICAgdHJ5IHtcbiAgICAgIHRleHQgPSBhd2FpdCByZWFkRmlsZSh0aGlzLmxvY2tGaWxlUGF0aCwgJ3V0Zi04Jyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChpc0Vycm9yV2l0aENvZGUoZXJyb3IsICdFTk9FTlQnKSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB2YWx1ZTogdW5rbm93biA9IEpTT04ucGFyc2UodGV4dCk7XG4gICAgICBpZiAoaXNCdWxrT3BlcmF0aW9uTG9jayh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gVXBkYXRlcyBhcmUgYXRvbWljLCBidXQgYSBsb2NrIGJlaW5nIGNyZWF0ZWQgY2FuIGJlIHJlYWQgYmVmb3JlIGl0cyBjb250ZW50IGlzIHdyaXR0ZW4uIFRoZSBmaWxlJ3MgYWdlXG4gICAgICAvLyBzdGFuZHMgaW4gZm9yIHRoZSBoZWFydGJlYXQsIHNvIHN1Y2ggYSBsb2NrIHJlYWRzIGFzIGZyZXNoIGFuZCBhIGNvcnJ1cHQgb25lIGdvZXMgc3RhbGUgbGlrZSBhbnkgb3RoZXIuXG4gICAgfVxuICAgIGNvbnN0IGZpbGVTdGF0cyA9IGF3YWl0IHN0YXQodGhpcy5sb2NrRmlsZVBhdGgpO1xuICAgIHJldHVybiB7XG4gICAgICBoZWFydGJlYXRBdDogZmlsZVN0YXRzLm10aW1lTXMsXG4gICAgICBob3N0OiAnJyxcbiAgICAgIG9wZXJhdGlvbklkOiAnJyxcbiAgICAgIHBsdWdpbklkOiAnJyxcbiAgICAgIHByb2Nlc3NJZDogMCxcbiAgICAgIHByb2Nlc3NTdGFydGVkQXQ6IDAsXG4gICAgICBzdGFydGVkQXQ6IDBcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWNvdmVyKGxvY2s6IEJ1bGtPcGVyYXRpb25Mb2NrKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBvcGVyYXRpb25JZCA9IGxvY2sub3BlcmF0aW9uSWQgfHwgYXdhaXQgdGhpcy5maW5kTmV4dE9wZXJhdGlvbklkKCk7XG4gICAgYXdhaXQgdGhpcy5jb21taXRPcGVyYXRpb24oeyBpc0ludGVycnVwdGVkOiB0cnVlLCBvcGVyYXRpb25JZCwgcGx1Z2luSWQ6IGxvY2sucGx1Z2luSWQgfHwgJ3Vua25vd24nIH0pO1xuICAgIGF3YWl0IHVubGluayh0aGlzLmxvY2tGaWxlUGF0aCkuY2F0Y2goKGVycm9yOiB1bmtub3duKSA9PiB7XG4gICAgICBpZiAoIWlzRXJyb3JXaXRoQ29kZShlcnJvciwgJ0VOT0VOVCcpKSB7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBvcGVyYXRpb25JZDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVsZWFzZUxvY2soKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgbG9jayA9IGF3YWl0IHRoaXMucmVhZExvY2soKTtcbiAgICBjb25zdCBpc093bkxvY2sgPSBsb2NrICE9PSBudWxsICYmIHRoaXMuaXNPd25Mb2NrKGxvY2spO1xuICAgIHRoaXMub3duTG9jayA9IG51bGw7XG4gICAgaWYgKCFpc093bkxvY2spIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYXdhaXQgdW5saW5rKHRoaXMubG9ja0ZpbGVQYXRoKS5jYXRjaCgoZXJyb3I6IHVua25vd24pID0+IHtcbiAgICAgIGlmICghaXNFcnJvcldpdGhDb2RlKGVycm9yLCAnRU5PRU5UJykpIHtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJ1bkdpdChwYXJhbXM6IEJ1bGtPcGVyYXRpb25HaXRSZXBvUnVuR2l0UGFyYW1zKTogUHJvbWlzZTxHaXRDb21tYW5kUmVzdWx0PiB7XG4gICAgY29uc3QgYWxsb3dlZEV4aXRDb2RlcyA9IHBhcmFtcy5hbGxvd2VkRXhpdENvZGVzID8/IFswXTtcbiAgICBmb3IgKGxldCBhdHRlbXB0ID0gMTs7IGF0dGVtcHQrKykge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZXhlY0dpdCh7IGN3ZDogdGhpcy53b3JraW5nRGlyZWN0b3J5LCBnaXRBcmd1bWVudHM6IHBhcmFtcy5naXRBcmd1bWVudHMgfSk7XG4gICAgICBpZiAoYWxsb3dlZEV4aXRDb2Rlcy5pbmNsdWRlcyhyZXN1bHQuZXhpdENvZGUpKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgICBpZiAoYXR0ZW1wdCA8IElOREVYX0xPQ0tfUkVUUllfQ09VTlQgJiYgcmVzdWx0LnN0ZGVyci5pbmNsdWRlcygnaW5kZXgubG9jaycpKSB7XG4gICAgICAgIGF3YWl0IHNldFRpbWVvdXRBc3luYyhJTkRFWF9MT0NLX1JFVFJZX0RFTEFZX0lOX01JTExJU0VDT05EUyk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEdpdENvbW1hbmRFcnJvcihwYXJhbXMuZ2l0QXJndW1lbnRzLCByZXN1bHQuZXhpdENvZGUsIHJlc3VsdC5zdGRlcnIpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc3RhZ2VBbGwoKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBhd2FpdCB0aGlzLnJ1bkdpdCh7IGdpdEFyZ3VtZW50czogWydhZGQnLCAnLS1hbGwnLCAnLS0nLCAnLiddIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMucnVuR2l0KHsgZ2l0QXJndW1lbnRzOiBbJ2RpZmYnLCAnLS1jYWNoZWQnLCAnLS1uYW1lLW9ubHknLCAnLXonLCAnLS0nLCAnLiddIH0pO1xuICAgIHJldHVybiByZXN1bHQuc3Rkb3V0LnNwbGl0KCdcXDAnKS5maWx0ZXIoQm9vbGVhbikubGVuZ3RoO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB0cnlDcmVhdGVMb2NrKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGxvY2sgPSBjcmVhdGVMb2NrUmVjb3JkKCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHdyaXRlRmlsZSh0aGlzLmxvY2tGaWxlUGF0aCwgSlNPTi5zdHJpbmdpZnkobG9jayksIHsgZmxhZzogJ3d4JyB9KTtcbiAgICAgIHRoaXMub3duTG9jayA9IGxvY2s7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGlzRXJyb3JXaXRoQ29kZShlcnJvciwgJ0VFWElTVCcpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgd3JpdGVMb2NrKGxvY2s6IEJ1bGtPcGVyYXRpb25Mb2NrKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gV3JpdHRlbiBiZXNpZGUgdGhlIGxvY2sgYW5kIHJlbmFtZWQgb3ZlciBpdCwgc28gYSByZWFkZXIgbmV2ZXIgc2VlcyBhIGhhbGYtd3JpdHRlbiBoZWFydGJlYXQuXG4gICAgY29uc3QgdGVtcG9yYXJ5UGF0aCA9IGAke3RoaXMubG9ja0ZpbGVQYXRofS4ke1N0cmluZyhsb2NrLnByb2Nlc3NJZCl9LnRtcGA7XG4gICAgYXdhaXQgd3JpdGVGaWxlKHRlbXBvcmFyeVBhdGgsIEpTT04uc3RyaW5naWZ5KGxvY2spKTtcbiAgICBhd2FpdCByZW5hbWUodGVtcG9yYXJ5UGF0aCwgdGhpcy5sb2NrRmlsZVBhdGgpO1xuICB9XG59XG5cbi8qKlxuICogQW4gZXJyb3IgdGhyb3duIHdoZW4gYSBgZ2l0YCBjb21tYW5kIGZhaWxzLlxuICovXG5leHBvcnQgY2xhc3MgR2l0Q29tbWFuZEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIGdpdEFyZ3VtZW50cyAtIFRoZSBhcmd1bWVudHMgYGdpdGAgd2FzIHJ1biB3aXRoLlxuICAgKiBAcGFyYW0gZXhpdENvZGUgLSBUaGUgZXhpdCBjb2RlLlxuICAgKiBAcGFyYW0gc3RkZXJyIC0gV2hhdCBgZ2l0YCBwcmludGVkIHRvIHN0ZGVyci5cbiAgICovXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgcmVhZG9ubHkgZ2l0QXJndW1lbnRzOiByZWFkb25seSBzdHJpbmdbXSwgcHVibGljIHJlYWRvbmx5IGV4aXRDb2RlOiBudW1iZXIsIHB1YmxpYyByZWFkb25seSBzdGRlcnI6IHN0cmluZykge1xuICAgIHN1cGVyKGBnaXQgJHtnaXRBcmd1bWVudHMuam9pbignICcpfSBmYWlsZWQgd2l0aCBleGl0IGNvZGUgJHtTdHJpbmcoZXhpdENvZGUpfTogJHtzdGRlcnIudHJpbSgpfWApO1xuICAgIHRoaXMubmFtZSA9ICdHaXRDb21tYW5kRXJyb3InO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUxvY2tSZWNvcmQoKTogQnVsa09wZXJhdGlvbkxvY2sge1xuICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICByZXR1cm4ge1xuICAgIGhlYXJ0YmVhdEF0OiBub3csXG4gICAgaG9zdDogaG9zdG5hbWUoKSxcbiAgICBvcGVyYXRpb25JZDogJycsXG4gICAgcGx1Z2luSWQ6ICcnLFxuICAgIHByb2Nlc3NJZDogcHJvY2Vzcy5waWQsXG4gICAgcHJvY2Vzc1N0YXJ0ZWRBdDogZ2V0UHJvY2Vzc1N0YXJ0ZWRBdCgpLFxuICAgIHN0YXJ0ZWRBdDogbm93XG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGV4ZWNHaXQocGFyYW1zOiBFeGVjR2l0UGFyYW1zKTogUHJvbWlzZTxHaXRDb21tYW5kUmVzdWx0PiB7XG4gIHJldHVybiBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgZXhlY0ZpbGUoJ2dpdCcsIFsuLi5wYXJhbXMuZ2l0QXJndW1lbnRzXSwgeyBjd2Q6IHBhcmFtcy5jd2QsIG1heEJ1ZmZlcjogTUFYX0JVRkZFUl9JTl9CWVRFUywgd2luZG93c0hpZGU6IHRydWUgfSwgKGVycm9yLCBzdGRvdXQsIHN0ZGVycikgPT4ge1xuICAgICAgaWYgKGVycm9yICYmIHR5cGVvZiBlcnJvci5jb2RlICE9PSAnbnVtYmVyJykge1xuICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gcnVuIGdpdCAke3BhcmFtcy5naXRBcmd1bWVudHMuam9pbignICcpfWAsIHsgY2F1c2U6IGVycm9yIH0pKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgcmVzb2x2ZSh7IGV4aXRDb2RlOiB0eXBlb2YgZXJyb3I/LmNvZGUgPT09ICdudW1iZXInID8gZXJyb3IuY29kZSA6IDAsIHN0ZGVyciwgc3Rkb3V0IH0pO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0UHJvY2Vzc1N0YXJ0ZWRBdCgpOiBudW1iZXIge1xuICByZXR1cm4gTWF0aC5yb3VuZChwZXJmb3JtYW5jZS50aW1lT3JpZ2luKTtcbn1cblxuZnVuY3Rpb24gaXNFcnJvcldpdGhDb2RlKGVycm9yOiB1bmtub3duLCBjb2RlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIHR5cGVvZiBlcnJvciA9PT0gJ29iamVjdCcgJiYgZXJyb3IgIT09IG51bGwgJiYgJ2NvZGUnIGluIGVycm9yICYmIGVycm9yLmNvZGUgPT09IGNvZGU7XG59XG5cbmZ1bmN0aW9uIGlzUHJvY2Vzc0FsaXZlKHByb2Nlc3NJZDogbnVtYmVyKTogYm9vbGVhbiB8IG51bGwge1xuICBpZiAocHJvY2Vzc0lkIDw9IDApIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgdHJ5IHtcbiAgICBwcm9jZXNzLmtpbGwocHJvY2Vzc0lkLCAwKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICByZXR1cm4gIWlzRXJyb3JXaXRoQ29kZShlcnJvciwgJ0VTUkNIJykgJiYgKGlzRXJyb3JXaXRoQ29kZShlcnJvciwgJ0VQRVJNJykgfHwgbnVsbCk7XG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBZ0JBLG1CQUFnQztBQUNoQyxzQkFBMEI7QUFDMUIscUJBQTZCO0FBQzdCLHlCQUFrQztBQUNsQyxnQ0FBeUI7QUFDekIsc0JBTU87QUFDUCxxQkFHTztBQUNQLHVCQUFxQjtBQU9yQixxQ0FBc0Q7QUFDdEQsNEJBU087QUFzR1AsTUFBTSw0Q0FBNEM7QUFDbEQsTUFBTSxxQ0FBcUM7QUFDM0MsTUFBTSx5QkFBeUI7QUFDL0IsTUFBTSx5Q0FBeUM7QUFDL0MsTUFBTSxxQ0FBcUM7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