@electron-forge/publisher-bitbucket 6.0.1 → 6.0.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.
- package/LICENSE +19 -0
- package/package.json +7 -3
- package/src/Config.ts +44 -0
- package/src/PublisherBitbucket.ts +83 -0
- package/dist/Config.d.ts +0 -43
- package/dist/Config.d.ts.map +0 -1
- package/dist/Config.js +0 -6
- package/dist/PublisherBitbucket.d.ts +0 -8
- package/dist/PublisherBitbucket.d.ts.map +0 -1
- package/dist/PublisherBitbucket.js +0 -89
package/LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
Copyright (c) 2016 Samuel Attard
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
5
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
6
|
+
the Software without restriction, including without limitation the rights to
|
|
7
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
8
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
9
|
+
subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
16
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
17
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
18
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
19
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@electron-forge/publisher-bitbucket",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.2",
|
|
4
4
|
"description": "Bitbucket publisher for Electron Forge",
|
|
5
5
|
"repository": "https://github.com/electron/forge",
|
|
6
6
|
"author": "Luke Batchelor",
|
|
@@ -15,9 +15,13 @@
|
|
|
15
15
|
"node": ">= 14.17.5"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@electron-forge/publisher-base": "6.0.
|
|
18
|
+
"@electron-forge/publisher-base": "^6.0.2",
|
|
19
19
|
"form-data": "^4.0.0",
|
|
20
20
|
"fs-extra": "^10.0.0",
|
|
21
21
|
"node-fetch": "^2.6.7"
|
|
22
|
-
}
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"gitHead": "11cf4b58359c9881c05c06e0d62be575a0ed70d1"
|
|
23
27
|
}
|
package/src/Config.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export interface BitbucketRepository {
|
|
2
|
+
/**
|
|
3
|
+
* The name of your repository
|
|
4
|
+
*/
|
|
5
|
+
name: string;
|
|
6
|
+
/**
|
|
7
|
+
* The owner of your repository, this is either your username or the name of
|
|
8
|
+
* the organization that owns the repository.
|
|
9
|
+
*/
|
|
10
|
+
owner: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface BitbucketAuth {
|
|
14
|
+
/**
|
|
15
|
+
* The username to use when uploading.
|
|
16
|
+
*
|
|
17
|
+
* You can set the BITBUCKET_USERNAME environment variable if you don't want to hard
|
|
18
|
+
* code this into your config.
|
|
19
|
+
*/
|
|
20
|
+
username?: string;
|
|
21
|
+
/**
|
|
22
|
+
* An authorization token with permission to upload downloads to this
|
|
23
|
+
* repository.
|
|
24
|
+
*
|
|
25
|
+
* You can set the BITBUCKET_APP_PASSWORD environment variable if you don't want to hard
|
|
26
|
+
* code this into your config.
|
|
27
|
+
*/
|
|
28
|
+
appPassword?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface PublisherBitbucketConfig {
|
|
32
|
+
/**
|
|
33
|
+
* Details that identify your repository (name and owner)
|
|
34
|
+
*/
|
|
35
|
+
repository: BitbucketRepository;
|
|
36
|
+
/**
|
|
37
|
+
* User details for uploading releases
|
|
38
|
+
*/
|
|
39
|
+
auth: BitbucketAuth;
|
|
40
|
+
/**
|
|
41
|
+
* If true, will replace an existing files of the same name (will throw an error otherwise).
|
|
42
|
+
*/
|
|
43
|
+
replaceExistingFiles?: boolean;
|
|
44
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
|
|
3
|
+
import { PublisherBase, PublisherOptions } from '@electron-forge/publisher-base';
|
|
4
|
+
import FormData from 'form-data';
|
|
5
|
+
import fs from 'fs-extra';
|
|
6
|
+
import fetch from 'node-fetch';
|
|
7
|
+
|
|
8
|
+
import { PublisherBitbucketConfig } from './Config';
|
|
9
|
+
|
|
10
|
+
export default class PublisherBitbucket extends PublisherBase<PublisherBitbucketConfig> {
|
|
11
|
+
name = 'bitbucket';
|
|
12
|
+
|
|
13
|
+
async publish({ makeResults, setStatusLine }: PublisherOptions): Promise<void> {
|
|
14
|
+
const { config } = this;
|
|
15
|
+
const hasRepositoryConfig = config.repository && typeof config.repository;
|
|
16
|
+
const replaceExistingFiles = Boolean(config.replaceExistingFiles);
|
|
17
|
+
const appPassword = process.env.BITBUCKET_APP_PASSWORD;
|
|
18
|
+
const username = process.env.BITBUCKET_USERNAME;
|
|
19
|
+
const auth = { appPassword, username, ...(config.auth || {}) };
|
|
20
|
+
const apiUrl = `https://api.bitbucket.org/2.0/repositories/${config.repository.owner}/${config.repository.name}/downloads`;
|
|
21
|
+
const encodedUserAndPass = Buffer.from(`${auth.username}:${auth.appPassword}`).toString('base64');
|
|
22
|
+
|
|
23
|
+
if (!(hasRepositoryConfig && config.repository.owner && config.repository.name)) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
'In order to publish to Bitbucket you must set the "repository.owner" and "repository.name" properties in your Forge config. See the docs for more info'
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!auth.appPassword || !auth.username) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
'In order to publish to Bitbucket provide credentials, either through "auth.appPassword" and "auth.username" properties in your Forge config or using BITBUCKET_APP_PASSWORD and BITBUCKET_USERNAME environment variables'
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (const [index, makeResult] of makeResults.entries()) {
|
|
36
|
+
const data = new FormData();
|
|
37
|
+
|
|
38
|
+
for (const artifactPath of makeResult.artifacts) {
|
|
39
|
+
data.append('files', fs.createReadStream(artifactPath));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// If we are not supposed to override an existing version, we'll check check if any of
|
|
43
|
+
// the files exist first
|
|
44
|
+
if (!replaceExistingFiles) {
|
|
45
|
+
for (const artifactPath of makeResult.artifacts) {
|
|
46
|
+
const fileName = path.basename(artifactPath);
|
|
47
|
+
|
|
48
|
+
const response = await fetch(`${apiUrl}/${fileName}`, {
|
|
49
|
+
headers: {
|
|
50
|
+
Authorization: `Basic ${encodedUserAndPass}`,
|
|
51
|
+
},
|
|
52
|
+
method: 'HEAD',
|
|
53
|
+
// We set redirect to 'manual' so that we get the 302 redirects if the file
|
|
54
|
+
// already exists
|
|
55
|
+
redirect: 'manual',
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (response.status === 302) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
`Unable to publish "${fileName}" as it has been published previously. Use the "replaceExistingFiles" property in your Forge config to override this.`
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
setStatusLine(`Uploading distributable (${index + 1}/${makeResults.length})`);
|
|
67
|
+
const response = await fetch(apiUrl, {
|
|
68
|
+
headers: {
|
|
69
|
+
Authorization: `Basic ${encodedUserAndPass}`,
|
|
70
|
+
},
|
|
71
|
+
method: 'POST',
|
|
72
|
+
body: data,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// We will get a 200 on the inital upload and a 201 if publishing over the same version
|
|
76
|
+
if (response.status !== 200 && response.status !== 201) {
|
|
77
|
+
throw new Error(`Unexpected response code from Bitbucket: ${response.status} ${response.statusText}\n\nBody:\n${await response.text()}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export { PublisherBitbucket, PublisherBitbucketConfig };
|
package/dist/Config.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
export interface BitbucketRepository {
|
|
2
|
-
/**
|
|
3
|
-
* The name of your repository
|
|
4
|
-
*/
|
|
5
|
-
name: string;
|
|
6
|
-
/**
|
|
7
|
-
* The owner of your repository, this is either your username or the name of
|
|
8
|
-
* the organization that owns the repository.
|
|
9
|
-
*/
|
|
10
|
-
owner: string;
|
|
11
|
-
}
|
|
12
|
-
export interface BitbucketAuth {
|
|
13
|
-
/**
|
|
14
|
-
* The username to use when uploading.
|
|
15
|
-
*
|
|
16
|
-
* You can set the BITBUCKET_USERNAME environment variable if you don't want to hard
|
|
17
|
-
* code this into your config.
|
|
18
|
-
*/
|
|
19
|
-
username?: string;
|
|
20
|
-
/**
|
|
21
|
-
* An authorization token with permission to upload downloads to this
|
|
22
|
-
* repository.
|
|
23
|
-
*
|
|
24
|
-
* You can set the BITBUCKET_APP_PASSWORD environment variable if you don't want to hard
|
|
25
|
-
* code this into your config.
|
|
26
|
-
*/
|
|
27
|
-
appPassword?: string;
|
|
28
|
-
}
|
|
29
|
-
export interface PublisherBitbucketConfig {
|
|
30
|
-
/**
|
|
31
|
-
* Details that identify your repository (name and owner)
|
|
32
|
-
*/
|
|
33
|
-
repository: BitbucketRepository;
|
|
34
|
-
/**
|
|
35
|
-
* User details for uploading releases
|
|
36
|
-
*/
|
|
37
|
-
auth: BitbucketAuth;
|
|
38
|
-
/**
|
|
39
|
-
* If true, will replace an existing files of the same name (will throw an error otherwise).
|
|
40
|
-
*/
|
|
41
|
-
replaceExistingFiles?: boolean;
|
|
42
|
-
}
|
|
43
|
-
//# sourceMappingURL=Config.d.ts.map
|
package/dist/Config.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Config.d.ts","sourceRoot":"","sources":["../src/Config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,UAAU,EAAE,mBAAmB,CAAC;IAChC;;OAEG;IACH,IAAI,EAAE,aAAa,CAAC;IACpB;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC"}
|
package/dist/Config.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { PublisherBase, PublisherOptions } from '@electron-forge/publisher-base';
|
|
2
|
-
import { PublisherBitbucketConfig } from './Config';
|
|
3
|
-
export default class PublisherBitbucket extends PublisherBase<PublisherBitbucketConfig> {
|
|
4
|
-
name: string;
|
|
5
|
-
publish({ makeResults, setStatusLine }: PublisherOptions): Promise<void>;
|
|
6
|
-
}
|
|
7
|
-
export { PublisherBitbucket, PublisherBitbucketConfig };
|
|
8
|
-
//# sourceMappingURL=PublisherBitbucket.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PublisherBitbucket.d.ts","sourceRoot":"","sources":["../src/PublisherBitbucket.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAKjF,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAEpD,MAAM,CAAC,OAAO,OAAO,kBAAmB,SAAQ,aAAa,CAAC,wBAAwB,CAAC;IACrF,IAAI,SAAe;IAEb,OAAO,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;CAoE/E;AAED,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,CAAC"}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "PublisherBitbucketConfig", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return _config.PublisherBitbucketConfig;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
exports.PublisherBitbucket = exports.default = void 0;
|
|
12
|
-
var _path = _interopRequireDefault(require("path"));
|
|
13
|
-
var _publisherBase = require("@electron-forge/publisher-base");
|
|
14
|
-
var _formData = _interopRequireDefault(require("form-data"));
|
|
15
|
-
var _fsExtra = _interopRequireDefault(require("fs-extra"));
|
|
16
|
-
var _nodeFetch = _interopRequireDefault(require("node-fetch"));
|
|
17
|
-
var _config = require("./Config");
|
|
18
|
-
function _interopRequireDefault(obj) {
|
|
19
|
-
return obj && obj.__esModule ? obj : {
|
|
20
|
-
default: obj
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
class PublisherBitbucket extends _publisherBase.PublisherBase {
|
|
24
|
-
async publish({ makeResults , setStatusLine }) {
|
|
25
|
-
const { config } = this;
|
|
26
|
-
const hasRepositoryConfig = config.repository && typeof config.repository;
|
|
27
|
-
const replaceExistingFiles = Boolean(config.replaceExistingFiles);
|
|
28
|
-
const appPassword = process.env.BITBUCKET_APP_PASSWORD;
|
|
29
|
-
const username = process.env.BITBUCKET_USERNAME;
|
|
30
|
-
const auth = {
|
|
31
|
-
appPassword,
|
|
32
|
-
username,
|
|
33
|
-
...config.auth || {}
|
|
34
|
-
};
|
|
35
|
-
const apiUrl = `https://api.bitbucket.org/2.0/repositories/${config.repository.owner}/${config.repository.name}/downloads`;
|
|
36
|
-
const encodedUserAndPass = Buffer.from(`${auth.username}:${auth.appPassword}`).toString('base64');
|
|
37
|
-
if (!(hasRepositoryConfig && config.repository.owner && config.repository.name)) {
|
|
38
|
-
throw new Error('In order to publish to Bitbucket you must set the "repository.owner" and "repository.name" properties in your Forge config. See the docs for more info');
|
|
39
|
-
}
|
|
40
|
-
if (!auth.appPassword || !auth.username) {
|
|
41
|
-
throw new Error('In order to publish to Bitbucket provide credentials, either through "auth.appPassword" and "auth.username" properties in your Forge config or using BITBUCKET_APP_PASSWORD and BITBUCKET_USERNAME environment variables');
|
|
42
|
-
}
|
|
43
|
-
for (const [index, makeResult] of makeResults.entries()){
|
|
44
|
-
const data = new _formData.default();
|
|
45
|
-
for (const artifactPath of makeResult.artifacts){
|
|
46
|
-
data.append('files', _fsExtra.default.createReadStream(artifactPath));
|
|
47
|
-
}
|
|
48
|
-
// If we are not supposed to override an existing version, we'll check check if any of
|
|
49
|
-
// the files exist first
|
|
50
|
-
if (!replaceExistingFiles) {
|
|
51
|
-
for (const artifactPath of makeResult.artifacts){
|
|
52
|
-
const fileName = _path.default.basename(artifactPath);
|
|
53
|
-
const response = await (0, _nodeFetch).default(`${apiUrl}/${fileName}`, {
|
|
54
|
-
headers: {
|
|
55
|
-
Authorization: `Basic ${encodedUserAndPass}`
|
|
56
|
-
},
|
|
57
|
-
method: 'HEAD',
|
|
58
|
-
// We set redirect to 'manual' so that we get the 302 redirects if the file
|
|
59
|
-
// already exists
|
|
60
|
-
redirect: 'manual'
|
|
61
|
-
});
|
|
62
|
-
if (response.status === 302) {
|
|
63
|
-
throw new Error(`Unable to publish "${fileName}" as it has been published previously. Use the "replaceExistingFiles" property in your Forge config to override this.`);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
setStatusLine(`Uploading distributable (${index + 1}/${makeResults.length})`);
|
|
68
|
-
const response = await (0, _nodeFetch).default(apiUrl, {
|
|
69
|
-
headers: {
|
|
70
|
-
Authorization: `Basic ${encodedUserAndPass}`
|
|
71
|
-
},
|
|
72
|
-
method: 'POST',
|
|
73
|
-
body: data
|
|
74
|
-
});
|
|
75
|
-
// We will get a 200 on the inital upload and a 201 if publishing over the same version
|
|
76
|
-
if (response.status !== 200 && response.status !== 201) {
|
|
77
|
-
throw new Error(`Unexpected response code from Bitbucket: ${response.status} ${response.statusText}\n\nBody:\n${await response.text()}`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
constructor(...args){
|
|
82
|
-
super(...args);
|
|
83
|
-
this.name = 'bitbucket';
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
exports.default = PublisherBitbucket;
|
|
87
|
-
exports.PublisherBitbucket = PublisherBitbucket;
|
|
88
|
-
|
|
89
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9QdWJsaXNoZXJCaXRidWNrZXQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5cbmltcG9ydCB7IFB1Ymxpc2hlckJhc2UsIFB1Ymxpc2hlck9wdGlvbnMgfSBmcm9tICdAZWxlY3Ryb24tZm9yZ2UvcHVibGlzaGVyLWJhc2UnO1xuaW1wb3J0IEZvcm1EYXRhIGZyb20gJ2Zvcm0tZGF0YSc7XG5pbXBvcnQgZnMgZnJvbSAnZnMtZXh0cmEnO1xuaW1wb3J0IGZldGNoIGZyb20gJ25vZGUtZmV0Y2gnO1xuXG5pbXBvcnQgeyBQdWJsaXNoZXJCaXRidWNrZXRDb25maWcgfSBmcm9tICcuL0NvbmZpZyc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFB1Ymxpc2hlckJpdGJ1Y2tldCBleHRlbmRzIFB1Ymxpc2hlckJhc2U8UHVibGlzaGVyQml0YnVja2V0Q29uZmlnPiB7XG4gIG5hbWUgPSAnYml0YnVja2V0JztcblxuICBhc3luYyBwdWJsaXNoKHsgbWFrZVJlc3VsdHMsIHNldFN0YXR1c0xpbmUgfTogUHVibGlzaGVyT3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgY29uZmlnIH0gPSB0aGlzO1xuICAgIGNvbnN0IGhhc1JlcG9zaXRvcnlDb25maWcgPSBjb25maWcucmVwb3NpdG9yeSAmJiB0eXBlb2YgY29uZmlnLnJlcG9zaXRvcnk7XG4gICAgY29uc3QgcmVwbGFjZUV4aXN0aW5nRmlsZXMgPSBCb29sZWFuKGNvbmZpZy5yZXBsYWNlRXhpc3RpbmdGaWxlcyk7XG4gICAgY29uc3QgYXBwUGFzc3dvcmQgPSBwcm9jZXNzLmVudi5CSVRCVUNLRVRfQVBQX1BBU1NXT1JEO1xuICAgIGNvbnN0IHVzZXJuYW1lID0gcHJvY2Vzcy5lbnYuQklUQlVDS0VUX1VTRVJOQU1FO1xuICAgIGNvbnN0IGF1dGggPSB7IGFwcFBhc3N3b3JkLCB1c2VybmFtZSwgLi4uKGNvbmZpZy5hdXRoIHx8IHt9KSB9O1xuICAgIGNvbnN0IGFwaVVybCA9IGBodHRwczovL2FwaS5iaXRidWNrZXQub3JnLzIuMC9yZXBvc2l0b3JpZXMvJHtjb25maWcucmVwb3NpdG9yeS5vd25lcn0vJHtjb25maWcucmVwb3NpdG9yeS5uYW1lfS9kb3dubG9hZHNgO1xuICAgIGNvbnN0IGVuY29kZWRVc2VyQW5kUGFzcyA9IEJ1ZmZlci5mcm9tKGAke2F1dGgudXNlcm5hbWV9OiR7YXV0aC5hcHBQYXNzd29yZH1gKS50b1N0cmluZygnYmFzZTY0Jyk7XG5cbiAgICBpZiAoIShoYXNSZXBvc2l0b3J5Q29uZmlnICYmIGNvbmZpZy5yZXBvc2l0b3J5Lm93bmVyICYmIGNvbmZpZy5yZXBvc2l0b3J5Lm5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdJbiBvcmRlciB0byBwdWJsaXNoIHRvIEJpdGJ1Y2tldCB5b3UgbXVzdCBzZXQgdGhlIFwicmVwb3NpdG9yeS5vd25lclwiIGFuZCBcInJlcG9zaXRvcnkubmFtZVwiIHByb3BlcnRpZXMgaW4geW91ciBGb3JnZSBjb25maWcuIFNlZSB0aGUgZG9jcyBmb3IgbW9yZSBpbmZvJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoIWF1dGguYXBwUGFzc3dvcmQgfHwgIWF1dGgudXNlcm5hbWUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ0luIG9yZGVyIHRvIHB1Ymxpc2ggdG8gQml0YnVja2V0IHByb3ZpZGUgY3JlZGVudGlhbHMsIGVpdGhlciB0aHJvdWdoIFwiYXV0aC5hcHBQYXNzd29yZFwiIGFuZCBcImF1dGgudXNlcm5hbWVcIiBwcm9wZXJ0aWVzIGluIHlvdXIgRm9yZ2UgY29uZmlnIG9yIHVzaW5nIEJJVEJVQ0tFVF9BUFBfUEFTU1dPUkQgYW5kIEJJVEJVQ0tFVF9VU0VSTkFNRSBlbnZpcm9ubWVudCB2YXJpYWJsZXMnXG4gICAgICApO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgW2luZGV4LCBtYWtlUmVzdWx0XSBvZiBtYWtlUmVzdWx0cy5lbnRyaWVzKCkpIHtcbiAgICAgIGNvbnN0IGRhdGEgPSBuZXcgRm9ybURhdGEoKTtcblxuICAgICAgZm9yIChjb25zdCBhcnRpZmFjdFBhdGggb2YgbWFrZVJlc3VsdC5hcnRpZmFjdHMpIHtcbiAgICAgICAgZGF0YS5hcHBlbmQoJ2ZpbGVzJywgZnMuY3JlYXRlUmVhZFN0cmVhbShhcnRpZmFjdFBhdGgpKTtcbiAgICAgIH1cblxuICAgICAgLy8gSWYgd2UgYXJlIG5vdCBzdXBwb3NlZCB0byBvdmVycmlkZSBhbiBleGlzdGluZyB2ZXJzaW9uLCB3ZSdsbCBjaGVjayBjaGVjayBpZiBhbnkgb2ZcbiAgICAgIC8vIHRoZSBmaWxlcyBleGlzdCBmaXJzdFxuICAgICAgaWYgKCFyZXBsYWNlRXhpc3RpbmdGaWxlcykge1xuICAgICAgICBmb3IgKGNvbnN0IGFydGlmYWN0UGF0aCBvZiBtYWtlUmVzdWx0LmFydGlmYWN0cykge1xuICAgICAgICAgIGNvbnN0IGZpbGVOYW1lID0gcGF0aC5iYXNlbmFtZShhcnRpZmFjdFBhdGgpO1xuXG4gICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChgJHthcGlVcmx9LyR7ZmlsZU5hbWV9YCwge1xuICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICBBdXRob3JpemF0aW9uOiBgQmFzaWMgJHtlbmNvZGVkVXNlckFuZFBhc3N9YCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBtZXRob2Q6ICdIRUFEJyxcbiAgICAgICAgICAgIC8vIFdlIHNldCByZWRpcmVjdCB0byAnbWFudWFsJyBzbyB0aGF0IHdlIGdldCB0aGUgMzAyIHJlZGlyZWN0cyBpZiB0aGUgZmlsZVxuICAgICAgICAgICAgLy8gYWxyZWFkeSBleGlzdHNcbiAgICAgICAgICAgIHJlZGlyZWN0OiAnbWFudWFsJyxcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgPT09IDMwMikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICBgVW5hYmxlIHRvIHB1Ymxpc2ggXCIke2ZpbGVOYW1lfVwiIGFzIGl0IGhhcyBiZWVuIHB1Ymxpc2hlZCBwcmV2aW91c2x5LiBVc2UgdGhlIFwicmVwbGFjZUV4aXN0aW5nRmlsZXNcIiBwcm9wZXJ0eSBpbiB5b3VyIEZvcmdlIGNvbmZpZyB0byBvdmVycmlkZSB0aGlzLmBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHNldFN0YXR1c0xpbmUoYFVwbG9hZGluZyBkaXN0cmlidXRhYmxlICgke2luZGV4ICsgMX0vJHttYWtlUmVzdWx0cy5sZW5ndGh9KWApO1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChhcGlVcmwsIHtcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgIEF1dGhvcml6YXRpb246IGBCYXNpYyAke2VuY29kZWRVc2VyQW5kUGFzc31gLFxuICAgICAgICB9LFxuICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgYm9keTogZGF0YSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBXZSB3aWxsIGdldCBhIDIwMCBvbiB0aGUgaW5pdGFsIHVwbG9hZCBhbmQgYSAyMDEgaWYgcHVibGlzaGluZyBvdmVyIHRoZSBzYW1lIHZlcnNpb25cbiAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgIT09IDIwMCAmJiByZXNwb25zZS5zdGF0dXMgIT09IDIwMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgcmVzcG9uc2UgY29kZSBmcm9tIEJpdGJ1Y2tldDogJHtyZXNwb25zZS5zdGF0dXN9ICR7cmVzcG9uc2Uuc3RhdHVzVGV4dH1cXG5cXG5Cb2R5OlxcbiR7YXdhaXQgcmVzcG9uc2UudGV4dCgpfWApO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgeyBQdWJsaXNoZXJCaXRidWNrZXQsIFB1Ymxpc2hlckJpdGJ1Y2tldENvbmZpZyB9O1xuIl0sIm5hbWVzIjpbIlB1Ymxpc2hlckJpdGJ1Y2tldENvbmZpZyIsIlB1Ymxpc2hlckJpdGJ1Y2tldCIsIlB1Ymxpc2hlckJhc2UiLCJwdWJsaXNoIiwibWFrZVJlc3VsdHMiLCJzZXRTdGF0dXNMaW5lIiwiY29uZmlnIiwiaGFzUmVwb3NpdG9yeUNvbmZpZyIsInJlcG9zaXRvcnkiLCJyZXBsYWNlRXhpc3RpbmdGaWxlcyIsIkJvb2xlYW4iLCJhcHBQYXNzd29yZCIsInByb2Nlc3MiLCJlbnYiLCJCSVRCVUNLRVRfQVBQX1BBU1NXT1JEIiwidXNlcm5hbWUiLCJCSVRCVUNLRVRfVVNFUk5BTUUiLCJhdXRoIiwiYXBpVXJsIiwib3duZXIiLCJuYW1lIiwiZW5jb2RlZFVzZXJBbmRQYXNzIiwiQnVmZmVyIiwiZnJvbSIsInRvU3RyaW5nIiwiRXJyb3IiLCJpbmRleCIsIm1ha2VSZXN1bHQiLCJlbnRyaWVzIiwiZGF0YSIsIkZvcm1EYXRhIiwiYXJ0aWZhY3RQYXRoIiwiYXJ0aWZhY3RzIiwiYXBwZW5kIiwiZnMiLCJjcmVhdGVSZWFkU3RyZWFtIiwiZmlsZU5hbWUiLCJwYXRoIiwiYmFzZW5hbWUiLCJyZXNwb25zZSIsImZldGNoIiwiaGVhZGVycyIsIkF1dGhvcml6YXRpb24iLCJtZXRob2QiLCJyZWRpcmVjdCIsInN0YXR1cyIsImxlbmd0aCIsImJvZHkiLCJzdGF0dXNUZXh0IiwidGV4dCJdLCJtYXBwaW5ncyI6Ijs7OzsrQkFrRjZCQSxDQUF3Qjs7O2VBQXhCQSxPQUF3Qjs7OztBQWxGcEMsR0FBTSxDQUFOLEtBQU07QUFFeUIsR0FBZ0MsQ0FBaEMsY0FBZ0M7QUFDM0QsR0FBVyxDQUFYLFNBQVc7QUFDakIsR0FBVSxDQUFWLFFBQVU7QUFDUCxHQUFZLENBQVosVUFBWTtBQUVXLEdBQVUsQ0FBVixPQUFVOzs7Ozs7TUFFOUJDLGtCQUFrQixTQUFTQyxjQUFhO1VBR3JEQyxPQUFPLENBQUMsQ0FBQyxDQUFDQyxXQUFXLEdBQUVDLGFBQWEsRUFBbUIsQ0FBQyxFQUFpQixDQUFD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
|