appium-android-driver 5.13.0 → 5.13.2

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 (151) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/build/index.js +43 -40
  3. package/build/lib/android-helpers.d.ts +136 -0
  4. package/build/lib/android-helpers.d.ts.map +1 -0
  5. package/build/lib/android-helpers.js +760 -679
  6. package/build/lib/android-helpers.js.map +1 -1
  7. package/build/lib/bootstrap.d.ts +29 -0
  8. package/build/lib/bootstrap.d.ts.map +1 -0
  9. package/build/lib/bootstrap.js +192 -179
  10. package/build/lib/bootstrap.js.map +1 -1
  11. package/build/lib/commands/actions.d.ts +209 -0
  12. package/build/lib/commands/actions.d.ts.map +1 -0
  13. package/build/lib/commands/actions.js +327 -265
  14. package/build/lib/commands/actions.js.map +1 -1
  15. package/build/lib/commands/alert.d.ts +10 -0
  16. package/build/lib/commands/alert.d.ts.map +1 -0
  17. package/build/lib/commands/alert.js +12 -18
  18. package/build/lib/commands/alert.js.map +1 -1
  19. package/build/lib/commands/app-management.d.ts +314 -0
  20. package/build/lib/commands/app-management.d.ts.map +1 -0
  21. package/build/lib/commands/app-management.js +278 -110
  22. package/build/lib/commands/app-management.js.map +1 -1
  23. package/build/lib/commands/context.d.ts +94 -0
  24. package/build/lib/commands/context.d.ts.map +1 -0
  25. package/build/lib/commands/context.js +412 -260
  26. package/build/lib/commands/context.js.map +1 -1
  27. package/build/lib/commands/coverage.d.ts +5 -0
  28. package/build/lib/commands/coverage.d.ts.map +1 -0
  29. package/build/lib/commands/coverage.js +14 -17
  30. package/build/lib/commands/coverage.js.map +1 -1
  31. package/build/lib/commands/element.d.ts +36 -0
  32. package/build/lib/commands/element.d.ts.map +1 -0
  33. package/build/lib/commands/element.js +97 -127
  34. package/build/lib/commands/element.js.map +1 -1
  35. package/build/lib/commands/emu-console.d.ts +49 -0
  36. package/build/lib/commands/emu-console.d.ts.map +1 -0
  37. package/build/lib/commands/emu-console.js +36 -25
  38. package/build/lib/commands/emu-console.js.map +1 -1
  39. package/build/lib/commands/execute.d.ts +6 -0
  40. package/build/lib/commands/execute.d.ts.map +1 -0
  41. package/build/lib/commands/execute.js +68 -69
  42. package/build/lib/commands/execute.js.map +1 -1
  43. package/build/lib/commands/file-actions.d.ts +129 -0
  44. package/build/lib/commands/file-actions.d.ts.map +1 -0
  45. package/build/lib/commands/file-actions.js +321 -178
  46. package/build/lib/commands/file-actions.js.map +1 -1
  47. package/build/lib/commands/find.d.ts +13 -0
  48. package/build/lib/commands/find.d.ts.map +1 -0
  49. package/build/lib/commands/find.js +69 -51
  50. package/build/lib/commands/find.js.map +1 -1
  51. package/build/lib/commands/general.d.ts +133 -0
  52. package/build/lib/commands/general.d.ts.map +1 -0
  53. package/build/lib/commands/general.js +275 -216
  54. package/build/lib/commands/general.js.map +1 -1
  55. package/build/lib/commands/ime.d.ts +11 -0
  56. package/build/lib/commands/ime.d.ts.map +1 -0
  57. package/build/lib/commands/ime.js +27 -33
  58. package/build/lib/commands/ime.js.map +1 -1
  59. package/build/lib/commands/index.d.ts +3 -0
  60. package/build/lib/commands/index.d.ts.map +1 -0
  61. package/build/lib/commands/index.js +32 -35
  62. package/build/lib/commands/index.js.map +1 -1
  63. package/build/lib/commands/intent.d.ts +418 -0
  64. package/build/lib/commands/intent.d.ts.map +1 -0
  65. package/build/lib/commands/intent.js +281 -151
  66. package/build/lib/commands/intent.js.map +1 -1
  67. package/build/lib/commands/keyboard.d.ts +6 -0
  68. package/build/lib/commands/keyboard.d.ts.map +1 -0
  69. package/build/lib/commands/keyboard.js +6 -14
  70. package/build/lib/commands/keyboard.js.map +1 -1
  71. package/build/lib/commands/log.d.ts +45 -0
  72. package/build/lib/commands/log.d.ts.map +1 -0
  73. package/build/lib/commands/log.js +117 -103
  74. package/build/lib/commands/log.js.map +1 -1
  75. package/build/lib/commands/media-projection.d.ts +144 -0
  76. package/build/lib/commands/media-projection.d.ts.map +1 -0
  77. package/build/lib/commands/media-projection.js +228 -171
  78. package/build/lib/commands/media-projection.js.map +1 -1
  79. package/build/lib/commands/network.d.ts +139 -0
  80. package/build/lib/commands/network.d.ts.map +1 -0
  81. package/build/lib/commands/network.js +249 -181
  82. package/build/lib/commands/network.js.map +1 -1
  83. package/build/lib/commands/performance.d.ts +101 -0
  84. package/build/lib/commands/performance.d.ts.map +1 -0
  85. package/build/lib/commands/performance.js +390 -236
  86. package/build/lib/commands/performance.js.map +1 -1
  87. package/build/lib/commands/permissions.d.ts +93 -0
  88. package/build/lib/commands/permissions.d.ts.map +1 -0
  89. package/build/lib/commands/permissions.js +133 -93
  90. package/build/lib/commands/permissions.js.map +1 -1
  91. package/build/lib/commands/recordscreen.d.ts +194 -0
  92. package/build/lib/commands/recordscreen.d.ts.map +1 -0
  93. package/build/lib/commands/recordscreen.js +293 -224
  94. package/build/lib/commands/recordscreen.js.map +1 -1
  95. package/build/lib/commands/shell.d.ts +8 -0
  96. package/build/lib/commands/shell.d.ts.map +1 -0
  97. package/build/lib/commands/shell.js +38 -43
  98. package/build/lib/commands/shell.js.map +1 -1
  99. package/build/lib/commands/streamscreen.d.ts +104 -0
  100. package/build/lib/commands/streamscreen.d.ts.map +1 -0
  101. package/build/lib/commands/streamscreen.js +364 -305
  102. package/build/lib/commands/streamscreen.js.map +1 -1
  103. package/build/lib/commands/system-bars.d.ts +100 -0
  104. package/build/lib/commands/system-bars.d.ts.map +1 -0
  105. package/build/lib/commands/system-bars.js +148 -90
  106. package/build/lib/commands/system-bars.js.map +1 -1
  107. package/build/lib/commands/touch.d.ts +30 -0
  108. package/build/lib/commands/touch.d.ts.map +1 -0
  109. package/build/lib/commands/touch.js +311 -287
  110. package/build/lib/commands/touch.js.map +1 -1
  111. package/build/lib/desired-caps.d.ts +353 -0
  112. package/build/lib/desired-caps.d.ts.map +1 -0
  113. package/build/lib/desired-caps.js +291 -292
  114. package/build/lib/desired-caps.js.map +1 -1
  115. package/build/lib/driver.d.ts +430 -0
  116. package/build/lib/driver.d.ts.map +1 -0
  117. package/build/lib/driver.js +449 -384
  118. package/build/lib/driver.js.map +1 -1
  119. package/build/lib/logger.d.ts +3 -0
  120. package/build/lib/logger.d.ts.map +1 -0
  121. package/build/lib/logger.js +5 -11
  122. package/build/lib/logger.js.map +1 -1
  123. package/build/lib/method-map.d.ts +389 -0
  124. package/build/lib/method-map.d.ts.map +1 -0
  125. package/build/lib/method-map.js +220 -394
  126. package/build/lib/method-map.js.map +1 -1
  127. package/build/lib/stubs.d.ts +8 -0
  128. package/build/lib/stubs.d.ts.map +1 -0
  129. package/build/lib/stubs.js +5 -0
  130. package/build/lib/stubs.js.map +1 -0
  131. package/build/lib/uiautomator.d.ts +24 -0
  132. package/build/lib/uiautomator.d.ts.map +1 -0
  133. package/build/lib/uiautomator.js +86 -82
  134. package/build/lib/uiautomator.js.map +1 -1
  135. package/build/lib/unlock-helpers.d.ts +38 -0
  136. package/build/lib/unlock-helpers.d.ts.map +1 -0
  137. package/build/lib/unlock-helpers.js +228 -204
  138. package/build/lib/unlock-helpers.js.map +1 -1
  139. package/build/lib/utils.d.ts +11 -0
  140. package/build/lib/utils.d.ts.map +1 -0
  141. package/build/lib/utils.js +23 -18
  142. package/build/lib/utils.js.map +1 -1
  143. package/build/lib/webview-helpers.d.ts +223 -0
  144. package/build/lib/webview-helpers.d.ts.map +1 -0
  145. package/build/lib/webview-helpers.js +476 -298
  146. package/build/lib/webview-helpers.js.map +1 -1
  147. package/index.js +3 -1
  148. package/lib/android-helpers.js +2 -1
  149. package/lib/stubs.ts +8 -0
  150. package/lib/unlock-helpers.js +2 -2
  151. package/package.json +23 -14
@@ -1,207 +1,350 @@
1
1
  "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.default = exports.commands = void 0;
