jsii-release 0.2.987 → 0.2.989
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +33 -0
- package/README.md +34 -12
- package/bin/publib-maven +2 -361
- package/lib/bin/publib-ca.js +20 -12
- package/lib/bin/publib-golang.js +19 -10
- package/lib/bin/publib-maven.d.ts +10 -0
- package/lib/bin/publib-maven.js +608 -0
- package/lib/codeartifact/codeartifact-cli.js +18 -8
- package/lib/codeartifact/codeartifact-repo.js +9 -13
- package/lib/codeartifact/display.js +2 -3
- package/lib/codeartifact/files.js +28 -20
- package/lib/codeartifact/shell.d.ts +0 -2
- package/lib/codeartifact/shell.js +30 -25
- package/lib/codeartifact/staging/maven.js +23 -16
- package/lib/codeartifact/staging/npm.js +21 -12
- package/lib/codeartifact/staging/nuget.js +3 -4
- package/lib/codeartifact/staging/parallel-shell.d.ts +0 -1
- package/lib/codeartifact/staging/parallel-shell.js +3 -4
- package/lib/codeartifact/staging/pip.js +3 -4
- package/lib/codeartifact/usage-dir.js +18 -8
- package/lib/help/corking.d.ts +2 -6
- package/lib/help/corking.js +18 -8
- package/lib/help/git.js +34 -27
- package/lib/help/os.js +19 -10
- package/lib/help/shell.js +23 -15
- package/lib/help/sleep.js +2 -3
- package/lib/targets/go.js +24 -16
- package/package.json +14 -12
- package/package.json.bak +14 -12
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
3
|
+
if (value !== null && value !== void 0) {
|
|
4
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
5
|
+
var dispose, inner;
|
|
6
|
+
if (async) {
|
|
7
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
8
|
+
dispose = value[Symbol.asyncDispose];
|
|
9
|
+
}
|
|
10
|
+
if (dispose === void 0) {
|
|
11
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
12
|
+
dispose = value[Symbol.dispose];
|
|
13
|
+
if (async) inner = dispose;
|
|
14
|
+
}
|
|
15
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
16
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
17
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
18
|
+
}
|
|
19
|
+
else if (async) {
|
|
20
|
+
env.stack.push({ async: true });
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
};
|
|
24
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
25
|
+
return function (env) {
|
|
26
|
+
function fail(e) {
|
|
27
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
28
|
+
env.hasError = true;
|
|
29
|
+
}
|
|
30
|
+
var r, s = 0;
|
|
31
|
+
function next() {
|
|
32
|
+
while (r = env.stack.pop()) {
|
|
33
|
+
try {
|
|
34
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
35
|
+
if (r.dispose) {
|
|
36
|
+
var result = r.dispose.call(r.value);
|
|
37
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
38
|
+
}
|
|
39
|
+
else s |= 1;
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
fail(e);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
46
|
+
if (env.hasError) throw env.error;
|
|
47
|
+
}
|
|
48
|
+
return next();
|
|
49
|
+
};
|
|
50
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
51
|
+
var e = new Error(message);
|
|
52
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
53
|
+
});
|
|
54
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
|
+
exports.autoCleanDir = autoCleanDir;
|
|
56
|
+
/**
|
|
57
|
+
* Legacy vs compatibility endpoint
|
|
58
|
+
* ==================================
|
|
59
|
+
*
|
|
60
|
+
* This script talks about legacy vs compatibility endpoint a bunch.
|
|
61
|
+
*
|
|
62
|
+
* Both implement the Nexus 2 protocol, however:
|
|
63
|
+
*
|
|
64
|
+
* - The "legacy" endpoint is the Sonatype OSSRH endpoint that was deprecated June 2025.
|
|
65
|
+
* - The "compatibility" endpoint is a Nexus 2-compatible endpoint stood up for the new
|
|
66
|
+
* publishing service, Central Publishing.
|
|
67
|
+
*
|
|
68
|
+
* It should be the same protocol but of course there are subtle differences
|
|
69
|
+
* between them (in how they signal error when you try to republish an already
|
|
70
|
+
* published version, and even in the wire protocol accepted) so we have to
|
|
71
|
+
* treat them differently here.
|
|
72
|
+
*
|
|
73
|
+
* There is also an "official new" protocol for the new publishing mechanism,
|
|
74
|
+
* but the Maven plugin they supply for that doesn't support that. In their words:
|
|
75
|
+
*
|
|
76
|
+
* > it appears that you are using the "two stage"[1] deployment process, which is
|
|
77
|
+
* > not yet supported by the new plugin. You are the first publisher to have
|
|
78
|
+
* > requested this, so we were not familiar with this specific usecase when
|
|
79
|
+
* > building the new plugin
|
|
80
|
+
* > [1] <https://github.com/sonatype/nexus-maven-plugins/blob/43a9940b134c3f87ebe4daa82552e844d9c578b8/staging/maven-plugin/WORKFLOWS.md#two-shots>
|
|
81
|
+
*/
|
|
82
|
+
const fs_1 = require("fs");
|
|
83
|
+
const zx_1 = require("zx");
|
|
84
|
+
const LEGACY_OSSRH_SERVER_ID = 'ossrh';
|
|
85
|
+
const COMPAT_CENTRAL_SERVER_ID = 'central-ossrh';
|
|
86
|
+
const NEXUS_MAVEN_STAGING_PLUGIN = 'org.sonatype.plugins:nexus-staging-maven-plugin:1.7.0';
|
|
87
|
+
async function main() {
|
|
88
|
+
const args = process.argv.slice(2);
|
|
89
|
+
const javaRoot = args[0] ?? 'dist/java';
|
|
90
|
+
(0, zx_1.cd)(javaRoot);
|
|
91
|
+
const poms = await (0, zx_1.glob)('**/*.pom');
|
|
92
|
+
if (poms.length === 0) {
|
|
93
|
+
throw new SimpleError(`No JARS to publish: no .pom files found under ${process.cwd()}`);
|
|
94
|
+
}
|
|
95
|
+
(0, zx_1.echo)(`POMs found: ${poms}`);
|
|
96
|
+
const sharedOptions = {
|
|
97
|
+
username: envVar('MAVEN_USERNAME'),
|
|
98
|
+
password: envVar('MAVEN_PASSWORD'),
|
|
99
|
+
dryRun: process.env.MAVEN_DRYRUN === 'true',
|
|
100
|
+
verbose: process.env.MAVEN_VERBOSE === 'true',
|
|
101
|
+
poms,
|
|
102
|
+
};
|
|
103
|
+
let options;
|
|
104
|
+
const serverId = process.env.MAVEN_SERVER_ID ?? LEGACY_OSSRH_SERVER_ID;
|
|
105
|
+
switch (serverId) {
|
|
106
|
+
case LEGACY_OSSRH_SERVER_ID:
|
|
107
|
+
options = {
|
|
108
|
+
type: 'legacy-ossrh',
|
|
109
|
+
...sharedOptions,
|
|
110
|
+
stagingProfileId: envVar('MAVEN_STAGING_PROFILE_ID'),
|
|
111
|
+
endpoint: process.env.MAVEN_ENDPOINT,
|
|
112
|
+
privateKey: parsePrivateKeyFromEnv(),
|
|
113
|
+
};
|
|
114
|
+
break;
|
|
115
|
+
case COMPAT_CENTRAL_SERVER_ID:
|
|
116
|
+
options = {
|
|
117
|
+
type: 'compat-ossrh',
|
|
118
|
+
...sharedOptions,
|
|
119
|
+
stagingProfileId: envVar('MAVEN_STAGING_PROFILE_ID'),
|
|
120
|
+
endpoint: process.env.MAVEN_ENDPOINT,
|
|
121
|
+
privateKey: parsePrivateKeyFromEnv(),
|
|
122
|
+
};
|
|
123
|
+
break;
|
|
124
|
+
default:
|
|
125
|
+
// We haven't implemented signing for this, so fail loudly if people try to use it anyway
|
|
126
|
+
if (process.env.MAVEN_GPG_PRIVATE_KEY || process.env.MAVEN_GPG_PRIVATE_KEY_FILE) {
|
|
127
|
+
throw new SimpleError('MAVEN_GPG_PRIVATE_KEY[_FILE] is only supported for OSSRH publishing');
|
|
128
|
+
}
|
|
129
|
+
options = {
|
|
130
|
+
type: 'custom-nexus',
|
|
131
|
+
...sharedOptions,
|
|
132
|
+
serverId,
|
|
133
|
+
repositoryUrl: envVar('MAVEN_REPOSITORY_URL'),
|
|
134
|
+
};
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
await mavenPublish(options);
|
|
138
|
+
(0, zx_1.echo)('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
|
|
139
|
+
(0, zx_1.echo)('✅ All Done!');
|
|
140
|
+
}
|
|
141
|
+
function parsePrivateKeyFromEnv() {
|
|
142
|
+
if (process.env.MAVEN_GPG_PRIVATE_KEY_FILE) {
|
|
143
|
+
return { type: 'file', fileName: process.env.MAVEN_GPG_PRIVATE_KEY_FILE, passPhrase: envVar('MAVEN_GPG_PRIVATE_KEY_PASSPHRASE') };
|
|
144
|
+
}
|
|
145
|
+
if (process.env.MAVEN_GPG_PRIVATE_KEY) {
|
|
146
|
+
return { type: 'material', keyMaterial: process.env.MAVEN_GPG_PRIVATE_KEY, passPhrase: envVar('MAVEN_GPG_PRIVATE_KEY_PASSPHRASE') };
|
|
147
|
+
}
|
|
148
|
+
throw new SimpleError('MAVEN_GPG_PRIVATE_KEY[_FILE] is required');
|
|
149
|
+
}
|
|
150
|
+
//----------------------------------------------------------------------
|
|
151
|
+
// Publishing functions
|
|
152
|
+
//
|
|
153
|
+
async function mavenPublish(options) {
|
|
154
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
155
|
+
try {
|
|
156
|
+
const workDir = __addDisposableResource(env_1, autoCleanDir(), true);
|
|
157
|
+
const maven = new Maven(workDir.dir, options.verbose, options.dryRun);
|
|
158
|
+
const x = options.type;
|
|
159
|
+
switch (x) {
|
|
160
|
+
case 'legacy-ossrh':
|
|
161
|
+
await deployLegacyOssrh(maven, options);
|
|
162
|
+
break;
|
|
163
|
+
case 'compat-ossrh':
|
|
164
|
+
await deployCompatOssrh(maven, options);
|
|
165
|
+
break;
|
|
166
|
+
case 'custom-nexus':
|
|
167
|
+
await deployCustomNexus(maven, options);
|
|
168
|
+
break;
|
|
169
|
+
default:
|
|
170
|
+
assertNever(x);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch (e_1) {
|
|
174
|
+
env_1.error = e_1;
|
|
175
|
+
env_1.hasError = true;
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
const result_1 = __disposeResources(env_1);
|
|
179
|
+
if (result_1)
|
|
180
|
+
await result_1;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Deploy to the legacy OSSRH Nexus server
|
|
185
|
+
*/
|
|
186
|
+
async function deployLegacyOssrh(maven, options) {
|
|
187
|
+
(0, zx_1.echo)('📦 Publishing to Maven Central');
|
|
188
|
+
const defaultEndpoint = 'https://oss.sonatype.org';
|
|
189
|
+
const staged = await deployStagedRepository(maven, {
|
|
190
|
+
...options,
|
|
191
|
+
endpoint: options.endpoint ?? defaultEndpoint,
|
|
192
|
+
republishWill400: false,
|
|
193
|
+
});
|
|
194
|
+
if (staged.type !== 'success') {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
/*
|
|
198
|
+
const released = await releaseRepo({
|
|
199
|
+
serverUrl: options.endpoint ?? defaultEndpoint,
|
|
200
|
+
username: options.username,
|
|
201
|
+
password: options.password,
|
|
202
|
+
repositoryId: staged.repositoryId,
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
if (released) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
*/
|
|
209
|
+
// Send a remote release command to the repository
|
|
210
|
+
const releaseOutput = await maven.exec(`${NEXUS_MAVEN_STAGING_PLUGIN}:rc-release`, {
|
|
211
|
+
properties: {
|
|
212
|
+
nexusUrl: options.endpoint ?? defaultEndpoint,
|
|
213
|
+
serverId: staged.serverId,
|
|
214
|
+
stagingRepositoryId: staged.repositoryId,
|
|
215
|
+
},
|
|
216
|
+
nothrow: true,
|
|
217
|
+
});
|
|
218
|
+
if (!releaseOutput) {
|
|
219
|
+
(0, zx_1.echo)('🏜️ Stopped here because of dry-run');
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (releaseOutput.exitCode !== 0) {
|
|
223
|
+
// If release failed, check if this was caused because we are trying to publish
|
|
224
|
+
// the same version again, which is not an error. The magic string "does not
|
|
225
|
+
// allow updating artifact" for a ".pom" file indicates that we are trying to
|
|
226
|
+
// override an existing version. Otherwise, fail!
|
|
227
|
+
const looksLikeDuplicatePublish = releaseOutput.lines()
|
|
228
|
+
.filter(l => l.includes('does not allow updating artifact'))
|
|
229
|
+
.filter(l => l.includes('.pom'))
|
|
230
|
+
.length > 0;
|
|
231
|
+
if (!looksLikeDuplicatePublish) {
|
|
232
|
+
throw new SimpleError('Release failed');
|
|
233
|
+
}
|
|
234
|
+
(0, zx_1.echo)('⚠️ Artifact already published. Skipping');
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Deploy to the compat OSSRH Nexus server
|
|
239
|
+
*/
|
|
240
|
+
async function deployCompatOssrh(maven, options) {
|
|
241
|
+
(0, zx_1.echo)('📦 Publishing to Maven Central (Compat endpoint)');
|
|
242
|
+
const defaultEndpoint = 'https://ossrh-staging-api.central.sonatype.com/';
|
|
243
|
+
const endpoint = options.endpoint ?? defaultEndpoint;
|
|
244
|
+
const staged = await deployStagedRepository(maven, {
|
|
245
|
+
...options,
|
|
246
|
+
endpoint,
|
|
247
|
+
republishWill400: true,
|
|
248
|
+
});
|
|
249
|
+
if (staged.type !== 'success') {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const released = await releaseRepo({
|
|
253
|
+
serverUrl: endpoint,
|
|
254
|
+
username: options.username,
|
|
255
|
+
password: options.password,
|
|
256
|
+
repositoryId: staged.repositoryId,
|
|
257
|
+
});
|
|
258
|
+
if (released === 'duplicate-version') {
|
|
259
|
+
(0, zx_1.echo)('⚠️ Version(s) already published. Skipping');
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Deploy to a custom Nexus server
|
|
264
|
+
*/
|
|
265
|
+
async function deployCustomNexus(maven, options) {
|
|
266
|
+
(0, zx_1.echo)(`📦 Publishing to ${options.serverId}`);
|
|
267
|
+
await maven.writeSettingsFile(options.serverId, false);
|
|
268
|
+
for (const pom of options.poms) {
|
|
269
|
+
const deployOutput = await maven.exec('deploy:deploy-file', {
|
|
270
|
+
properties: {
|
|
271
|
+
url: options.repositoryUrl,
|
|
272
|
+
repositoryId: options.serverId,
|
|
273
|
+
pomFile: pom,
|
|
274
|
+
...jarsFromPom(pom),
|
|
275
|
+
},
|
|
276
|
+
nothrow: true,
|
|
277
|
+
});
|
|
278
|
+
if (deployOutput?.exitCode && deployOutput.exitCode > 0) {
|
|
279
|
+
if (deployOutput.stdout.includes('409 Conflict')) {
|
|
280
|
+
(0, zx_1.echo)('⚠️ Artifact already published. Skipping');
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
throw new SimpleError('Release failed');
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Create the staging repository. This is the same between the legacy and compat endpoints.
|
|
290
|
+
*
|
|
291
|
+
* `republishWill400`: in the compatibility endpoint, staging a version that has already
|
|
292
|
+
* been published will lead to a `400 Bad Request`, with no further info. We needed to have
|
|
293
|
+
* run the Maven command with `--debug` logging to see the actual error message in the output.
|
|
294
|
+
*
|
|
295
|
+
* In the legacy endpoint, staging takes multiple minutes, and Maven will poll
|
|
296
|
+
* every 3s and print the output. We therefore don't use verbose mode to avoid
|
|
297
|
+
* stdout spam. In the legacy endpoint, duplicate version publishing gets
|
|
298
|
+
* reported during the 'release' step anyway, not during staging.
|
|
299
|
+
*/
|
|
300
|
+
async function deployStagedRepository(maven, options) {
|
|
301
|
+
const serverId = 'ossrh';
|
|
302
|
+
await maven.writeSettingsFile(serverId, true);
|
|
303
|
+
// First -- sign artifacts
|
|
304
|
+
const signedDir = zx_1.path.join(maven.workDir, 'signed');
|
|
305
|
+
await fs_1.promises.mkdir(signedDir, { recursive: true });
|
|
306
|
+
await signJars(maven, options.poms, signedDir, serverId, options.privateKey);
|
|
307
|
+
(0, zx_1.echo)('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
|
|
308
|
+
(0, zx_1.echo)(' Deploying and closing repository...');
|
|
309
|
+
(0, zx_1.echo)('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
|
|
310
|
+
const nexusMavenStaging = 'org.sonatype.plugins:nexus-staging-maven-plugin:1.7.0';
|
|
311
|
+
const stageOutput = await maven.exec(`${nexusMavenStaging}:deploy-staged-repository`, {
|
|
312
|
+
properties: {
|
|
313
|
+
repositoryDirectory: signedDir,
|
|
314
|
+
nexusUrl: options.endpoint,
|
|
315
|
+
serverId,
|
|
316
|
+
stagingProgressTimeoutMinutes: '30',
|
|
317
|
+
stagingProfileId: options.stagingProfileId,
|
|
318
|
+
},
|
|
319
|
+
nothrow: true,
|
|
320
|
+
verbose: options.republishWill400,
|
|
321
|
+
});
|
|
322
|
+
// FIXME: New staging API throws an error here on duplicate versions
|
|
323
|
+
if (stageOutput === undefined) {
|
|
324
|
+
(0, zx_1.echo)('🏜️ Stopped here because of dry-run');
|
|
325
|
+
return { type: 'dry-run' };
|
|
326
|
+
}
|
|
327
|
+
if (options.republishWill400 && stageOutput.text().match(/Component with package url.*already exists/)) {
|
|
328
|
+
// We've seen this fail with the above error message on the OSSRH compatibility API when trying to republish
|
|
329
|
+
// an already-published version.
|
|
330
|
+
//
|
|
331
|
+
// This is potentially a problem if there are multiple versions in the source directory at once, because nothing
|
|
332
|
+
// will be published if there's one package in there that has already been published previously. But c'est la vie.
|
|
333
|
+
(0, zx_1.echo)('⚠️ Version(s) already published. Skipping');
|
|
334
|
+
return { type: 'already-published' };
|
|
335
|
+
}
|
|
336
|
+
else if (stageOutput.exitCode && stageOutput.exitCode > 0) {
|
|
337
|
+
throw stageOutput;
|
|
338
|
+
}
|
|
339
|
+
// Grep the repository ID out of the printed output
|
|
340
|
+
// [INFO] * Closing staging repository with ID "XXXXXXXXXX".
|
|
341
|
+
const m = stageOutput.stdout.match(/Closing staging repository with ID "([^"]+)"/);
|
|
342
|
+
if (!m) {
|
|
343
|
+
throw new SimpleError('Unable to extract repository ID from deploy-staged-repository output. This means it failed to close or there was an unexpected problem. At any rate, we can\'t release it. Sorry.');
|
|
344
|
+
}
|
|
345
|
+
const repositoryId = m[1];
|
|
346
|
+
return { type: 'success', repositoryId, serverId };
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Send a custom "release" command to the new Sonatype backwards compatibility endpoint
|
|
350
|
+
*
|
|
351
|
+
* When using the `nexus-staging-maven-plugin`'s `release` or `rc-release` commands, we get the following
|
|
352
|
+
* error:
|
|
353
|
+
*
|
|
354
|
+
* Sending:
|
|
355
|
+
*
|
|
356
|
+
* ```
|
|
357
|
+
* <stagingActionRequest><data><stagedRepositoryIds class="java.util.Arrays$ArrayList"><a class="string-array"><string>io.github.rix0rrr--63edbcbe-f058-44eb-85f4-fd9dce1aef40</string></a></stagedRepositoryIds><description>unknown</description><autoDropAfterRelease>true</autoDropAfterRelease></data></stagingActionRequest>
|
|
358
|
+
* ```
|
|
359
|
+
*
|
|
360
|
+
* Error:
|
|
361
|
+
*
|
|
362
|
+
* ```
|
|
363
|
+
* Failed to process request: Got unexpected XML element when reading stagedRepositoryIds: Got unexpected element StartElement(a, {"": "", "xml": "http://www.w3.org/XML/1998/namespace", "xmlns": "http://www.w3.org/2000/xmlns/"}, [class -> string-array]), expected one of: string
|
|
364
|
+
* ```
|
|
365
|
+
*
|
|
366
|
+
* Doing a manual slightly modified version of the above request succeeds, so we'll just proceed with doing
|
|
367
|
+
* that.
|
|
368
|
+
*
|
|
369
|
+
* The endpoint also supports JSON, which we prefer over XML.
|
|
370
|
+
*
|
|
371
|
+
* This endpoint will never return an error, even if the publish didn't happen because
|
|
372
|
+
* of duplicate version publishing (not for the legacy, nor for the compatibility endpoint).
|
|
373
|
+
*
|
|
374
|
+
* @see https://central.sonatype.org/publish/publish-portal-ossrh-staging-api/
|
|
375
|
+
* @see https://support.sonatype.com/hc/en-us/articles/213465448-Automatically-dropping-old-staging-repositories
|
|
376
|
+
*/
|
|
377
|
+
async function releaseRepo(options) {
|
|
378
|
+
(0, zx_1.echo)(`🚀 Releasing repository ${options.repositoryId} at ${options.serverUrl}`);
|
|
379
|
+
const url = new URL('service/local/staging/bulk/promote', options.serverUrl);
|
|
380
|
+
const response = await fetch(url, {
|
|
381
|
+
method: 'POST',
|
|
382
|
+
body: JSON.stringify({
|
|
383
|
+
data: {
|
|
384
|
+
stagedRepositoryIds: [options.repositoryId],
|
|
385
|
+
description: options.description ?? 'Deployment',
|
|
386
|
+
autoDropAfterRelease: true,
|
|
387
|
+
},
|
|
388
|
+
}),
|
|
389
|
+
headers: {
|
|
390
|
+
'Content-Type': 'application/json',
|
|
391
|
+
'Accept': 'application/json',
|
|
392
|
+
'Authorization': `Basic ${btoa(`${options.username}:${options.password}`)}`,
|
|
393
|
+
},
|
|
394
|
+
});
|
|
395
|
+
const body = await response.text();
|
|
396
|
+
// It's possible that (due to some replication latency?) the initial "stage" succeeds,
|
|
397
|
+
// but the "release" fails, if we try to publish an already-published version again.
|
|
398
|
+
//
|
|
399
|
+
// Unfortunately there is no great error code to detect this right now, but I've observed
|
|
400
|
+
// this error when it happened.
|
|
401
|
+
// I have a support request out to Sonatype for this, we'll see if this changes over time.
|
|
402
|
+
if (response.status === 400 && body === 'Failed to process request: service error') {
|
|
403
|
+
return 'duplicate-version';
|
|
404
|
+
}
|
|
405
|
+
if (!response.ok) {
|
|
406
|
+
throw new Error(`HTTP ${response.status} ${response.statusText}: ${body}`);
|
|
407
|
+
}
|
|
408
|
+
console.log(body);
|
|
409
|
+
return 'ok';
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Sign and stage our artifacts into a local directory
|
|
413
|
+
*/
|
|
414
|
+
async function signJars(maven, poms, targetDir, serverId, key) {
|
|
415
|
+
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
416
|
+
try {
|
|
417
|
+
const gpg = __addDisposableResource(env_2, await importGpgKey(key), true);
|
|
418
|
+
// on a mac, --pinentry-mode to "loopback" are required and I couldn't find a
|
|
419
|
+
// way to do so via -Dgpg.gpgArguments or the settings file, so here we are.
|
|
420
|
+
let gpgBin = 'gpg';
|
|
421
|
+
if (zx_1.os.platform() === 'darwin') {
|
|
422
|
+
gpgBin = zx_1.path.join(maven.workDir, 'publib-gpg.sh');
|
|
423
|
+
await fs_1.promises.writeFile(gpgBin, [
|
|
424
|
+
'#!/bin/bash',
|
|
425
|
+
'exec gpg --pinentry-mode loopback "\$@"',
|
|
426
|
+
].join('\n'), 'utf-8');
|
|
427
|
+
await (0, zx_1.$) `chmod +x ${gpgBin}`;
|
|
428
|
+
}
|
|
429
|
+
for (const pom of poms) {
|
|
430
|
+
await maven.exec('gpg:sign-and-deploy-file', {
|
|
431
|
+
properties: {
|
|
432
|
+
'url': `file://${targetDir}`,
|
|
433
|
+
'repositoryId': serverId, // Most likely not necessary
|
|
434
|
+
'gpg.homedir': gpg.home,
|
|
435
|
+
'gpg.keyname': gpg.keyId,
|
|
436
|
+
'gpg.executable': gpgBin,
|
|
437
|
+
'pomFile': pom,
|
|
438
|
+
...jarsFromPom(pom),
|
|
439
|
+
},
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
catch (e_2) {
|
|
444
|
+
env_2.error = e_2;
|
|
445
|
+
env_2.hasError = true;
|
|
446
|
+
}
|
|
447
|
+
finally {
|
|
448
|
+
const result_2 = __disposeResources(env_2);
|
|
449
|
+
if (result_2)
|
|
450
|
+
await result_2;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Based on the path of a .pom file, return the paths of the corresponding jars
|
|
455
|
+
*/
|
|
456
|
+
function jarsFromPom(pom) {
|
|
457
|
+
return {
|
|
458
|
+
file: pom.replace(/\.pom$/, '.jar'),
|
|
459
|
+
sources: pom.replace(/\.pom$/, '-sources.jar'),
|
|
460
|
+
javadoc: pom.replace(/\.pom$/, '-javadoc.jar'),
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Create a temporary directory and import the GPG key material into a new keychain there
|
|
465
|
+
*/
|
|
466
|
+
async function importGpgKey(key) {
|
|
467
|
+
// GnuPG will occasionally bail out with "gpg: <whatever> failed: Inappropriate ioctl for device", the following attempts to fix
|
|
468
|
+
const gpgHome = autoCleanDir();
|
|
469
|
+
try {
|
|
470
|
+
const tty = (await (0, zx_1.$)({ stdio: ['inherit', 'pipe', 'pipe'] }) `tty`).stdout;
|
|
471
|
+
let privateKeyFile;
|
|
472
|
+
const type = key.type;
|
|
473
|
+
switch (type) {
|
|
474
|
+
case 'file':
|
|
475
|
+
privateKeyFile = key.fileName;
|
|
476
|
+
break;
|
|
477
|
+
case 'material':
|
|
478
|
+
privateKeyFile = zx_1.path.join(gpgHome.dir, 'private.pem');
|
|
479
|
+
await (0, zx_1.$) `echo -e ${key.keyMaterial} > ${privateKeyFile}`;
|
|
480
|
+
break;
|
|
481
|
+
default:
|
|
482
|
+
assertNever(type);
|
|
483
|
+
}
|
|
484
|
+
const env = {
|
|
485
|
+
GNUPGHOME: gpgHome.dir,
|
|
486
|
+
GPG_TTY: tty,
|
|
487
|
+
};
|
|
488
|
+
const $$ = (0, zx_1.$)({ env: { ...process.env, ...env } });
|
|
489
|
+
await $$ `gpg --allow-secret-key-import --batch --yes --no-tty --import ${privateKeyFile}`;
|
|
490
|
+
const gpgKeyId = (await $$ `gpg --list-keys --with-colons | grep pub | cut -d: -f5`).stdout.trim();
|
|
491
|
+
(0, zx_1.echo)(`gpg_key_id=${gpgKeyId}`);
|
|
492
|
+
return {
|
|
493
|
+
keyId: gpgKeyId,
|
|
494
|
+
env,
|
|
495
|
+
home: gpgHome.dir,
|
|
496
|
+
[Symbol.asyncDispose]: async () => gpgHome[Symbol.asyncDispose](),
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
catch (e) {
|
|
500
|
+
await gpgHome[Symbol.asyncDispose]();
|
|
501
|
+
throw e;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
class Maven {
|
|
505
|
+
constructor(workDir, verbose, dryRun) {
|
|
506
|
+
this.workDir = workDir;
|
|
507
|
+
this.verbose = verbose;
|
|
508
|
+
this.dryRun = dryRun;
|
|
509
|
+
this.settingsFile = zx_1.path.join(workDir, 'mvn-settings.xml');
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Create a settings.xml file with the user+password for maven
|
|
513
|
+
*/
|
|
514
|
+
async writeSettingsFile(serverId, signedArtifacts) {
|
|
515
|
+
const lines = [];
|
|
516
|
+
lines.push('<?xml version="1.0" encoding="UTF-8" ?>', '<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"', ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"', ' xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0', ' http://maven.apache.org/xsd/settings-1.0.0.xsd">', ' <servers>', ' <server>', ` <id>${serverId}</id>`,
|
|
517
|
+
// Maven will read these, surrounding code has already made sure they are set
|
|
518
|
+
' <username>${env.MAVEN_USERNAME}</username>', ' <password>${env.MAVEN_PASSWORD}</password>', ' </server>');
|
|
519
|
+
if (signedArtifacts) {
|
|
520
|
+
lines.push(' <server>', ' <id>gpg.passphrase</id>',
|
|
521
|
+
// Maven will read these, surrounding code has already made sure they are set
|
|
522
|
+
' <passphrase>${env.MAVEN_GPG_PRIVATE_KEY_PASSPHRASE}</passphrase>', ' </server>');
|
|
523
|
+
}
|
|
524
|
+
lines.push(' </servers>', '</settings>');
|
|
525
|
+
await fs_1.promises.writeFile(this.settingsFile, lines.join('\n'), 'utf-8');
|
|
526
|
+
}
|
|
527
|
+
async exec(mojo, options) {
|
|
528
|
+
const args = [
|
|
529
|
+
`--settings=${this.settingsFile}`,
|
|
530
|
+
...(options.verbose ?? this.verbose ? ['-X'] : []),
|
|
531
|
+
mojo,
|
|
532
|
+
...Object.entries(options.properties).map(([k, v]) => `-D${k}=${v}`),
|
|
533
|
+
];
|
|
534
|
+
if (this.dryRun) {
|
|
535
|
+
(0, zx_1.echo)(`[DRY-RUN] mvn ${args.map(zx_1.quote).join(' ')}`);
|
|
536
|
+
return undefined;
|
|
537
|
+
}
|
|
538
|
+
const env = {
|
|
539
|
+
...process.env,
|
|
540
|
+
JDK_JAVA_OPTIONS: [
|
|
541
|
+
// If we don't add this, we'll get an error like the following during the nexus-staging-maven-plugin:rc-release mojo.
|
|
542
|
+
// Don't know where this is coming from all of a sudden.
|
|
543
|
+
//
|
|
544
|
+
// [ERROR] message : No converter available
|
|
545
|
+
// [ERROR] type : java.util.Arrays$ArrayList
|
|
546
|
+
// [ERROR] converter : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
|
|
547
|
+
// [ERROR] message[1] : Unable to make field protected transient int java.util.AbstractList.modCount accessible: module java.base does not "opens java.util" to unnamed module @7c8d5312
|
|
548
|
+
'--add-opens=java.base/java.util=ALL-UNNAMED',
|
|
549
|
+
'--add-opens=java.base/java.lang=ALL-UNNAMED',
|
|
550
|
+
'--add-opens=java.base/java.lang.invoke=ALL-UNNAMED',
|
|
551
|
+
].join(' '),
|
|
552
|
+
};
|
|
553
|
+
return (0, zx_1.$)({ verbose: true, nothrow: options.nothrow, env }) `mvn ${args}`;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* A expected error that doesn't need a stack trace
|
|
558
|
+
*/
|
|
559
|
+
class SimpleError extends Error {
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Require an environment variable
|
|
563
|
+
*/
|
|
564
|
+
function envVar(name) {
|
|
565
|
+
const ret = process.env[name];
|
|
566
|
+
if (!ret) {
|
|
567
|
+
throw new SimpleError(`${name} is required`);
|
|
568
|
+
}
|
|
569
|
+
return ret;
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* A temporary directory that cleans when it goes out of scope
|
|
573
|
+
*
|
|
574
|
+
* Use with `using`. Could have been async but it's depending
|
|
575
|
+
* on an already-sync API, so why not sync?
|
|
576
|
+
*/
|
|
577
|
+
function autoCleanDir() {
|
|
578
|
+
const dir = (0, zx_1.tmpdir)();
|
|
579
|
+
return {
|
|
580
|
+
dir,
|
|
581
|
+
[Symbol.asyncDispose]: async () => {
|
|
582
|
+
await fs_1.promises.rm(dir, { force: true, recursive: true });
|
|
583
|
+
},
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
function assertNever(value) {
|
|
587
|
+
throw new Error('Unexpected value: ' + value);
|
|
588
|
+
}
|
|
589
|
+
// A 'zx' primer
|
|
590
|
+
//
|
|
591
|
+
// - By default: stderr is printed to the terminal if it is captured.
|
|
592
|
+
// - { verbose: true }: print the command, stdout and stderr to the terminal
|
|
593
|
+
// - { quiet: true }: print neither stdout nor stderr
|
|
594
|
+
//
|
|
595
|
+
// .text(): return everything that's captured (stderr and stdout together if stderr is captured)
|
|
596
|
+
main().catch(e => {
|
|
597
|
+
if (e instanceof zx_1.ProcessOutput) {
|
|
598
|
+
(0, zx_1.echo)(`❌ Subprocess failed with exit code ${e.exitCode}`);
|
|
599
|
+
}
|
|
600
|
+
else if (e instanceof SimpleError) {
|
|
601
|
+
(0, zx_1.echo)('❌', e.message);
|
|
602
|
+
}
|
|
603
|
+
else {
|
|
604
|
+
console.error(e);
|
|
605
|
+
}
|
|
606
|
+
process.exitCode = 1;
|
|
607
|
+
});
|
|
608
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGliLW1hdmVuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Jpbi9wdWJsaWItbWF2ZW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBeW5CQSxvQ0FRQztBQWpvQkQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5Qkc7QUFDSCwyQkFBb0M7QUFDcEMsMkJBQStFO0FBRS9FLE1BQU0sc0JBQXNCLEdBQUcsT0FBTyxDQUFDO0FBQ3ZDLE1BQU0sd0JBQXdCLEdBQUcsZUFBZSxDQUFDO0FBRWpELE1BQU0sMEJBQTBCLEdBQUcsdURBQXVELENBQUM7QUFFM0YsS0FBSyxVQUFVLElBQUk7SUFDakIsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbkMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLFdBQVcsQ0FBQztJQUV4QyxJQUFBLE9BQUUsRUFBQyxRQUFRLENBQUMsQ0FBQztJQUViLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBQSxTQUFJLEVBQUMsVUFBVSxDQUFDLENBQUM7SUFDcEMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3RCLE1BQU0sSUFBSSxXQUFXLENBQUMsaURBQWlELE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDMUYsQ0FBQztJQUVELElBQUEsU0FBSSxFQUFDLGVBQWUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUU1QixNQUFNLGFBQWEsR0FBeUI7UUFDMUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQztRQUNsQyxRQUFRLEVBQUUsTUFBTSxDQUFDLGdCQUFnQixDQUFDO1FBQ2xDLE1BQU0sRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVksS0FBSyxN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S0FDRixDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsV0FBVyxDQUFDLEtBQVk7SUFDL0IsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQkFBb0IsR0FBRyxLQUFLLENBQUMsQ0FBQztBQUNoRCxDQUFDO0FBRUQsZ0JBQWdCO0FBQ2hCLEVBQUU7QUFDRixxRUFBcUU7QUFDckUsNEVBQTRFO0FBQzVFLHFEQUFxRDtBQUNyRCxFQUFFO0FBQ0YsZ0dBQWdHO0FBRWhHLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtJQUNmLElBQUksQ0FBQyxZQUFZLGtCQUFhLEVBQUUsQ0FBQztRQUMvQixJQUFBLFNBQUksRUFBQyxzQ0FBc0MsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDM0QsQ0FBQztTQUFNLElBQUksQ0FBQyxZQUFZLFdBQVcsRUFBRSxDQUFDO1FBQ3BDLElBQUEsU0FBSSxFQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdkIsQ0FBQztTQUFNLENBQUM7UUFDTixPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ25CLENBQUM7SUFDRCxPQUFPLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQztBQUN2QixDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTGVnYWN5IHZzIGNvbXBhdGliaWxpdHkgZW5kcG9pbnRcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqXG4gKiBUaGlzIHNjcmlwdCB0YWxrcyBhYm91dCBsZWdhY3kgdnMgY29tcGF0aWJpbGl0eSBlbmRwb2ludCBhIGJ1bmNoLlxuICpcbiAqIEJvdGggaW1wbGVtZW50IHRoZSBOZXh1cyAyIHByb3RvY29sLCBob3dldmVyOlxuICpcbiAqIC0gVGhlIFwibGVnYWN5XCIgZW5kcG9pbnQgaXMgdGhlIFNvbmF0eXBlIE9TU1JIIGVuZHBvaW50IHRoYXQgd2FzIGRlcHJlY2F0ZWQgSnVuZSAyMDI1LlxuICogLSBUaGUgXCJjb21wYXRpYmlsaXR5XCIgZW5kcG9pbnQgaXMgYSBOZXh1cyAyLWNvbXBhdGlibGUgZW5kcG9pbnQgc3Rvb2QgdXAgZm9yIHRoZSBuZXdcbiAqICAgcHVibGlzaGluZyBzZXJ2aWNlLCBDZW50cmFsIFB1Ymxpc2hpbmcuXG4gKlxuICogSXQgc2hvdWxkIGJlIHRoZSBzYW1lIHByb3RvY29sIGJ1dCBvZiBjb3Vyc2UgdGhlcmUgYXJlIHN1YnRsZSBkaWZmZXJlbmNlc1xuICogYmV0d2VlbiB0aGVtIChpbiBob3cgdGhleSBzaWduYWwgZXJyb3Igd2hlbiB5b3UgdHJ5IHRvIHJlcHVibGlzaCBhbiBhbHJlYWR5XG4gKiBwdWJsaXNoZWQgdmVyc2lvbiwgYW5kIGV2ZW4gaW4gdGhlIHdpcmUgcHJvdG9jb2wgYWNjZXB0ZWQpIHNvIHdlIGhhdmUgdG9cbiAqIHRyZWF0IHRoZW0gZGlmZmVyZW50bHkgaGVyZS5cbiAqXG4gKiBUaGVyZSBpcyBhbHNvIGFuIFwib2ZmaWNpYWwgbmV3XCIgcHJvdG9jb2wgZm9yIHRoZSBuZXcgcHVibGlzaGluZyBtZWNoYW5pc20sXG4gKiBidXQgdGhlIE1hdmVuIHBsdWdpbiB0aGV5IHN1cHBseSBmb3IgdGhhdCBkb2Vzbid0IHN1cHBvcnQgdGhhdC4gSW4gdGhlaXIgd29yZHM6XG4gKlxuICogPiBpdCBhcHBlYXJzIHRoYXQgeW91IGFyZSB1c2luZyB0aGUgXCJ0d28gc3RhZ2VcIlsxXSBkZXBsb3ltZW50IHByb2Nlc3MsIHdoaWNoIGlzXG4gKiA+IG5vdCB5ZXQgc3VwcG9ydGVkIGJ5IHRoZSBuZXcgcGx1Z2luLiBZb3UgYXJlIHRoZSBmaXJzdCBwdWJsaXNoZXIgdG8gaGF2ZVxuICogPiByZXF1ZXN0ZWQgdGhpcywgc28gd2Ugd2VyZSBub3QgZmFtaWxpYXIgd2l0aCB0aGlzIHNwZWNpZmljIHVzZWNhc2Ugd2hlblxuICogPiBidWlsZGluZyB0aGUgbmV3IHBsdWdpblxuICogPiBbMV0gPGh0dHBzOi8vZ2l0aHViLmNvbS9zb25hdHlwZS9uZXh1cy1tYXZlbi1wbHVnaW5zL2Jsb2IvNDNhOTk0MGIxMzRjM2Y4N2ViZTRkYWE4MjU1MmU4NDRkOWM1NzhiOC9zdGFnaW5nL21hdmVuLXBsdWdpbi9XT1JLRkxPV1MubWQjdHdvLXNob3RzPlxuICovXG5pbXBvcnQgeyBwcm9taXNlcyBhcyBmcyB9IGZyb20gJ2ZzJztcbmltcG9ydCB7ICQsIGNkLCBlY2hvLCBnbG9iLCBvcywgcGF0aCwgUHJvY2Vzc091dHB1dCwgcXVvdGUsIHRtcGRpciB9IGZyb20gJ3p4JztcblxuY29uc3QgTEVHQUNZX09TU1JIX1NFUlZFUl9JRCA9ICdvc3NyaCc7XG5jb25zdCBDT01QQVRfQ0VOVFJBTF9TRVJWRVJfSUQgPSAnY2VudHJhbC1vc3NyaCc7XG5cbmNvbnN0IE5FWFVTX01BVkVOX1NUQUdJTkdfUExVR0lOID0gJ29yZy5zb25hdHlwZS5wbHVnaW5zOm5leHVzLXN0YWdpbmctbWF2ZW4tcGx1Z2luOjEuNy4wJztcblxuYXN5bmMgZnVuY3Rpb24gbWFpbigpIHtcbiAgY29uc3QgYXJncyA9IHByb2Nlc3MuYXJndi5zbGljZSgyKTtcbiAgY29uc3QgamF2YVJvb3QgPSBhcmdzWzBdID8/ICdkaXN0L2phdmEnO1xuXG4gIGNkKGphdmFSb290KTtcblxuICBjb25zdCBwb21zID0gYXdhaXQgZ2xvYignKiovKi5wb20nKTtcbiAgaWYgKHBvbXMubGVuZ3RoID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IFNpbXBsZUVycm9yKGBObyBKQVJTIHRvIHB1Ymxpc2g6IG5vIC5wb20gZmlsZXMgZm91bmQgdW5kZXIgJHtwcm9jZXNzLmN3ZCgpfWApO1xuICB9XG5cbiAgZWNobyhgUE9NcyBmb3VuZDogJHtwb21zfWApO1xuXG4gIGNvbnN0IHNoYXJlZE9wdGlvbnM6IFNoYXJlZFB1Ymxpc2hPcHRpb25zID0ge1xuICAgIHVzZXJuYW1lOiBlbnZWYXIoJ01BVkVOX1VTRVJOQU1FJyksXG4gICAgcGFzc3dvcmQ6IGVudlZhcignTUFWRU5fUEFTU1dPUkQnKSxcbiAgICBkcnlSdW46IHByb2Nlc3MuZW52Lk1BVkVOX0RSWVJVTiA9PT0gJ3RydWUnLFxuICAgIHZlcmJvc2U6IHByb2Nlc3MuZW52Lk1BVkVOX1ZFUkJPU0UgPT09ICd0cnVlJyxcbiAgICBwb21zLFxuICB9O1xuXG4gIGxldCBvcHRpb25zOiBNYXZlblB1Ymxpc2hPcHRpb25zO1xuICBjb25zdCBzZXJ2ZXJJZCA9IHByb2Nlc3MuZW52Lk1BVkVOX1NFUlZFUl9JRCA/PyBMRUdBQ1lfT1NTUkhfU0VSVkVSX0lEO1xuXG4gIHN3aXRjaCAoc2VydmVySWQpIHtcbiAgICBjYXNlIExFR0FDWV9PU1NSSF9TRVJWRVJfSUQ6XG4gICAgICBvcHRpb25zID0ge1xuICAgICAgICB0eXBlOiAnbGVnYWN5LW9zc3JoJyxcbiAgICAgICAgLi4uc2hhcmVkT3B0aW9ucyxcbiAgICAgICAgc3RhZ2luZ1Byb2ZpbGVJZDogZW52VmFyKCdNQVZFTl9TVEFHSU5HX1BST0ZJTEVfSUQnKSxcbiAgICAgICAgZW5kcG9pbnQ6IHByb2Nlc3MuZW52Lk1BVkVOX0VORFBPSU5ULFxuICAgICAgICBwcml2YXRlS2V5OiBwYXJzZVByaXZhdGVLZXlGcm9tRW52KCksXG4gICAgICB9O1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBDT01QQVRfQ0VOVFJBTF9TRVJWRVJfSUQ6XG4gICAgICBvcHRpb25zID0ge1xuICAgICAgICB0eXBlOiAnY29tcGF0LW9zc3JoJyxcbiAgICAgICAgLi4uc2hhcmVkT3B0aW9ucyxcbiAgICAgICAgc3RhZ2luZ1Byb2ZpbGVJZDogZW52VmFyKCdNQVZFTl9TVEFHSU5HX1BST0ZJTEVfSUQnKSxcbiAgICAgICAgZW5kcG9pbnQ6IHByb2Nlc3MuZW52Lk1BVkVOX0VORFBPSU5ULFxuICAgICAgICBwcml2YXRlS2V5OiBwYXJzZVByaXZhdGVLZXlGcm9tRW52KCksXG4gICAgICB9O1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIC8vIFdlIGhhdmVuJ3QgaW1wbGVtZW50ZWQgc2lnbmluZyBmb3IgdGhpcywgc28gZmFpbCBsb3VkbHkgaWYgcGVvcGxlIHRyeSB0byB1c2UgaXQgYW55d2F5XG4gICAgICBpZiAocHJvY2Vzcy5lbnYuTUFWRU5fR1BHX1BSSVZBVEVfS0VZIHx8IHByb2Nlc3MuZW52Lk1BVkVOX0dQR19QUklWQVRFX0tFWV9GSUxFKSB7XG4gICAgICAgIHRocm93IG5ldyBTaW1wbGVFcnJvcignTUFWRU5fR1BHX1BSSVZBVEVfS0VZW19GSUxFXSBpcyBvbmx5IHN1cHBvcnRlZCBmb3IgT1NTUkggcHVibGlzaGluZycpO1xuICAgICAgfVxuXG4gICAgICBvcHRpb25zID0ge1xuICAgICAgICB0eXBlOiAnY3VzdG9tLW5leHVzJyxcbiAgICAgICAgLi4uc2hhcmVkT3B0aW9ucyxcbiAgICAgICAgc2VydmVySWQsXG4gICAgICAgIHJlcG9zaXRvcnlVcmw6IGVudlZhcignTUFWRU5fUkVQT1NJVE9SWV9VUkwnKSxcbiAgICAgIH07XG4gICAgICBicmVhaztcbiAgfVxuXG4gIGF3YWl0IG1hdmVuUHVibGlzaChvcHRpb25zKTtcblxuICBlY2hvKCd+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+Jyk7XG4gIGVjaG8oJ+KchSBBbGwgRG9uZSEnKTtcbn1cblxuZnVuY3Rpb24gcGFyc2VQcml2YXRlS2V5RnJvbUVudigpOiBQcml2YXRlS2V5IHtcbiAgaWYgKHByb2Nlc3MuZW52Lk1BVkVOX0dQR19QUklWQVRFX0tFWV9GSUxFKSB7XG4gICAgcmV0dXJuIHsgdHlwZTogJ2ZpbGUnLCBmaWxlTmFtZTogcHJvY2Vzcy5lbnYuTUFWRU5fR1BHX1BSSVZBVEVfS0VZX0ZJTEUsIHBhc3NQaHJhc2U6IGVudlZhcignTUFWRU5fR1BHX1BSSVZBVEVfS0VZX1BBU1NQSFJBU0UnKSB9O1xuICB9XG4gIGlmIChwcm9jZXNzLmVudi5NQVZFTl9HUEdfUFJJVkFURV9LRVkpIHtcbiAgICByZXR1cm4geyB0eXBlOiAnbWF0ZXJpYWwnLCBrZXlNYXRlcmlhbDogcHJvY2Vzcy5lbnYuTUFWRU5fR1BHX1BSSVZBVEVfS0VZLCBwYXNzUGhyYXNlOiBlbnZWYXIoJ01BVkVOX0dQR19QUklWQVRFX0tFWV9QQVNTUEhSQVNFJykgfTtcbiAgfVxuICB0aHJvdyBuZXcgU2ltcGxlRXJyb3IoJ01BVkVOX0dQR19QUklWQVRFX0tFWVtfRklMRV0gaXMgcmVxdWlyZWQnKTtcbn1cblxuLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyAgTW9kZWxpbmcgYWxsIHRoZSBwYXJhbWV0ZXJzIHNvIHRoYXQgd2UgY2FuIHB1bGwgdGhlIGVudmlyb25tZW50IHBhcnNpbmcgZm9yd2FyZFxuLy9cblxuaW50ZXJmYWNlIFNoYXJlZFB1Ymxpc2hPcHRpb25zIHtcbiAgcmVhZG9ubHkgdXNlcm5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgcGFzc3dvcmQ6IHN0cmluZztcbiAgcmVhZG9ubHkgZHJ5UnVuOiBib29sZWFuO1xuICByZWFkb25seSB2ZXJib3NlOiBib29sZWFuO1xuICByZWFkb25seSBwb21zOiBzdHJpbmdbXTtcbn1cblxuaW50ZXJmYWNlIExlZ2FjeU9zc3JoUHVibGlzaE9wdGlvbnMgZXh0ZW5kcyBTaGFyZWRQdWJsaXNoT3B0aW9ucyB7XG4gIHR5cGU6ICdsZWdhY3ktb3NzcmgnO1xuICByZWFkb25seSBwcml2YXRlS2V5OiBQcml2YXRlS2V5O1xuICByZWFkb25seSBlbmRwb2ludD86IHN0cmluZztcbiAgcmVhZG9ubHkgc3RhZ2luZ1Byb2ZpbGVJZDogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgQ29tcGF0T3NzcmhQdWJsaXNoT3B0aW9ucyBleHRlbmRzIFNoYXJlZFB1Ymxpc2hPcHRpb25zIHtcbiAgdHlwZTogJ2NvbXBhdC1vc3NyaCc7XG4gIHJlYWRvbmx5IHByaXZhdGVLZXk6IFByaXZhdGVLZXk7XG4gIHJlYWRvbmx5IGVuZHBvaW50Pzogc3RyaW5nO1xuICByZWFkb25seSBzdGFnaW5nUHJvZmlsZUlkOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBDdXN0b21OZXh1c1B1Ymxpc2hPcHRpb25zIGV4dGVuZHMgU2hhcmVkUHVibGlzaE9wdGlvbnMge1xuICB0eXBlOiAnY3VzdG9tLW5leHVzJztcbiAgcmVhZG9ubHkgcmVwb3NpdG9yeVVybDogc3RyaW5nO1xuICByZWFkb25seSBzZXJ2ZXJJZDogc3RyaW5nO1xufVxuXG50eXBlIFByaXZhdGVLZXkgPVxuICB8IHsgdHlwZTogJ2ZpbGUnOyBmaWxlTmFtZTogc3RyaW5nOyBwYXNzUGhyYXNlOiBzdHJpbmcgfVxuICB8IHsgdHlwZTogJ21hdGVyaWFsJzsga2V5TWF0ZXJpYWw6IHN0cmluZzsgcGFzc1BocmFzZTogc3RyaW5nIH1cbiAgO1xuXG50eXBlIE1hdmVuUHVibGlzaE9wdGlvbnMgPSBMZWdhY3lPc3NyaFB1Ymxpc2hPcHRpb25zIHwgQ29tcGF0T3NzcmhQdWJsaXNoT3B0aW9uc3wgQ3VzdG9tTmV4dXNQdWJsaXNoT3B0aW9ucztcblxuLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyAgUHVibGlzaGluZyBmdW5jdGlvbnNcbi8vXG5cbmFzeW5jIGZ1bmN0aW9uIG1hdmVuUHVibGlzaChvcHRpb25zOiBNYXZlblB1Ymxpc2hPcHRpb25zKSB7XG4gIGF3YWl0IHVzaW5nIHdvcmtEaXIgPSBhdXRvQ2xlYW5EaXIoKTtcbiAgY29uc3QgbWF2ZW4gPSBuZXcgTWF2ZW4od29ya0Rpci5kaXIsIG9wdGlvbnMudmVyYm9zZSwgb3B0aW9ucy5kcnlSdW4pO1xuXG4gIGNvbnN0IHggPSBvcHRpb25zLnR5cGU7XG4gIHN3aXRjaCAoeCkge1xuICAgIGNhc2UgJ2xlZ2FjeS1vc3NyaCc6XG4gICAgICBhd2FpdCBkZXBsb3lMZWdhY3lPc3NyaChtYXZlbiwgb3B0aW9ucyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdjb21wYXQtb3NzcmgnOlxuICAgICAgYXdhaXQgZGVwbG95Q29tcGF0T3NzcmgobWF2ZW4sIG9wdGlvbnMpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnY3VzdG9tLW5leHVzJzpcbiAgICAgIGF3YWl0IGRlcGxveUN1c3RvbU5leHVzKG1hdmVuLCBvcHRpb25zKTtcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICBhc3NlcnROZXZlcih4KTtcbiAgfVxufVxuXG4vKipcbiAqIERlcGxveSB0byB0aGUgbGVnYWN5IE9TU1JIIE5leHVzIHNlcnZlclxuICovXG5hc3luYyBmdW5jdGlvbiBkZXBsb3lMZWdhY3lPc3NyaChtYXZlbjogTWF2ZW4sIG9wdGlvbnM6IExlZ2FjeU9zc3JoUHVibGlzaE9wdGlvbnMpIHtcbiAgZWNobygn8J+TpiBQdWJsaXNoaW5nIHRvIE1hdmVuIENlbnRyYWwnKTtcbiAgY29uc3QgZGVmYXVsdEVuZHBvaW50ID0gJ2h0dHBzOi8vb3NzLnNvbmF0eXBlLm9yZyc7XG5cbiAgY29uc3Qgc3RhZ2VkID0gYXdhaXQgZGVwbG95U3RhZ2VkUmVwb3NpdG9yeShtYXZlbiwge1xuICAgIC4uLm9wdGlvbnMsXG4gICAgZW5kcG9pbnQ6IG9wdGlvbnMuZW5kcG9pbnQgPz8gZGVmYXVsdEVuZHBvaW50LFxuICAgIHJlcHVibGlzaFdpbGw0MDA6IGZhbHNlLFxuICB9KTtcblxuICBpZiAoc3RhZ2VkLnR5cGUgIT09ICdzdWNjZXNzJykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8qXG4gIGNvbnN0IHJlbGVhc2VkID0gYXdhaXQgcmVsZWFzZVJlcG8oe1xuICAgIHNlcnZlclVybDogb3B0aW9ucy5lbmRwb2ludCA/PyBkZWZhdWx0RW5kcG9pbnQsXG4gICAgdXNlcm5hbWU6IG9wdGlvbnMudXNlcm5hbWUsXG4gICAgcGFzc3dvcmQ6IG9wdGlvbnMucGFzc3dvcmQsXG4gICAgcmVwb3NpdG9yeUlkOiBzdGFnZWQucmVwb3NpdG9yeUlkLFxuICB9KTtcblxuICBpZiAocmVsZWFzZWQpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgKi9cblxuICAvLyBTZW5kIGEgcmVtb3RlIHJlbGVhc2UgY29tbWFuZCB0byB0aGUgcmVwb3NpdG9yeVxuICBjb25zdCByZWxlYXNlT3V0cHV0ID0gYXdhaXQgbWF2ZW4uZXhlYyhgJHtORVhVU19NQVZFTl9TVEFHSU5HX1BMVUdJTn06cmMtcmVsZWFzZWAsIHtcbiAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICBuZXh1c1VybDogb3B0aW9ucy5lbmRwb2ludCA/PyBkZWZhdWx0RW5kcG9pbnQsXG4gICAgICBzZXJ2ZXJJZDogc3RhZ2VkLnNlcnZlcklkLFxuICAgICAgc3RhZ2luZ1JlcG9zaXRvcnlJZDogc3RhZ2VkLnJlcG9zaXRvcnlJZCxcbiAgICB9LFxuICAgIG5vdGhyb3c6IHRydWUsXG4gIH0pO1xuICBpZiAoIXJlbGVhc2VPdXRwdXQpIHtcbiAgICBlY2hvKCfwn4+c77iPIFN0b3BwZWQgaGVyZSBiZWNhdXNlIG9mIGRyeS1ydW4nKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAocmVsZWFzZU91dHB1dC5leGl0Q29kZSAhPT0gMCkge1xuICAgIC8vIElmIHJlbGVhc2UgZmFpbGVkLCBjaGVjayBpZiB0aGlzIHdhcyBjYXVzZWQgYmVjYXVzZSB3ZSBhcmUgdHJ5aW5nIHRvIHB1Ymxpc2hcbiAgICAvLyB0aGUgc2FtZSB2ZXJzaW9uIGFnYWluLCB3aGljaCBpcyBub3QgYW4gZXJyb3IuIFRoZSBtYWdpYyBzdHJpbmcgXCJkb2VzIG5vdFxuICAgIC8vIGFsbG93IHVwZGF0aW5nIGFydGlmYWN0XCIgZm9yIGEgXCIucG9tXCIgZmlsZSBpbmRpY2F0ZXMgdGhhdCB3ZSBhcmUgdHJ5aW5nIHRvXG4gICAgLy8gb3ZlcnJpZGUgYW4gZXhpc3RpbmcgdmVyc2lvbi4gT3RoZXJ3aXNlLCBmYWlsIVxuXG4gICAgY29uc3QgbG9va3NMaWtlRHVwbGljYXRlUHVibGlzaCA9IHJlbGVhc2VPdXRwdXQubGluZXMoKVxuICAgICAgLmZpbHRlcihsID0+IGwuaW5jbHVkZXMoJ2RvZXMgbm90IGFsbG93IHVwZGF0aW5nIGFydGlmYWN0JykpXG4gICAgICAuZmlsdGVyKGwgPT4gbC5pbmNsdWRlcygnLnBvbScpKVxuICAgICAgLmxlbmd0aCA+IDA7XG5cbiAgICBpZiAoIWxvb2tzTGlrZUR1cGxpY2F0ZVB1Ymxpc2gpIHtcbiAgICAgIHRocm93IG5ldyBTaW1wbGVFcnJvcignUmVsZWFzZSBmYWlsZWQnKTtcbiAgICB9XG5cbiAgICBlY2hvKCfimqDvuI8gQXJ0aWZhY3QgYWxyZWFkeSBwdWJsaXNoZWQuIFNraXBwaW5nJyk7XG4gIH1cbn1cblxuLyoqXG4gKiBEZXBsb3kgdG8gdGhlIGNvbXBhdCBPU1NSSCBOZXh1cyBzZXJ2ZXJcbiAqL1xuYXN5bmMgZnVuY3Rpb24gZGVwbG95Q29tcGF0T3NzcmgobWF2ZW46IE1hdmVuLCBvcHRpb25zOiBDb21wYXRPc3NyaFB1Ymxpc2hPcHRpb25zKSB7XG4gIGVjaG8oJ/Cfk6YgUHVibGlzaGluZyB0byBNYXZlbiBDZW50cmFsIChDb21wYXQgZW5kcG9pbnQpJyk7XG5cbiAgY29uc3QgZGVmYXVsdEVuZHBvaW50ID0gJ2h0dHBzOi8vb3Nzcmgtc3RhZ2luZy1hcGkuY2VudHJhbC5zb25hdHlwZS5jb20vJztcbiAgY29uc3QgZW5kcG9pbnQgPSBvcHRpb25zLmVuZHBvaW50ID8/IGRlZmF1bHRFbmRwb2ludDtcblxuICBjb25zdCBzdGFnZWQgPSBhd2FpdCBkZXBsb3lTdGFnZWRSZXBvc2l0b3J5KG1hdmVuLCB7XG4gICAgLi4ub3B0aW9ucyxcbiAgICBlbmRwb2ludCxcbiAgICByZXB1Ymxpc2hXaWxsNDAwOiB0cnVlLFxuICB9KTtcblxuICBpZiAoc3RhZ2VkLnR5cGUgIT09ICdzdWNjZXNzJykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHJlbGVhc2VkID0gYXdhaXQgcmVsZWFzZVJlcG8oe1xuICAgIHNlcnZlclVybDogZW5kcG9pbnQsXG4gICAgdXNlcm5hbWU6IG9wdGlvbnMudXNlcm5hbWUsXG4gICAgcGFzc3dvcmQ6IG9wdGlvbnMucGFzc3dvcmQsXG4gICAgcmVwb3NpdG9yeUlkOiBzdGFnZWQucmVwb3NpdG9yeUlkLFxuICB9KTtcblxuICBpZiAocmVsZWFzZWQgPT09ICdkdXBsaWNhdGUtdmVyc2lvbicpIHtcbiAgICBlY2hvKCfimqDvuI8gVmVyc2lvbihzKSBhbHJlYWR5IHB1Ymxpc2hlZC4gU2tpcHBpbmcnKTtcbiAgfVxufVxuXG4vKipcbiAqIERlcGxveSB0byBhIGN1c3RvbSBOZXh1cyBzZXJ2ZXJcbiAqL1xuYXN5bmMgZnVuY3Rpb24gZGVwbG95Q3VzdG9tTmV4dXMobWF2ZW46IE1hdmVuLCBvcHRpb25zOiBDdXN0b21OZXh1c1B1Ymxpc2hPcHRpb25zKSB7XG4gIGVjaG8oYPCfk6YgUHVibGlzaGluZyB0byAke29wdGlvbnMuc2VydmVySWR9YCk7XG4gIGF3YWl0IG1hdmVuLndyaXRlU2V0dGluZ3NGaWxlKG9wdGlvbnMuc2VydmVySWQsIGZhbHNlKTtcblxuICBmb3IgKGNvbnN0IHBvbSBvZiBvcHRpb25zLnBvbXMpIHtcbiAgICBjb25zdCBkZXBsb3lPdXRwdXQgPSBhd2FpdCBtYXZlbi5leGVjKCdkZXBsb3k6ZGVwbG95LWZpbGUnLCB7XG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIHVybDogb3B0aW9ucy5yZXBvc2l0b3J5VXJsLFxuICAgICAgICByZXBvc2l0b3J5SWQ6IG9wdGlvbnMuc2VydmVySWQsXG4gICAgICAgIHBvbUZpbGU6IHBvbSxcbiAgICAgICAgLi4uamFyc0Zyb21Qb20ocG9tKSxcbiAgICAgIH0sXG4gICAgICBub3Rocm93OiB0cnVlLFxuICAgIH0pO1xuXG4gICAgaWYgKGRlcGxveU91dHB1dD8uZXhpdENvZGUgJiYgZGVwbG95T3V0cHV0LmV4aXRDb2RlID4gMCkge1xuICAgICAgaWYgKGRlcGxveU91dHB1dC5zdGRvdXQuaW5jbHVkZXMoJzQwOSBDb25mbGljdCcpKSB7XG4gICAgICAgIGVjaG8oJ+KaoO+4jyBBcnRpZmFjdCBhbHJlYWR5IHB1Ymxpc2hlZC4gU2tpcHBpbmcnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBTaW1wbGVFcnJvcignUmVsZWFzZSBmYWlsZWQnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxudHlwZSBEZXBsb3lTdGFnZWRSZXBvUmVzdWx0ID1cbiAgfCB7IHR5cGU6ICdzdWNjZXNzJzsgcmVwb3NpdG9yeUlkOiBzdHJpbmc7IHNlcnZlcklkOiBzdHJpbmcgfVxuICB8IHsgdHlwZTogJ2FscmVhZHktcHVibGlzaGVkJyB9XG4gIHwgeyB0eXBlOiAnZHJ5LXJ1bicgfTtcblxuLyoqXG4gKiBDcmVhdGUgdGhlIHN0YWdpbmcgcmVwb3NpdG9yeS4gVGhpcyBpcyB0aGUgc2FtZSBiZXR3ZWVuIHRoZSBsZWdhY3kgYW5kIGNvbXBhdCBlbmRwb2ludHMuXG4gKlxuICogYHJlcHVibGlzaFdpbGw0MDBgOiBpbiB0aGUgY29tcGF0aWJpbGl0eSBlbmRwb2ludCwgc3RhZ2luZyBhIHZlcnNpb24gdGhhdCBoYXMgYWxyZWFkeVxuICogYmVlbiBwdWJsaXNoZWQgd2lsbCBsZWFkIHRvIGEgYDQwMCBCYWQgUmVxdWVzdGAsIHdpdGggbm8gZnVydGhlciBpbmZvLiBXZSBuZWVkZWQgdG8gaGF2ZVxuICogcnVuIHRoZSBNYXZlbiBjb21tYW5kIHdpdGggYC0tZGVidWdgIGxvZ2dpbmcgdG8gc2VlIHRoZSBhY3R1YWwgZXJyb3IgbWVzc2FnZSBpbiB0aGUgb3V0cHV0LlxuICpcbiAqIEluIHRoZSBsZWdhY3kgZW5kcG9pbnQsIHN0YWdpbmcgdGFrZXMgbXVsdGlwbGUgbWludXRlcywgYW5kIE1hdmVuIHdpbGwgcG9sbFxuICogZXZlcnkgM3MgYW5kIHByaW50IHRoZSBvdXRwdXQuIFdlIHRoZXJlZm9yZSBkb24ndCB1c2UgdmVyYm9zZSBtb2RlIHRvIGF2b2lkXG4gKiBzdGRvdXQgc3BhbS4gSW4gdGhlIGxlZ2FjeSBlbmRwb2ludCwgZHVwbGljYXRlIHZlcnNpb24gcHVibGlzaGluZyBnZXRzXG4gKiByZXBvcnRlZCBkdXJpbmcgdGhlICdyZWxlYXNlJyBzdGVwIGFueXdheSwgbm90IGR1cmluZyBzdGFnaW5nLlxuICovXG5hc3luYyBmdW5jdGlvbiBkZXBsb3lTdGFnZWRSZXBvc2l0b3J5KG1hdmVuOiBNYXZlbiwgb3B0aW9uczogT21pdDxMZWdhY3lPc3NyaFB1Ymxpc2hPcHRpb25zIHwgQ29tcGF0T3NzcmhQdWJsaXNoT3B0aW9ucywgJ2VuZHBvaW50Jz4gJiB7IGVuZHBvaW50OiBzdHJpbmc7IHJlcHVibGlzaFdpbGw0MDA6IGJvb2xlYW4gfSk6IFByb21pc2U8RGVwbG95U3RhZ2VkUmVwb1Jlc3VsdD4ge1xuICBjb25zdCBzZXJ2ZXJJZCA9ICdvc3NyaCc7XG5cbiAgYXdhaXQgbWF2ZW4ud3JpdGVTZXR0aW5nc0ZpbGUoc2VydmVySWQsIHRydWUpO1xuXG4gIC8vIEZpcnN0IC0tIHNpZ24gYXJ0aWZhY3RzXG4gIGNvbnN0IHNpZ25lZERpciA9IHBhdGguam9pbihtYXZlbi53b3JrRGlyLCAnc2lnbmVkJyk7XG4gIGF3YWl0IGZzLm1rZGlyKHNpZ25lZERpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgYXdhaXQgc2lnbkphcnMobWF2ZW4sIG9wdGlvbnMucG9tcywgc2lnbmVkRGlyLCBzZXJ2ZXJJZCwgb3B0aW9ucy5wcml2YXRlS2V5KTtcblxuICBlY2hvKCd+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+Jyk7XG4gIGVjaG8oJyBEZXBsb3lpbmcgYW5kIGNsb3NpbmcgcmVwb3NpdG9yeS4uLicpO1xuICBlY2hvKCd+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+Jyk7XG5cbiAgY29uc3QgbmV4dXNNYXZlblN0YWdpbmcgPSAnb3JnLnNvbmF0eXBlLnBsdWdpbnM6bmV4dXMtc3RhZ2luZy1tYXZlbi1wbHVnaW46MS43LjAnO1xuICBjb25zdCBzdGFnZU91dHB1dCA9IGF3YWl0IG1hdmVuLmV4ZWMoYCR7bmV4dXNNYXZlblN0YWdpbmd9OmRlcGxveS1zdGFnZWQtcmVwb3NpdG9yeWAsIHtcbiAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICByZXBvc2l0b3J5RGlyZWN0b3J5OiBzaWduZWREaXIsXG4gICAgICBuZXh1c1VybDogb3B0aW9ucy5lbmRwb2ludCxcbiAgICAgIHNlcnZlcklkLFxuICAgICAgc3RhZ2luZ1Byb2dyZXNzVGltZW91dE1pbnV0ZXM6ICczMCcsXG4gICAgICBzdGFnaW5nUHJvZmlsZUlkOiBvcHRpb25zLnN0YWdpbmdQcm9maWxlSWQsXG4gICAgfSxcbiAgICBub3Rocm93OiB0cnVlLFxuICAgIHZlcmJvc2U6IG9wdGlvbnMucmVwdWJsaXNoV2lsbDQwMCxcbiAgfSk7XG4gIC8vIEZJWE1FOiBOZXcgc3RhZ2luZyBBUEkgdGhyb3dzIGFuIGVycm9yIGhlcmUgb24gZHVwbGljYXRlIHZlcnNpb25zXG4gIGlmIChzdGFnZU91dHB1dCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgZWNobygn8J+PnO+4jyBTdG9wcGVkIGhlcmUgYmVjYXVzZSBvZiBkcnktcnVuJyk7XG4gICAgcmV0dXJuIHsgdHlwZTogJ2RyeS1ydW4nIH07XG4gIH1cblxuICBpZiAob3B0aW9ucy5yZXB1Ymxpc2hXaWxsNDAwICYmIHN0YWdlT3V0cHV0LnRleHQoKS5tYXRjaCgvQ29tcG9uZW50IHdpdGggcGFja2FnZSB1cmwuKmFscmVhZHkgZXhpc3RzLykpIHtcbiAgICAvLyBXZSd2ZSBzZWVuIHRoaXMgZmFpbCB3aXRoIHRoZSBhYm92ZSBlcnJvciBtZXNzYWdlIG9uIHRoZSBPU1NSSCBjb21wYXRpYmlsaXR5IEFQSSB3aGVuIHRyeWluZyB0byByZXB1Ymxpc2hcbiAgICAvLyBhbiBhbHJlYWR5LXB1Ymxpc2hlZCB2ZXJzaW9uLlxuICAgIC8vXG4gICAgLy8gVGhpcyBpcyBwb3RlbnRpYWxseSBhIHByb2JsZW0gaWYgdGhlcmUgYXJlIG11bHRpcGxlIHZlcnNpb25zIGluIHRoZSBzb3VyY2UgZGlyZWN0b3J5IGF0IG9uY2UsIGJlY2F1c2Ugbm90aGluZ1xuICAgIC8vIHdpbGwgYmUgcHVibGlzaGVkIGlmIHRoZXJlJ3Mgb25lIHBhY2thZ2UgaW4gdGhlcmUgdGhhdCBoYXMgYWxyZWFkeSBiZWVuIHB1Ymxpc2hlZCBwcmV2aW91c2x5LiBCdXQgYydlc3QgbGEgdmllLlxuICAgIGVjaG8oJ+KaoO+4jyBWZXJzaW9uKHMpIGFscmVhZHkgcHVibGlzaGVkLiBTa2lwcGluZycpO1xuICAgIHJldHVybiB7IHR5cGU6ICdhbHJlYWR5LXB1Ymxpc2hlZCcgfTtcbiAgfSBlbHNlIGlmIChzdGFnZU91dHB1dC5leGl0Q29kZSAmJiBzdGFnZU91dHB1dC5leGl0Q29kZSA+IDApIHtcbiAgICB0aHJvdyBzdGFnZU91dHB1dDtcbiAgfVxuXG4gIC8vIEdyZXAgdGhlIHJlcG9zaXRvcnkgSUQgb3V0IG9mIHRoZSBwcmludGVkIG91dHB1dFxuICAvLyBbSU5GT10gICogQ2xvc2luZyBzdGFnaW5nIHJlcG9zaXRvcnkgd2l0aCBJRCBcIlhYWFhYWFhYWFhcIi5cbiAgY29uc3QgbSA9IHN0YWdlT3V0cHV0LnN0ZG91dC5tYXRjaCgvQ2xvc2luZyBzdGFnaW5nIHJlcG9zaXRvcnkgd2l0aCBJRCBcIihbXlwiXSspXCIvKTtcbiAgaWYgKCFtKSB7XG4gICAgdGhyb3cgbmV3IFNpbXBsZUVycm9yKCdVbmFibGUgdG8gZXh0cmFjdCByZXBvc2l0b3J5IElEIGZyb20gZGVwbG95LXN0YWdlZC1yZXBvc2l0b3J5IG91dHB1dC4gVGhpcyBtZWFucyBpdCBmYWlsZWQgdG8gY2xvc2Ugb3IgdGhlcmUgd2FzIGFuIHVuZXhwZWN0ZWQgcHJvYmxlbS4gQXQgYW55IHJhdGUsIHdlIGNhblxcJ3QgcmVsZWFzZSBpdC4gU29ycnkuJyk7XG4gIH1cbiAgY29uc3QgcmVwb3NpdG9yeUlkID0gbVsxXTtcblxuICByZXR1cm4geyB0eXBlOiAnc3VjY2VzcycsIHJlcG9zaXRvcnlJZCwgc2VydmVySWQgfTtcbn1cblxuLyoqXG4gKiBTZW5kIGEgY3VzdG9tIFwicmVsZWFzZVwiIGNvbW1hbmQgdG8gdGhlIG5ldyBTb25hdHlwZSBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSBlbmRwb2ludFxuICpcbiAqIFdoZW4gdXNpbmcgdGhlIGBuZXh1cy1zdGFnaW5nLW1hdmVuLXBsdWdpbmAncyBgcmVsZWFzZWAgb3IgYHJjLXJlbGVhc2VgIGNvbW1hbmRzLCB3ZSBnZXQgdGhlIGZvbGxvd2luZ1xuICogZXJyb3I6XG4gKlxuICogU2VuZGluZzpcbiAqXG4gKiBgYGBcbiAqIDxzdGFnaW5nQWN0aW9uUmVxdWVzdD48ZGF0YT48c3RhZ2VkUmVwb3NpdG9yeUlkcyBjbGFzcz1cImphdmEudXRpbC5BcnJheXMkQXJyYXlMaXN0XCI+PGEgY2xhc3M9XCJzdHJpbmctYXJyYXlcIj48c3RyaW5nPmlvLmdpdGh1Yi5yaXgwcnJyLS02M2VkYmNiZS1mMDU4LTQ0ZWItODVmNC1mZDlkY2UxYWVmNDA8L3N0cmluZz48L2E+PC9zdGFnZWRSZXBvc2l0b3J5SWRzPjxkZXNjcmlwdGlvbj51bmtub3duPC9kZXNjcmlwdGlvbj48YXV0b0Ryb3BBZnRlclJlbGVhc2U+dHJ1ZTwvYXV0b0Ryb3BBZnRlclJlbGVhc2U+PC9kYXRhPjwvc3RhZ2luZ0FjdGlvblJlcXVlc3Q+XG4gKiBgYGBcbiAqXG4gKiBFcnJvcjpcbiAqXG4gKiBgYGBcbiAqIEZhaWxlZCB0byBwcm9jZXNzIHJlcXVlc3Q6IEdvdCB1bmV4cGVjdGVkIFhNTCBlbGVtZW50IHdoZW4gcmVhZGluZyBzdGFnZWRSZXBvc2l0b3J5SWRzOiBHb3QgdW5leHBlY3RlZCBlbGVtZW50IFN0YXJ0RWxlbWVudChhLCB7XCJcIjogXCJcIiwgXCJ4bWxcIjogXCJodHRwOi8vd3d3LnczLm9yZy9YTUwvMTk5OC9uYW1lc3BhY2VcIiwgXCJ4bWxuc1wiOiBcImh0dHA6Ly93d3cudzMub3JnLzIwMDAveG1sbnMvXCJ9LCBbY2xhc3MgLT4gc3RyaW5nLWFycmF5XSksIGV4cGVjdGVkIG9uZSBvZjogc3RyaW5nXG4gKiBgYGBcbiAqXG4gKiBEb2luZyBhIG1hbnVhbCBzbGlnaHRseSBtb2RpZmllZCB2ZXJzaW9uIG9mIHRoZSBhYm92ZSByZXF1ZXN0IHN1Y2NlZWRzLCBzbyB3ZSdsbCBqdXN0IHByb2NlZWQgd2l0aCBkb2luZ1xuICogdGhhdC5cbiAqXG4gKiBUaGUgZW5kcG9pbnQgYWxzbyBzdXBwb3J0cyBKU09OLCB3aGljaCB3ZSBwcmVmZXIgb3ZlciBYTUwuXG4gKlxuICogVGhpcyBlbmRwb2ludCB3aWxsIG5ldmVyIHJldHVybiBhbiBlcnJvciwgZXZlbiBpZiB0aGUgcHVibGlzaCBkaWRuJ3QgaGFwcGVuIGJlY2F1c2VcbiAqIG9mIGR1cGxpY2F0ZSB2ZXJzaW9uIHB1Ymxpc2hpbmcgKG5vdCBmb3IgdGhlIGxlZ2FjeSwgbm9yIGZvciB0aGUgY29tcGF0aWJpbGl0eSBlbmRwb2ludCkuXG4gKlxuICogQHNlZSBodHRwczovL2NlbnRyYWwuc29uYXR5cGUub3JnL3B1Ymxpc2gvcHVibGlzaC1wb3J0YWwtb3Nzcmgtc3RhZ2luZy1hcGkvXG4gKiBAc2VlIGh0dHBzOi8vc3VwcG9ydC5zb25hdHlwZS5jb20vaGMvZW4tdXMvYXJ0aWNsZXMvMjEzNDY1NDQ4LUF1dG9tYXRpY2FsbHktZHJvcHBpbmctb2xkLXN0YWdpbmctcmVwb3NpdG9yaWVzXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlbGVhc2VSZXBvKG9wdGlvbnM6IHsgc2VydmVyVXJsOiBzdHJpbmc7IHVzZXJuYW1lOiBzdHJpbmc7IHBhc3N3b3JkOiBzdHJpbmc7IHJlcG9zaXRvcnlJZDogc3RyaW5nOyBkZXNjcmlwdGlvbj86IHN0cmluZyB9KTogUHJvbWlzZTwnb2snIHwgJ2R1cGxpY2F0ZS12ZXJzaW9uJz4ge1xuICBlY2hvKGDwn5qAIFJlbGVhc2luZyByZXBvc2l0b3J5ICR7b3B0aW9ucy5yZXBvc2l0b3J5SWR9IGF0ICR7b3B0aW9ucy5zZXJ2ZXJVcmx9YCk7XG4gIGNvbnN0IHVybCA9IG5ldyBVUkwoJ3NlcnZpY2UvbG9jYWwvc3RhZ2luZy9idWxrL3Byb21vdGUnLCBvcHRpb25zLnNlcnZlclVybCk7XG5cbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh1cmwsIHtcbiAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICBkYXRhOiB7XG4gICAgICAgIHN0YWdlZFJlcG9zaXRvcnlJZHM6IFtvcHRpb25zLnJlcG9zaXRvcnlJZF0sXG4gICAgICAgIGRlc2NyaXB0aW9uOiBvcHRpb25zLmRlc2NyaXB0aW9uID8/ICdEZXBsb3ltZW50JyxcbiAgICAgICAgYXV0b0Ryb3BBZnRlclJlbGVhc2U6IHRydWUsXG4gICAgICB9LFxuICAgIH0pLFxuICAgIGhlYWRlcnM6IHtcbiAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAnQWNjZXB0JzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgJ0F1dGhvcml6YXRpb24nOiBgQmFzaWMgJHtidG9hKGAke29wdGlvbnMudXNlcm5hbWV9OiR7b3B0aW9ucy5wYXNzd29yZH1gKX1gLFxuICAgIH0sXG4gIH0pO1xuXG4gIGNvbnN0IGJvZHkgPSBhd2FpdCByZXNwb25zZS50ZXh0KCk7XG5cbiAgLy8gSXQncyBwb3NzaWJsZSB0aGF0IChkdWUgdG8gc29tZSByZXBsaWNhdGlvbiBsYXRlbmN5PykgdGhlIGluaXRpYWwgXCJzdGFnZVwiIHN1Y2NlZWRzLFxuICAvLyBidXQgdGhlIFwicmVsZWFzZVwiIGZhaWxzLCBpZiB3ZSB0cnkgdG8gcHVibGlzaCBhbiBhbHJlYWR5LXB1Ymxpc2hlZCB2ZXJzaW9uIGFnYWluLlxuICAvL1xuICAvLyBVbmZvcnR1bmF0ZWx5IHRoZXJlIGlzIG5vIGdyZWF0IGVycm9yIGNvZGUgdG8gZGV0ZWN0IHRoaXMgcmlnaHQgbm93LCBidXQgSSd2ZSBvYnNlcnZlZFxuICAvLyB0aGlzIGVycm9yIHdoZW4gaXQgaGFwcGVuZWQuXG4gIC8vIEkgaGF2ZSBhIHN1cHBvcnQgcmVxdWVzdCBvdXQgdG8gU29uYXR5cGUgZm9yIHRoaXMsIHdlJ2xsIHNlZSBpZiB0aGlzIGNoYW5nZXMgb3ZlciB0aW1lLlxuICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSA0MDAgJiYgYm9keSA9PT0gJ0ZhaWxlZCB0byBwcm9jZXNzIHJlcXVlc3Q6IHNlcnZpY2UgZXJyb3InKSB7XG4gICAgcmV0dXJuICdkdXBsaWNhdGUtdmVyc2lvbic7XG4gIH1cblxuICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBIVFRQICR7cmVzcG9uc2Uuc3RhdHVzfSAke3Jlc3BvbnNlLnN0YXR1c1RleHR9OiAke2JvZHl9YCk7XG4gIH1cblxuICBjb25zb2xlLmxvZyhib2R5KTtcblxuICByZXR1cm4gJ29rJztcbn1cblxuLyoqXG4gKiBTaWduIGFuZCBzdGFnZSBvdXIgYXJ0aWZhY3RzIGludG8gYSBsb2NhbCBkaXJlY3RvcnlcbiAqL1xuYXN5bmMgZnVuY3Rpb24gc2lnbkphcnMobWF2ZW46IE1hdmVuLCBwb21zOiBzdHJpbmdbXSwgdGFyZ2V0RGlyOiBzdHJpbmcsIHNlcnZlcklkOiBzdHJpbmcsIGtleTogUHJpdmF0ZUtleSkge1xuICBhd2FpdCB1c2luZyBncGcgPSBhd2FpdCBpbXBvcnRHcGdLZXkoa2V5KTtcblxuICAvLyBvbiBhIG1hYywgLS1waW5lbnRyeS1tb2RlIHRvIFwibG9vcGJhY2tcIiBhcmUgcmVxdWlyZWQgYW5kIEkgY291bGRuJ3QgZmluZCBhXG4gIC8vIHdheSB0byBkbyBzbyB2aWEgLURncGcuZ3BnQXJndW1lbnRzIG9yIHRoZSBzZXR0aW5ncyBmaWxlLCBzbyBoZXJlIHdlIGFyZS5cbiAgbGV0IGdwZ0JpbiA9ICdncGcnO1xuICBpZiAob3MucGxhdGZvcm0oKSA9PT0gJ2RhcndpbicpIHtcbiAgICBncGdCaW4gPSBwYXRoLmpvaW4obWF2ZW4ud29ya0RpciwgJ3B1YmxpYi1ncGcuc2gnKTtcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUoZ3BnQmluLCBbXG4gICAgICAnIyEvYmluL2Jhc2gnLFxuICAgICAgJ2V4ZWMgZ3BnIC0tcGluZW50cnktbW9kZSBsb29wYmFjayBcIlxcJEBcIicsXG4gICAgXS5qb2luKCdcXG4nKSwgJ3V0Zi04Jyk7XG4gICAgYXdhaXQgJGBjaG1vZCAreCAke2dwZ0Jpbn1gO1xuICB9XG5cbiAgZm9yIChjb25zdCBwb20gb2YgcG9tcykge1xuICAgIGF3YWl0IG1hdmVuLmV4ZWMoJ2dwZzpzaWduLWFuZC1kZXBsb3ktZmlsZScsIHtcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgJ3VybCc6IGBmaWxlOi8vJHt0YXJnZXREaXJ9YCxcbiAgICAgICAgJ3JlcG9zaXRvcnlJZCc6IHNlcnZlcklkLCAvLyBNb3N0IGxpa2VseSBub3QgbmVjZXNzYXJ5XG4gICAgICAgICdncGcuaG9tZWRpcic6IGdwZy5ob21lLFxuICAgICAgICAnZ3BnLmtleW5hbWUnOiBncGcua2V5SWQsXG4gICAgICAgICdncGcuZXhlY3V0YWJsZSc6IGdwZ0JpbixcbiAgICAgICAgJ3BvbUZpbGUnOiBwb20sXG4gICAgICAgIC4uLmphcnNGcm9tUG9tKHBvbSksXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogQmFzZWQgb24gdGhlIHBhdGggb2YgYSAucG9tIGZpbGUsIHJldHVybiB0aGUgcGF0aHMgb2YgdGhlIGNvcnJlc3BvbmRpbmcgamFyc1xuICovXG5mdW5jdGlvbiBqYXJzRnJvbVBvbShwb206IHN0cmluZykge1xuICByZXR1cm4ge1xuICAgIGZpbGU6IHBvbS5yZXBsYWNlKC9cXC5wb20kLywgJy5qYXInKSxcbiAgICBzb3VyY2VzOiBwb20ucmVwbGFjZSgvXFwucG9tJC8sICctc291cmNlcy5qYXInKSxcbiAgICBqYXZhZG9jOiBwb20ucmVwbGFjZSgvXFwucG9tJC8sICctamF2YWRvYy5qYXInKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSB0ZW1wb3JhcnkgZGlyZWN0b3J5IGFuZCBpbXBvcnQgdGhlIEdQRyBrZXkgbWF0ZXJpYWwgaW50byBhIG5ldyBrZXljaGFpbiB0aGVyZVxuICovXG5hc3luYyBmdW5jdGlvbiBpbXBvcnRHcGdLZXkoa2V5OiBQcml2YXRlS2V5KSB7XG4gIC8vIEdudVBHIHdpbGwgb2NjYXNpb25hbGx5IGJhaWwgb3V0IHdpdGggXCJncGc6IDx3aGF0ZXZlcj4gZmFpbGVkOiBJbmFwcHJvcHJpYXRlIGlvY3RsIGZvciBkZXZpY2VcIiwgdGhlIGZvbGxvd2luZyBhdHRlbXB0cyB0byBmaXhcbiAgY29uc3QgZ3BnSG9tZSA9IGF1dG9DbGVhbkRpcigpO1xuICB0cnkge1xuICAgIGNvbnN0IHR0eSA9IChhd2FpdCAkKHsgc3RkaW86IFsnaW5oZXJpdCcsICdwaXBlJywgJ3BpcGUnXSB9KWB0dHlgKS5zdGRvdXQ7XG5cbiAgICBsZXQgcHJpdmF0ZUtleUZpbGU7XG4gICAgY29uc3QgdHlwZSA9IGtleS50eXBlO1xuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSAnZmlsZSc6XG4gICAgICAgIHByaXZhdGVLZXlGaWxlID0ga2V5LmZpbGVOYW1lO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ21hdGVyaWFsJzpcbiAgICAgICAgcHJpdmF0ZUtleUZpbGUgPSBwYXRoLmpvaW4oZ3BnSG9tZS5kaXIsICdwcml2YXRlLnBlbScpO1xuICAgICAgICBhd2FpdCAkYGVjaG8gLWUgJHtrZXkua2V5TWF0ZXJpYWx9ID4gJHtwcml2YXRlS2V5RmlsZX1gO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGFzc2VydE5ldmVyKHR5cGUpO1xuICAgIH1cblxuICAgIGNvbnN0IGVudiA9IHtcbiAgICAgIEdOVVBHSE9NRTogZ3BnSG9tZS5kaXIsXG4gICAgICBHUEdfVFRZOiB0dHksXG4gICAgfTtcblxuICAgIGNvbnN0ICQkID0gJCh7IGVudjogeyAuLi5wcm9jZXNzLmVudiwgLi4uZW52IH0gfSk7XG5cbiAgICBhd2FpdCAkJGBncGcgLS1hbGxvdy1zZWNyZXQta2V5LWltcG9ydCAtLWJhdGNoIC0teWVzIC0tbm8tdHR5IC0taW1wb3J0ICR7cHJpdmF0ZUtleUZpbGV9YDtcbiAgICBjb25zdCBncGdLZXlJZCA9IChhd2FpdCAkJGBncGcgLS1saXN0LWtleXMgLS13aXRoLWNvbG9ucyB8IGdyZXAgcHViIHwgY3V0IC1kOiAtZjVgKS5zdGRvdXQudHJpbSgpO1xuXG4gICAgZWNobyhgZ3BnX2tleV9pZD0ke2dwZ0tleUlkfWApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGtleUlkOiBncGdLZXlJZCxcbiAgICAgIGVudixcbiAgICAgIGhvbWU6IGdwZ0hvbWUuZGlyLFxuICAgICAgW1N5bWJvbC5hc3luY0Rpc3Bvc2VdOiBhc3luYyAoKSA9PiBncGdIb21lW1N5bWJvbC5hc3luY0Rpc3Bvc2VdKCksXG4gICAgfTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGF3YWl0IGdwZ0hvbWVbU3ltYm9sLmFzeW5jRGlzcG9zZV0oKTtcbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbmNsYXNzIE1hdmVuIHtcbiAgcHJpdmF0ZSByZWFkb25seSBzZXR0aW5nc0ZpbGU6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihwdWJsaWMgcmVhZG9ubHkgd29ya0Rpcjogc3RyaW5nLCBwcml2YXRlIHJlYWRvbmx5IHZlcmJvc2U6IGJvb2xlYW4sIHB1YmxpYyByZWFkb25seSBkcnlSdW46IGJvb2xlYW4pIHtcbiAgICB0aGlzLnNldHRpbmdzRmlsZSA9IHBhdGguam9pbih3b3JrRGlyLCAnbXZuLXNldHRpbmdzLnhtbCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIHNldHRpbmdzLnhtbCBmaWxlIHdpdGggdGhlIHVzZXIrcGFzc3dvcmQgZm9yIG1hdmVuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgd3JpdGVTZXR0aW5nc0ZpbGUoc2VydmVySWQ6IHN0cmluZywgc2lnbmVkQXJ0aWZhY3RzOiBib29sZWFuKSB7XG4gICAgY29uc3QgbGluZXMgPSBbXTtcblxuICAgIGxpbmVzLnB1c2goXG4gICAgICAnPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwiVVRGLThcIiA/PicsXG4gICAgICAnPHNldHRpbmdzIHhtbG5zPVwiaHR0cDovL21hdmVuLmFwYWNoZS5vcmcvU0VUVElOR1MvMS4wLjBcIicsXG4gICAgICAnICAgICAgICB4bWxuczp4c2k9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZVwiJyxcbiAgICAgICcgICAgICAgIHhzaTpzY2hlbWFMb2NhdGlvbj1cImh0dHA6Ly9tYXZlbi5hcGFjaGUub3JnL1NFVFRJTkdTLzEuMC4wJyxcbiAgICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHR0cDovL21hdmVuLmFwYWNoZS5vcmcveHNkL3NldHRpbmdzLTEuMC4wLnhzZFwiPicsXG4gICAgICAnICA8c2VydmVycz4nLFxuICAgICAgJyAgICA8c2VydmVyPicsXG4gICAgICBgICAgICAgPGlkPiR7c2VydmVySWR9PC9pZD5gLFxuICAgICAgLy8gTWF2ZW4gd2lsbCByZWFkIHRoZXNlLCBzdXJyb3VuZGluZyBjb2RlIGhhcyBhbHJlYWR5IG1hZGUgc3VyZSB0aGV5IGFyZSBzZXRcbiAgICAgICcgICAgICA8dXNlcm5hbWU+JHtlbnYuTUFWRU5fVVNFUk5BTUV9PC91c2VybmFtZT4nLFxuICAgICAgJyAgICAgIDxwYXNzd29yZD4ke2Vudi5NQVZFTl9QQVNTV09SRH08L3Bhc3N3b3JkPicsXG4gICAgICAnICAgIDwvc2VydmVyPicsXG4gICAgKTtcblxuICAgIGlmIChzaWduZWRBcnRpZmFjdHMpIHtcbiAgICAgIGxpbmVzLnB1c2goXG4gICAgICAgICcgICAgPHNlcnZlcj4nLFxuICAgICAgICAnICAgICAgPGlkPmdwZy5wYXNzcGhyYXNlPC9pZD4nLFxuICAgICAgICAvLyBNYXZlbiB3aWxsIHJlYWQgdGhlc2UsIHN1cnJvdW5kaW5nIGNvZGUgaGFzIGFscmVhZHkgbWFkZSBzdXJlIHRoZXkgYXJlIHNldFxuICAgICAgICAnICAgICAgPHBhc3NwaHJhc2U+JHtlbnYuTUFWRU5fR1BHX1BSSVZBVEVfS0VZX1BBU1NQSFJBU0V9PC9wYXNzcGhyYXNlPicsXG4gICAgICAgICcgICAgPC9zZXJ2ZXI+JyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgbGluZXMucHVzaChcbiAgICAgICcgIDwvc2VydmVycz4nLFxuICAgICAgJzwvc2V0dGluZ3M+JyxcbiAgICApO1xuXG4gICAgYXdhaXQgZnMud3JpdGVGaWxlKHRoaXMuc2V0dGluZ3NGaWxlLCBsaW5lcy5qb2luKCdcXG4nKSwgJ3V0Zi04Jyk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZXhlYyhtb2pvOiBzdHJpbmcsIG9wdGlvbnM6IE1hdmVuRXhlY09wdGlvbnMpOiBQcm9taXNlPFByb2Nlc3NPdXRwdXQgfCB1bmRlZmluZWQ+IHtcbiAgICBjb25zdCBhcmdzID0gW1xuICAgICAgYC0tc2V0dGluZ3M9JHt0aGlzLnNldHRpbmdzRmlsZX1gLFxuICAgICAgLi4uKG9wdGlvbnMudmVyYm9zZSA/PyB0aGlzLnZlcmJvc2UgPyBbJy1YJ10gOiBbXSksXG4gICAgICBtb2pvLFxuICAgICAgLi4uT2JqZWN0LmVudHJpZXMob3B0aW9ucy5wcm9wZXJ0aWVzKS5tYXAoKFtrLCB2XSkgPT4gYC1EJHtrfT0ke3Z9YCksXG4gICAgXTtcblxuICAgIGlmICh0aGlzLmRyeVJ1bikge1xuICAgICAgZWNobyhgW0RSWS1SVU5dIG12biAke2FyZ3MubWFwKHF1b3RlKS5qb2luKCcgJyl9YCk7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBjb25zdCBlbnYgPSB7XG4gICAgICAuLi5wcm9jZXNzLmVudixcbiAgICAgIEpES19KQVZBX09QVElPTlM6IFtcbiAgICAgICAgLy8gSWYgd2UgZG9uJ3QgYWRkIHRoaXMsIHdlJ2xsIGdldCBhbiBlcnJvciBsaWtlIHRoZSBmb2xsb3dpbmcgZHVyaW5nIHRoZSBuZXh1cy1zdGFnaW5nLW1hdmVuLXBsdWdpbjpyYy1yZWxlYXNlIG1vam8uXG4gICAgICAgIC8vIERvbid0IGtub3cgd2hlcmUgdGhpcyBpcyBjb21pbmcgZnJvbSBhbGwgb2YgYSBzdWRkZW4uXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFtFUlJPUl0gbWVzc2FnZSAgICAgICAgICAgICA6IE5vIGNvbnZlcnRlciBhdmFpbGFibGVcbiAgICAgICAgLy8gW0VSUk9SXSB0eXBlICAgICAgICAgICAgICAgIDogamF2YS51dGlsLkFycmF5cyRBcnJheUxpc3RcbiAgICAgICAgLy8gW0VSUk9SXSBjb252ZXJ0ZXIgICAgICAgICAgIDogY29tLnRob3VnaHR3b3Jrcy54c3RyZWFtLmNvbnZlcnRlcnMucmVmbGVjdGlvbi5SZWZsZWN0aW9uQ29udmVydGVyXG4gICAgICAgIC8vIFtFUlJPUl0gbWVzc2FnZVsxXSAgICAgICAgICA6IFVuYWJsZSB0byBtYWtlIGZpZWxkIHByb3RlY3RlZCB0cmFuc2llbnQgaW50IGphdmEudXRpbC5BYnN0cmFjdExpc3QubW9kQ291bnQgYWNjZXNzaWJsZTogbW9kdWxlIGphdmEuYmFzZSBkb2VzIG5vdCBcIm9wZW5zIGphdmEudXRpbFwiIHRvIHVubmFtZWQgbW9kdWxlIEA3YzhkNTMxMlxuICAgICAgICAnLS1hZGQtb3BlbnM9amF2YS5iYXNlL2phdmEudXRpbD1BTEwtVU5OQU1FRCcsXG4gICAgICAgICctLWFkZC1vcGVucz1qYXZhLmJhc2UvamF2YS5sYW5nPUFMTC1VTk5BTUVEJyxcbiAgICAgICAgJy0tYWRkLW9wZW5zPWphdmEuYmFzZS9qYXZhLmxhbmcuaW52b2tlPUFMTC1VTk5BTUVEJyxcbiAgICAgIF0uam9pbignICcpLFxuICAgIH07XG5cbiAgICByZXR1cm4gJCh7IHZlcmJvc2U6IHRydWUsIG5vdGhyb3c6IG9wdGlvbnMubm90aHJvdywgZW52IH0pYG12biAke2FyZ3N9YDtcbiAgfVxufVxuXG5pbnRlcmZhY2UgTWF2ZW5FeGVjT3B0aW9ucyB7XG4gIHByb3BlcnRpZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIG5vdGhyb3c/OiBib29sZWFuO1xuICB2ZXJib3NlPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBBIGV4cGVjdGVkIGVycm9yIHRoYXQgZG9lc24ndCBuZWVkIGEgc3RhY2sgdHJhY2VcbiAqL1xuY2xhc3MgU2ltcGxlRXJyb3IgZXh0ZW5kcyBFcnJvciB7IH1cblxuLyoqXG4gKiBSZXF1aXJlIGFuIGVudmlyb25tZW50IHZhcmlhYmxlXG4gKi9cbmZ1bmN0aW9uIGVudlZhcihuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCByZXQgPSBwcm9jZXNzLmVudltuYW1lXTtcbiAgaWYgKCFyZXQpIHtcbiAgICB0aHJvdyBuZXcgU2ltcGxlRXJyb3IoYCR7bmFtZX0gaXMgcmVxdWlyZWRgKTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIEEgdGVtcG9yYXJ5IGRpcmVjdG9yeSB0aGF0IGNsZWFucyB3aGVuIGl0IGdvZXMgb3V0IG9mIHNjb3BlXG4gKlxuICogVXNlIHdpdGggYHVzaW5nYC4gQ291bGQgaGF2ZSBiZWVuIGFzeW5jIGJ1dCBpdCdzIGRlcGVuZGluZ1xuICogb24gYW4gYWxyZWFkeS1zeW5jIEFQSSwgc28gd2h5IG5vdCBzeW5jP1xuICovXG5leHBvcnQgZnVuY3Rpb24gYXV0b0NsZWFuRGlyKCkge1xuICBjb25zdCBkaXIgPSB0bXBkaXIoKTtcbiAgcmV0dXJuIHtcbiAgICBkaXIsXG4gICAgW1N5bWJvbC5hc3luY0Rpc3Bvc2VdOiBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBmcy5ybShkaXIsIHsgZm9yY2U6IHRydWUsIHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICB9LFxuICB9O1xufVxuXG5mdW5jdGlvbiBhc3NlcnROZXZlcih2YWx1ZTogbmV2ZXIpIHtcbiAgdGhyb3cgbmV3IEVycm9yKCdVbmV4cGVjdGVkIHZhbHVlOiAnICsgdmFsdWUpO1xufVxuXG4vLyBBICd6eCcgcHJpbWVyXG4vL1xuLy8gLSBCeSBkZWZhdWx0OiBzdGRlcnIgaXMgcHJpbnRlZCB0byB0aGUgdGVybWluYWwgaWYgaXQgaXMgY2FwdHVyZWQuXG4vLyAtIHsgdmVyYm9zZTogdHJ1ZSB9OiBwcmludCB0aGUgY29tbWFuZCwgc3Rkb3V0IGFuZCBzdGRlcnIgdG8gdGhlIHRlcm1pbmFsXG4vLyAtIHsgcXVpZXQ6IHRydWUgfTogcHJpbnQgbmVpdGhlciBzdGRvdXQgbm9yIHN0ZGVyclxuLy9cbi8vIC50ZXh0KCk6IHJldHVybiBldmVyeXRoaW5nIHRoYXQncyBjYXB0dXJlZCAoc3RkZXJyIGFuZCBzdGRvdXQgdG9nZXRoZXIgaWYgc3RkZXJyIGlzIGNhcHR1cmVkKVxuXG5tYWluKCkuY2F0Y2goZSA9PiB7XG4gIGlmIChlIGluc3RhbmNlb2YgUHJvY2Vzc091dHB1dCkge1xuICAgIGVjaG8oYOKdjCBTdWJwcm9jZXNzIGZhaWxlZCB3aXRoIGV4aXQgY29kZSAke2UuZXhpdENvZGV9YCk7XG4gIH0gZWxzZSBpZiAoZSBpbnN0YW5jZW9mIFNpbXBsZUVycm9yKSB7XG4gICAgZWNobygn4p2MJywgZS5tZXNzYWdlKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmVycm9yKGUpO1xuICB9XG4gIHByb2Nlc3MuZXhpdENvZGUgPSAxO1xufSk7XG4iXX0=
|