netlify-cli 17.3.2 → 17.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -138
- package/npm-shrinkwrap.json +76 -76
- package/package.json +16 -15
- package/src/commands/addons/addons-auth.mjs +27 -30
- package/src/commands/addons/addons-config.mjs +145 -154
- package/src/commands/addons/addons-create.mjs +94 -108
- package/src/commands/addons/addons-delete.mjs +36 -41
- package/src/commands/addons/addons-list.mjs +38 -42
- package/src/commands/addons/addons.mjs +26 -28
- package/src/commands/addons/index.mjs +1 -1
- package/src/commands/api/api.mjs +45 -53
- package/src/commands/api/index.mjs +1 -1
- package/src/commands/base-command.mjs +597 -684
- package/src/commands/blobs/blobs-delete.mjs +35 -0
- package/src/commands/blobs/blobs-get.mjs +44 -0
- package/src/commands/blobs/blobs-list.mjs +48 -0
- package/src/commands/blobs/blobs-set.mjs +54 -0
- package/src/commands/blobs/blobs.mjs +32 -0
- package/src/commands/blobs/index.mjs +1 -0
- package/src/commands/build/build.mjs +55 -67
- package/src/commands/build/index.mjs +1 -1
- package/src/commands/completion/completion.mjs +41 -46
- package/src/commands/completion/index.mjs +1 -1
- package/src/commands/deploy/deploy.mjs +675 -710
- package/src/commands/deploy/index.mjs +1 -1
- package/src/commands/dev/dev-exec.mjs +20 -32
- package/src/commands/dev/dev.mjs +217 -302
- package/src/commands/dev/index.mjs +1 -1
- package/src/commands/dev/types.d.ts +30 -0
- package/src/commands/env/env-clone.mjs +157 -184
- package/src/commands/env/env-get.mjs +49 -68
- package/src/commands/env/env-import.mjs +100 -119
- package/src/commands/env/env-list.mjs +104 -129
- package/src/commands/env/env-set.mjs +160 -185
- package/src/commands/env/env-unset.mjs +104 -122
- package/src/commands/env/env.mjs +28 -30
- package/src/commands/env/index.mjs +1 -1
- package/src/commands/functions/functions-build.mjs +29 -41
- package/src/commands/functions/functions-create.mjs +533 -601
- package/src/commands/functions/functions-invoke.mjs +193 -216
- package/src/commands/functions/functions-list.mjs +45 -55
- package/src/commands/functions/functions-serve.mjs +51 -61
- package/src/commands/functions/functions.mjs +26 -32
- package/src/commands/functions/index.mjs +1 -1
- package/src/commands/index.mjs +2 -2
- package/src/commands/init/index.mjs +1 -1
- package/src/commands/init/init.mjs +138 -167
- package/src/commands/integration/deploy.mjs +337 -399
- package/src/commands/integration/index.mjs +12 -13
- package/src/commands/link/index.mjs +1 -1
- package/src/commands/link/link.mjs +298 -317
- package/src/commands/lm/index.mjs +1 -1
- package/src/commands/lm/lm-info.mjs +23 -31
- package/src/commands/lm/lm-install.mjs +13 -17
- package/src/commands/lm/lm-setup.mjs +80 -84
- package/src/commands/lm/lm-uninstall.mjs +7 -12
- package/src/commands/lm/lm.mjs +18 -22
- package/src/commands/login/index.mjs +1 -1
- package/src/commands/login/login.mjs +35 -41
- package/src/commands/logout/index.mjs +1 -1
- package/src/commands/logout/logout.mjs +25 -31
- package/src/commands/main.mjs +166 -201
- package/src/commands/open/index.mjs +1 -1
- package/src/commands/open/open-admin.mjs +15 -18
- package/src/commands/open/open-site.mjs +16 -19
- package/src/commands/open/open.mjs +24 -27
- package/src/commands/recipes/common.mjs +23 -34
- package/src/commands/recipes/index.mjs +1 -1
- package/src/commands/recipes/recipes-list.mjs +13 -20
- package/src/commands/recipes/recipes.mjs +59 -72
- package/src/commands/serve/index.mjs +1 -1
- package/src/commands/serve/serve.mjs +142 -189
- package/src/commands/sites/index.mjs +2 -2
- package/src/commands/sites/sites-create-template.mjs +214 -236
- package/src/commands/sites/sites-create.mjs +145 -157
- package/src/commands/sites/sites-delete.mjs +75 -81
- package/src/commands/sites/sites-list.mjs +63 -66
- package/src/commands/sites/sites.mjs +18 -20
- package/src/commands/status/index.mjs +1 -1
- package/src/commands/status/status-hooks.mjs +32 -34
- package/src/commands/status/status.mjs +99 -106
- package/src/commands/switch/index.mjs +1 -1
- package/src/commands/switch/switch.mjs +32 -37
- package/src/commands/types.d.ts +31 -0
- package/src/commands/unlink/index.mjs +1 -1
- package/src/commands/unlink/unlink.mjs +23 -29
- package/src/commands/watch/index.mjs +1 -1
- package/src/commands/watch/watch.mjs +91 -105
- package/src/functions-templates/javascript/hello/{{name}}.js +2 -3
- package/src/lib/account.mjs +4 -5
- package/src/lib/api.mjs +22 -20
- package/src/lib/blobs/blobs.mjs +36 -45
- package/src/lib/build.mjs +82 -85
- package/src/lib/completion/constants.mjs +2 -4
- package/src/lib/completion/generate-autocompletion.mjs +33 -36
- package/src/lib/completion/get-autocompletion.mjs +31 -35
- package/src/lib/completion/index.mjs +1 -1
- package/src/lib/completion/script.mjs +12 -19
- package/src/lib/edge-functions/bootstrap.mjs +3 -5
- package/src/lib/edge-functions/consts.mjs +9 -10
- package/src/lib/edge-functions/deploy.mjs +28 -34
- package/src/lib/edge-functions/editor-helper.mjs +29 -42
- package/src/lib/edge-functions/headers.mjs +24 -26
- package/src/lib/edge-functions/internal.mjs +38 -44
- package/src/lib/edge-functions/proxy.mjs +229 -228
- package/src/lib/edge-functions/registry.mjs +473 -574
- package/src/lib/exec-fetcher.mjs +115 -122
- package/src/lib/fs.mjs +28 -27
- package/src/lib/functions/background.mjs +16 -20
- package/src/lib/functions/config.mjs +12 -9
- package/src/lib/functions/form-submissions-handler.mjs +143 -149
- package/src/lib/functions/local-proxy.mjs +40 -44
- package/src/lib/functions/memoized-build.mjs +19 -21
- package/src/lib/functions/netlify-function.mjs +269 -249
- package/src/lib/functions/registry.mjs +509 -568
- package/src/lib/functions/runtimes/go/index.mjs +62 -71
- package/src/lib/functions/runtimes/index.mjs +8 -15
- package/src/lib/functions/runtimes/js/builders/netlify-lambda.mjs +55 -64
- package/src/lib/functions/runtimes/js/builders/zisi.mjs +135 -154
- package/src/lib/functions/runtimes/js/constants.mjs +1 -1
- package/src/lib/functions/runtimes/js/index.mjs +92 -109
- package/src/lib/functions/runtimes/js/worker.mjs +43 -45
- package/src/lib/functions/runtimes/rust/index.mjs +64 -73
- package/src/lib/functions/scheduled.mjs +70 -88
- package/src/lib/functions/server.mjs +269 -327
- package/src/lib/functions/synchronous.mjs +118 -147
- package/src/lib/functions/utils.mjs +38 -46
- package/src/lib/geo-location.mjs +69 -81
- package/src/lib/http-agent.mjs +87 -90
- package/src/lib/images/proxy.mjs +97 -99
- package/src/lib/log.mjs +6 -9
- package/src/lib/path.mjs +2 -1
- package/src/lib/render-error-template.mjs +19 -20
- package/src/lib/settings.mjs +17 -19
- package/src/lib/spinner.mjs +21 -23
- package/src/lib/string.mjs +4 -2
- package/src/recipes/vscode/index.mjs +69 -85
- package/src/recipes/vscode/settings.mjs +53 -58
- package/src/utils/addons/compare.mjs +31 -32
- package/src/utils/addons/diffs/index.mjs +16 -17
- package/src/utils/addons/diffs/options.mjs +99 -101
- package/src/utils/addons/prepare.mjs +100 -97
- package/src/utils/addons/prompts.mjs +73 -76
- package/src/utils/addons/render.mjs +33 -36
- package/src/utils/addons/validation.mjs +19 -15
- package/src/utils/banner.mjs +11 -16
- package/src/utils/build-info.mjs +65 -66
- package/src/utils/command-helpers.mjs +185 -199
- package/src/utils/create-deferred.mjs +9 -12
- package/src/utils/create-stream-promise.mjs +54 -47
- package/src/utils/deploy/constants.mjs +9 -11
- package/src/utils/deploy/deploy-site.mjs +162 -182
- package/src/utils/deploy/hash-config.mjs +21 -21
- package/src/utils/deploy/hash-files.mjs +34 -38
- package/src/utils/deploy/hash-fns.mjs +149 -154
- package/src/utils/deploy/hasher-segments.mjs +58 -52
- package/src/utils/deploy/upload-files.mjs +99 -113
- package/src/utils/deploy/util.mjs +85 -91
- package/src/utils/detect-server-settings.mjs +236 -268
- package/src/utils/dev.mjs +163 -178
- package/src/utils/dot-env.mjs +37 -42
- package/src/utils/env/index.mjs +148 -148
- package/src/utils/execa.mjs +9 -13
- package/src/utils/feature-flags.mjs +6 -5
- package/src/utils/framework-server.mjs +43 -52
- package/src/utils/functions/constants.mjs +1 -1
- package/src/utils/functions/functions.mjs +30 -40
- package/src/utils/functions/get-functions.mjs +28 -29
- package/src/utils/functions/index.mjs +3 -3
- package/src/utils/get-global-config.mjs +33 -36
- package/src/utils/get-package-json.mjs +14 -15
- package/src/utils/get-repo-data.mjs +54 -64
- package/src/utils/get-site.mjs +14 -14
- package/src/utils/gh-auth.mjs +79 -100
- package/src/utils/gitignore.mjs +37 -40
- package/src/utils/headers.mjs +33 -35
- package/src/utils/hooks/requires-site-info.mjs +26 -22
- package/src/utils/init/config-github.mjs +207 -219
- package/src/utils/init/config-manual.mjs +83 -100
- package/src/utils/init/config.mjs +25 -26
- package/src/utils/init/node-version.mjs +23 -30
- package/src/utils/init/plugins.mjs +12 -8
- package/src/utils/init/utils.mjs +152 -172
- package/src/utils/live-tunnel.mjs +118 -141
- package/src/utils/lm/install.mjs +220 -259
- package/src/utils/lm/requirements.mjs +54 -63
- package/src/utils/lm/steps.mjs +31 -31
- package/src/utils/lm/ui.mjs +13 -20
- package/src/utils/open-browser.mjs +31 -32
- package/src/utils/parse-raw-flags.mjs +39 -35
- package/src/utils/proxy-server.mjs +84 -71
- package/src/utils/proxy.mjs +696 -750
- package/src/utils/read-repo-url.mjs +48 -47
- package/src/utils/redirects.mjs +49 -49
- package/src/utils/request-id.mjs +2 -4
- package/src/utils/rules-proxy.mjs +96 -100
- package/src/utils/run-build.mjs +109 -132
- package/src/utils/shell.mjs +99 -106
- package/src/utils/sign-redirect.mjs +14 -14
- package/src/utils/sites/utils.mjs +48 -55
- package/src/utils/state-config.mjs +101 -101
- package/src/utils/static-server.mjs +28 -34
- package/src/utils/telemetry/index.mjs +2 -2
- package/src/utils/telemetry/report-error.mjs +45 -49
- package/src/utils/telemetry/request.mjs +36 -43
- package/src/utils/telemetry/telemetry.mjs +90 -105
- package/src/utils/telemetry/utils.mjs +5 -6
- package/src/utils/telemetry/validation.mjs +55 -53
- package/src/utils/types.d.ts +46 -0
- package/src/utils/validation.mjs +10 -13
package/src/utils/lm/install.mjs
CHANGED
|
@@ -1,295 +1,256 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const PACKAGE_NAME = 'netlify-credential-helper'
|
|
22
|
-
const EXEC_NAME = 'git-credential-netlify'
|
|
23
|
-
|
|
24
|
-
const GIT_CONFIG = '.gitconfig'
|
|
25
|
-
|
|
1
|
+
import { appendFile, copyFile, readFile, rm, writeFile } from 'fs/promises';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import path, { dirname } from 'path';
|
|
4
|
+
import process from 'process';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import execa from 'execa';
|
|
7
|
+
// @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'hasb... Remove this comment to see the full error message
|
|
8
|
+
import hasbin from 'hasbin';
|
|
9
|
+
import { Listr } from 'listr2';
|
|
10
|
+
import pathKey from 'path-key';
|
|
11
|
+
import { fetchLatestVersion, shouldFetchLatestVersion } from '../../lib/exec-fetcher.mjs';
|
|
12
|
+
import { fileExistsAsync } from '../../lib/fs.mjs';
|
|
13
|
+
import { normalizeBackslash } from '../../lib/path.mjs';
|
|
14
|
+
import { getLegacyPathInHome, getPathInHome } from '../../lib/settings.mjs';
|
|
15
|
+
import { chalk } from '../command-helpers.mjs';
|
|
16
|
+
import { checkGitLFSVersionStep, checkGitVersionStep, checkLFSFiltersStep } from './steps.mjs';
|
|
17
|
+
const PACKAGE_NAME = 'netlify-credential-helper';
|
|
18
|
+
const EXEC_NAME = 'git-credential-netlify';
|
|
19
|
+
const GIT_CONFIG = '.gitconfig';
|
|
26
20
|
const SUPPORTED_PLATFORMS = {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
21
|
+
linux: 'Linux',
|
|
22
|
+
darwin: 'Mac OS X',
|
|
23
|
+
win32: 'Windows',
|
|
24
|
+
};
|
|
25
|
+
const dirPath = dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
// @ts-expect-error TS(7031) FIXME: Binding element 'skipInstall' implicitly has an 'a... Remove this comment to see the full error message
|
|
34
27
|
const getSetupStep = ({ skipInstall }) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
28
|
+
const platform = os.platform();
|
|
29
|
+
// @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
|
30
|
+
const platformName = SUPPORTED_PLATFORMS[platform];
|
|
31
|
+
if (platformName === undefined) {
|
|
32
|
+
throw new Error(`Platform not supported: ${platform}.
|
|
33
|
+
See manual setup instructions in https://github.com/netlify/netlify-credential-helper#install`);
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
title: `Installing Netlify's Git Credential Helper for ${platformName}`,
|
|
37
|
+
skip: () => {
|
|
38
|
+
if (skipInstall) {
|
|
39
|
+
return `Netlify's Git Credential Helper already installed with a package manager`;
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
task: async () => {
|
|
43
|
+
await installHelper();
|
|
44
|
+
await (platform === 'win32' ? setupWindowsPath() : setupUnixPath());
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
};
|
|
56
48
|
const setupGitConfigStep = {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
49
|
+
title: `Configuring Git to use Netlify's Git Credential Helper`,
|
|
50
|
+
task: () => configureGitConfig(),
|
|
51
|
+
};
|
|
52
|
+
// @ts-expect-error TS(7031) FIXME: Binding element 'force' implicitly has an 'any' ty... Remove this comment to see the full error message
|
|
61
53
|
export const installPlatform = async function ({ force }) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
54
|
+
const skipInstall = !force && (await installedWithPackageManager());
|
|
55
|
+
const steps = [
|
|
56
|
+
checkGitVersionStep,
|
|
57
|
+
checkGitLFSVersionStep,
|
|
58
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'ctx' implicitly has an 'any' type.
|
|
59
|
+
checkLFSFiltersStep(async (ctx, task, installed) => {
|
|
60
|
+
if (!installed) {
|
|
61
|
+
await execa('git', ['lfs', 'install']);
|
|
62
|
+
task.title += chalk.dim(' [installed]');
|
|
63
|
+
}
|
|
64
|
+
}),
|
|
65
|
+
getSetupStep({ skipInstall }),
|
|
66
|
+
setupGitConfigStep,
|
|
67
|
+
];
|
|
68
|
+
const tasks = new Listr(steps);
|
|
69
|
+
await tasks.run();
|
|
70
|
+
return !skipInstall;
|
|
71
|
+
};
|
|
82
72
|
const installedWithPackageManager = async function () {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
73
|
+
const installed = hasbin.sync('git-credential-netlify');
|
|
74
|
+
if (!installed) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
// we check for the older location too via getLegacyBinPath
|
|
78
|
+
const binExist = await Promise.all([getBinPath(), getLegacyBinPath()].map(fileExistsAsync));
|
|
79
|
+
const withPackageManager = binExist.every((exists) => !exists);
|
|
80
|
+
return withPackageManager;
|
|
81
|
+
};
|
|
93
82
|
const installHelper = async function () {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
83
|
+
// remove any old versions that might still exist in `~/.netlify/helper/bin`
|
|
84
|
+
await rm(getLegacyBinPath(), { force: true, recursive: true });
|
|
85
|
+
const binPath = getBinPath();
|
|
86
|
+
// @ts-expect-error TS(2345) FIXME: Argument of type '{ binPath: string; packageName: ... Remove this comment to see the full error message
|
|
87
|
+
const shouldFetch = await shouldFetchLatestVersion({
|
|
88
|
+
binPath,
|
|
89
|
+
packageName: PACKAGE_NAME,
|
|
90
|
+
execArgs: ['version'],
|
|
91
|
+
pattern: `${EXEC_NAME}\\/v?([^\\s]+)`,
|
|
92
|
+
execName: EXEC_NAME,
|
|
93
|
+
});
|
|
94
|
+
if (!shouldFetch) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
// @ts-expect-error TS(2345) FIXME: Argument of type '{ packageName: string; execName:... Remove this comment to see the full error message
|
|
98
|
+
await fetchLatestVersion({
|
|
99
|
+
packageName: PACKAGE_NAME,
|
|
100
|
+
execName: EXEC_NAME,
|
|
101
|
+
destination: binPath,
|
|
102
|
+
extension: process.platform === 'win32' ? 'zip' : 'tar.gz',
|
|
103
|
+
});
|
|
104
|
+
};
|
|
116
105
|
export const isBinInPath = () => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
106
|
+
const envPath = process.env[pathKey()];
|
|
107
|
+
const binPath = getBinPath();
|
|
108
|
+
// @ts-expect-error TS(2532) FIXME: Object is possibly 'undefined'.
|
|
109
|
+
return envPath.replace(/"+/g, '').split(path.delimiter).includes(binPath);
|
|
110
|
+
};
|
|
122
111
|
const setupWindowsPath = async function () {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
'powershell',
|
|
130
|
-
['-ExecutionPolicy', 'unrestricted', '-windowstyle', 'hidden', '-File', scriptPath, getBinPath()],
|
|
131
|
-
{ stdio: 'inherit' },
|
|
132
|
-
)
|
|
133
|
-
}
|
|
134
|
-
|
|
112
|
+
if (isBinInPath()) {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
const scriptPath = path.join(dirPath, 'scripts', 'path.ps1');
|
|
116
|
+
return await execa('powershell', ['-ExecutionPolicy', 'unrestricted', '-windowstyle', 'hidden', '-File', scriptPath, getBinPath()], { stdio: 'inherit' });
|
|
117
|
+
};
|
|
135
118
|
const CONTENT_COMMENT = `
|
|
136
119
|
# The next line updates PATH for Netlify's Git Credential Helper.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const getInitContent = (incFilePath) => `${CONTENT_COMMENT}test -f '${incFilePath}' && source '${incFilePath}'
|
|
140
|
-
|
|
120
|
+
`;
|
|
121
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'incFilePath' implicitly has an 'any' ty... Remove this comment to see the full error message
|
|
122
|
+
const getInitContent = (incFilePath) => `${CONTENT_COMMENT}test -f '${incFilePath}' && source '${incFilePath}'`;
|
|
141
123
|
const setupUnixPath = async () => {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
])
|
|
158
|
-
}
|
|
159
|
-
|
|
124
|
+
if (isBinInPath()) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
const { configFile, incFilePath, shell } = getShellInfo();
|
|
128
|
+
if (configFile === undefined) {
|
|
129
|
+
const error = `Unable to set credential helper in PATH. We don't how to set the path for ${shell} shell.
|
|
130
|
+
Set the helper path in your environment PATH: ${getBinPath()}`;
|
|
131
|
+
throw new Error(error);
|
|
132
|
+
}
|
|
133
|
+
return await Promise.all([
|
|
134
|
+
await copyFile(`${dirPath}/scripts/${shell}.sh`, incFilePath),
|
|
135
|
+
await writeConfig(configFile, getInitContent(incFilePath)),
|
|
136
|
+
]);
|
|
137
|
+
};
|
|
138
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type.
|
|
160
139
|
const writeConfig = async function (name, initContent) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return await appendFile(configPath, initContent, 'utf-8')
|
|
172
|
-
}
|
|
173
|
-
|
|
140
|
+
const configPath = path.join(os.homedir(), name);
|
|
141
|
+
if (!(await fileExistsAsync(configPath))) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const content = await readFile(configPath, 'utf8');
|
|
145
|
+
if (content.includes(initContent)) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
return await appendFile(configPath, initContent, 'utf-8');
|
|
149
|
+
};
|
|
174
150
|
const getCurrentCredentials = async () => {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
} catch (error) {
|
|
180
|
-
// ignore error caused by not having any credential configured
|
|
181
|
-
if (error.stdout !== '') {
|
|
182
|
-
throw error
|
|
151
|
+
try {
|
|
152
|
+
const { stdout } = await execa('git', ['config', '--no-includes', '--get-regexp', '^credential']);
|
|
153
|
+
const currentCredentials = stdout.split('\\n');
|
|
154
|
+
return currentCredentials;
|
|
183
155
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
156
|
+
catch (error) {
|
|
157
|
+
// ignore error caused by not having any credential configured
|
|
158
|
+
// @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
|
|
159
|
+
if (error.stdout !== '') {
|
|
160
|
+
throw error;
|
|
161
|
+
}
|
|
162
|
+
return [];
|
|
163
|
+
}
|
|
164
|
+
};
|
|
188
165
|
// Git expects the config path to always use / even on Windows
|
|
166
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'gitConfigPath' implicitly has an 'any' ... Remove this comment to see the full error message
|
|
189
167
|
const getGitConfigContent = (gitConfigPath) => `
|
|
190
168
|
# This next lines include Netlify's Git Credential Helper configuration in your Git configuration.
|
|
191
169
|
[include]
|
|
192
170
|
path = ${normalizeBackslash(gitConfigPath)}
|
|
193
|
-
|
|
194
|
-
|
|
171
|
+
`;
|
|
195
172
|
const configureGitConfig = async function () {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
let helperConfig = `
|
|
173
|
+
const currentCredentials = await getCurrentCredentials();
|
|
174
|
+
let helperConfig = `
|
|
199
175
|
# The first line resets the list of helpers so we can check Netlify's first.
|
|
200
176
|
[credential]
|
|
201
177
|
helper = ""
|
|
202
178
|
|
|
203
179
|
[credential]
|
|
204
180
|
helper = netlify
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
const gitConfigPath = getGitConfigPath()
|
|
226
|
-
await writeFile(gitConfigPath, helperConfig, 'utf-8')
|
|
227
|
-
|
|
228
|
-
return writeConfig(GIT_CONFIG, getGitConfigContent(gitConfigPath))
|
|
229
|
-
}
|
|
230
|
-
|
|
181
|
+
`;
|
|
182
|
+
let section = 'credential';
|
|
183
|
+
if (currentCredentials.length !== 0) {
|
|
184
|
+
currentCredentials.forEach((line) => {
|
|
185
|
+
const parts = line.split(' ');
|
|
186
|
+
if (parts.length === 2) {
|
|
187
|
+
const keys = parts[0].split('.');
|
|
188
|
+
const localSection = keys.slice(0, -1).join('.');
|
|
189
|
+
if (section !== localSection) {
|
|
190
|
+
helperConfig += keys.length > 2 ? `\n[credential "${keys[1]}"]\n` : '\n[credential]\n';
|
|
191
|
+
section = localSection;
|
|
192
|
+
}
|
|
193
|
+
helperConfig += ` ${keys.pop()} = ${parts[1]}\n`;
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
const gitConfigPath = getGitConfigPath();
|
|
198
|
+
await writeFile(gitConfigPath, helperConfig, 'utf-8');
|
|
199
|
+
return writeConfig(GIT_CONFIG, getGitConfigContent(gitConfigPath));
|
|
200
|
+
};
|
|
231
201
|
const getHelperPath = function () {
|
|
232
|
-
|
|
233
|
-
}
|
|
234
|
-
|
|
202
|
+
return getPathInHome(['helper']);
|
|
203
|
+
};
|
|
235
204
|
const getBinPath = function () {
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
|
|
205
|
+
return path.join(getHelperPath(), 'bin');
|
|
206
|
+
};
|
|
239
207
|
const getGitConfigPath = function () {
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
|
|
208
|
+
return path.join(getHelperPath(), 'git-config');
|
|
209
|
+
};
|
|
243
210
|
const getLegacyBinPath = function () {
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
|
|
211
|
+
return path.join(getLegacyPathInHome(['helper', 'bin']));
|
|
212
|
+
};
|
|
247
213
|
const CONFIG_FILES = {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
252
|
-
|
|
214
|
+
bash: '.bashrc',
|
|
215
|
+
zsh: '.zshrc',
|
|
216
|
+
fish: '.config/fish/config.fish',
|
|
217
|
+
};
|
|
253
218
|
export const getShellInfo = function () {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
266
|
-
|
|
219
|
+
const shellEnv = process.env.SHELL;
|
|
220
|
+
if (!shellEnv) {
|
|
221
|
+
throw new Error('Unable to detect SHELL type, make sure the variable is defined in your environment');
|
|
222
|
+
}
|
|
223
|
+
const shell = shellEnv.split(path.sep).pop();
|
|
224
|
+
return {
|
|
225
|
+
shell,
|
|
226
|
+
incFilePath: `${getHelperPath()}/path.${shell}.inc`,
|
|
227
|
+
// @ts-expect-error TS(2538) FIXME: Type 'undefined' cannot be used as an index type.
|
|
228
|
+
configFile: CONFIG_FILES[shell],
|
|
229
|
+
};
|
|
230
|
+
};
|
|
267
231
|
const cleanupShell = async function () {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
232
|
+
try {
|
|
233
|
+
const { configFile, incFilePath } = getShellInfo();
|
|
234
|
+
if (configFile === undefined) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
await removeConfig(configFile, getInitContent(incFilePath));
|
|
272
238
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
} catch {}
|
|
276
|
-
}
|
|
277
|
-
|
|
239
|
+
catch { }
|
|
240
|
+
};
|
|
278
241
|
export const uninstall = async function () {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
}
|
|
285
|
-
|
|
242
|
+
await Promise.all([
|
|
243
|
+
rm(getHelperPath(), { force: true, recursive: true }),
|
|
244
|
+
removeConfig(GIT_CONFIG, getGitConfigContent(getGitConfigPath())),
|
|
245
|
+
cleanupShell(),
|
|
246
|
+
]);
|
|
247
|
+
};
|
|
248
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type.
|
|
286
249
|
const removeConfig = async function (name, toRemove) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
return await writeFile(configPath, content.replace(toRemove, ''))
|
|
295
|
-
}
|
|
250
|
+
const configPath = path.join(os.homedir(), name);
|
|
251
|
+
if (!(await fileExistsAsync(configPath))) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const content = await readFile(configPath, 'utf8');
|
|
255
|
+
return await writeFile(configPath, content.replace(toRemove, ''));
|
|
256
|
+
};
|
|
@@ -1,70 +1,61 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import execa from '../execa.mjs'
|
|
5
|
-
|
|
1
|
+
import semver from 'semver';
|
|
2
|
+
// @ts-expect-error TS(7034) FIXME: Variable 'execa' implicitly has type 'any' in some... Remove this comment to see the full error message
|
|
3
|
+
import execa from '../execa.mjs';
|
|
6
4
|
export const checkLFSFilters = async function () {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
5
|
+
try {
|
|
6
|
+
// @ts-expect-error TS(7005) FIXME: Variable 'execa' implicitly has an 'any' type.
|
|
7
|
+
const { stdout } = await execa('git', ['config', '--get-regexp', 'filter.lfs']);
|
|
8
|
+
return stdout.length !== 0;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
15
14
|
const getHelperVersion = async function () {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
try {
|
|
16
|
+
// @ts-expect-error TS(7005) FIXME: Variable 'execa' implicitly has an 'any' type.
|
|
17
|
+
const { stdout } = await execa('git-credential-netlify', ['version']);
|
|
18
|
+
return stdout;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
throw new Error(`Check that Netlify's Git Credential helper is installed and updated to the latest version`);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
24
|
export const checkHelperVersion = async function () {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
/git-credential-netlify\/([.\d]+).*/,
|
|
30
|
-
expectedVersion,
|
|
31
|
-
`Invalid Netlify's Git Credential version MATCH_PLACEHOLDER. Please update to version ${expectedVersion} or above by running 'ntl lm:install'`,
|
|
32
|
-
)
|
|
33
|
-
}
|
|
34
|
-
|
|
25
|
+
const version = await getHelperVersion();
|
|
26
|
+
const expectedVersion = '0.1.10';
|
|
27
|
+
return matchVersion(version, /git-credential-netlify\/([.\d]+).*/, expectedVersion, `Invalid Netlify's Git Credential version MATCH_PLACEHOLDER. Please update to version ${expectedVersion} or above by running 'ntl lm:install'`);
|
|
28
|
+
};
|
|
35
29
|
export const checkGitVersion = async function () {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
30
|
+
try {
|
|
31
|
+
// @ts-expect-error TS(7005) FIXME: Variable 'execa' implicitly has an 'any' type.
|
|
32
|
+
const { stdout } = await execa('git', ['--version']);
|
|
33
|
+
return stdout.split(' ').pop();
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
throw new Error('Check that Git is installed in your system');
|
|
37
|
+
}
|
|
38
|
+
};
|
|
44
39
|
const getLFSVersion = async function () {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
40
|
+
try {
|
|
41
|
+
// @ts-expect-error TS(7005) FIXME: Variable 'execa' implicitly has an 'any' type.
|
|
42
|
+
const { stdout } = await execa('git-lfs', ['version']);
|
|
43
|
+
return stdout;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
throw new Error('Check that Git LFS is installed in your system');
|
|
47
|
+
}
|
|
48
|
+
};
|
|
53
49
|
export const checkLFSVersion = async function () {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
expectedVersion,
|
|
60
|
-
`Invalid Git LFS version MATCH_PLACEHOLDER. Please update to version ${expectedVersion} or above`,
|
|
61
|
-
)
|
|
62
|
-
}
|
|
63
|
-
|
|
50
|
+
const version = await getLFSVersion();
|
|
51
|
+
const expectedVersion = '2.5.1';
|
|
52
|
+
return matchVersion(version, /git-lfs\/([.\d]+).*/, expectedVersion, `Invalid Git LFS version MATCH_PLACEHOLDER. Please update to version ${expectedVersion} or above`);
|
|
53
|
+
};
|
|
54
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'out' implicitly has an 'any' type.
|
|
64
55
|
const matchVersion = function (out, regex, version, message) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
56
|
+
const match = out.match(regex);
|
|
57
|
+
if (!match || match.length !== 2 || semver.lt(match[1], version)) {
|
|
58
|
+
throw new Error(message.replace('MATCH_PLACEHOLDER', match[1]));
|
|
59
|
+
}
|
|
60
|
+
return match[1];
|
|
61
|
+
};
|