8
- require("source-map-support/register");
9
- var _lodash = _interopRequireDefault(require("lodash"));
10
- var _support = require("@appium/support");
11
- var _path = _interopRequireDefault(require("path"));
12
- var _driver = require("appium/driver");
13
- var _utils = require("../utils");
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.commands = void 0;
7
+ const lodash_1 = __importDefault(require("lodash"));
8
+ const support_1 = require("@appium/support");
9
+ const path_1 = __importDefault(require("path"));
10
+ const driver_1 = require("appium/driver");
11
+ const utils_1 = require("../utils");
14
12
  const CONTAINER_PATH_MARKER = '@';
13
+ // https://regex101.com/r/PLdB0G/2
15
14
  const CONTAINER_PATH_PATTERN = new RegExp(`^${CONTAINER_PATH_MARKER}([^/]+)/(.+)`);
16
15
  const ANDROID_MEDIA_RESCAN_INTENT = 'android.intent.action.MEDIA_SCANNER_SCAN_FILE';
17
16
  const commands = {};
18
17
  exports.commands = commands;
18
+ /**
19
+ * Parses the actual destination path from the given value
20
+ *
21
+ * @param {string} remotePath The preformatted remote path, which looks like
22
+ * `@my.app.id/my/path`
23
+ * @returns {Array<string>} An array, where the first item is the parsed package
24
+ * identifier and the second one is the actual destination path inside the package.
25
+ * @throws {Error} If the given string cannot be parsed
26
+ */
19
27
  function parseContainerPath(remotePath) {
20
- const match = CONTAINER_PATH_PATTERN.exec(remotePath);
21
- if (!match) {
22
- throw new Error(`It is expected that package identifier is separated from the relative path with a single slash. ` + `'${remotePath}' is given instead`);
23
- }
24
- return [match[1], _path.default.posix.resolve(`/data/data/${match[1]}`, match[2])];
28
+ const match = CONTAINER_PATH_PATTERN.exec(remotePath);
29
+ if (!match) {
30
+ throw new Error(`It is expected that package identifier is separated from the relative path with a single slash. ` +
31
+ `'${remotePath}' is given instead`);
32
+ }
33
+ return [match[1], path_1.default.posix.resolve(`/data/data/${match[1]}`, match[2])];
25
34
  }
35
+ /**
36
+ * Scans the given file/folder on the remote device
37
+ * and adds matching items to the device's media library.
38
+ * Exceptions are ignored and written into the log.
39
+ *
40
+ * @param {ADB} adb ADB instance
41
+ * @param {Object?} log Logger instance
42
+ * @param {string} remotePath The file/folder path on the remote device
43
+ */
26
44
  async function scanMedia(adb, remotePath, log = null) {
27
- log === null || log === void 0 ? void 0 : log.debug(`Performing media scan of '${remotePath}'`);
28
- try {
29
- if ((await adb.getApiLevel()) >= 29) {
30
- await adb.scanMedia(remotePath);
31
- } else {
32
- await adb.shell(['am', 'broadcast', '-a', ANDROID_MEDIA_RESCAN_INTENT, '-d', `file://${remotePath}`]);
33
- }
34
- } catch (e) {
35
- log === null || log === void 0 ? void 0 : log.warn(`Ignoring an unexpected error upon media scanning of '${remotePath}': ${e.stderr || e.message}`);
36
- }
45
+ log?.debug(`Performing media scan of '${remotePath}'`);
46
+ try {
47
+ // https://github.com/appium/appium/issues/16184
48
+ if (await adb.getApiLevel() >= 29) {
49
+ await adb.scanMedia(remotePath);
50
+ }
51
+ else {
52
+ await adb.shell([
53
+ 'am', 'broadcast',
54
+ '-a', ANDROID_MEDIA_RESCAN_INTENT,
55
+ '-d', `file://${remotePath}`
56
+ ]);
57
+ }
58
+ }
59
+ catch (e) {
60
+ log?.warn(`Ignoring an unexpected error upon media scanning of '${remotePath}': ${e.stderr || e.message}`);
61
+ }
37
62
  }
63
+ /**
64
+ * A small helper, which escapes single quotes in paths,
65
+ * so they are safe to be passed as arguments of shell commands
66
+ *
67
+ * @param {string} p The initial remote path
68
+ * @returns {string} The escaped path value
69
+ */
38
70
  function escapePath(p) {
39
- return p.replace(/'/g, `\\'`);
71
+ return p.replace(/'/g, `\\'`);
40
72
  }
73
+ /**
74
+ * Pulls a remote file from the device.
75
+ * It is required, that a package has debugging flag enabled
76
+ * in order to access its files.
77
+ *
78
+ * @param {string} remotePath The full path to the remote file
79
+ * or a specially formatted path, which points to an item inside app bundle
80
+ * @returns {string} Base64 encoded content of the pulled file
81
+ * @throws {Error} If the pull operation failed
82
+ */
41
83
  commands.pullFile = async function pullFile(remotePath) {
42
- if (remotePath.endsWith('/')) {
43
- throw new _driver.errors.InvalidArgumentError(`It is expected that remote path points to a file and not to a folder. ` + `'${remotePath}' is given instead`);
44
- }
45
- let tmpDestination = null;
46
- if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
47
- const [packageId, pathInContainer] = parseContainerPath(remotePath);
48
- this.log.debug(`Parsed package identifier '${packageId}' from '${remotePath}'. Will get the data from '${pathInContainer}'`);
49
- tmpDestination = `/data/local/tmp/${_path.default.posix.basename(pathInContainer)}`;
84
+ if (remotePath.endsWith('/')) {
85
+ throw new driver_1.errors.InvalidArgumentError(`It is expected that remote path points to a file and not to a folder. ` +
86
+ `'${remotePath}' is given instead`);
87
+ }
88
+ let tmpDestination = null;
89
+ if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
90
+ const [packageId, pathInContainer] = parseContainerPath(remotePath);
91
+ this.log.debug(`Parsed package identifier '${packageId}' from '${remotePath}'. Will get the data from '${pathInContainer}'`);
92
+ tmpDestination = `/data/local/tmp/${path_1.default.posix.basename(pathInContainer)}`;
93
+ try {
94
+ await this.adb.shell(['run-as', packageId, `chmod 777 '${escapePath(pathInContainer)}'`]);
95
+ await this.adb.shell([
96
+ 'run-as', packageId,
97
+ `cp -f '${escapePath(pathInContainer)}' '${escapePath(tmpDestination)}'`
98
+ ]);
99
+ }
100
+ catch (e) {
101
+ this.log.errorAndThrow(`Cannot access the container of '${packageId}' application. ` +
102
+ `Is the application installed and has 'debuggable' build option set to true? ` +
103
+ `Original error: ${e.message}`);
104
+ }
105
+ }
106
+ const localFile = await support_1.tempDir.path({ prefix: 'appium', suffix: '.tmp' });
50
107
  try {
51
- await this.adb.shell(['run-as', packageId, `chmod 777 '${escapePath(pathInContainer)}'`]);
52
- await this.adb.shell(['run-as', packageId, `cp -f '${escapePath(pathInContainer)}' '${escapePath(tmpDestination)}'`]);
53
- } catch (e) {
54
- this.log.errorAndThrow(`Cannot access the container of '${packageId}' application. ` + `Is the application installed and has 'debuggable' build option set to true? ` + `Original error: ${e.message}`);
55
- }
56
- }
57
- const localFile = await _support.tempDir.path({
58
- prefix: 'appium',
59
- suffix: '.tmp'
60
- });
61
- try {
62
- await this.adb.pull(tmpDestination || remotePath, localFile);
63
- return (await _support.util.toInMemoryBase64(localFile)).toString();
64
- } finally {
65
- if (await _support.fs.exists(localFile)) {
66
- await _support.fs.unlink(localFile);
67
- }
68
- if (tmpDestination) {
69
- await this.adb.shell(['rm', '-f', tmpDestination]);
70
- }
71
- }
108
+ await this.adb.pull(tmpDestination || remotePath, localFile);
109
+ return (await support_1.util.toInMemoryBase64(localFile)).toString();
110
+ }
111
+ finally {
112
+ if (await support_1.fs.exists(localFile)) {
113
+ await support_1.fs.unlink(localFile);
114
+ }
115
+ if (tmpDestination) {
116
+ await this.adb.shell(['rm', '-f', tmpDestination]);
117
+ }
118
+ }
72
119
  };
120
+ /**
121
+ * @typedef {Object} PullFileOptions
122
+ * @property {string} remotePath The full path to the remote file
123
+ * or a specially formatted path, which points to an item inside an app bundle,
124
+ * for example `@my.app.id/my/path`. It is mandatory for the app bundle to have
125
+ * debugging enabled in order to use the latter remotePath format.
126
+ */
127
+ /**
128
+ * Pulls a remote file from the device.
129
+ *
130
+ * @param {PullFileOptions} opts
131
+ * @returns {string} The same as `pullFile`
132
+ */
73
133
  commands.mobilePullFile = async function mobilePullFile(opts = {}) {
74
- const {
75
- remotePath
76
- } = (0, _utils.requireArgs)('remotePath', opts);
77
- return await this.pullFile(remotePath);
134
+ const { remotePath } = (0, utils_1.requireArgs)('remotePath', opts);
135
+ return await this.pullFile(remotePath);
78
136
  };
