nx 19.7.2 → 19.7.4
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/package.json +12 -12
- package/schemas/nx-schema.json +2 -2
- package/src/command-line/add/add.js +2 -2
- package/src/command-line/affected/command-object.js +6 -6
- package/src/command-line/deprecated/command-objects.js +3 -3
- package/src/command-line/generate/generate.js +2 -1
- package/src/command-line/import/command-object.js +8 -6
- package/src/command-line/import/import.d.ts +1 -1
- package/src/command-line/import/import.js +45 -29
- package/src/command-line/import/utils/prepare-source-repo.js +7 -35
- package/src/command-line/init/init-v2.js +6 -2
- package/src/command-line/login/login.js +2 -2
- package/src/command-line/logout/logout.js +2 -2
- package/src/command-line/migrate/migrate.js +2 -2
- package/src/command-line/new/new.js +2 -1
- package/src/command-line/release/changelog.js +2 -2
- package/src/command-line/release/command-object.d.ts +2 -2
- package/src/command-line/release/config/config.js +10 -3
- package/src/command-line/release/plan-check.js +2 -2
- package/src/command-line/release/plan.js +2 -2
- package/src/command-line/release/publish.js +2 -2
- package/src/command-line/release/release.js +2 -2
- package/src/command-line/release/utils/git.d.ts +2 -2
- package/src/command-line/release/utils/git.js +12 -2
- package/src/command-line/release/utils/shared.d.ts +1 -1
- package/src/command-line/release/version.js +6 -1
- package/src/command-line/repair/repair.js +2 -2
- package/src/command-line/run/command-object.js +3 -3
- package/src/command-line/run/run.js +3 -2
- package/src/command-line/run-many/command-object.js +2 -2
- package/src/command-line/show/command-object.js +3 -3
- package/src/command-line/sync/sync.js +69 -11
- package/src/config/nx-json.d.ts +13 -5
- package/src/daemon/client/client.d.ts +3 -3
- package/src/daemon/server/handle-flush-sync-generator-changes-to-disk.js +2 -2
- package/src/daemon/server/handle-get-sync-generator-changes.js +8 -6
- package/src/daemon/server/sync-generators.d.ts +4 -4
- package/src/daemon/server/sync-generators.js +11 -2
- package/src/hasher/hash-task.js +2 -2
- package/src/native/nx.wasi-browser.js +42 -54
- package/src/native/nx.wasi.cjs +42 -54
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.js +0 -1
- package/src/nx-cloud/utilities/get-cloud-options.d.ts +1 -0
- package/src/nx-cloud/utilities/get-cloud-options.js +4 -0
- package/src/nx-cloud/utilities/is-workspace-claimed.d.ts +1 -1
- package/src/nx-cloud/utilities/is-workspace-claimed.js +6 -5
- package/src/nx-cloud/utilities/onboarding.js +2 -2
- package/src/plugins/js/utils/register.js +7 -0
- package/src/project-graph/error-types.d.ts +1 -1
- package/src/project-graph/error-types.js +19 -5
- package/src/tasks-runner/cache.js +2 -1
- package/src/tasks-runner/run-command.js +142 -30
- package/src/tasks-runner/task-orchestrator.d.ts +0 -1
- package/src/tasks-runner/task-orchestrator.js +3 -6
- package/src/utils/git-utils.d.ts +3 -2
- package/src/utils/git-utils.index-filter.d.ts +0 -0
- package/src/utils/git-utils.index-filter.js +20 -0
- package/src/utils/git-utils.js +44 -13
- package/src/utils/git-utils.tree-filter.d.ts +11 -0
- package/src/utils/git-utils.tree-filter.js +43 -0
- package/src/utils/handle-errors.d.ts +1 -0
- package/src/utils/handle-errors.js +71 -0
- package/src/utils/nx-cloud-utils.d.ts +0 -1
- package/src/utils/nx-cloud-utils.js +0 -10
- package/src/utils/params.d.ts +0 -1
- package/src/utils/params.js +0 -50
- package/src/utils/plugins/plugin-capabilities.js +4 -1
- package/src/utils/sync-generators.d.ts +35 -6
- package/src/utils/sync-generators.js +144 -47
@@ -11,12 +11,13 @@ const nx_json_1 = require("../config/nx-json");
|
|
11
11
|
const client_1 = require("../daemon/client/client");
|
12
12
|
const create_task_hasher_1 = require("../hasher/create-task-hasher");
|
13
13
|
const hash_task_1 = require("../hasher/hash-task");
|
14
|
+
const native_1 = require("../native");
|
14
15
|
const project_graph_1 = require("../project-graph/project-graph");
|
15
16
|
const fileutils_1 = require("../utils/fileutils");
|
16
17
|
const is_ci_1 = require("../utils/is-ci");
|
17
18
|
const nx_cloud_utils_1 = require("../utils/nx-cloud-utils");
|
18
19
|
const output_1 = require("../utils/output");
|
19
|
-
const
|
20
|
+
const handle_errors_1 = require("../utils/handle-errors");
|
20
21
|
const sync_generators_1 = require("../utils/sync-generators");
|
21
22
|
const workspace_root_1 = require("../utils/workspace-root");
|
22
23
|
const create_task_graph_1 = require("./create-task-graph");
|
@@ -33,7 +34,6 @@ const task_timings_life_cycle_1 = require("./life-cycles/task-timings-life-cycle
|
|
33
34
|
const task_graph_utils_1 = require("./task-graph-utils");
|
34
35
|
const utils_1 = require("./utils");
|
35
36
|
const chalk = require("chalk");
|
36
|
-
const native_1 = require("../native");
|
37
37
|
async function getTerminalOutputLifeCycle(initiatingProject, projectNames, tasks, nxArgs, nxJson, overrides) {
|
38
38
|
const { runnerOptions } = getRunner(nxArgs, nxJson);
|
39
39
|
const isRunOne = initiatingProject != null;
|
@@ -98,7 +98,7 @@ function createTaskGraphAndRunValidations(projectGraph, extraTargetDependencies,
|
|
98
98
|
return taskGraph;
|
99
99
|
}
|
100
100
|
async function runCommand(projectsToRun, currentProjectGraph, { nxJson }, nxArgs, overrides, initiatingProject, extraTargetDependencies, extraOptions) {
|
101
|
-
const status = await (0,
|
101
|
+
const status = await (0, handle_errors_1.handleErrors)(process.env.NX_VERBOSE_LOGGING === 'true', async () => {
|
102
102
|
const projectNames = projectsToRun.map((t) => t.name);
|
103
103
|
const { projectGraph, taskGraph } = await ensureWorkspaceIsInSyncAndGetGraphs(currentProjectGraph, nxJson, projectNames, nxArgs, overrides, extraTargetDependencies, extraOptions);
|
104
104
|
const tasks = Object.values(taskGraph.tasks);
|
@@ -135,14 +135,49 @@ async function ensureWorkspaceIsInSyncAndGetGraphs(projectGraph, nxJson, project
|
|
135
135
|
// There are no changes to sync, workspace is up to date
|
136
136
|
return { projectGraph, taskGraph };
|
137
137
|
}
|
138
|
+
const { failedGeneratorsCount, areAllResultsFailures, anySyncGeneratorsFailed, } = (0, sync_generators_1.processSyncGeneratorResultErrors)(results);
|
139
|
+
const failedSyncGeneratorsFixMessageLines = (0, sync_generators_1.getFailedSyncGeneratorsFixMessageLines)(results, nxArgs.verbose);
|
138
140
|
const outOfSyncTitle = 'The workspace is out of sync';
|
139
|
-
const resultBodyLines =
|
140
|
-
const fixMessage = 'You can manually run `nx sync` to update your workspace or you can set `sync.applyChanges` to `true` in your `nx.json` to apply the changes automatically when running tasks in interactive environments.';
|
141
|
-
const willErrorOnCiMessage = 'Please note that
|
141
|
+
const resultBodyLines = (0, sync_generators_1.getSyncGeneratorSuccessResultsMessageLines)(results);
|
142
|
+
const fixMessage = 'You can manually run `nx sync` to update your workspace with the identified changes or you can set `sync.applyChanges` to `true` in your `nx.json` to apply the changes automatically when running tasks in interactive environments.';
|
143
|
+
const willErrorOnCiMessage = 'Please note that having the workspace out of sync will result in an error in CI.';
|
142
144
|
if ((0, is_ci_1.isCI)() || !process.stdout.isTTY) {
|
143
145
|
// If the user is running in CI or is running in a non-TTY environment we
|
144
146
|
// throw an error to stop the execution of the tasks.
|
145
|
-
|
147
|
+
if (areAllResultsFailures) {
|
148
|
+
output_1.output.error({
|
149
|
+
title: `The workspace is probably out of sync because ${failedGeneratorsCount === 1
|
150
|
+
? 'a sync generator'
|
151
|
+
: 'some sync generators'} failed to run`,
|
152
|
+
bodyLines: failedSyncGeneratorsFixMessageLines,
|
153
|
+
});
|
154
|
+
}
|
155
|
+
else {
|
156
|
+
output_1.output.error({
|
157
|
+
title: outOfSyncTitle,
|
158
|
+
bodyLines: [...resultBodyLines, '', fixMessage],
|
159
|
+
});
|
160
|
+
if (anySyncGeneratorsFailed) {
|
161
|
+
output_1.output.error({
|
162
|
+
title: failedGeneratorsCount === 1
|
163
|
+
? 'A sync generator failed to run'
|
164
|
+
: 'Some sync generators failed to run',
|
165
|
+
bodyLines: failedSyncGeneratorsFixMessageLines,
|
166
|
+
});
|
167
|
+
}
|
168
|
+
}
|
169
|
+
process.exit(1);
|
170
|
+
}
|
171
|
+
if (areAllResultsFailures) {
|
172
|
+
output_1.output.warn({
|
173
|
+
title: `The workspace is probably out of sync because ${failedGeneratorsCount === 1
|
174
|
+
? 'a sync generator'
|
175
|
+
: 'some sync generators'} failed to run`,
|
176
|
+
bodyLines: failedSyncGeneratorsFixMessageLines,
|
177
|
+
});
|
178
|
+
await confirmRunningTasksWithSyncFailures();
|
179
|
+
// if all sync generators failed to run there's nothing to sync, we just let the tasks run
|
180
|
+
return { projectGraph, taskGraph };
|
146
181
|
}
|
147
182
|
if (nxJson.sync?.applyChanges === false) {
|
148
183
|
// If the user has set `sync.applyChanges` to `false` in their `nx.json`
|
@@ -153,19 +188,30 @@ async function ensureWorkspaceIsInSyncAndGetGraphs(projectGraph, nxJson, project
|
|
153
188
|
title: outOfSyncTitle,
|
154
189
|
bodyLines: [
|
155
190
|
...resultBodyLines,
|
156
|
-
'
|
191
|
+
'',
|
192
|
+
'Your workspace is set to not apply the identified changes automatically (`sync.applyChanges` is set to `false` in your `nx.json`).',
|
157
193
|
willErrorOnCiMessage,
|
158
194
|
fixMessage,
|
159
195
|
],
|
160
196
|
});
|
197
|
+
if (anySyncGeneratorsFailed) {
|
198
|
+
output_1.output.warn({
|
199
|
+
title: failedGeneratorsCount === 1
|
200
|
+
? 'A sync generator failed to run'
|
201
|
+
: 'Some sync generators failed to run',
|
202
|
+
bodyLines: failedSyncGeneratorsFixMessageLines,
|
203
|
+
});
|
204
|
+
await confirmRunningTasksWithSyncFailures();
|
205
|
+
}
|
161
206
|
return { projectGraph, taskGraph };
|
162
207
|
}
|
163
208
|
output_1.output.warn({
|
164
209
|
title: outOfSyncTitle,
|
165
210
|
bodyLines: [
|
166
211
|
...resultBodyLines,
|
212
|
+
'',
|
167
213
|
nxJson.sync?.applyChanges === true
|
168
|
-
? 'Proceeding to sync the changes automatically (`sync.applyChanges` is set to `true` in your `nx.json`).'
|
214
|
+
? 'Proceeding to sync the identified changes automatically (`sync.applyChanges` is set to `true` in your `nx.json`).'
|
169
215
|
: willErrorOnCiMessage,
|
170
216
|
],
|
171
217
|
});
|
@@ -175,31 +221,66 @@ async function ensureWorkspaceIsInSyncAndGetGraphs(projectGraph, nxJson, project
|
|
175
221
|
const spinner = ora('Syncing the workspace...');
|
176
222
|
spinner.start();
|
177
223
|
// Flush sync generator changes to disk
|
178
|
-
await (0, sync_generators_1.flushSyncGeneratorChanges)(results);
|
224
|
+
const flushResult = await (0, sync_generators_1.flushSyncGeneratorChanges)(results);
|
225
|
+
if ('generatorFailures' in flushResult) {
|
226
|
+
spinner.fail();
|
227
|
+
output_1.output.error({
|
228
|
+
title: 'Failed to sync the workspace',
|
229
|
+
bodyLines: [
|
230
|
+
...(0, sync_generators_1.getFlushFailureMessageLines)(flushResult, nxArgs.verbose),
|
231
|
+
...(flushResult.generalFailure
|
232
|
+
? [
|
233
|
+
'If needed, you can run the tasks with the `--skip-sync` flag to disable syncing.',
|
234
|
+
]
|
235
|
+
: []),
|
236
|
+
],
|
237
|
+
});
|
238
|
+
await confirmRunningTasksWithSyncFailures();
|
239
|
+
}
|
179
240
|
// Re-create project graph and task graph
|
180
241
|
projectGraph = await (0, project_graph_1.createProjectGraphAsync)();
|
181
242
|
taskGraph = createTaskGraphAndRunValidations(projectGraph, extraTargetDependencies ?? {}, projectNames, nxArgs, overrides, extraOptions);
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
Please make sure to commit the changes to your repository
|
243
|
+
const successTitle = anySyncGeneratorsFailed
|
244
|
+
? // the identified changes were synced successfully, but the workspace
|
245
|
+
// is still not up to date, which we'll mention next
|
246
|
+
'The identified changes were synced successfully!'
|
247
|
+
: // the workspace is fully up to date
|
248
|
+
'The workspace was synced successfully!';
|
249
|
+
const successSubtitle = nxJson.sync?.applyChanges === true
|
250
|
+
? 'Please make sure to commit the changes to your repository or this will error in CI.'
|
251
|
+
: // The user was prompted and we already logged a message about erroring in CI
|
252
|
+
// so here we just tell them to commit the changes.
|
253
|
+
'Please make sure to commit the changes to your repository.';
|
254
|
+
spinner.succeed(`${successTitle}\n\n${successSubtitle}`);
|
255
|
+
if (anySyncGeneratorsFailed) {
|
256
|
+
output_1.output.warn({
|
257
|
+
title: `The workspace is probably still out of sync because ${failedGeneratorsCount === 1
|
258
|
+
? 'a sync generator'
|
259
|
+
: 'some sync generators'} failed to run`,
|
260
|
+
bodyLines: failedSyncGeneratorsFixMessageLines,
|
261
|
+
});
|
262
|
+
await confirmRunningTasksWithSyncFailures();
|
193
263
|
}
|
194
264
|
}
|
195
265
|
else {
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
266
|
+
if (anySyncGeneratorsFailed) {
|
267
|
+
output_1.output.warn({
|
268
|
+
title: failedGeneratorsCount === 1
|
269
|
+
? 'A sync generator failed to report the sync status'
|
270
|
+
: 'Some sync generators failed to report the sync status',
|
271
|
+
bodyLines: failedSyncGeneratorsFixMessageLines,
|
272
|
+
});
|
273
|
+
await confirmRunningTasksWithSyncFailures();
|
274
|
+
}
|
275
|
+
else {
|
276
|
+
output_1.output.warn({
|
277
|
+
title: 'Syncing the workspace was skipped',
|
278
|
+
bodyLines: [
|
279
|
+
'This could lead to unexpected results or errors when running tasks.',
|
280
|
+
fixMessage,
|
281
|
+
],
|
282
|
+
});
|
283
|
+
}
|
203
284
|
}
|
204
285
|
return { projectGraph, taskGraph };
|
205
286
|
}
|
@@ -208,7 +289,7 @@ async function promptForApplyingSyncGeneratorChanges() {
|
|
208
289
|
const promptConfig = {
|
209
290
|
name: 'applyChanges',
|
210
291
|
type: 'select',
|
211
|
-
message: 'Would you like to sync the changes to get your worskpace up to date?',
|
292
|
+
message: 'Would you like to sync the identified changes to get your worskpace up to date?',
|
212
293
|
choices: [
|
213
294
|
{
|
214
295
|
name: 'yes',
|
@@ -227,6 +308,35 @@ async function promptForApplyingSyncGeneratorChanges() {
|
|
227
308
|
process.exit(1);
|
228
309
|
}
|
229
310
|
}
|
311
|
+
async function confirmRunningTasksWithSyncFailures() {
|
312
|
+
try {
|
313
|
+
const promptConfig = {
|
314
|
+
name: 'runTasks',
|
315
|
+
type: 'select',
|
316
|
+
message: 'Would you like to ignore the sync failures and continue running the tasks?',
|
317
|
+
choices: [
|
318
|
+
{
|
319
|
+
name: 'yes',
|
320
|
+
message: 'Yes, ignore the failures and run the tasks',
|
321
|
+
},
|
322
|
+
{
|
323
|
+
name: 'no',
|
324
|
+
message: `No, don't run the tasks`,
|
325
|
+
},
|
326
|
+
],
|
327
|
+
footer: () => chalk.dim(`\nWhen running in CI and there are sync failures, the tasks won't run. Addressing the errors above is highly recommended to prevent failures in CI.`),
|
328
|
+
};
|
329
|
+
const runTasks = await (0, enquirer_1.prompt)([
|
330
|
+
promptConfig,
|
331
|
+
]).then(({ runTasks }) => runTasks === 'yes');
|
332
|
+
if (!runTasks) {
|
333
|
+
process.exit(1);
|
334
|
+
}
|
335
|
+
}
|
336
|
+
catch {
|
337
|
+
process.exit(1);
|
338
|
+
}
|
339
|
+
}
|
230
340
|
function setEnvVarsBasedOnArgs(nxArgs, loadDotEnvFiles) {
|
231
341
|
if (nxArgs.outputStyle == 'stream' ||
|
232
342
|
process.env.NX_BATCH_MODE === 'true' ||
|
@@ -329,7 +439,9 @@ function constructLifeCycles(lifeCycle) {
|
|
329
439
|
lifeCycles.push(new task_profiling_life_cycle_1.TaskProfilingLifeCycle(process.env.NX_PROFILE));
|
330
440
|
}
|
331
441
|
if (!(0, nx_cloud_utils_1.isNxCloudUsed)((0, nx_json_1.readNxJson)())) {
|
332
|
-
lifeCycles.push(
|
442
|
+
lifeCycles.push(process.env.NX_DISABLE_DB !== 'true' && !native_1.IS_WASM
|
443
|
+
? new task_history_life_cycle_1.TaskHistoryLifeCycle()
|
444
|
+
: new task_history_life_cycle_old_1.LegacyTaskHistoryLifeCycle());
|
333
445
|
}
|
334
446
|
return lifeCycles;
|
335
447
|
}
|
@@ -43,7 +43,7 @@ class TaskOrchestrator {
|
|
43
43
|
// Init the ForkedProcessTaskRunner
|
44
44
|
await this.forkedProcessTaskRunner.init();
|
45
45
|
// initial scheduling
|
46
|
-
await this.scheduleNextTasks();
|
46
|
+
await this.tasksSchedule.scheduleNextTasks();
|
47
47
|
perf_hooks_1.performance.mark('task-execution:start');
|
48
48
|
const threads = [];
|
49
49
|
process.stdout.setMaxListeners(this.options.parallel + events_1.defaultMaxListeners);
|
@@ -65,6 +65,7 @@ class TaskOrchestrator {
|
|
65
65
|
}
|
66
66
|
const doNotSkipCache = this.options.skipNxCache === false ||
|
67
67
|
this.options.skipNxCache === undefined;
|
68
|
+
this.processAllScheduledTasks();
|
68
69
|
const batch = this.tasksSchedule.nextBatch();
|
69
70
|
if (batch) {
|
70
71
|
const groupId = this.closeGroup();
|
@@ -373,15 +374,11 @@ class TaskOrchestrator {
|
|
373
374
|
status,
|
374
375
|
};
|
375
376
|
}));
|
376
|
-
await this.scheduleNextTasks();
|
377
|
+
await this.tasksSchedule.scheduleNextTasks();
|
377
378
|
// release blocked threads
|
378
379
|
this.waitingForTasks.forEach((f) => f(null));
|
379
380
|
this.waitingForTasks.length = 0;
|
380
381
|
}
|
381
|
-
async scheduleNextTasks() {
|
382
|
-
await this.tasksSchedule.scheduleNextTasks();
|
383
|
-
this.processAllScheduledTasks();
|
384
|
-
}
|
385
382
|
complete(taskResults) {
|
386
383
|
this.tasksSchedule.complete(taskResults.map(({ taskId }) => taskId));
|
387
384
|
for (const { taskId, status } of taskResults) {
|
package/src/utils/git-utils.d.ts
CHANGED
@@ -25,10 +25,11 @@ export declare class GitRepository {
|
|
25
25
|
deleteGitRemote(name: string): Promise<string>;
|
26
26
|
addGitRemote(name: string, url: string): Promise<string>;
|
27
27
|
hasFilterRepoInstalled(): Promise<boolean>;
|
28
|
-
filterRepo(
|
29
|
-
filterBranch(
|
28
|
+
filterRepo(source: string, destination: string): Promise<void>;
|
29
|
+
filterBranch(source: string, destination: string, branchName: string): Promise<void>;
|
30
30
|
private execAsync;
|
31
31
|
private quotePath;
|
32
|
+
private quoteArg;
|
32
33
|
}
|
33
34
|
/**
|
34
35
|
* This is currently duplicated in Nx Console. Please let @MaxKless know if you make changes here.
|
File without changes
|
@@ -0,0 +1,20 @@
|
|
1
|
+
/**
|
2
|
+
* This is meant to be used with `git filter-branch --index-filter` to rewrite
|
3
|
+
* history such that only commits related to the subdirectory is kept.
|
4
|
+
*
|
5
|
+
* Example:
|
6
|
+
* NX_IMPORT_SOURCE=<source> git filter-branch --index-filter 'node git-utils.index-filter.js' --prune-empty -- --all
|
7
|
+
*/
|
8
|
+
try {
|
9
|
+
const { execSync } = require('child_process');
|
10
|
+
// NOTE: Using env vars because Windows PowerShell has its own handling of quotes (") messes up quotes in args, even if escaped.
|
11
|
+
const src = process.env.NX_IMPORT_SOURCE;
|
12
|
+
execSync('git read-tree --empty', { stdio: 'inherit' });
|
13
|
+
execSync(`git reset ${process.env.GIT_COMMIT} -- "${src}"`, {
|
14
|
+
stdio: 'inherit',
|
15
|
+
});
|
16
|
+
}
|
17
|
+
catch (error) {
|
18
|
+
console.error(`Error executing Git commands: ${error}`);
|
19
|
+
process.exit(1);
|
20
|
+
}
|
package/src/utils/git-utils.js
CHANGED
@@ -105,32 +105,63 @@ class GitRepository {
|
|
105
105
|
}
|
106
106
|
// git-filter-repo is much faster than filter-branch, but needs to be installed by user
|
107
107
|
// Use `hasFilterRepoInstalled` to check if it's installed
|
108
|
-
async filterRepo(
|
109
|
-
// filter-repo requires POSIX path to work
|
110
|
-
const
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
108
|
+
async filterRepo(source, destination) {
|
109
|
+
// NOTE: filter-repo requires POSIX path to work
|
110
|
+
const sourcePosixPath = source.split(path_1.sep).join(path_1.posix.sep);
|
111
|
+
const destinationPosixPath = destination.split(path_1.sep).join(path_1.posix.sep);
|
112
|
+
await this.execAsync(`git filter-repo -f ${source !== '' ? `--path ${this.quotePath(sourcePosixPath)}` : ''} ${source !== destination
|
113
|
+
? `--path-rename ${this.quotePath(sourcePosixPath, true)}:${this.quotePath(destinationPosixPath, true)}`
|
114
|
+
: ''}`);
|
115
|
+
}
|
116
|
+
async filterBranch(source, destination, branchName) {
|
116
117
|
// We need non-ASCII file names to not be quoted, or else filter-branch will exclude them.
|
117
118
|
await this.execAsync(`git config core.quotepath false`);
|
118
|
-
|
119
|
+
// NOTE: filter-repo requires POSIX path to work
|
120
|
+
const sourcePosixPath = source.split(path_1.sep).join(path_1.posix.sep);
|
121
|
+
const destinationPosixPath = destination.split(path_1.sep).join(path_1.posix.sep);
|
122
|
+
// First, if the source is not a root project, then only include commits relevant to the subdirectory.
|
123
|
+
if (source !== '') {
|
124
|
+
const indexFilterCommand = this.quoteArg(`node ${(0, path_1.join)(__dirname, 'git-utils.index-filter.js')}`);
|
125
|
+
await this.execAsync(`git filter-branch -f --index-filter ${indexFilterCommand} --prune-empty -- ${branchName}`, {
|
126
|
+
NX_IMPORT_SOURCE: sourcePosixPath,
|
127
|
+
NX_IMPORT_DESTINATION: destinationPosixPath,
|
128
|
+
});
|
129
|
+
}
|
130
|
+
// Then, move files to their new location if necessary.
|
131
|
+
if (source === '' || source !== destination) {
|
132
|
+
const treeFilterCommand = this.quoteArg(`node ${(0, path_1.join)(__dirname, 'git-utils.tree-filter.js')}`);
|
133
|
+
await this.execAsync(`git filter-branch -f --tree-filter ${treeFilterCommand} -- ${branchName}`, {
|
134
|
+
NX_IMPORT_SOURCE: sourcePosixPath,
|
135
|
+
NX_IMPORT_DESTINATION: destinationPosixPath,
|
136
|
+
});
|
137
|
+
}
|
119
138
|
}
|
120
|
-
execAsync(command) {
|
139
|
+
execAsync(command, env) {
|
121
140
|
return execAsync(command, {
|
122
141
|
cwd: this.root,
|
123
142
|
maxBuffer: 10 * 1024 * 1024,
|
143
|
+
env: {
|
144
|
+
...process.env,
|
145
|
+
...env,
|
146
|
+
},
|
124
147
|
});
|
125
148
|
}
|
126
|
-
quotePath(path) {
|
149
|
+
quotePath(path, ensureTrailingSlash) {
|
150
|
+
return this.quoteArg(ensureTrailingSlash && path !== '' && !path.endsWith('/')
|
151
|
+
? `${path}/`
|
152
|
+
: path);
|
153
|
+
}
|
154
|
+
quoteArg(arg) {
|
127
155
|
return process.platform === 'win32'
|
128
156
|
? // Windows/CMD only understands double-quotes, single-quotes are treated as part of the file name
|
129
157
|
// Bash and other shells will substitute `$` in file names with a variable value.
|
130
|
-
`"${
|
158
|
+
`"${arg
|
159
|
+
// Need to keep two slashes for Windows or else the path will be invalid.
|
160
|
+
// e.g. 'C:\Users\bob\projects\repo' is invalid, but 'C:\\Users\\bob\\projects\\repo' is valid
|
161
|
+
.replaceAll('\\', '\\\\')}"`
|
131
162
|
: // e.g. `git mv "$$file.txt" "libs/a/$$file.txt"` will not work since `$$` is swapped with the PID of the last process.
|
132
163
|
// Using single-quotes prevents this substitution.
|
133
|
-
`'${
|
164
|
+
`'${arg}'`;
|
134
165
|
}
|
135
166
|
}
|
136
167
|
exports.GitRepository = GitRepository;
|
@@ -0,0 +1,11 @@
|
|
1
|
+
/**
|
2
|
+
* This is meant to be used with `git filter-branch --tree-filter` to rewrite
|
3
|
+
* history to only include commits related to the source project folder. If the
|
4
|
+
* destination folder is different, this script also moves the files over.
|
5
|
+
*
|
6
|
+
* Example:
|
7
|
+
* NX_IMPORT_SOURCE=<source> NX_IMPORT_DESTINATION=<destination> git filter-branch --tree-filter 'node git-utils.tree-filter.js' --prune-empty -- --all
|
8
|
+
*/
|
9
|
+
declare const execSync: any;
|
10
|
+
declare const existsSync: any, mkdirSync: any, renameSync: any, rmSync: any;
|
11
|
+
declare const posix: any;
|
@@ -0,0 +1,43 @@
|
|
1
|
+
/**
|
2
|
+
* This is meant to be used with `git filter-branch --tree-filter` to rewrite
|
3
|
+
* history to only include commits related to the source project folder. If the
|
4
|
+
* destination folder is different, this script also moves the files over.
|
5
|
+
*
|
6
|
+
* Example:
|
7
|
+
* NX_IMPORT_SOURCE=<source> NX_IMPORT_DESTINATION=<destination> git filter-branch --tree-filter 'node git-utils.tree-filter.js' --prune-empty -- --all
|
8
|
+
*/
|
9
|
+
const { execSync } = require('child_process');
|
10
|
+
const { existsSync, mkdirSync, renameSync, rmSync } = require('fs');
|
11
|
+
// NOTE: The path passed to `git filter-branch` is POSIX, so we need to use the `posix` module.
|
12
|
+
const { posix } = require('path');
|
13
|
+
try {
|
14
|
+
// NOTE: Using env vars because Windows PowerShell has its own handling of quotes (") messes up quotes in args, even if escaped.
|
15
|
+
const src = process.env.NX_IMPORT_SOURCE;
|
16
|
+
const dest = process.env.NX_IMPORT_DESTINATION;
|
17
|
+
const files = execSync(`git ls-files -z ${src}`)
|
18
|
+
.toString()
|
19
|
+
.trim()
|
20
|
+
.split('\x00')
|
21
|
+
.map((s) => s.trim())
|
22
|
+
.filter(Boolean);
|
23
|
+
for (const file of files) {
|
24
|
+
if (src === '' || file.startsWith(src)) {
|
25
|
+
// If source and destination are the same, then keep the file as is.
|
26
|
+
if (src === dest)
|
27
|
+
continue;
|
28
|
+
const destFile = posix.join(dest, file.replace(src, ''));
|
29
|
+
const dir = posix.dirname(destFile);
|
30
|
+
if (!existsSync(dir))
|
31
|
+
mkdirSync(dir, { recursive: true });
|
32
|
+
renameSync(file, destFile);
|
33
|
+
}
|
34
|
+
else {
|
35
|
+
// If not matching the source we are filtering, remove it.
|
36
|
+
rmSync(file);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
catch (error) {
|
41
|
+
console.error(`Error executing Git commands: ${error}`);
|
42
|
+
process.exit(1);
|
43
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function handleErrors(isVerbose: boolean, fn: Function): Promise<number>;
|
@@ -0,0 +1,71 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.handleErrors = handleErrors;
|
4
|
+
const client_1 = require("../daemon/client/client");
|
5
|
+
const logger_1 = require("./logger");
|
6
|
+
const output_1 = require("./output");
|
7
|
+
async function handleErrors(isVerbose, fn) {
|
8
|
+
try {
|
9
|
+
const result = await fn();
|
10
|
+
if (typeof result === 'number') {
|
11
|
+
return result;
|
12
|
+
}
|
13
|
+
return 0;
|
14
|
+
}
|
15
|
+
catch (err) {
|
16
|
+
err ||= new Error('Unknown error caught');
|
17
|
+
if (err.constructor.name === 'UnsuccessfulWorkflowExecution') {
|
18
|
+
logger_1.logger.error('The generator workflow failed. See above.');
|
19
|
+
}
|
20
|
+
else if (err.name === 'ProjectGraphError') {
|
21
|
+
const projectGraphError = err;
|
22
|
+
let title = projectGraphError.message;
|
23
|
+
if (projectGraphError.cause &&
|
24
|
+
typeof projectGraphError.cause === 'object' &&
|
25
|
+
'message' in projectGraphError.cause) {
|
26
|
+
title += ' ' + projectGraphError.cause.message + '.';
|
27
|
+
}
|
28
|
+
if (isVerbose) {
|
29
|
+
title += ' See errors below.';
|
30
|
+
}
|
31
|
+
const bodyLines = isVerbose
|
32
|
+
? formatErrorStackAndCause(projectGraphError)
|
33
|
+
: ['Pass --verbose to see the stacktraces.'];
|
34
|
+
output_1.output.error({
|
35
|
+
title,
|
36
|
+
bodyLines: bodyLines,
|
37
|
+
});
|
38
|
+
}
|
39
|
+
else {
|
40
|
+
const lines = (err.message ? err.message : err.toString()).split('\n');
|
41
|
+
const bodyLines = lines.slice(1);
|
42
|
+
if (isVerbose) {
|
43
|
+
bodyLines.push(...formatErrorStackAndCause(err));
|
44
|
+
}
|
45
|
+
else if (err.stack) {
|
46
|
+
bodyLines.push('Pass --verbose to see the stacktrace.');
|
47
|
+
}
|
48
|
+
output_1.output.error({
|
49
|
+
title: lines[0],
|
50
|
+
bodyLines,
|
51
|
+
});
|
52
|
+
}
|
53
|
+
if (client_1.daemonClient.enabled()) {
|
54
|
+
client_1.daemonClient.reset();
|
55
|
+
}
|
56
|
+
return 1;
|
57
|
+
}
|
58
|
+
}
|
59
|
+
function formatErrorStackAndCause(error) {
|
60
|
+
return [
|
61
|
+
error.stack || error.message,
|
62
|
+
...(error.cause && typeof error.cause === 'object'
|
63
|
+
? [
|
64
|
+
'Caused by:',
|
65
|
+
'stack' in error.cause
|
66
|
+
? error.cause.stack.toString()
|
67
|
+
: error.cause.toString(),
|
68
|
+
]
|
69
|
+
: []),
|
70
|
+
];
|
71
|
+
}
|
@@ -1,4 +1,3 @@
|
|
1
1
|
import { NxJsonConfiguration } from '../config/nx-json';
|
2
2
|
export declare function isNxCloudUsed(nxJson: NxJsonConfiguration): boolean;
|
3
3
|
export declare function getNxCloudUrl(nxJson: NxJsonConfiguration): string;
|
4
|
-
export declare function getNxCloudToken(nxJson: NxJsonConfiguration): string;
|
@@ -2,7 +2,6 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.isNxCloudUsed = isNxCloudUsed;
|
4
4
|
exports.getNxCloudUrl = getNxCloudUrl;
|
5
|
-
exports.getNxCloudToken = getNxCloudToken;
|
6
5
|
function isNxCloudUsed(nxJson) {
|
7
6
|
return (!!process.env.NX_CLOUD_ACCESS_TOKEN ||
|
8
7
|
!!nxJson.nxCloudAccessToken ||
|
@@ -17,12 +16,3 @@ function getNxCloudUrl(nxJson) {
|
|
17
16
|
throw new Error('nx-cloud runner not found in nx.json');
|
18
17
|
return cloudRunner?.options?.url ?? nxJson.nxCloudUrl ?? 'https://nx.app';
|
19
18
|
}
|
20
|
-
function getNxCloudToken(nxJson) {
|
21
|
-
const cloudRunner = Object.values(nxJson.tasksRunnerOptions ?? {}).find((r) => r.runner == '@nrwl/nx-cloud' || r.runner == 'nx-cloud');
|
22
|
-
if (!cloudRunner &&
|
23
|
-
!(nxJson.nxCloudAccessToken || process.env.NX_CLOUD_ACCESS_TOKEN))
|
24
|
-
throw new Error('nx-cloud runner not found in nx.json');
|
25
|
-
return (process.env.NX_CLOUD_ACCESS_TOKEN ??
|
26
|
-
cloudRunner?.options.accessToken ??
|
27
|
-
nxJson.nxCloudAccessToken);
|
28
|
-
}
|
package/src/utils/params.d.ts
CHANGED
@@ -79,7 +79,6 @@ export type Options = {
|
|
79
79
|
'--'?: Unmatched[];
|
80
80
|
[k: string]: string | number | boolean | string[] | Unmatched[] | undefined;
|
81
81
|
};
|
82
|
-
export declare function handleErrors(isVerbose: boolean, fn: Function): Promise<number>;
|
83
82
|
export declare function convertToCamelCase(parsed: {
|
84
83
|
[k: string]: any;
|
85
84
|
}, schema: Schema): Options;
|
package/src/utils/params.js
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.SchemaError = void 0;
|
4
|
-
exports.handleErrors = handleErrors;
|
5
4
|
exports.convertToCamelCase = convertToCamelCase;
|
6
5
|
exports.coerceTypesInOptions = coerceTypesInOptions;
|
7
6
|
exports.convertAliases = convertAliases;
|
@@ -15,55 +14,6 @@ exports.warnDeprecations = warnDeprecations;
|
|
15
14
|
exports.convertSmartDefaultsIntoNamedParams = convertSmartDefaultsIntoNamedParams;
|
16
15
|
exports.getPromptsForSchema = getPromptsForSchema;
|
17
16
|
const logger_1 = require("./logger");
|
18
|
-
const output_1 = require("./output");
|
19
|
-
const client_1 = require("../daemon/client/client");
|
20
|
-
async function handleErrors(isVerbose, fn) {
|
21
|
-
try {
|
22
|
-
const result = await fn();
|
23
|
-
if (typeof result === 'number') {
|
24
|
-
return result;
|
25
|
-
}
|
26
|
-
return 0;
|
27
|
-
}
|
28
|
-
catch (err) {
|
29
|
-
err ||= new Error('Unknown error caught');
|
30
|
-
if (err.constructor.name === 'UnsuccessfulWorkflowExecution') {
|
31
|
-
logger_1.logger.error('The generator workflow failed. See above.');
|
32
|
-
}
|
33
|
-
else if (err.name === 'ProjectGraphError') {
|
34
|
-
const projectGraphError = err;
|
35
|
-
let title = projectGraphError.message;
|
36
|
-
if (isVerbose) {
|
37
|
-
title += ' See errors below.';
|
38
|
-
}
|
39
|
-
const bodyLines = isVerbose
|
40
|
-
? [projectGraphError.stack]
|
41
|
-
: ['Pass --verbose to see the stacktraces.'];
|
42
|
-
output_1.output.error({
|
43
|
-
title,
|
44
|
-
bodyLines: bodyLines,
|
45
|
-
});
|
46
|
-
}
|
47
|
-
else {
|
48
|
-
const lines = (err.message ? err.message : err.toString()).split('\n');
|
49
|
-
const bodyLines = lines.slice(1);
|
50
|
-
if (err.stack && !isVerbose) {
|
51
|
-
bodyLines.push('Pass --verbose to see the stacktrace.');
|
52
|
-
}
|
53
|
-
output_1.output.error({
|
54
|
-
title: lines[0],
|
55
|
-
bodyLines,
|
56
|
-
});
|
57
|
-
if (err.stack && isVerbose) {
|
58
|
-
logger_1.logger.info(err.stack);
|
59
|
-
}
|
60
|
-
}
|
61
|
-
if (client_1.daemonClient.enabled()) {
|
62
|
-
client_1.daemonClient.reset();
|
63
|
-
}
|
64
|
-
return 1;
|
65
|
-
}
|
66
|
-
}
|
67
17
|
function camelCase(input) {
|
68
18
|
if (input.indexOf('-') > 1) {
|
69
19
|
return input
|