dugite 3.0.0-rc0 → 3.0.0-rc10
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/.node-version +1 -0
- package/build/lib/env-map.d.ts +20 -0
- package/build/lib/env-map.js +65 -0
- package/build/lib/env-map.js.map +1 -0
- package/build/lib/errors.d.ts +24 -7
- package/build/lib/errors.js +42 -8
- package/build/lib/errors.js.map +1 -1
- package/build/lib/exec.d.ts +102 -0
- package/build/lib/exec.js +53 -0
- package/build/lib/exec.js.map +1 -0
- package/build/lib/git-environment.d.ts +5 -4
- package/build/lib/git-environment.js +39 -45
- package/build/lib/git-environment.js.map +1 -1
- package/build/lib/ignore-closed-input-stream.d.ts +30 -0
- package/build/lib/ignore-closed-input-stream.js +65 -0
- package/build/lib/ignore-closed-input-stream.js.map +1 -0
- package/build/lib/index.d.ts +6 -2
- package/build/lib/index.js +7 -6
- package/build/lib/index.js.map +1 -1
- package/build/lib/parse-bad-config-value-error-info.d.ts +4 -0
- package/build/lib/parse-bad-config-value-error-info.js +20 -0
- package/build/lib/parse-bad-config-value-error-info.js.map +1 -0
- package/build/lib/parse-error.d.ts +2 -0
- package/build/lib/parse-error.js +8 -0
- package/build/lib/parse-error.js.map +1 -0
- package/build/lib/spawn.d.ts +21 -0
- package/build/lib/spawn.js +21 -0
- package/build/lib/spawn.js.map +1 -0
- package/package.json +11 -21
- package/script/clean.js +6 -0
- package/script/config.js +7 -11
- package/script/download-git.js +104 -105
- package/script/embedded-git.json +29 -24
- package/script/test.mjs +23 -0
- package/build/lib/git-process.d.ts +0 -121
- package/build/lib/git-process.js +0 -297
- package/build/lib/git-process.js.map +0 -1
- package/jest.external.config.js +0 -13
- package/jest.fast.config.js +0 -13
- package/jest.slow.config.js +0 -13
- package/script/utils.js +0 -27
@@ -0,0 +1,65 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.ignoreClosedInputStream = void 0;
|
4
|
+
/**
|
5
|
+
* Prevent errors originating from the stdin stream related
|
6
|
+
* to the child process closing the pipe from bubbling up and
|
7
|
+
* causing an unhandled exception when no error handler is
|
8
|
+
* attached to the input stream.
|
9
|
+
*
|
10
|
+
* The common scenario where this happens is if the consumer
|
11
|
+
* is writing data to the stdin stream of a child process and
|
12
|
+
* the child process for one reason or another decides to either
|
13
|
+
* terminate or simply close its standard input. Imagine this
|
14
|
+
* scenario
|
15
|
+
*
|
16
|
+
* cat /dev/zero | head -c 1
|
17
|
+
*
|
18
|
+
* The 'head' command would close its standard input (by terminating)
|
19
|
+
* the moment it has read one byte. In the case of Git this could
|
20
|
+
* happen if you for example pass badly formed input to apply-patch.
|
21
|
+
*
|
22
|
+
* Since consumers of dugite using the `exec` api are unable to get
|
23
|
+
* a hold of the stream until after we've written data to it they're
|
24
|
+
* unable to fix it themselves so we'll just go ahead and ignore the
|
25
|
+
* error for them. By supressing the stream error we can pick up on
|
26
|
+
* the real error when the process exits when we parse the exit code
|
27
|
+
* and the standard error.
|
28
|
+
*
|
29
|
+
* See https://github.com/desktop/desktop/pull/4027#issuecomment-366213276
|
30
|
+
*/
|
31
|
+
function ignoreClosedInputStream({ stdin }) {
|
32
|
+
// If Node fails to spawn due to a runtime error (EACCESS, EAGAIN, etc)
|
33
|
+
// it will not setup the stdio streams, see
|
34
|
+
// https://github.com/nodejs/node/blob/v10.16.0/lib/internal/child_process.js#L342-L354
|
35
|
+
// The error itself will be emitted asynchronously but we're still in
|
36
|
+
// the synchronous path so if we attempts to call `.on` on `.stdin`
|
37
|
+
// (which is undefined) that error would be thrown before the underlying
|
38
|
+
// error.
|
39
|
+
if (!stdin) {
|
40
|
+
return;
|
41
|
+
}
|
42
|
+
stdin.on('error', err => {
|
43
|
+
const code = 'code' in err && typeof err.code === 'string' ? err.code : undefined;
|
44
|
+
// Is the error one that we'd expect from the input stream being
|
45
|
+
// closed, i.e. EPIPE on macOS and EOF on Windows. We've also
|
46
|
+
// seen ECONNRESET failures on Linux hosts so let's throw that in
|
47
|
+
// there for good measure.
|
48
|
+
if (code === 'EPIPE' || code === 'EOF' || code === 'ECONNRESET') {
|
49
|
+
return;
|
50
|
+
}
|
51
|
+
// Nope, this is something else. Are there any other error listeners
|
52
|
+
// attached than us? If not we'll have to mimic the behavior of
|
53
|
+
// EventEmitter.
|
54
|
+
//
|
55
|
+
// See https://nodejs.org/api/errors.html#errors_error_propagation_and_interception
|
56
|
+
//
|
57
|
+
// "For all EventEmitter objects, if an 'error' event handler is not
|
58
|
+
// provided, the error will be thrown"
|
59
|
+
if (stdin.listeners('error').length <= 1) {
|
60
|
+
throw err;
|
61
|
+
}
|
62
|
+
});
|
63
|
+
}
|
64
|
+
exports.ignoreClosedInputStream = ignoreClosedInputStream;
|
65
|
+
//# sourceMappingURL=ignore-closed-input-stream.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ignore-closed-input-stream.js","sourceRoot":"","sources":["../../lib/ignore-closed-input-stream.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,SAAgB,uBAAuB,CAAC,EAAE,KAAK,EAAgB;IAC7D,uEAAuE;IACvE,2CAA2C;IAC3C,uFAAuF;IACvF,qEAAqE;IACrE,mEAAmE;IACnE,wEAAwE;IACxE,SAAS;IACT,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAM;IACR,CAAC;IAED,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE;QACtB,MAAM,IAAI,GACR,MAAM,IAAI,GAAG,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;QAEtE,gEAAgE;QAChE,6DAA6D;QAC7D,iEAAiE;QACjE,0BAA0B;QAC1B,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;YAChE,OAAM;QACR,CAAC;QAED,oEAAoE;QACpE,+DAA+D;QAC/D,gBAAgB;QAChB,EAAE;QACF,mFAAmF;QACnF,EAAE;QACF,oEAAoE;QACpE,uCAAuC;QACvC,IAAI,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACzC,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AApCD,0DAoCC"}
|
package/build/lib/index.d.ts
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
-
export
|
2
|
-
export
|
1
|
+
export * from './exec';
|
2
|
+
export * from './spawn';
|
3
|
+
export * from './parse-error';
|
4
|
+
export * from './parse-bad-config-value-error-info';
|
5
|
+
export { GitError, ExecError } from './errors';
|
3
6
|
export * from './git-environment';
|
7
|
+
export * from './ignore-closed-input-stream';
|
package/build/lib/index.js
CHANGED
@@ -14,13 +14,14 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
15
15
|
};
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
17
|
-
exports.
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
exports.ExecError = exports.GitError = void 0;
|
18
|
+
__exportStar(require("./exec"), exports);
|
19
|
+
__exportStar(require("./spawn"), exports);
|
20
|
+
__exportStar(require("./parse-error"), exports);
|
21
|
+
__exportStar(require("./parse-bad-config-value-error-info"), exports);
|
21
22
|
var errors_1 = require("./errors");
|
22
23
|
Object.defineProperty(exports, "GitError", { enumerable: true, get: function () { return errors_1.GitError; } });
|
23
|
-
Object.defineProperty(exports, "
|
24
|
-
Object.defineProperty(exports, "GitNotFoundErrorCode", { enumerable: true, get: function () { return errors_1.GitNotFoundErrorCode; } });
|
24
|
+
Object.defineProperty(exports, "ExecError", { enumerable: true, get: function () { return errors_1.ExecError; } });
|
25
25
|
__exportStar(require("./git-environment"), exports);
|
26
|
+
__exportStar(require("./ignore-closed-input-stream"), exports);
|
26
27
|
//# sourceMappingURL=index.js.map
|
package/build/lib/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,yCAAsB;AACtB,0CAAuB;AACvB,gDAA6B;AAC7B,sEAAmD;AACnD,mCAA8C;AAArC,kGAAA,QAAQ,OAAA;AAAE,mGAAA,SAAS,OAAA;AAC5B,oDAAiC;AACjC,+DAA4C"}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.parseBadConfigValueErrorInfo = void 0;
|
4
|
+
const errors_1 = require("./errors");
|
5
|
+
function parseBadConfigValueErrorInfo(stderr) {
|
6
|
+
const errorEntry = Object.entries(errors_1.GitErrorRegexes).find(([_, v]) => v === errors_1.GitError.BadConfigValue);
|
7
|
+
if (errorEntry === undefined) {
|
8
|
+
return null;
|
9
|
+
}
|
10
|
+
const m = stderr.match(errorEntry[0]);
|
11
|
+
if (m === null) {
|
12
|
+
return null;
|
13
|
+
}
|
14
|
+
if (!m[1] || !m[2]) {
|
15
|
+
return null;
|
16
|
+
}
|
17
|
+
return { key: m[2], value: m[1] };
|
18
|
+
}
|
19
|
+
exports.parseBadConfigValueErrorInfo = parseBadConfigValueErrorInfo;
|
20
|
+
//# sourceMappingURL=parse-bad-config-value-error-info.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"parse-bad-config-value-error-info.js","sourceRoot":"","sources":["../../lib/parse-bad-config-value-error-info.ts"],"names":[],"mappings":";;;AAAA,qCAAoD;AAEpD,SAAgB,4BAA4B,CAC1C,MAAc;IAEd,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,wBAAe,CAAC,CAAC,IAAI,CACrD,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,iBAAQ,CAAC,cAAc,CAC1C,CAAA;IAED,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;IAErC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QACf,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;AACnC,CAAC;AAtBD,oEAsBC"}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.parseError = void 0;
|
4
|
+
const errors_1 = require("./errors");
|
5
|
+
/** Try to parse an error type from stderr. */
|
6
|
+
const parseError = (stderr) => Object.entries(errors_1.GitErrorRegexes).find(([re]) => stderr.match(re))?.[1] ?? null;
|
7
|
+
exports.parseError = parseError;
|
8
|
+
//# sourceMappingURL=parse-error.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"parse-error.js","sourceRoot":"","sources":["../../lib/parse-error.ts"],"names":[],"mappings":";;;AAAA,qCAA0C;AAE1C,8CAA8C;AACvC,MAAM,UAAU,GAAG,CAAC,MAAc,EAAE,EAAE,CAC3C,MAAM,CAAC,OAAO,CAAC,wBAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAA;AADlE,QAAA,UAAU,cACwD"}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
/// <reference types="node" />
|
2
|
+
/**
|
3
|
+
* A set of configuration options that can be passed when
|
4
|
+
* executing a streaming Git command.
|
5
|
+
*/
|
6
|
+
export interface IGitSpawnOptions {
|
7
|
+
/**
|
8
|
+
* An optional collection of key-value pairs which will be
|
9
|
+
* set as environment variables before executing the git
|
10
|
+
* process.
|
11
|
+
*/
|
12
|
+
readonly env?: Record<string, string | undefined>;
|
13
|
+
}
|
14
|
+
/**
|
15
|
+
* Execute a command and interact with the process outputs directly.
|
16
|
+
*
|
17
|
+
* The returned promise will reject when the git executable fails to launch,
|
18
|
+
* in which case the thrown Error will have a string `code` property. See
|
19
|
+
* `errors.ts` for some of the known error codes.
|
20
|
+
*/
|
21
|
+
export declare function spawn(args: string[], path: string, opts?: IGitSpawnOptions): import("child_process").ChildProcessWithoutNullStreams;
|
@@ -0,0 +1,21 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.spawn = void 0;
|
4
|
+
const ignore_closed_input_stream_1 = require("./ignore-closed-input-stream");
|
5
|
+
const git_environment_1 = require("./git-environment");
|
6
|
+
const child_process_1 = require("child_process");
|
7
|
+
/**
|
8
|
+
* Execute a command and interact with the process outputs directly.
|
9
|
+
*
|
10
|
+
* The returned promise will reject when the git executable fails to launch,
|
11
|
+
* in which case the thrown Error will have a string `code` property. See
|
12
|
+
* `errors.ts` for some of the known error codes.
|
13
|
+
*/
|
14
|
+
function spawn(args, path, opts) {
|
15
|
+
const { env, gitLocation } = (0, git_environment_1.setupEnvironment)(opts?.env ?? {});
|
16
|
+
const spawnedProcess = (0, child_process_1.spawn)(gitLocation, args, { env, cwd: path });
|
17
|
+
(0, ignore_closed_input_stream_1.ignoreClosedInputStream)(spawnedProcess);
|
18
|
+
return spawnedProcess;
|
19
|
+
}
|
20
|
+
exports.spawn = spawn;
|
21
|
+
//# sourceMappingURL=spawn.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"spawn.js","sourceRoot":"","sources":["../../lib/spawn.ts"],"names":[],"mappings":";;;AAAA,6EAAsE;AACtE,uDAAoD;AACpD,iDAA+C;AAe/C;;;;;;GAMG;AACH,SAAgB,KAAK,CAAC,IAAc,EAAE,IAAY,EAAE,IAAuB;IACzE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,IAAA,kCAAgB,EAAC,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,CAAA;IAC9D,MAAM,cAAc,GAAG,IAAA,qBAAM,EAAC,WAAW,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAA;IAEpE,IAAA,oDAAuB,EAAC,cAAc,CAAC,CAAA;IAEvC,OAAO,cAAc,CAAA;AACvB,CAAC;AAPD,sBAOC"}
|
package/package.json
CHANGED
@@ -1,26 +1,23 @@
|
|
1
1
|
{
|
2
2
|
"name": "dugite",
|
3
|
-
"version": "3.0.0-
|
3
|
+
"version": "3.0.0-rc10",
|
4
4
|
"description": "Elegant bindings for Git",
|
5
5
|
"main": "./build/lib/index.js",
|
6
6
|
"typings": "./build/lib/index.d.ts",
|
7
7
|
"scripts": {
|
8
|
-
"clean": "
|
8
|
+
"clean": "node script/clean.js",
|
9
9
|
"build": "yarn clean && tsc -p ./tsconfig.json && tsc -p ./examples/tsconfig.json",
|
10
10
|
"prepack": "yarn build && yarn test",
|
11
11
|
"postpublish": "git push --follow-tags",
|
12
|
-
"test": "
|
13
|
-
"test:fast": "cross-env LOCAL_GIT_DIRECTORY=./git/ jest --runInBand --silent --config ./jest.fast.config.js",
|
14
|
-
"test:slow": "cross-env LOCAL_GIT_DIRECTORY=./git/ jest --runInBand --silent --config ./jest.slow.config.js",
|
15
|
-
"test:external": "jest --runInBand --silent --config ./jest.external.config.js",
|
12
|
+
"test": "node script/test.mjs",
|
16
13
|
"download-git": "node ./script/download-git.js",
|
17
14
|
"postinstall": "node ./script/download-git.js",
|
18
|
-
"prettify": "prettier \"{examples,lib,script,test}/**/*.ts\" --write",
|
19
|
-
"is-it-pretty": "prettier
|
15
|
+
"prettify": "prettier \"{examples,lib,script,test}/**/*.{ts,js,mjs}\" --write",
|
16
|
+
"is-it-pretty": "prettier \"{examples,lib,script,test}/**/*.{ts,js,mjs}\" --check",
|
20
17
|
"update-embedded-git": "node ./script/update-embedded-git.js"
|
21
18
|
},
|
22
19
|
"engines": {
|
23
|
-
"node": ">=
|
20
|
+
"node": ">= 20"
|
24
21
|
},
|
25
22
|
"repository": {
|
26
23
|
"type": "git",
|
@@ -34,21 +31,14 @@
|
|
34
31
|
"homepage": "https://github.com/desktop/dugite#readme",
|
35
32
|
"dependencies": {
|
36
33
|
"progress": "^2.0.3",
|
37
|
-
"tar": "^
|
34
|
+
"tar-stream": "^3.1.7"
|
38
35
|
},
|
39
36
|
"devDependencies": {
|
40
|
-
"@types/
|
41
|
-
"@types/node": "18",
|
37
|
+
"@types/node": "20",
|
42
38
|
"@types/progress": "^2.0.1",
|
43
|
-
"
|
44
|
-
"
|
45
|
-
"
|
46
|
-
"find-git-exec": "^0.0.4",
|
47
|
-
"jest": "^28.1.3",
|
48
|
-
"prettier": "^2.7.1",
|
49
|
-
"rimraf": "^2.5.4",
|
50
|
-
"temp": "^0.9.0",
|
51
|
-
"ts-jest": "^28.0.8",
|
39
|
+
"node-test-github-reporter": "^1.2.0",
|
40
|
+
"prettier": "^3.3.1",
|
41
|
+
"tsx": "^4.10.5",
|
52
42
|
"typescript": "^5.4.5"
|
53
43
|
}
|
54
44
|
}
|
package/script/clean.js
ADDED
package/script/config.js
CHANGED
@@ -11,22 +11,16 @@ function getConfig() {
|
|
11
11
|
source: '',
|
12
12
|
checksum: '',
|
13
13
|
fileName: '',
|
14
|
-
tempFile: ''
|
14
|
+
tempFile: '',
|
15
15
|
}
|
16
16
|
|
17
17
|
// Possible values are ‘x64’, ‘arm’, ‘arm64’, ‘s390’, ‘s390x’, ‘mipsel’, ‘ia32’, ‘mips’, ‘ppc’ and ‘ppc64’
|
18
|
-
let arch = os.arch()
|
18
|
+
let arch = os.arch()
|
19
19
|
|
20
20
|
if (process.env.npm_config_arch) {
|
21
21
|
// If a specific npm_config_arch is set, we use that one instead of the OS arch (to support cross compilation)
|
22
|
-
console.log('npm_config_arch detected: ' + process.env.npm_config_arch)
|
23
|
-
arch = process.env.npm_config_arch
|
24
|
-
}
|
25
|
-
|
26
|
-
if (process.platform === 'win32' && arch === 'arm64') {
|
27
|
-
// Use the Dugite Native ia32 package for Windows arm64 (arm64 can run 32-bit code through emulation)
|
28
|
-
console.log('Downloading 32-bit Dugite Native for Windows arm64');
|
29
|
-
arch = 'ia32';
|
22
|
+
console.log('npm_config_arch detected: ' + process.env.npm_config_arch)
|
23
|
+
arch = process.env.npm_config_arch
|
30
24
|
}
|
31
25
|
|
32
26
|
const key = `${process.platform}-${arch}`
|
@@ -37,7 +31,9 @@ function getConfig() {
|
|
37
31
|
config.checksum = entry.checksum
|
38
32
|
config.source = entry.url
|
39
33
|
} else {
|
40
|
-
console.log(
|
34
|
+
console.log(
|
35
|
+
`No embedded Git found for ${process.platform} and architecture ${arch}`
|
36
|
+
)
|
41
37
|
}
|
42
38
|
|
43
39
|
if (config.source !== '') {
|
package/script/download-git.js
CHANGED
@@ -1,132 +1,131 @@
|
|
1
|
-
const fs = require('fs')
|
2
|
-
|
3
1
|
const ProgressBar = require('progress')
|
4
|
-
const tar = require('tar')
|
5
|
-
const https = require('https')
|
6
2
|
const { createHash } = require('crypto')
|
7
|
-
const {
|
3
|
+
const { createReadStream, createWriteStream } = require('fs')
|
4
|
+
const { rm, mkdir, access, symlink } = require('fs/promises')
|
5
|
+
const { extract } = require('tar-stream')
|
6
|
+
const { createGunzip } = require('zlib')
|
7
|
+
const { join } = require('path')
|
8
|
+
const assert = require('node:assert')
|
9
|
+
/**
|
10
|
+
* Returns a value indicating whether or not the provided path exists (as in
|
11
|
+
* whether it's visible to the current process or not).
|
12
|
+
*/
|
13
|
+
const pathExists = path =>
|
14
|
+
access(path).then(
|
15
|
+
() => true,
|
16
|
+
() => false
|
17
|
+
)
|
8
18
|
|
9
|
-
const
|
19
|
+
const { Readable } = require('stream')
|
10
20
|
|
11
|
-
const
|
12
|
-
const h = createHash('sha256').on('finish', () => {
|
13
|
-
const hash = h.digest('hex')
|
14
|
-
const match = hash === config.checksum
|
15
|
-
if (!match) {
|
16
|
-
console.log(`Validation failed. Expected '${config.checksum}' but got '${hash}'`)
|
17
|
-
}
|
18
|
-
callback(match)
|
19
|
-
})
|
21
|
+
const config = require('./config')()
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
+
const verifyFile = function (file, callback) {
|
24
|
+
return new Promise((resolve, reject) => {
|
25
|
+
const h = createHash('sha256')
|
26
|
+
.on('error', reject)
|
27
|
+
.on('finish', () => {
|
28
|
+
const hash = h.digest('hex')
|
29
|
+
if (hash !== config.checksum) {
|
30
|
+
reject(
|
31
|
+
new Error(
|
32
|
+
`Validation failed. Expected '${config.checksum}' but got '${hash}'`
|
33
|
+
)
|
34
|
+
)
|
35
|
+
} else {
|
36
|
+
resolve()
|
37
|
+
}
|
38
|
+
})
|
23
39
|
|
24
|
-
|
25
|
-
tar.x({ cwd: config.outputPath, file }).catch(e => {
|
26
|
-
console.log('Unable to extract archive, aborting...', error)
|
27
|
-
process.exit(1)
|
40
|
+
createReadStream(file).pipe(h).on('error', reject)
|
28
41
|
})
|
29
42
|
}
|
30
43
|
|
31
|
-
const
|
32
|
-
|
33
|
-
|
34
|
-
|
44
|
+
const unpackFile = file =>
|
45
|
+
new Promise((resolve, reject) => {
|
46
|
+
createReadStream(file)
|
47
|
+
.pipe(new createGunzip())
|
48
|
+
.pipe(extract())
|
49
|
+
.on('entry', ({ type, name, mode, linkname }, stream, next) => {
|
50
|
+
if (name.includes('..')) {
|
51
|
+
throw new Error(`invalid file name: ${name}`)
|
52
|
+
}
|
53
|
+
const p = join(config.outputPath, name)
|
54
|
+
if (type === 'file') {
|
55
|
+
stream.pipe(createWriteStream(p, { mode })).on('finish', next)
|
56
|
+
} else if (type === 'directory') {
|
57
|
+
mkdir(p).then(next)
|
58
|
+
} else if (type === 'symlink') {
|
59
|
+
symlink(linkname, p).then(next)
|
60
|
+
} else {
|
61
|
+
throw new Error(`unknown file type: ${type}`)
|
62
|
+
}
|
63
|
+
})
|
64
|
+
.on('error', reject)
|
65
|
+
.on('finish', resolve)
|
66
|
+
})
|
35
67
|
|
36
|
-
|
68
|
+
const downloadAndUnpack = async url => {
|
69
|
+
const res = await fetch(url, {
|
37
70
|
headers: {
|
38
71
|
Accept: 'application/octet-stream',
|
39
|
-
'User-Agent': 'dugite'
|
72
|
+
'User-Agent': 'dugite',
|
40
73
|
},
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
const req = https.get(url, options)
|
45
|
-
|
46
|
-
req.on('error', function(error) {
|
47
|
-
if (error.code === 'ETIMEDOUT') {
|
48
|
-
console.log(
|
49
|
-
`A timeout has occurred while downloading '${url}' - check ` +
|
50
|
-
`your internet connection and try again. If you are using a proxy, ` +
|
51
|
-
`make sure that the HTTP_PROXY and HTTPS_PROXY environment variables are set.`,
|
52
|
-
error
|
53
|
-
)
|
54
|
-
} else {
|
55
|
-
console.log(`Error raised while downloading ${url}`, error)
|
56
|
-
}
|
74
|
+
}).catch(e => {
|
75
|
+
console.log('Unable to download archive, aborting...', e)
|
57
76
|
process.exit(1)
|
58
77
|
})
|
59
78
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
}
|
65
|
-
|
66
|
-
if (res.statusCode !== 200) {
|
67
|
-
console.log(`Non-200 response returned from ${url} - (${res.statusCode})`)
|
68
|
-
process.exit(1)
|
69
|
-
}
|
70
|
-
|
71
|
-
const len = parseInt(res.headers['content-length'], 10)
|
79
|
+
if (!res.ok) {
|
80
|
+
console.log(`Got ${res.status} trying to download archive, aborting...`)
|
81
|
+
process.exit(1)
|
82
|
+
}
|
72
83
|
|
73
|
-
|
74
|
-
complete: '=',
|
75
|
-
incomplete: ' ',
|
76
|
-
width: 50,
|
77
|
-
total: len
|
78
|
-
})
|
84
|
+
const len = parseInt(res.headers.get('content-length'), 10)
|
79
85
|
|
80
|
-
|
86
|
+
const bar = new ProgressBar('Downloading Git [:bar] :percent :etas', {
|
87
|
+
complete: '=',
|
88
|
+
incomplete: ' ',
|
89
|
+
width: 50,
|
90
|
+
total: len,
|
91
|
+
})
|
81
92
|
|
82
|
-
|
83
|
-
res.
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
console.log(`checksum verification failed, refusing to unpack...`)
|
89
|
-
process.exit(1)
|
90
|
-
}
|
91
|
-
})
|
92
|
-
})
|
93
|
+
await new Promise((resolve, reject) => {
|
94
|
+
Readable.fromWeb(res.body)
|
95
|
+
.on('data', c => bar.tick(c.length))
|
96
|
+
.pipe(createWriteStream(config.tempFile))
|
97
|
+
.on('error', reject)
|
98
|
+
.on('finish', resolve)
|
93
99
|
})
|
100
|
+
await verifyFile(config.tempFile)
|
101
|
+
await unpackFile(config.tempFile)
|
94
102
|
}
|
95
103
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
104
|
+
;(async function run() {
|
105
|
+
if (config.source === '') {
|
106
|
+
console.log(
|
107
|
+
`Skipping downloading embedded Git as platform '${process.platform}' is not supported.`
|
108
|
+
)
|
109
|
+
console.log(
|
110
|
+
`To learn more about using dugite with a system Git: https://git.io/vF5oj`
|
111
|
+
)
|
112
|
+
process.exit(0)
|
113
|
+
}
|
103
114
|
|
104
|
-
rm(config.outputPath, { recursive: true, force: true }
|
105
|
-
if (error) {
|
115
|
+
await rm(config.outputPath, { recursive: true, force: true }).catch(error => {
|
106
116
|
console.log(`Unable to clean directory at ${config.outputPath}`, error)
|
107
117
|
process.exit(1)
|
108
|
-
}
|
109
|
-
|
110
|
-
mkdir(config.outputPath, { recursive: true }, function(error) {
|
111
|
-
if (error) {
|
112
|
-
console.log(`Unable to create directory at ${config.outputPath}`, error)
|
113
|
-
process.exit(1)
|
114
|
-
}
|
115
|
-
|
116
|
-
const tempFile = config.tempFile
|
118
|
+
})
|
117
119
|
|
118
|
-
|
119
|
-
verifyFile(tempFile, valid => {
|
120
|
-
if (valid) {
|
121
|
-
unpackFile(tempFile)
|
122
|
-
} else {
|
123
|
-
rmSync(tempFile)
|
124
|
-
downloadAndUnpack(config.source)
|
125
|
-
}
|
126
|
-
})
|
127
|
-
return
|
128
|
-
}
|
120
|
+
const tempFile = config.tempFile
|
129
121
|
|
130
|
-
|
131
|
-
|
132
|
-
|
122
|
+
if (await pathExists(tempFile)) {
|
123
|
+
await verifyFile(tempFile).catch(e => {
|
124
|
+
console.log('Unable to verify cached archive, removing...', e)
|
125
|
+
return rm(tempFile)
|
126
|
+
})
|
127
|
+
await unpackFile(tempFile)
|
128
|
+
} else {
|
129
|
+
await downloadAndUnpack(config.source)
|
130
|
+
}
|
131
|
+
})()
|
package/script/embedded-git.json
CHANGED
@@ -1,42 +1,47 @@
|
|
1
1
|
{
|
2
2
|
"win32-x64": {
|
3
|
-
"name": "dugite-native-v2.
|
4
|
-
"url": "https://github.com/desktop/dugite-native/releases/download/v2.
|
5
|
-
"checksum": "
|
3
|
+
"name": "dugite-native-v2.47.1-8d348e6-windows-x64.tar.gz",
|
4
|
+
"url": "https://github.com/desktop/dugite-native/releases/download/v2.47.1/dugite-native-v2.47.1-8d348e6-windows-x64.tar.gz",
|
5
|
+
"checksum": "bca0fb95b136ec4227452ee603eb5b8bf5213f9a8c99b72a617db654046c17c7"
|
6
6
|
},
|
7
7
|
"win32-ia32": {
|
8
|
-
"name": "dugite-native-v2.
|
9
|
-
"url": "https://github.com/desktop/dugite-native/releases/download/v2.
|
10
|
-
"checksum": "
|
8
|
+
"name": "dugite-native-v2.47.1-8d348e6-windows-x86.tar.gz",
|
9
|
+
"url": "https://github.com/desktop/dugite-native/releases/download/v2.47.1/dugite-native-v2.47.1-8d348e6-windows-x86.tar.gz",
|
10
|
+
"checksum": "f938bc2ef0ae702479b53bb0838b5cfeea14d35c4215757e1a6df95dea52cad4"
|
11
|
+
},
|
12
|
+
"win32-arm64": {
|
13
|
+
"name": "dugite-native-v2.47.1-8d348e6-windows-arm64.tar.gz",
|
14
|
+
"url": "https://github.com/desktop/dugite-native/releases/download/v2.47.1/dugite-native-v2.47.1-8d348e6-windows-arm64.tar.gz",
|
15
|
+
"checksum": "4a3f4d77f3fec67b1c3235a6a82c3e259eb8eb4babd868da5a3e5d5ac309c590"
|
11
16
|
},
|
12
17
|
"darwin-x64": {
|
13
|
-
"name": "dugite-native-v2.
|
14
|
-
"url": "https://github.com/desktop/dugite-native/releases/download/v2.
|
15
|
-
"checksum": "
|
18
|
+
"name": "dugite-native-v2.47.1-8d348e6-macOS-x64.tar.gz",
|
19
|
+
"url": "https://github.com/desktop/dugite-native/releases/download/v2.47.1/dugite-native-v2.47.1-8d348e6-macOS-x64.tar.gz",
|
20
|
+
"checksum": "475040cf643a3962d557aad9b91e861eace6d6bb28c01bb54535544c43e19459"
|
16
21
|
},
|
17
22
|
"darwin-arm64": {
|
18
|
-
"name": "dugite-native-v2.
|
19
|
-
"url": "https://github.com/desktop/dugite-native/releases/download/v2.
|
20
|
-
"checksum": "
|
23
|
+
"name": "dugite-native-v2.47.1-8d348e6-macOS-arm64.tar.gz",
|
24
|
+
"url": "https://github.com/desktop/dugite-native/releases/download/v2.47.1/dugite-native-v2.47.1-8d348e6-macOS-arm64.tar.gz",
|
25
|
+
"checksum": "451dc41889a4deef06e2d3495364f74f6416bda8234b876144f5c254874b306d"
|
21
26
|
},
|
22
27
|
"linux-x64": {
|
23
|
-
"name": "dugite-native-v2.
|
24
|
-
"url": "https://github.com/desktop/dugite-native/releases/download/v2.
|
25
|
-
"checksum": "
|
28
|
+
"name": "dugite-native-v2.47.1-8d348e6-ubuntu-x64.tar.gz",
|
29
|
+
"url": "https://github.com/desktop/dugite-native/releases/download/v2.47.1/dugite-native-v2.47.1-8d348e6-ubuntu-x64.tar.gz",
|
30
|
+
"checksum": "0e6b3a0776e92ddef3a3fdc966d960fbf150b3f5bb74632576c0bdfbcb638042"
|
26
31
|
},
|
27
32
|
"linux-ia32": {
|
28
|
-
"name": "dugite-native-v2.
|
29
|
-
"url": "https://github.com/desktop/dugite-native/releases/download/v2.
|
30
|
-
"checksum": "
|
33
|
+
"name": "dugite-native-v2.47.1-8d348e6-ubuntu-x86.tar.gz",
|
34
|
+
"url": "https://github.com/desktop/dugite-native/releases/download/v2.47.1/dugite-native-v2.47.1-8d348e6-ubuntu-x86.tar.gz",
|
35
|
+
"checksum": "7263bed583503808a11a5e3b5e259e63fe66e08d8c8c3934bef3bc6ca42f1e2e"
|
31
36
|
},
|
32
37
|
"linux-arm": {
|
33
|
-
"name": "dugite-native-v2.
|
34
|
-
"url": "https://github.com/desktop/dugite-native/releases/download/v2.
|
35
|
-
"checksum": "
|
38
|
+
"name": "dugite-native-v2.47.1-8d348e6-ubuntu-arm.tar.gz",
|
39
|
+
"url": "https://github.com/desktop/dugite-native/releases/download/v2.47.1/dugite-native-v2.47.1-8d348e6-ubuntu-arm.tar.gz",
|
40
|
+
"checksum": "a89292d44106150037932b95ddc233e09c6faf7489b44672c93d801838f496cd"
|
36
41
|
},
|
37
42
|
"linux-arm64": {
|
38
|
-
"name": "dugite-native-v2.
|
39
|
-
"url": "https://github.com/desktop/dugite-native/releases/download/v2.
|
40
|
-
"checksum": "
|
43
|
+
"name": "dugite-native-v2.47.1-8d348e6-ubuntu-arm64.tar.gz",
|
44
|
+
"url": "https://github.com/desktop/dugite-native/releases/download/v2.47.1/dugite-native-v2.47.1-8d348e6-ubuntu-arm64.tar.gz",
|
45
|
+
"checksum": "b9fcc671557a86259408b31875badaedd43408c9ef1fd4d502386d2bd36923ef"
|
41
46
|
}
|
42
47
|
}
|