137
+ /**
138
+ * Pushes the given data to a file on the remote device
139
+ * It is required, that a package has debugging flag enabled
140
+ * in order to access its files.
141
+ * After a file is pushed it gets automatically scanned for possible
142
+ * media occurrences. If the scan succeeds then the file is added to the
143
+ * media library.
144
+ *
145
+ * @param {string} remotePath The full path to the remote file or
146
+ * a file inside a package bundle
147
+ * @param {string} base64Data Base64 encoded data to be written to the
148
+ * remote file. The remote file will be silently overridden if it already exists.
149
+ * @throws {Error} If there was an error while pushing the data
150
+ */
79
151
  commands.pushFile = async function pushFile(remotePath, base64Data) {
80
- if (remotePath.endsWith('/')) {
81
- throw new _driver.errors.InvalidArgumentError(`It is expected that remote path points to a file and not to a folder. ` + `'${remotePath}' is given instead`);
82
- }
83
- const localFile = await _support.tempDir.path({
84
- prefix: 'appium',
85
- suffix: '.tmp'
86
- });
87
- if (_lodash.default.isArray(base64Data)) {
88
- base64Data = Buffer.from(base64Data).toString('utf8');
89
- }
90
- const content = Buffer.from(base64Data, 'base64');
91
- let tmpDestination = null;
92
- try {
93
- await _support.fs.writeFile(localFile, content.toString('binary'), 'binary');
94
- if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
95
- const [packageId, pathInContainer] = parseContainerPath(remotePath);
96
- this.log.debug(`Parsed package identifier '${packageId}' from '${remotePath}'. ` + `Will put the data into '${pathInContainer}'`);
97
- tmpDestination = `/data/local/tmp/${_path.default.posix.basename(pathInContainer)}`;
98
- try {
99
- await this.adb.shell(['run-as', packageId, `mkdir -p '${escapePath(_path.default.posix.dirname(pathInContainer))}'`]);
100
- await this.adb.shell(['run-as', packageId, `touch '${escapePath(pathInContainer)}'`]);
101
- await this.adb.shell(['run-as', packageId, `chmod 777 '${escapePath(pathInContainer)}'`]);
102
- await this.adb.push(localFile, tmpDestination);
103
- await this.adb.shell(['run-as', packageId, `cp -f '${escapePath(tmpDestination)}' '${escapePath(pathInContainer)}'`]);
104
- } catch (e) {
105
- this.log.errorAndThrow(`Cannot access the container of '${packageId}' application. ` + `Is the application installed and has 'debuggable' build option set to true? ` + `Original error: ${e.message}`);
106
- }
107
- } else {
108
- await this.adb.push(localFile, remotePath);
109
- await scanMedia(this.adb, remotePath, this.log);
110
- }
111
- } finally {
112
- if (await _support.fs.exists(localFile)) {
113
- await _support.fs.unlink(localFile);
114
- }
115
- if (tmpDestination) {
116
- await this.adb.shell(['rm', '-f', tmpDestination]);
117
- }
118
- }
152
+ if (remotePath.endsWith('/')) {
153
+ throw new driver_1.errors.InvalidArgumentError(`It is expected that remote path points to a file and not to a folder. ` +
154
+ `'${remotePath}' is given instead`);
155
+ }
156
+ const localFile = await support_1.tempDir.path({ prefix: 'appium', suffix: '.tmp' });
157
+ if (lodash_1.default.isArray(base64Data)) {
158
+ // some clients (ahem) java, send a byte array encoding utf8 characters
159
+ // instead of a string, which would be infinitely better!
160
+ base64Data = Buffer.from(base64Data).toString('utf8');
161
+ }
162
+ const content = Buffer.from(base64Data, 'base64');
163
+ let tmpDestination = null;
164
+ try {
165
+ await support_1.fs.writeFile(localFile, content.toString('binary'), 'binary');
166
+ if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
167
+ const [packageId, pathInContainer] = parseContainerPath(remotePath);
168
+ this.log.debug(`Parsed package identifier '${packageId}' from '${remotePath}'. ` +
169
+ `Will put the data into '${pathInContainer}'`);
170
+ tmpDestination = `/data/local/tmp/${path_1.default.posix.basename(pathInContainer)}`;
171
+ try {
172
+ await this.adb.shell(['run-as', packageId, `mkdir -p '${escapePath(path_1.default.posix.dirname(pathInContainer))}'`]);
173
+ await this.adb.shell(['run-as', packageId, `touch '${escapePath(pathInContainer)}'`]);
174
+ await this.adb.shell(['run-as', packageId, `chmod 777 '${escapePath(pathInContainer)}'`]);
175
+ await this.adb.push(localFile, tmpDestination);
176
+ await this.adb.shell([
177
+ 'run-as', packageId,
178
+ `cp -f '${escapePath(tmpDestination)}' '${escapePath(pathInContainer)}'`
179
+ ]);
180
+ }
181
+ catch (e) {
182
+ this.log.errorAndThrow(`Cannot access the container of '${packageId}' application. ` +
183
+ `Is the application installed and has 'debuggable' build option set to true? ` +
184
+ `Original error: ${e.message}`);
185
+ }
186
+ }
187
+ else {
188
+ // adb push creates folders and overwrites existing files.
189
+ await this.adb.push(localFile, remotePath);
190
+ // if we have pushed a file, it might be a media file, so ensure that
191
+ // apps know about it
192
+ await scanMedia(this.adb, remotePath, this.log);
193
+ }
194
+ }
195
+ finally {
196
+ if (await support_1.fs.exists(localFile)) {
197
+ await support_1.fs.unlink(localFile);
198
+ }
199
+ if (tmpDestination) {
200
+ await this.adb.shell(['rm', '-f', tmpDestination]);
201
+ }
202
+ }
119
203
  };
204
+ /**
205
+ * @typedef {Object} PushFileOptions
206
+ * @property {string} remotePath The full path to the remote file
207
+ * or a specially formatted path, which points to an item inside an app bundle,
208
+ * for example `@my.app.id/my/path`. It is mandatory for the app bundle to have
209
+ * debugging enabled in order to use the latter remotePath format.
210
+ * @property {string} payload Base64-encoded content of the file to be pushed.
211
+ */
212
+ /**
213
+ * Pushes the given data to a file on the remote device.
214
+ *
215
+ * @param {PushFileOptions} opts
216
+ */
120
217
  commands.mobilePushFile = async function mobilePushFile(opts = {}) {
121
- const {
122
- remotePath,
123
- payload
124
- } = (0, _utils.requireArgs)(['remotePath', 'payload'], opts);
125
- return await this.pushFile(remotePath, payload);
218
+ const { remotePath, payload } = (0, utils_1.requireArgs)(['remotePath', 'payload'], opts);
219
+ return await this.pushFile(remotePath, payload);
126
220
  };
221
+ /**
222
+ * Pulls the whole folder from the remote device
223
+ *
224
+ * @param {string} remotePath The full path to a folder on the
225
+ * remote device or a folder inside an application bundle
226
+ * @returns {string} Base64-encoded and zipped content of the folder
227
+ * @throws {Error} If there was a failure while getting the folder content
228
+ */
127
229
  commands.pullFolder = async function pullFolder(remotePath) {
128
- const tmpRoot = await _support.tempDir.openDir();
129
- try {
130
- await this.adb.pull(remotePath, tmpRoot);
131
- return (await _support.zip.toInMemoryZip(tmpRoot, {
132
- encodeToBase64: true
133
- })).toString();
134
- } finally {
135
- await _support.fs.rimraf(tmpRoot);
136
- }
230
+ const tmpRoot = await support_1.tempDir.openDir();
231
+ try {
232
+ await this.adb.pull(remotePath, tmpRoot);
233
+ return (await support_1.zip.toInMemoryZip(tmpRoot, {
234
+ encodeToBase64: true,
235
+ })).toString();
236
+ }
237
+ finally {
238
+ await support_1.fs.rimraf(tmpRoot);
239
+ }
137
240
  };
241
+ /**
242
+ * @typedef {Object} PullFolderOptions
243
+ * @property {string} remotePath The full path to the remote folder.
244
+ */
245
+ /**
246
+ * Pulls the whole folder from the device under test.
247
+ *
248
+ * @param {PullFolderOptions} opts
249
+ * @returns {string} The same as `pullFolder`
250
+ */
138
251
  commands.mobilePullFolder = async function mobilePullFolder(opts = {}) {
139
- const {
140
- remotePath
141
- } = (0, _utils.requireArgs)('remotePath', opts);
142
- return await this.pullFolder(remotePath);
252
+ const { remotePath } = (0, utils_1.requireArgs)('remotePath', opts);
253
+ return await this.pullFolder(remotePath);
143
254
  };
255
+ /**
256
+ * Deletes the given folder or file from the remote device
257
+ *
258
+ * @param {ADB} adb
259
+ * @param {string} remotePath The full path to the remote folder
260
+ * or file (folder names must end with a single slash)
261
+ * @throws {Error} If the provided remote path is invalid or
262
+ * the package content cannot be accessed
263
+ * @returns {boolean} `true` if the remote item has been successfully deleted.
264
+ * If the remote path is valid, but the remote path does not exist
265
+ * this function return `false`.
266
+ */
144
267
  async function deleteFileOrFolder(adb, remotePath) {
145
- const performRemoteFsCheck = async (p, op, runAs = null) => {
146
- const passFlag = '__PASS__';
147
- const checkCmd = `[ -${op} '${escapePath(p)}' ] && echo ${passFlag}`;
148
- const fullCmd = runAs ? `run-as ${runAs} ${checkCmd}` : checkCmd;
149
- try {
150
- return _lodash.default.includes(await adb.shell([fullCmd]), passFlag);
151
- } catch (ign) {
152
- return false;
153
- }
154
- };
155
- const isFile = async (p, runAs = null) => await performRemoteFsCheck(p, 'f', runAs);
156
- const isDir = async (p, runAs = null) => await performRemoteFsCheck(p, 'd', runAs);
157
- const isPresent = async (p, runAs = null) => await performRemoteFsCheck(p, 'e', runAs);
158
- let dstPath = remotePath;
159
- let pkgId = null;
160
- if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
161
- const [packageId, pathInContainer] = parseContainerPath(remotePath);
162
- this.log.debug(`Parsed package identifier '${packageId}' from '${remotePath}'`);
163
- dstPath = pathInContainer;
164
- pkgId = packageId;
165
- }
166
- if (pkgId) {
167
- try {
168
- await adb.shell(['run-as', pkgId, 'ls']);
169
- } catch (e) {
170
- this.log.errorAndThrow(`Cannot access the container of '${pkgId}' application. ` + `Is the application installed and has 'debuggable' build option set to true? ` + `Original error: ${e.message}`);
171
- }
172
- }
173
- if (!(await isPresent(dstPath, pkgId))) {
174
- this.log.info(`The item at '${dstPath}' does not exist. Perhaps, already deleted?`);
175
- return false;
176
- }
177
- const expectsFile = !remotePath.endsWith('/');
178
- if (expectsFile && !(await isFile(dstPath, pkgId))) {
179
- this.log.errorAndThrow(`The item at '${dstPath}' is not a file`);
180
- } else if (!expectsFile && !(await isDir(dstPath, pkgId))) {
181
- this.log.errorAndThrow(`The item at '${dstPath}' is not a folder`);
182
- }
183
- if (pkgId) {
184
- await adb.shell(['run-as', pkgId, `rm -f${expectsFile ? '' : 'r'} '${escapePath(dstPath)}'`]);
185
- } else {
186
- await adb.shell(['rm', `-f${expectsFile ? '' : 'r'}`, dstPath]);
187
- }
188
- if (await isPresent(dstPath, pkgId)) {
189
- this.log.errorAndThrow(`The item at '${dstPath}' still exists after being deleted. ` + `Is it writable?`);
190
- }
191
- return true;
268
+ const performRemoteFsCheck = async (p, op, runAs = null) => {
269
+ const passFlag = '__PASS__';
270
+ const checkCmd = `[ -${op} '${escapePath(p)}' ] && echo ${passFlag}`;
271
+ const fullCmd = runAs ? `run-as ${runAs} ${checkCmd}` : checkCmd;
272
+ try {
273
+ return lodash_1.default.includes(await adb.shell([fullCmd]), passFlag);
274
+ }
275
+ catch (ign) {
276
+ return false;
277
+ }
278
+ };
279
+ const isFile = async (p, runAs = null) => await performRemoteFsCheck(p, 'f', runAs);
280
+ const isDir = async (p, runAs = null) => await performRemoteFsCheck(p, 'd', runAs);
281
+ const isPresent = async (p, runAs = null) => await performRemoteFsCheck(p, 'e', runAs);
282
+ let dstPath = remotePath;
283
+ let pkgId = null;
284
+ if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
285
+ const [packageId, pathInContainer] = parseContainerPath(remotePath);
286
+ this.log.debug(`Parsed package identifier '${packageId}' from '${remotePath}'`);
287
+ dstPath = pathInContainer;
288
+ pkgId = packageId;
289
+ }
290
+ if (pkgId) {
291
+ try {
292
+ await adb.shell(['run-as', pkgId, 'ls']);
293
+ }
294
+ catch (e) {
295
+ this.log.errorAndThrow(`Cannot access the container of '${pkgId}' application. ` +
296
+ `Is the application installed and has 'debuggable' build option set to true? ` +
297
+ `Original error: ${e.message}`);
298
+ }
299
+ }
300
+ if (!await isPresent(dstPath, pkgId)) {
301
+ this.log.info(`The item at '${dstPath}' does not exist. Perhaps, already deleted?`);
302
+ return false;
303
+ }
304
+ const expectsFile = !remotePath.endsWith('/');
305
+ if (expectsFile && !await isFile(dstPath, pkgId)) {
306
+ this.log.errorAndThrow(`The item at '${dstPath}' is not a file`);
307
+ }
308
+ else if (!expectsFile && !await isDir(dstPath, pkgId)) {
309
+ this.log.errorAndThrow(`The item at '${dstPath}' is not a folder`);
310
+ }
311
+ if (pkgId) {
312
+ await adb.shell(['run-as', pkgId, `rm -f${expectsFile ? '' : 'r'} '${escapePath(dstPath)}'`]);
313
+ }
314
+ else {
315
+ await adb.shell(['rm', `-f${expectsFile ? '' : 'r'}`, dstPath]);
316
+ }
317
+ if (await isPresent(dstPath, pkgId)) {
318
+ this.log.errorAndThrow(`The item at '${dstPath}' still exists after being deleted. ` +
319
+ `Is it writable?`);
320
+ }
321
+ return true;
192
322
  }
323
+ /**
324
+ * @typedef {Object} DeleteFileOpts
325
+ * @property {!string} remotePath The full path to the remote file
326
+ * or a file inside an application bundle (for example `@my.app.id/path/in/bundle`)
327
+ */
328
+ /**
329
+ * Deletes a file on the remote device
330
+ *
331
+ * @param {DeleteFileOpts} opts
332
+ * @returns {boolean} `true` if the remote file has been successfully deleted.
333
+ * If the path to a remote file is valid, but the file itself does not exist
334
+ * then `false` is returned.
335
+ * @throws {Error} If the argument is invalid or there was an error while
336
+ * deleting the file
337
+ */
193
338
  commands.mobileDeleteFile = async function mobileDeleteFile(opts = {}) {
194
- const {
195
- remotePath
196
- } = opts;
197
- if (!remotePath) {
198
- throw new _driver.errors.InvalidArgumentError(`The 'remotePath' argument is mandatory`);
199
- }
200
- if (remotePath.endsWith('/')) {
201
- throw new _driver.errors.InvalidArgumentError(`It is expected that remote path points to a folder and not to a file. ` + `'${remotePath}' is given instead`);
202
- }
203
- return await deleteFileOrFolder(this.adb, remotePath);
339
+ const { remotePath } = opts;
340
+ if (!remotePath) {
341
+ throw new driver_1.errors.InvalidArgumentError(`The 'remotePath' argument is mandatory`);
342
+ }
343
+ if (remotePath.endsWith('/')) {
344
+ throw new driver_1.errors.InvalidArgumentError(`It is expected that remote path points to a folder and not to a file. ` +
345
+ `'${remotePath}' is given instead`);
346
+ }
347
+ return await deleteFileOrFolder(this.adb, remotePath);
204
348
  };
205
- var _default = commands;
206
- exports.default = _default;
207
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbG9kYXNoIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfc3VwcG9ydCIsIl9wYXRoIiwiX2RyaXZlciIsIl91dGlscyIsIkNPTlRBSU5FUl9QQVRIX01BUktFUiIsIkNPTlRBSU5FUl9QQVRIX1BBVFRFUk4iLCJSZWdFeHAiLCJBTkRST0lEX01FRElBX1JFU0NBTl9JTlRFTlQiLCJjb21tYW5kcyIsImV4cG9ydHMiLCJwYXJzZUNvbnRhaW5lclBhdGgiLCJyZW1vdGVQYXRoIiwibWF0Y2giLCJleGVjIiwiRXJyb3IiLCJwYXRoIiwicG9zaXgiLCJyZXNvbHZlIiwic2Nhbk1lZGlhIiwiYWRiIiwibG9nIiwiZGVidWciLCJnZXRBcGlMZXZlbCIsInNoZWxsIiwiZSIsIndhcm4iLCJzdGRlcnIiLCJtZXNzYWdlIiwiZXNjYXBlUGF0aCIsInAiLCJyZXBsYWNlIiwicHVsbEZpbGUiLCJlbmRzV2l0aCIsImVycm9ycyIsIkludmFsaWRBcmd1bWVudEVycm9yIiwidG1wRGVzdGluYXRpb24iLCJzdGFydHNXaXRoIiwicGFja2FnZUlkIiwicGF0aEluQ29udGFpbmVyIiwiYmFzZW5hbWUiLCJlcnJvckFuZFRocm93IiwibG9jYWxGaWxlIiwidGVtcERpciIsInByZWZpeCIsInN1ZmZpeCIsInB1bGwiLCJ1dGlsIiwidG9Jbk1lbW9yeUJhc2U2NCIsInRvU3RyaW5nIiwiZnMiLCJleGlzdHMiLCJ1bmxpbmsiLCJtb2JpbGVQdWxsRmlsZSIsIm9wdHMiLCJyZXF1aXJlQXJncyIsInB1c2hGaWxlIiwiYmFzZTY0RGF0YSIsIl8iLCJpc0FycmF5IiwiQnVmZmVyIiwiZnJvbSIsImNvbnRlbnQiLCJ3cml0ZUZpbGUiLCJkaXJuYW1lIiwicHVzaCIsIm1vYmlsZVB1c2hGaWxlIiwicGF5bG9hZCIsInB1bGxGb2xkZXIiLCJ0bXBSb290Iiwib3BlbkRpciIsInppcCIsInRvSW5NZW1vcnlaaXAiLCJlbmNvZGVUb0Jhc2U2NCIsInJpbXJhZiIsIm1vYmlsZVB1bGxGb2xkZXIiLCJkZWxldGVGaWxlT3JGb2xkZXIiLCJwZXJmb3JtUmVtb3RlRnNDaGVjayIsIm9wIiwicnVuQXMiLCJwYXNzRmxhZyIsImNoZWNrQ21kIiwiZnVsbENtZCIsImluY2x1ZGVzIiwiaWduIiwiaXNGaWxlIiwiaXNEaXIiLCJpc1ByZXNlbnQiLCJkc3RQYXRoIiwicGtnSWQiLCJpbmZvIiwiZXhwZWN0c0ZpbGUiLCJtb2JpbGVEZWxldGVGaWxlIiwiX2RlZmF1bHQiLCJkZWZhdWx0Il0sInNvdXJjZXMiOlsiLi4vLi4vLi4vbGliL2NvbW1hbmRzL2ZpbGUtYWN0aW9ucy5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHsgZnMsIHV0aWwsIHppcCwgdGVtcERpciB9IGZyb20gJ0BhcHBpdW0vc3VwcG9ydCc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IGVycm9ycyB9IGZyb20gJ2FwcGl1bS9kcml2ZXInO1xuaW1wb3J0IHsgcmVxdWlyZUFyZ3MgfSBmcm9tICcuLi91dGlscyc7XG5cblxuY29uc3QgQ09OVEFJTkVSX1BBVEhfTUFSS0VSID0gJ0AnO1xuLy8gaHR0cHM6Ly9yZWdleDEwMS5jb20vci9QTGRCMEcvMlxuY29uc3QgQ09OVEFJTkVSX1BBVEhfUEFUVEVSTiA9IG5ldyBSZWdFeHAoYF4ke0NPTlRBSU5FUl9QQVRIX01BUktFUn0oW14vXSspLyguKylgKTtcbmNvbnN0IEFORFJPSURfTUVESUFfUkVTQ0FOX0lOVEVOVCA9ICdhbmRyb2lkLmludGVudC5hY3Rpb24uTUVESUFfU0NBTk5FUl9TQ0FOX0ZJTEUnO1xuXG5cbmNvbnN0IGNvbW1hbmRzID0ge307XG5cbi8qKlxuICogUGFyc2VzIHRoZSBhY3R1YWwgZGVzdGluYXRpb24gcGF0aCBmcm9tIHRoZSBnaXZlbiB2YWx1ZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSByZW1vdGVQYXRoIFRoZSBwcmVmb3JtYXR0ZWQgcmVtb3RlIHBhdGgsIHdoaWNoIGxvb2tzIGxpa2VcbiAqIGBAbXkuYXBwLmlkL215L3BhdGhgXG4gKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn0gQW4gYXJyYXksIHdoZXJlIHRoZSBmaXJzdCBpdGVtIGlzIHRoZSBwYXJzZWQgcGFja2FnZVxuICogaWRlbnRpZmllciBhbmQgdGhlIHNlY29uZCBvbmUgaXMgdGhlIGFjdHVhbCBkZXN0aW5hdGlvbiBwYXRoIGluc2lkZSB0aGUgcGFja2FnZS5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgZ2l2ZW4gc3RyaW5nIGNhbm5vdCBiZSBwYXJzZWRcbiAqL1xuZnVuY3Rpb24gcGFyc2VDb250YWluZXJQYXRoIChyZW1vdGVQYXRoKSB7XG4gIGNvbnN0IG1hdGNoID0gQ09OVEFJTkVSX1BBVEhfUEFUVEVSTi5leGVjKHJlbW90ZVBhdGgpO1xuICBpZiAoIW1hdGNoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJdCBpcyBleHBlY3RlZCB0aGF0IHBhY2thZ2UgaWRlbnRpZmllciBpcyBzZXBhcmF0ZWQgZnJvbSB0aGUgcmVsYXRpdmUgcGF0aCB3aXRoIGEgc2luZ2xlIHNsYXNoLiBgICtcbiAgICAgIGAnJHtyZW1vdGVQYXRofScgaXMgZ2l2ZW4gaW5zdGVhZGApO1xuICB9XG4gIHJldHVybiBbbWF0Y2hbMV0sIHBhdGgucG9zaXgucmVzb2x2ZShgL2RhdGEvZGF0YS8ke21hdGNoWzFdfWAsIG1hdGNoWzJdKV07XG59XG5cbi8qKlxuICogU2NhbnMgdGhlIGdpdmVuIGZpbGUvZm9sZGVyIG9uIHRoZSByZW1vdGUgZGV2aWNlXG4gKiBhbmQgYWRkcyBtYXRjaGluZyBpdGVtcyB0byB0aGUgZGV2aWNlJ3MgbWVkaWEgbGlicmFyeS5cbiAqIEV4Y2VwdGlvbnMgYXJlIGlnbm9yZWQgYW5kIHdyaXR0ZW4gaW50byB0aGUgbG9nLlxuICpcbiAqIEBwYXJhbSB7QURCfSBhZGIgQURCIGluc3RhbmNlXG4gKiBAcGFyYW0ge09iamVjdD99IGxvZyBMb2dnZXIgaW5zdGFuY2VcbiAqIEBwYXJhbSB7c3RyaW5nfSByZW1vdGVQYXRoIFRoZSBmaWxlL2ZvbGRlciBwYXRoIG9uIHRoZSByZW1vdGUgZGV2aWNlXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHNjYW5NZWRpYSAoYWRiLCByZW1vdGVQYXRoLCBsb2cgPSBudWxsKSB7XG4gIGxvZz8uZGVidWcoYFBlcmZvcm1pbmcgbWVkaWEgc2NhbiBvZiAnJHtyZW1vdGVQYXRofSdgKTtcbiAgdHJ5IHtcbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vYXBwaXVtL2FwcGl1bS9pc3N1ZXMvMTYxODRcbiAgICBpZiAoYXdhaXQgYWRiLmdldEFwaUxldmVsKCkgPj0gMjkpIHtcbiAgICAgIGF3YWl0IGFkYi5zY2FuTWVkaWEocmVtb3RlUGF0aCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IGFkYi5zaGVsbChbXG4gICAgICAgICdhbScsICdicm9hZGNhc3QnLFxuICAgICAgICAnLWEnLCBBTkRST0lEX01FRElBX1JFU0NBTl9JTlRFTlQsXG4gICAgICAgICctZCcsIGBmaWxlOi8vJHtyZW1vdGVQYXRofWBcbiAgICAgIF0pO1xuICAgIH1cbiAgfSBjYXRjaCAoZSkge1xuICAgIGxvZz8ud2FybihgSWdub3JpbmcgYW4gdW5leHBlY3RlZCBlcnJvciB1cG9uIG1lZGlhIHNjYW5uaW5nIG9mICcke3JlbW90ZVBhdGh9JzogJHtlLnN0ZGVyciB8fCBlLm1lc3NhZ2V9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBBIHNtYWxsIGhlbHBlciwgd2hpY2ggZXNjYXBlcyBzaW5nbGUgcXVvdGVzIGluIHBhdGhzLFxuICogc28gdGhleSBhcmUgc2FmZSB0byBiZSBwYXNzZWQgYXMgYXJndW1lbnRzIG9mIHNoZWxsIGNvbW1hbmRzXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHAgVGhlIGluaXRpYWwgcmVtb3RlIHBhdGhcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBlc2NhcGVkIHBhdGggdmFsdWVcbiAqL1xuZnVuY3Rpb24gZXNjYXBlUGF0aCAocCkge1xuICByZXR1cm4gcC5yZXBsYWNlKC8nL2csIGBcXFxcJ2ApO1xufVxuXG4vKipcbiAqIFB1bGxzIGEgcmVtb3RlIGZpbGUgZnJvbSB0aGUgZGV2aWNlLlxuICogSXQgaXMgcmVxdWlyZWQsIHRoYXQgYSBwYWNrYWdlIGhhcyBkZWJ1Z2dpbmcgZmxhZyBlbmFibGVkXG4gKiBpbiBvcmRlciB0byBhY2Nlc3MgaXRzIGZpbGVzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSByZW1vdGVQYXRoIFRoZSBmdWxsIHBhdGggdG8gdGhlIHJlbW90ZSBmaWxlXG4gKiBvciBhIHNwZWNpYWxseSBmb3JtYXR0ZWQgcGF0aCwgd2hpY2ggcG9pbnRzIHRvIGFuIGl0ZW0gaW5zaWRlIGFwcCBidW5kbGVcbiAqIEByZXR1cm5zIHtzdHJpbmd9IEJhc2U2NCBlbmNvZGVkIGNvbnRlbnQgb2YgdGhlIHB1bGxlZCBmaWxlXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHB1bGwgb3BlcmF0aW9uIGZhaWxlZFxuICovXG5jb21tYW5kcy5wdWxsRmlsZSA9IGFzeW5jIGZ1bmN0aW9uIHB1bGxGaWxlIChyZW1vdGVQYXRoKSB7XG4gIGlmIChyZW1vdGVQYXRoLmVuZHNXaXRoKCcvJykpIHtcbiAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKGBJdCBpcyBleHBlY3RlZCB0aGF0IHJlbW90ZSBwYXRoIHBvaW50cyB0byBhIGZpbGUgYW5kIG5vdCB0byBhIGZvbGRlci4gYCArXG4gICAgICBgJyR7cmVtb3RlUGF0aH0nIGlzIGdpdmVuIGluc3RlYWRgKTtcbiAgfVxuICBsZXQgdG1wRGVzdGluYXRpb24gPSBudWxsO1xuICBpZiAocmVtb3RlUGF0aC5zdGFydHNXaXRoKENPTlRBSU5FUl9QQVRIX01BUktFUikpIHtcbiAgICBjb25zdCBbcGFja2FnZUlkLCBwYXRoSW5Db250YWluZXJdID0gcGFyc2VDb250YWluZXJQYXRoKHJlbW90ZVBhdGgpO1xuICAgIHRoaXMubG9nLmRlYnVnKGBQYXJzZWQgcGFja2FnZSBpZGVudGlmaWVyICcke3BhY2thZ2VJZH0nIGZyb20gJyR7cmVtb3RlUGF0aH0nLiBXaWxsIGdldCB0aGUgZGF0YSBmcm9tICcke3BhdGhJbkNvbnRhaW5lcn0nYCk7XG4gICAgdG1wRGVzdGluYXRpb24gPSBgL2RhdGEvbG9jYWwvdG1wLyR7cGF0aC5wb3NpeC5iYXNlbmFtZShwYXRoSW5Db250YWluZXIpfWA7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuYWRiLnNoZWxsKFsncnVuLWFzJywgcGFja2FnZUlkLCBgY2htb2QgNzc3ICcke2VzY2FwZVBhdGgocGF0aEluQ29udGFpbmVyKX0nYF0pO1xuICAgICAgYXdhaXQgdGhpcy5hZGIuc2hlbGwoW1xuICAgICAgICAncnVuLWFzJywgcGFja2FnZUlkLFxuICAgICAgICBgY3AgLWYgJyR7ZXNjYXBlUGF0aChwYXRoSW5Db250YWluZXIpfScgJyR7ZXNjYXBlUGF0aCh0bXBEZXN0aW5hdGlvbil9J2BcbiAgICAgIF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRoaXMubG9nLmVycm9yQW5kVGhyb3coYENhbm5vdCBhY2Nlc3MgdGhlIGNvbnRhaW5lciBvZiAnJHtwYWNrYWdlSWR9JyBhcHBsaWNhdGlvbi4gYCArXG4gICAgICAgICAgICAgICAgICAgICAgICBgSXMgdGhlIGFwcGxpY2F0aW9uIGluc3RhbGxlZCBhbmQgaGFzICdkZWJ1Z2dhYmxlJyBidWlsZCBvcHRpb24gc2V0IHRvIHRydWU/IGAgK1xuICAgICAgICAgICAgICAgICAgICAgICAgYE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgICB9XG4gIH1cbiAgY29uc3QgbG9jYWxGaWxlID0gYXdhaXQgdGVtcERpci5wYXRoKHtwcmVmaXg6ICdhcHBpdW0nLCBzdWZmaXg6ICcudG1wJ30pO1xuICB0cnkge1xuICAgIGF3YWl0IHRoaXMuYWRiLnB1bGwodG1wRGVzdGluYXRpb24gfHwgcmVtb3RlUGF0aCwgbG9jYWxGaWxlKTtcbiAgICByZXR1cm4gKGF3YWl0IHV0aWwudG9Jbk1lbW9yeUJhc2U2NChsb2NhbEZpbGUpKS50b1N0cmluZygpO1xuICB9IGZpbmFsbHkge1xuICAgIGlmIChhd2FpdCBmcy5leGlzdHMobG9jYWxGaWxlKSkge1xuICAgICAgYXdhaXQgZnMudW5saW5rKGxvY2FsRmlsZSk7XG4gICAgfVxuICAgIGlmICh0bXBEZXN0aW5hdGlvbikge1xuICAgICAgYXdhaXQgdGhpcy5hZGIuc2hlbGwoWydybScsICctZicsIHRtcERlc3RpbmF0aW9uXSk7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFB1bGxGaWxlT3B0aW9uc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IHJlbW90ZVBhdGggVGhlIGZ1bGwgcGF0aCB0byB0aGUgcmVtb3RlIGZpbGVcbiAqIG9yIGEgc3BlY2lhbGx5IGZvcm1hdHRlZCBwYXRoLCB3aGljaCBwb2ludHMgdG8gYW4gaXRlbSBpbnNpZGUgYW4gYXBwIGJ1bmRsZSxcbiAqIGZvciBleGFtcGxlIGBAbXkuYXBwLmlkL215L3BhdGhgLiBJdCBpcyBtYW5kYXRvcnkgZm9yIHRoZSBhcHAgYnVuZGxlIHRvIGhhdmVcbiAqIGRlYnVnZ2luZyBlbmFibGVkIGluIG9yZGVyIHRvIHVzZSB0aGUgbGF0dGVyIHJlbW90ZVBhdGggZm9ybWF0LlxuICovXG5cbi8qKlxuICogUHVsbHMgYSByZW1vdGUgZmlsZSBmcm9tIHRoZSBkZXZpY2UuXG4gKlxuICogQHBhcmFtIHtQdWxsRmlsZU9wdGlvbnN9IG9wdHNcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBzYW1lIGFzIGBwdWxsRmlsZWBcbiAqL1xuY29tbWFuZHMubW9iaWxlUHVsbEZpbGUgPSBhc3luYyBmdW5jdGlvbiBtb2JpbGVQdWxsRmlsZSAob3B0cyA9IHt9KSB7XG4gIGNvbnN0IHsgcmVtb3RlUGF0aCB9ID0gcmVxdWlyZUFyZ3MoJ3JlbW90ZVBhdGgnLCBvcHRzKTtcbiAgcmV0dXJuIGF3YWl0IHRoaXMucHVsbEZpbGUocmVtb3RlUGF0aCk7XG59O1xuXG4vKipcbiAqIFB1c2hlcyB0aGUgZ2l2ZW4gZGF0YSB0byBhIGZpbGUgb24gdGhlIHJlbW90ZSBkZXZpY2VcbiAqIEl0IGlzIHJlcXVpcmVkLCB0aGF0IGEgcGFja2FnZSBoYXMgZGVidWdnaW5nIGZsYWcgZW5hYmxlZFxuICogaW4gb3JkZXIgdG8gYWNjZXNzIGl0cyBmaWxlcy5cbiAqIEFmdGVyIGEgZmlsZSBpcyBwdXNoZWQgaXQgZ2V0cyBhdXRvbWF0aWNhbGx5IHNjYW5uZWQgZm9yIHBvc3NpYmxlXG4gKiBtZWRpYSBvY2N1cnJlbmNlcy4gSWYgdGhlIHNjYW4gc3VjY2VlZHMgdGhlbiB0aGUgZmlsZSBpcyBhZGRlZCB0byB0aGVcbiAqIG1lZGlhIGxpYnJhcnkuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHJlbW90ZVBhdGggVGhlIGZ1bGwgcGF0aCB0byB0aGUgcmVtb3RlIGZpbGUgb3JcbiAqIGEgZmlsZSBpbnNpZGUgYSBwYWNrYWdlIGJ1bmRsZVxuICogQHBhcmFtIHtzdHJpbmd9IGJhc2U2NERhdGEgQmFzZTY0IGVuY29kZWQgZGF0YSB0byBiZSB3cml0dGVuIHRvIHRoZVxuICogcmVtb3RlIGZpbGUuIFRoZSByZW1vdGUgZmlsZSB3aWxsIGJlIHNpbGVudGx5IG92ZXJyaWRkZW4gaWYgaXQgYWxyZWFkeSBleGlzdHMuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIHB1c2hpbmcgdGhlIGRhdGFcbiAqL1xuY29tbWFuZHMucHVzaEZpbGUgPSBhc3luYyBmdW5jdGlvbiBwdXNoRmlsZSAocmVtb3RlUGF0aCwgYmFzZTY0RGF0YSkge1xuICBpZiAocmVtb3RlUGF0aC5lbmRzV2l0aCgnLycpKSB7XG4gICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihcbiAgICAgIGBJdCBpcyBleHBlY3RlZCB0aGF0IHJlbW90ZSBwYXRoIHBvaW50cyB0byBhIGZpbGUgYW5kIG5vdCB0byBhIGZvbGRlci4gYCArXG4gICAgICBgJyR7cmVtb3RlUGF0aH0nIGlzIGdpdmVuIGluc3RlYWRgXG4gICAgKTtcbiAgfVxuICBjb25zdCBsb2NhbEZpbGUgPSBhd2FpdCB0ZW1wRGlyLnBhdGgoe3ByZWZpeDogJ2FwcGl1bScsIHN1ZmZpeDogJy50bXAnfSk7XG4gIGlmIChfLmlzQXJyYXkoYmFzZTY0RGF0YSkpIHtcbiAgICAvLyBzb21lIGNsaWVudHMgKGFoZW0pIGphdmEsIHNlbmQgYSBieXRlIGFycmF5IGVuY29kaW5nIHV0ZjggY2hhcmFjdGVyc1xuICAgIC8vIGluc3RlYWQgb2YgYSBzdHJpbmcsIHdoaWNoIHdvdWxkIGJlIGluZmluaXRlbHkgYmV0dGVyIVxuICAgIGJhc2U2NERhdGEgPSBCdWZmZXIuZnJvbShiYXNlNjREYXRhKS50b1N0cmluZygndXRmOCcpO1xuICB9XG4gIGNvbnN0IGNvbnRlbnQgPSBCdWZmZXIuZnJvbShiYXNlNjREYXRhLCAnYmFzZTY0Jyk7XG4gIGxldCB0bXBEZXN0aW5hdGlvbiA9IG51bGw7XG4gIHRyeSB7XG4gICAgYXdhaXQgZnMud3JpdGVGaWxlKGxvY2FsRmlsZSwgY29udGVudC50b1N0cmluZygnYmluYXJ5JyksICdiaW5hcnknKTtcbiAgICBpZiAocmVtb3RlUGF0aC5zdGFydHNXaXRoKENPTlRBSU5FUl9QQVRIX01BUktFUikpIHtcbiAgICAgIGNvbnN0IFtwYWNrYWdlSWQsIHBhdGhJbkNvbnRhaW5lcl0gPSBwYXJzZUNvbnRhaW5lclBhdGgocmVtb3RlUGF0aCk7XG4gICAgICB0aGlzLmxvZy5kZWJ1ZyhgUGFyc2VkIHBhY2thZ2UgaWRlbnRpZmllciAnJHtwYWNrYWdlSWR9JyBmcm9tICcke3JlbW90ZVBhdGh9Jy4gYCArXG4gICAgICAgIGBXaWxsIHB1dCB0aGUgZGF0YSBpbnRvICcke3BhdGhJbkNvbnRhaW5lcn0nYCk7XG4gICAgICB0bXBEZXN0aW5hdGlvbiA9IGAvZGF0YS9sb2NhbC90bXAvJHtwYXRoLnBvc2l4LmJhc2VuYW1lKHBhdGhJbkNvbnRhaW5lcil9YDtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMuYWRiLnNoZWxsKFxuICAgICAgICAgIFsncnVuLWFzJywgcGFja2FnZUlkLCBgbWtkaXIgLXAgJyR7ZXNjYXBlUGF0aChwYXRoLnBvc2l4LmRpcm5hbWUocGF0aEluQ29udGFpbmVyKSl9J2BdXG4gICAgICAgICk7XG4gICAgICAgIGF3YWl0IHRoaXMuYWRiLnNoZWxsKFsncnVuLWFzJywgcGFja2FnZUlkLCBgdG91Y2ggJyR7ZXNjYXBlUGF0aChwYXRoSW5Db250YWluZXIpfSdgXSk7XG4gICAgICAgIGF3YWl0IHRoaXMuYWRiLnNoZWxsKFsncnVuLWFzJywgcGFja2FnZUlkLCBgY2htb2QgNzc3ICcke2VzY2FwZVBhdGgocGF0aEluQ29udGFpbmVyKX0nYF0pO1xuICAgICAgICBhd2FpdCB0aGlzLmFkYi5wdXNoKGxvY2FsRmlsZSwgdG1wRGVzdGluYXRpb24pO1xuICAgICAgICBhd2FpdCB0aGlzLmFkYi5zaGVsbChbXG4gICAgICAgICAgJ3J1bi1hcycsIHBhY2thZ2VJZCxcbiAgICAgICAgICBgY3AgLWYgJyR7ZXNjYXBlUGF0aCh0bXBEZXN0aW5hdGlvbil9JyAnJHtlc2NhcGVQYXRoKHBhdGhJbkNvbnRhaW5lcil9J2BcbiAgICAgICAgXSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRoaXMubG9nLmVycm9yQW5kVGhyb3coYENhbm5vdCBhY2Nlc3MgdGhlIGNvbnRhaW5lciBvZiAnJHtwYWNrYWdlSWR9JyBhcHBsaWNhdGlvbi4gYCArXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGBJcyB0aGUgYXBwbGljYXRpb24gaW5zdGFsbGVkIGFuZCBoYXMgJ2RlYnVnZ2FibGUnIGJ1aWxkIG9wdGlvbiBzZXQgdG8gdHJ1ZT8gYCArXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGFkYiBwdXNoIGNyZWF0ZXMgZm9sZGVycyBhbmQgb3ZlcndyaXRlcyBleGlzdGluZyBmaWxlcy5cbiAgICAgIGF3YWl0IHRoaXMuYWRiLnB1c2gobG9jYWxGaWxlLCByZW1vdGVQYXRoKTtcblxuICAgICAgLy8gaWYgd2UgaGF2ZSBwdXNoZWQgYSBmaWxlLCBpdCBtaWdodCBiZSBhIG1lZGlhIGZpbGUsIHNvIGVuc3VyZSB0aGF0XG4gICAgICAvLyBhcHBzIGtub3cgYWJvdXQgaXRcbiAgICAgIGF3YWl0IHNjYW5NZWRpYSh0aGlzLmFkYiwgcmVtb3RlUGF0aCwgdGhpcy5sb2cpO1xuICAgIH1cbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYXdhaXQgZnMuZXhpc3RzKGxvY2FsRmlsZSkpIHtcbiAgICAgIGF3YWl0IGZzLnVubGluayhsb2NhbEZpbGUpO1xuICAgIH1cbiAgICBpZiAodG1wRGVzdGluYXRpb24pIHtcbiAgICAgIGF3YWl0IHRoaXMuYWRiLnNoZWxsKFsncm0nLCAnLWYnLCB0bXBEZXN0aW5hdGlvbl0pO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBQdXNoRmlsZU9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSByZW1vdGVQYXRoIFRoZSBmdWxsIHBhdGggdG8gdGhlIHJlbW90ZSBmaWxlXG4gKiBvciBhIHNwZWNpYWxseSBmb3JtYXR0ZWQgcGF0aCwgd2hpY2ggcG9pbnRzIHRvIGFuIGl0ZW0gaW5zaWRlIGFuIGFwcCBidW5kbGUsXG4gKiBmb3IgZXhhbXBsZSBgQG15LmFwcC5pZC9teS9wYXRoYC4gSXQgaXMgbWFuZGF0b3J5IGZvciB0aGUgYXBwIGJ1bmRsZSB0byBoYXZlXG4gKiBkZWJ1Z2dpbmcgZW5hYmxlZCBpbiBvcmRlciB0byB1c2UgdGhlIGxhdHRlciByZW1vdGVQYXRoIGZvcm1hdC5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBwYXlsb2FkIEJhc2U2NC1lbmNvZGVkIGNvbnRlbnQgb2YgdGhlIGZpbGUgdG8gYmUgcHVzaGVkLlxuICovXG5cbi8qKlxuICogUHVzaGVzIHRoZSBnaXZlbiBkYXRhIHRvIGEgZmlsZSBvbiB0aGUgcmVtb3RlIGRldmljZS5cbiAqXG4gKiBAcGFyYW0ge1B1c2hGaWxlT3B0aW9uc30gb3B0c1xuICovXG5jb21tYW5kcy5tb2JpbGVQdXNoRmlsZSA9IGFzeW5jIGZ1bmN0aW9uIG1vYmlsZVB1c2hGaWxlIChvcHRzID0ge30pIHtcbiAgY29uc3QgeyByZW1vdGVQYXRoLCBwYXlsb2FkIH0gPSByZXF1aXJlQXJncyhbJ3JlbW90ZVBhdGgnLCAncGF5bG9hZCddLCBvcHRzKTtcbiAgcmV0dXJuIGF3YWl0IHRoaXMucHVzaEZpbGUocmVtb3RlUGF0aCwgcGF5bG9hZCk7XG59O1xuXG4vKipcbiAqIFB1bGxzIHRoZSB3aG9sZSBmb2xkZXIgZnJvbSB0aGUgcmVtb3RlIGRldmljZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSByZW1vdGVQYXRoIFRoZSBmdWxsIHBhdGggdG8gYSBmb2xkZXIgb24gdGhlXG4gKiByZW1vdGUgZGV2aWNlIG9yIGEgZm9sZGVyIGluc2lkZSBhbiBhcHBsaWNhdGlvbiBidW5kbGVcbiAqIEByZXR1cm5zIHtzdHJpbmd9IEJhc2U2NC1lbmNvZGVkIGFuZCB6aXBwZWQgY29udGVudCBvZiB0aGUgZm9sZGVyXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlcmUgd2FzIGEgZmFpbHVyZSB3aGlsZSBnZXR0aW5nIHRoZSBmb2xkZXIgY29udGVudFxuICovXG5jb21tYW5kcy5wdWxsRm9sZGVyID0gYXN5bmMgZnVuY3Rpb24gcHVsbEZvbGRlciAocmVtb3RlUGF0aCkge1xuICBjb25zdCB0bXBSb290ID0gYXdhaXQgdGVtcERpci5vcGVuRGlyKCk7XG4gIHRyeSB7XG4gICAgYXdhaXQgdGhpcy5hZGIucHVsbChyZW1vdGVQYXRoLCB0bXBSb290KTtcbiAgICByZXR1cm4gKGF3YWl0IHppcC50b0luTWVtb3J5WmlwKHRtcFJvb3QsIHtcbiAgICAgIGVuY29kZVRvQmFzZTY0OiB0cnVlLFxuICAgIH0pKS50b1N0cmluZygpO1xuICB9IGZpbmFsbHkge1xuICAgIGF3YWl0IGZzLnJpbXJhZih0bXBSb290KTtcbiAgfVxufTtcblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBQdWxsRm9sZGVyT3B0aW9uc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IHJlbW90ZVBhdGggVGhlIGZ1bGwgcGF0aCB0byB0aGUgcmVtb3RlIGZvbGRlci5cbiAqL1xuXG4vKipcbiAqIFB1bGxzIHRoZSB3aG9sZSBmb2xkZXIgZnJvbSB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtQdWxsRm9sZGVyT3B0aW9uc30gb3B0c1xuICogQHJldHVybnMge3N0cmluZ30gVGhlIHNhbWUgYXMgYHB1bGxGb2xkZXJgXG4gKi9cbmNvbW1hbmRzLm1vYmlsZVB1bGxGb2xkZXIgPSBhc3luYyBmdW5jdGlvbiBtb2JpbGVQdWxsRm9sZGVyIChvcHRzID0ge30pIHtcbiAgY29uc3QgeyByZW1vdGVQYXRoIH0gPSByZXF1aXJlQXJncygncmVtb3RlUGF0aCcsIG9wdHMpO1xuICByZXR1cm4gYXdhaXQgdGhpcy5wdWxsRm9sZGVyKHJlbW90ZVBhdGgpO1xufTtcblxuLyoqXG4gKiBEZWxldGVzIHRoZSBnaXZlbiBmb2xkZXIgb3IgZmlsZSBmcm9tIHRoZSByZW1vdGUgZGV2aWNlXG4gKlxuICogQHBhcmFtIHtBREJ9IGFkYlxuICogQHBhcmFtIHtzdHJpbmd9IHJlbW90ZVBhdGggVGhlIGZ1bGwgcGF0aCB0byB0aGUgcmVtb3RlIGZvbGRlclxuICogb3IgZmlsZSAoZm9sZGVyIG5hbWVzIG11c3QgZW5kIHdpdGggYSBzaW5nbGUgc2xhc2gpXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHByb3ZpZGVkIHJlbW90ZSBwYXRoIGlzIGludmFsaWQgb3JcbiAqIHRoZSBwYWNrYWdlIGNvbnRlbnQgY2Fubm90IGJlIGFjY2Vzc2VkXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIGlmIHRoZSByZW1vdGUgaXRlbSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZGVsZXRlZC5cbiAqIElmIHRoZSByZW1vdGUgcGF0aCBpcyB2YWxpZCwgYnV0IHRoZSByZW1vdGUgcGF0aCBkb2VzIG5vdCBleGlzdFxuICogdGhpcyBmdW5jdGlvbiByZXR1cm4gYGZhbHNlYC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZGVsZXRlRmlsZU9yRm9sZGVyIChhZGIsIHJlbW90ZVBhdGgpIHtcbiAgY29uc3QgcGVyZm9ybVJlbW90ZUZzQ2hlY2sgPSBhc3luYyAocCwgb3AsIHJ1bkFzID0gbnVsbCkgPT4ge1xuICAgIGNvbnN0IHBhc3NGbGFnID0gJ19fUEFTU19fJztcbiAgICBjb25zdCBjaGVja0NtZCA9IGBbIC0ke29wfSAnJHtlc2NhcGVQYXRoKHApfScgXSAmJiBlY2hvICR7cGFzc0ZsYWd9YDtcbiAgICBjb25zdCBmdWxsQ21kID0gcnVuQXMgPyBgcnVuLWFzICR7cnVuQXN9ICR7Y2hlY2tDbWR9YCA6IGNoZWNrQ21kO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gXy5pbmNsdWRlcyhhd2FpdCBhZGIuc2hlbGwoW2Z1bGxDbWRdKSwgcGFzc0ZsYWcpO1xuICAgIH0gY2F0Y2ggKGlnbikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfTtcbiAgY29uc3QgaXNGaWxlID0gYXN5bmMgKHAsIHJ1bkFzID0gbnVsbCkgPT4gYXdhaXQgcGVyZm9ybVJlbW90ZUZzQ2hlY2socCwgJ2YnLCBydW5Bcyk7XG4gIGNvbnN0IGlzRGlyID0gYXN5bmMgKHAsIHJ1bkFzID0gbnVsbCkgPT4gYXdhaXQgcGVyZm9ybVJlbW90ZUZzQ2hlY2socCwgJ2QnLCBydW5Bcyk7XG4gIGNvbnN0IGlzUHJlc2VudCA9IGFzeW5jIChwLCBydW5BcyA9IG51bGwpID0+IGF3YWl0IHBlcmZvcm1SZW1vdGVGc0NoZWNrKHAsICdlJywgcnVuQXMpO1xuXG4gIGxldCBkc3RQYXRoID0gcmVtb3RlUGF0aDtcbiAgbGV0IHBrZ0lkID0gbnVsbDtcbiAgaWYgKHJlbW90ZVBhdGguc3RhcnRzV2l0aChDT05UQUlORVJfUEFUSF9NQVJLRVIpKSB7XG4gICAgY29uc3QgW3BhY2thZ2VJZCwgcGF0aEluQ29udGFpbmVyXSA9IHBhcnNlQ29udGFpbmVyUGF0aChyZW1vdGVQYXRoKTtcbiAgICB0aGlzLmxvZy5kZWJ1ZyhgUGFyc2VkIHBhY2thZ2UgaWRlbnRpZmllciAnJHtwYWNrYWdlSWR9JyBmcm9tICcke3JlbW90ZVBhdGh9J2ApO1xuICAgIGRzdFBhdGggPSBwYXRoSW5Db250YWluZXI7XG4gICAgcGtnSWQgPSBwYWNrYWdlSWQ7XG4gIH1cblxuICBpZiAocGtnSWQpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgYWRiLnNoZWxsKFsncnVuLWFzJywgcGtnSWQsICdscyddKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aGlzLmxvZy5lcnJvckFuZFRocm93KGBDYW5ub3QgYWNjZXNzIHRoZSBjb250YWluZXIgb2YgJyR7cGtnSWR9JyBhcHBsaWNhdGlvbi4gYCArXG4gICAgICAgIGBJcyB0aGUgYXBwbGljYXRpb24gaW5zdGFsbGVkIGFuZCBoYXMgJ2RlYnVnZ2FibGUnIGJ1aWxkIG9wdGlvbiBzZXQgdG8gdHJ1ZT8gYCArXG4gICAgICAgIGBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFhd2FpdCBpc1ByZXNlbnQoZHN0UGF0aCwgcGtnSWQpKSB7XG4gICAgdGhpcy5sb2cuaW5mbyhgVGhlIGl0ZW0gYXQgJyR7ZHN0UGF0aH0nIGRvZXMgbm90IGV4aXN0LiBQZXJoYXBzLCBhbHJlYWR5IGRlbGV0ZWQ/YCk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgZXhwZWN0c0ZpbGUgPSAhcmVtb3RlUGF0aC5lbmRzV2l0aCgnLycpO1xuICBpZiAoZXhwZWN0c0ZpbGUgJiYgIWF3YWl0IGlzRmlsZShkc3RQYXRoLCBwa2dJZCkpIHtcbiAgICB0aGlzLmxvZy5lcnJvckFuZFRocm93KGBUaGUgaXRlbSBhdCAnJHtkc3RQYXRofScgaXMgbm90IGEgZmlsZWApO1xuICB9IGVsc2UgaWYgKCFleHBlY3RzRmlsZSAmJiAhYXdhaXQgaXNEaXIoZHN0UGF0aCwgcGtnSWQpKSB7XG4gICAgdGhpcy5sb2cuZXJyb3JBbmRUaHJvdyhgVGhlIGl0ZW0gYXQgJyR7ZHN0UGF0aH0nIGlzIG5vdCBhIGZvbGRlcmApO1xuICB9XG5cbiAgaWYgKHBrZ0lkKSB7XG4gICAgYXdhaXQgYWRiLnNoZWxsKFxuICAgICAgWydydW4tYXMnLCBwa2dJZCwgYHJtIC1mJHtleHBlY3RzRmlsZSA/ICcnIDogJ3InfSAnJHtlc2NhcGVQYXRoKGRzdFBhdGgpfSdgXSk7XG4gIH0gZWxzZSB7XG4gICAgYXdhaXQgYWRiLnNoZWxsKFsncm0nLCBgLWYke2V4cGVjdHNGaWxlID8gJycgOiAncid9YCwgZHN0UGF0aF0pO1xuICB9XG4gIGlmIChhd2FpdCBpc1ByZXNlbnQoZHN0UGF0aCwgcGtnSWQpKSB7XG4gICAgdGhpcy5sb2cuZXJyb3JBbmRUaHJvdyhgVGhlIGl0ZW0gYXQgJyR7ZHN0UGF0aH0nIHN0aWxsIGV4aXN0cyBhZnRlciBiZWluZyBkZWxldGVkLiBgICtcbiAgICAgIGBJcyBpdCB3cml0YWJsZT9gKTtcbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBEZWxldGVGaWxlT3B0c1xuICogQHByb3BlcnR5IHshc3RyaW5nfSByZW1vdGVQYXRoIFRoZSBmdWxsIHBhdGggdG8gdGhlIHJlbW90ZSBmaWxlXG4gKiBvciBhIGZpbGUgaW5zaWRlIGFuIGFwcGxpY2F0aW9uIGJ1bmRsZSAoZm9yIGV4YW1wbGUgYEBteS5hcHAuaWQvcGF0aC9pbi9idW5kbGVgKVxuICovXG5cbi8qKlxuICogRGVsZXRlcyBhIGZpbGUgb24gdGhlIHJlbW90ZSBkZXZpY2VcbiAqXG4gKiBAcGFyYW0ge0RlbGV0ZUZpbGVPcHRzfSBvcHRzXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIGlmIHRoZSByZW1vdGUgZmlsZSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZGVsZXRlZC5cbiAqIElmIHRoZSBwYXRoIHRvIGEgcmVtb3RlIGZpbGUgaXMgdmFsaWQsIGJ1dCB0aGUgZmlsZSBpdHNlbGYgZG9lcyBub3QgZXhpc3RcbiAqIHRoZW4gYGZhbHNlYCBpcyByZXR1cm5lZC5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgYXJndW1lbnQgaXMgaW52YWxpZCBvciB0aGVyZSB3YXMgYW4gZXJyb3Igd2hpbGVcbiAqIGRlbGV0aW5nIHRoZSBmaWxlXG4gKi9cbmNvbW1hbmRzLm1vYmlsZURlbGV0ZUZpbGUgPSBhc3luYyBmdW5jdGlvbiBtb2JpbGVEZWxldGVGaWxlIChvcHRzID0ge30pIHtcbiAgY29uc3Qge3JlbW90ZVBhdGh9ID0gb3B0cztcbiAgaWYgKCFyZW1vdGVQYXRoKSB7XG4gICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihgVGhlICdyZW1vdGVQYXRoJyBhcmd1bWVudCBpcyBtYW5kYXRvcnlgKTtcbiAgfVxuICBpZiAocmVtb3RlUGF0aC5lbmRzV2l0aCgnLycpKSB7XG4gICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihcbiAgICAgIGBJdCBpcyBleHBlY3RlZCB0aGF0IHJlbW90ZSBwYXRoIHBvaW50cyB0byBhIGZvbGRlciBhbmQgbm90IHRvIGEgZmlsZS4gYCArXG4gICAgICBgJyR7cmVtb3RlUGF0aH0nIGlzIGdpdmVuIGluc3RlYWRgXG4gICAgKTtcbiAgfVxuICByZXR1cm4gYXdhaXQgZGVsZXRlRmlsZU9yRm9sZGVyKHRoaXMuYWRiLCByZW1vdGVQYXRoKTtcbn07XG5cbmV4cG9ydCB7IGNvbW1hbmRzIH07XG5leHBvcnQgZGVmYXVsdCBjb21tYW5kcztcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFBQSxJQUFBQSxPQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxRQUFBLEdBQUFELE9BQUE7QUFDQSxJQUFBRSxLQUFBLEdBQUFILHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBRyxPQUFB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
349
+ exports.default = commands;
350
+ //# sourceMappingURL=file-actions.js.map