@jayree/sfdx-plugin-manifest 2.9.0 → 3.0.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.
@@ -4,179 +4,108 @@
4
4
  * Licensed under the BSD 3-Clause license.
5
5
  * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
6
  */
7
- import { join, basename, sep, posix, dirname, relative, resolve } from 'node:path';
7
+ import { join, dirname } from 'node:path';
8
8
  import { fileURLToPath } from 'node:url';
9
- import { format } from 'node:util';
10
- import { SfCommand, Flags, arrayWithDeprecation } from '@salesforce/sf-plugins-core';
11
- import { Messages, SfError, SfProject } from '@salesforce/core';
12
- import { Args } from '@oclif/core';
9
+ import { Messages } from '@salesforce/core';
13
10
  import fs from 'fs-extra';
14
- import { Logger, Listr } from 'listr2';
15
- import { env } from '@salesforce/kit';
11
+ import { DestructiveChangesType } from '@salesforce/source-deploy-retrieve';
12
+ import { SfCommand, Flags, orgApiVersionFlagWithDeprecations, arrayWithDeprecation } from '@salesforce/sf-plugins-core';
13
+ import { Args } from '@oclif/core';
16
14
  import { getString } from '@salesforce/ts-types';
17
- import equal from 'fast-deep-equal';
18
- import { ComponentSet, RegistryAccess, registry, VirtualTreeContainer, MetadataResolver, DestructiveChangesType, } from '@salesforce/source-deploy-retrieve';
19
- import { parseMetadataXml } from '@salesforce/source-deploy-retrieve/lib/src/utils/index.js';
20
- import Debug from 'debug';
21
- import git from 'isomorphic-git';
15
+ import { ComponentSetExtra } from '../../../../SDR-extra/index.js';
22
16
  // eslint-disable-next-line no-underscore-dangle
23
17
  const __filename = fileURLToPath(import.meta.url);
24
18
  // eslint-disable-next-line no-underscore-dangle
25
19
  const __dirname = dirname(__filename);
26
20
  Messages.importMessagesDirectory(__dirname);
27
21
  const messages = Messages.loadMessages('@jayree/sfdx-plugin-manifest', 'gitdiff');
28
- const logger = new Logger({ useIcons: false });
29
- const debug = Debug('jayree:manifest:git:diff');
30
- const registryAccess = new RegistryAccess();
31
- export default class GitDiff extends SfCommand {
22
+ export default class GitDiffCommand extends SfCommand {
23
+ // eslint-disable-next-line sf-plugin/should-parse-flags
32
24
  async run() {
33
- const { flags, args } = await this.parse(GitDiff);
34
- const sourcepath = flags['source-dir'];
35
- this.destructiveChangesOnly = flags['destructive-changes-only'];
25
+ await this.createManifest();
26
+ return this.formatResult();
27
+ }
28
+ async getSourceApiVersion() {
29
+ const projectConfig = await this.project.resolveProjectConfig();
30
+ return getString(projectConfig, 'sourceApiVersion') ?? undefined;
31
+ }
32
+ async createManifest() {
33
+ const { flags, args } = await this.parse(GitDiffCommand);
34
+ this.manifestName = 'package.xml';
35
+ this.destructiveChangesName = 'destructiveChanges.xml';
36
36
  this.outputDir = flags['output-dir'];
37
- this.projectRoot = this.project.getPath();
38
- this.sourceApiVersion = (await this.getSourceApiVersion());
39
- this.destructiveChanges = join(this.outputDir, 'destructiveChanges.xml');
40
- this.manifest = join(this.outputDir, 'package.xml');
41
- debug({
42
- outputDir: this.outputDir,
43
- projectRoot: this.projectRoot,
37
+ this.destructiveChangesOnly = flags['destructive-changes-only'];
38
+ this.componentSet = await ComponentSetExtra.fromGitDiff({
39
+ ref: [args.ref1, args.ref2],
40
+ fsPaths: flags['source-dir'],
44
41
  });
45
- const isContentTypeJSON = env.getString('SFDX_CONTENT_TYPE', '').toUpperCase() === 'JSON';
46
- this.isOutputEnabled = !(this.argv.find((arg) => arg === '--json') ?? isContentTypeJSON);
47
- const gitArgs = await getGitArgsFromArgv(args.ref1, args.ref2, this.argv, this.projectRoot);
48
- debug({ gitArgs });
49
- const tasks = new Listr([
50
- {
51
- title: `Execute 'git --no-pager diff --name-status --no-renames ${gitArgs.refString}'`,
52
- task: async (ctx, task) => {
53
- const { gitlines, warnings } = await getGitDiff(gitArgs.ref1, gitArgs.ref2, this.projectRoot);
54
- this.gitLines = gitlines;
55
- this.outputWarnings = warnings;
56
- task.output = `Changed files: ${this.gitLines.length}`;
57
- },
58
- options: { persistentOutput: true },
59
- },
60
- {
61
- // title: 'Warning output',
62
- skip: () => !this.outputWarnings?.length,
63
- task: (ctx, task) => {
64
- debug({ warnings: this.outputWarnings });
65
- const moreWarnings = this.outputWarnings.splice(5);
66
- for (const message of this.outputWarnings) {
67
- task.output = `Warning: unstaged file ${message}`;
68
- }
69
- task.output = moreWarnings.length ? `... ${moreWarnings.length} more warnings` : '';
70
- },
71
- options: { persistentOutput: true, bottomBar: 6 },
72
- },
73
- {
74
- title: 'Create virtual tree container',
75
- skip: () => !this.gitLines.length,
76
- task: (ctx, task) => task.newListr([
77
- {
78
- title: `ref1: ${gitArgs.ref1}`,
79
- task: async () => {
80
- this.ref1VirtualTreeContainer = await createVirtualTreeContainer(gitArgs.ref1, this.projectRoot, this.gitLines.filter((l) => l.status === 'M').map((l) => l.path));
81
- },
82
- },
83
- {
84
- title: gitArgs.ref2 !== '' ? `ref2: ${gitArgs.ref2}` : 'ref2: (staging area)',
85
- task: async () => {
86
- this.ref2VirtualTreeContainer = await createVirtualTreeContainer(gitArgs.ref2, this.projectRoot, this.gitLines.filter((l) => l.status === 'M').map((l) => l.path));
87
- },
88
- },
89
- ], { concurrent: true }),
90
- },
91
- {
92
- title: 'Analyze git diff results',
93
- skip: () => !this.gitLines.length,
94
- task: async (ctx, task) => {
95
- if (sourcepath) {
96
- this.fsPaths = sourcepath.map((filepath) => {
97
- filepath = resolve(filepath);
98
- if (!this.ref1VirtualTreeContainer.exists(filepath) &&
99
- !this.ref2VirtualTreeContainer.exists(filepath)) {
100
- throw new SfError(`The sourcepath "${filepath}" is not a valid source file path.`);
101
- }
102
- return filepath;
103
- });
104
- debug(`fsPaths: ${this.fsPaths.join(', ')}`);
42
+ this.componentSet.sourceApiVersion = flags['api-version'] ?? (await this.getSourceApiVersion());
43
+ if (this.outputDir) {
44
+ await fs.ensureDir(this.outputDir);
45
+ this.outputPath = join(this.outputDir, this.manifestName);
46
+ }
47
+ else {
48
+ this.outputPath = this.manifestName;
49
+ }
50
+ if (this.componentSet.size) {
51
+ if (this.componentSet.getTypesOfDestructiveChanges().length) {
52
+ await fs.writeFile(join(this.outputDir, this.destructiveChangesName), await this.componentSet.getPackageXml(undefined, DestructiveChangesType.POST));
53
+ }
54
+ if (this.destructiveChangesOnly) {
55
+ if (this.componentSet.getTypesOfDestructiveChanges().length) {
56
+ const emptyCompSet = new ComponentSetExtra();
57
+ emptyCompSet.sourceApiVersion = this.componentSet.sourceApiVersion;
58
+ return fs.writeFile(this.outputPath, await emptyCompSet.getPackageXml());
59
+ }
60
+ return;
61
+ }
62
+ return fs.writeFile(this.outputPath, await this.componentSet.getPackageXml());
63
+ }
64
+ }
65
+ formatResult() {
66
+ if (!this.jsonEnabled()) {
67
+ if (this.componentSet.size) {
68
+ if (this.destructiveChangesOnly && !this.componentSet.getTypesOfDestructiveChanges().length) {
69
+ this.log(messages.getMessage('noComponents'));
70
+ }
71
+ else if (this.outputDir) {
72
+ this.log(messages.getMessage('successOutputDir', [this.manifestName, this.outputDir]));
73
+ if (this.componentSet.getTypesOfDestructiveChanges().length) {
74
+ this.log(messages.getMessage('successOutputDir', [this.destructiveChangesName, this.outputDir]));
105
75
  }
106
- const { manifest, output } = await getGitResults(this.gitLines, this.ref1VirtualTreeContainer, this.ref2VirtualTreeContainer, this.destructiveChangesOnly, this.fsPaths);
107
- task.output = `Added: ${output.counts.added}, Deleted: ${output.counts.deleted}, Modified: ${output.counts.modified}, Unchanged: ${output.counts.unchanged}, Ignored: ${output.counts.ignored}${output.counts.error ? `, Errors: ${output.counts.error}` : ''}`;
108
- this.outputErrors = output.errors;
109
- debug({ manifest });
110
- this.componentSet = fixComponentSetChilds(manifest);
111
- this.componentSet.sourceApiVersion = this.sourceApiVersion;
112
- },
113
- options: { persistentOutput: true },
114
- },
115
- {
116
- // title: 'Error output',
117
- skip: () => !this.outputErrors?.length,
118
- task: (ctx, task) => {
119
- debug({ errors: this.outputErrors });
120
- const moreErrors = this.outputErrors.splice(5);
121
- for (const message of this.outputErrors) {
122
- task.output = `Error: ${message}`;
76
+ }
77
+ else {
78
+ this.log(messages.getMessage('success', [this.manifestName]));
79
+ if (this.componentSet.getTypesOfDestructiveChanges().length) {
80
+ this.log(messages.getMessage('success', [this.destructiveChangesName]));
123
81
  }
124
- task.output = moreErrors.length ? `... ${moreErrors.length} more errors` : '';
125
- },
126
- options: { persistentOutput: true, bottomBar: 6 },
127
- },
128
- {
129
- title: 'Generate manifests',
130
- skip: () => !this.componentSet?.size,
131
- task: (ctx, task) => task.newListr([
132
- {
133
- title: this.manifest,
134
- skip: () => !this.isOutputEnabled,
135
- task: async () => {
136
- await fs.ensureDir(dirname(this.manifest));
137
- await fs.writeFile(this.manifest, await this.componentSet.getPackageXml());
138
- },
139
- options: { persistentOutput: true },
140
- },
141
- {
142
- title: this.destructiveChanges,
143
- skip: () => !this.componentSet.getTypesOfDestructiveChanges().length || !this.isOutputEnabled,
144
- task: async () => {
145
- await fs.ensureDir(dirname(this.destructiveChanges));
146
- await fs.writeFile(this.destructiveChanges, await this.componentSet.getPackageXml(undefined, DestructiveChangesType.POST));
147
- },
148
- options: { persistentOutput: true },
149
- },
150
- ], { concurrent: true }),
151
- },
152
- ], {
153
- rendererOptions: { showTimer: true, collapse: false, lazy: true, collapseErrors: false },
154
- rendererSilent: !this.isOutputEnabled,
155
- rendererFallback: debug.enabled,
156
- });
157
- try {
158
- await tasks.run();
82
+ }
83
+ }
84
+ else {
85
+ this.log(messages.getMessage('noComponents'));
86
+ }
87
+ }
88
+ if (this.componentSet.getTypesOfDestructiveChanges().length) {
159
89
  return {
160
- destructiveChanges: await this.componentSet?.getObject(DestructiveChangesType.POST),
161
- manifest: await this.componentSet?.getObject(),
90
+ manifest: { path: this.outputPath, name: this.manifestName },
91
+ destructiveChanges: {
92
+ path: join(this.outputDir, this.destructiveChangesName),
93
+ name: this.destructiveChangesName,
94
+ },
162
95
  };
163
96
  }
164
- catch (e) {
165
- if (debug.enabled && this.isOutputEnabled) {
166
- logger.fail(e.message);
167
- }
168
- throw e;
97
+ else if (this.componentSet.size && !this.destructiveChangesOnly) {
98
+ return { manifest: { path: this.outputPath, name: this.manifestName } };
99
+ }
100
+ else {
101
+ return {};
169
102
  }
170
- }
171
- async getSourceApiVersion() {
172
- const projectConfig = await this.project.resolveProjectConfig();
173
- return getString(projectConfig, 'sourceApiVersion') ?? undefined;
174
103
  }
175
104
  }
176
- GitDiff.summary = messages.getMessage('summary');
177
- GitDiff.description = messages.getMessage('description');
178
- GitDiff.examples = messages.getMessages('examples');
179
- GitDiff.args = {
105
+ GitDiffCommand.summary = messages.getMessage('summary');
106
+ GitDiffCommand.description = messages.getMessage('description');
107
+ GitDiffCommand.examples = messages.getMessages('examples');
108
+ GitDiffCommand.args = {
180
109
  ref1: Args.string({
181
110
  required: true,
182
111
  description: messages.getMessage('args.ref1.description'),
@@ -185,8 +114,11 @@ GitDiff.args = {
185
114
  description: messages.getMessage('args.ref2.description'),
186
115
  }),
187
116
  };
188
- GitDiff.requiresProject = true;
189
- GitDiff.flags = {
117
+ GitDiffCommand.requiresProject = true;
118
+ GitDiffCommand.deprecateAliases = true;
119
+ GitDiffCommand.aliases = ['jayree:manifest:beta:git:diff'];
120
+ GitDiffCommand.flags = {
121
+ 'api-version': orgApiVersionFlagWithDeprecations,
190
122
  'source-dir': arrayWithDeprecation({
191
123
  char: 'd',
192
124
  summary: messages.getMessage('flags.source-dir.summary'),
@@ -208,433 +140,4 @@ GitDiff.flags = {
208
140
  aliases: ['destructivechangesonly'],
209
141
  }),
210
142
  };
211
- async function resolveRef(refOrig, dir) {
212
- if (refOrig === '') {
213
- return '';
214
- }
215
- const getCommitLog = async (ref) => {
216
- try {
217
- const [log] = await git.log({
218
- fs,
219
- dir,
220
- ref,
221
- depth: 1,
222
- });
223
- return { oid: log.oid, parents: log.commit.parent };
224
- }
225
- catch (error) {
226
- throw new Error(`ambiguous argument '${ref}': unknown revision or path not in the working tree.
227
- See more help with --help`);
228
- }
229
- };
230
- if (!['~', '^'].some((el) => refOrig.includes(el))) {
231
- return (await getCommitLog(refOrig)).oid;
232
- }
233
- const firstIndex = [refOrig.indexOf('^'), refOrig.indexOf('~')]
234
- .filter((a) => a >= 0)
235
- .reduce((a, b) => Math.min(a, b));
236
- let path = refOrig.substring(firstIndex);
237
- let ref = refOrig.substring(0, firstIndex);
238
- while (path.length && ref !== undefined) {
239
- if (path.startsWith('^')) {
240
- path = path.substring(1);
241
- let next = Number(path.substring(0, 1));
242
- path = next ? path.substring(1) : path;
243
- next = next ? next : 1;
244
- // eslint-disable-next-line no-await-in-loop
245
- ref = (await getCommitLog(ref)).parents[next - 1];
246
- }
247
- else if (path.startsWith('~')) {
248
- path = path.substring(1);
249
- let next = Number(path.substring(0, 1));
250
- path = next ? path.substring(1) : path;
251
- next = next ? next : 1;
252
- for (let index = 0; index <= next - 1; index++) {
253
- // eslint-disable-next-line no-await-in-loop
254
- ref = (await getCommitLog(ref)).parents[0];
255
- }
256
- }
257
- else {
258
- ref = undefined;
259
- }
260
- }
261
- if (ref === undefined) {
262
- throw new Error(`ambiguous argument '${refOrig}': unknown revision or path not in the working tree.`);
263
- }
264
- return ref;
265
- }
266
- async function getGitArgsFromArgv(ref1, ref2, argv, dir) {
267
- const newArgv = [];
268
- while (argv.length) {
269
- let [e] = argv.splice(0, 1);
270
- if (e.includes('=')) {
271
- // skip parameter=value
272
- }
273
- else if (e.includes('-')) {
274
- // remove value
275
- if (argv[0] && !argv[0].includes('-') && ![ref1, ref2].includes(argv[0])) {
276
- [e] = argv.splice(0, 1);
277
- }
278
- }
279
- else {
280
- newArgv.push(e);
281
- }
282
- }
283
- argv = newArgv;
284
- let refString = ref1;
285
- const a = argv.join('.').split('.');
286
- if ((a.length === 3 || a.length === 4) && typeof ref2 === 'undefined') {
287
- ref1 = a[0];
288
- ref2 = a[a.length - 1];
289
- }
290
- else if (a.length === 2 && typeof ref2 !== 'undefined') {
291
- refString = `${ref1}..${ref2}`;
292
- }
293
- else if (a.length === 1) {
294
- ref2 = '';
295
- }
296
- else {
297
- throw new Error(`Ambiguous ${format('argument%s', argv.length === 1 ? '' : 's')}: ${argv.join(', ')}
298
- See more help with --help`);
299
- }
300
- ref1 = await resolveRef(ref1, dir);
301
- ref2 = await resolveRef(ref2, dir);
302
- if (a.length === 4) {
303
- ref1 = (await git.findMergeBase({
304
- fs,
305
- dir,
306
- oids: [ref2, ref1],
307
- }))[0];
308
- }
309
- return { ref1, ref2, refString };
310
- }
311
- function ensureOSPath(path) {
312
- return path.split(posix.sep).join(sep);
313
- }
314
- function ensureGitRelPath(dir, path) {
315
- return relative(dir, path).split(sep).join(posix.sep);
316
- }
317
- async function createVirtualTreeContainer(ref, dir, modifiedFiles) {
318
- const paths = (await git.listFiles({ fs, dir, ref })).map((p) => join(dir, ensureOSPath(p)));
319
- const oid = ref ? await git.resolveRef({ fs, dir, ref }) : '';
320
- const virtualDirectoryByFullPath = new Map();
321
- for await (const filename of paths) {
322
- let dirPath = dirname(filename);
323
- virtualDirectoryByFullPath.set(dirPath, {
324
- dirPath,
325
- children: Array.from(new Set(virtualDirectoryByFullPath.get(dirPath)?.children ?? []).add({
326
- name: basename(filename),
327
- data: parseMetadataXml(filename) && modifiedFiles.includes(filename)
328
- ? oid
329
- ? Buffer.from((await git.readBlob({ fs, dir, oid, filepath: ensureGitRelPath(dir, filename) })).blob)
330
- : await fs.readFile(ensureOSPath(filename))
331
- : Buffer.from(''),
332
- })),
333
- });
334
- const splits = filename.split(sep);
335
- for (let i = 1; i < splits.length - 1; i++) {
336
- dirPath = splits.slice(0, i + 1).join(sep);
337
- virtualDirectoryByFullPath.set(dirPath, {
338
- dirPath,
339
- children: Array.from(new Set(virtualDirectoryByFullPath.get(dirPath)?.children ?? []).add(splits[i + 1])),
340
- });
341
- }
342
- }
343
- return new VirtualTreeContainer(Array.from(virtualDirectoryByFullPath.values()));
344
- }
345
- async function analyzeFile(path, ref1VirtualTreeContainer, ref2VirtualTreeContainer) {
346
- if (!parseMetadataXml(path)) {
347
- return { path, status: 0 };
348
- }
349
- const ref2resolver = new MetadataResolver(registryAccess, ref2VirtualTreeContainer);
350
- const [ref2Component] = ref2resolver.getComponentsFromPath(path); // git path only conaints files
351
- const ref1resolver = new MetadataResolver(registryAccess, ref1VirtualTreeContainer);
352
- const [ref1Component] = ref1resolver.getComponentsFromPath(path); // git path only conaints files
353
- if (ref1resolver.forceIgnoredPaths.has(path) || ref2resolver.forceIgnoredPaths.has(path)) {
354
- return { path, status: -2 };
355
- }
356
- if (equal(await ref1Component.parseXml(), await ref2Component.parseXml())) {
357
- return { path, status: -1 };
358
- }
359
- if (ref1Component.type.strictDirectoryName === true || !ref1Component.type.children) {
360
- return { path, status: 0 };
361
- }
362
- const ref2ChildUniqueIdArray = ref2Component
363
- .getChildren()
364
- .map((childComponent) => getUniqueIdentifier(childComponent));
365
- const ref1ChildUniqueIdArray = ref1Component
366
- .getChildren()
367
- .map((childComponent) => getUniqueIdentifier(childComponent));
368
- const childComponentsNotInRef2 = ref1Component
369
- .getChildren()
370
- .filter((childComponent) => !ref2ChildUniqueIdArray.includes(getUniqueIdentifier(childComponent))); // deleted
371
- const childComponentsNotInRef1 = ref2Component
372
- .getChildren()
373
- .filter((childComponent) => !ref1ChildUniqueIdArray.includes(getUniqueIdentifier(childComponent))); // added
374
- const childComponentsInRef1AndRef2 = ref1Component
375
- .getChildren()
376
- .filter((childComponent) => ref2ChildUniqueIdArray.includes(getUniqueIdentifier(childComponent))); // modified?
377
- debug({ childComponentsNotInRef2, childComponentsNotInRef1, childComponentsInRef1AndRef2 });
378
- for await (const childComponentRef1 of childComponentsInRef1AndRef2) {
379
- const [childComponentRef2] = ref2Component
380
- .getChildren()
381
- .filter((childComponent) => getUniqueIdentifier(childComponentRef1) === getUniqueIdentifier(childComponent));
382
- if (!equal(await childComponentRef1.parseXml(), await childComponentRef2.parseXml())) {
383
- childComponentsNotInRef1.push(childComponentRef2); // modified! -> add to added
384
- }
385
- }
386
- debug({ childComponentsNotInRef1 });
387
- return {
388
- path,
389
- status: 1 + childComponentsNotInRef2.length + childComponentsNotInRef1.length,
390
- toManifest: childComponentsNotInRef1,
391
- toDestructiveChanges: childComponentsNotInRef2,
392
- };
393
- }
394
- function getUniqueIdentifier(component) {
395
- return `${component.type.name}#${getString(component, component.type.uniqueIdElement)}`;
396
- }
397
- async function getFileStateChanges(commitHash1, commitHash2, dir) {
398
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
399
- return git.walk({
400
- fs,
401
- dir,
402
- trees: [git.TREE({ ref: commitHash1 }), git.TREE({ ref: commitHash2 })],
403
- async map(filepath, [A, B]) {
404
- if (filepath === '.' || (await A?.type()) === 'tree' || (await B?.type()) === 'tree') {
405
- return;
406
- }
407
- const Aoid = await A?.oid();
408
- const Boid = await B?.oid();
409
- let type = 'EQ';
410
- if (Aoid !== Boid) {
411
- type = 'M';
412
- }
413
- if (Aoid === undefined) {
414
- type = 'A';
415
- }
416
- if (Boid === undefined) {
417
- type = 'D';
418
- }
419
- if (type !== 'EQ') {
420
- return {
421
- path: join(dir, ensureOSPath(filepath)),
422
- status: type,
423
- };
424
- }
425
- },
426
- });
427
- }
428
- async function getStatusMatrix(dir, ref) {
429
- const getStatus = (row) => {
430
- if ([
431
- [0, 2, 2],
432
- [0, 2, 3], // added, staged, with unstaged changes
433
- ].some((a) => a.every((val, index) => val === row[index]))) {
434
- return 'A';
435
- }
436
- if ([
437
- [1, 0, 0],
438
- [1, 0, 1],
439
- [1, 1, 0],
440
- [1, 2, 0],
441
- [1, 0, 3], // modified, staged, with unstaged deletion
442
- ].some((a) => a.every((val, index) => val === row[index]))) {
443
- return 'D';
444
- }
445
- if ([
446
- [1, 2, 1],
447
- [1, 2, 2],
448
- [1, 2, 3], // modified, staged, with unstaged changes
449
- ].some((a) => a.every((val, index) => val === row[index]))) {
450
- return 'M';
451
- }
452
- return undefined;
453
- };
454
- const statusMatrix = await git.statusMatrix({ fs, dir, ref });
455
- const warnings = statusMatrix
456
- .filter((row) => [
457
- [0, 2, 0],
458
- [0, 0, 3],
459
- [0, 2, 3],
460
- [1, 2, 1],
461
- [1, 0, 3],
462
- [1, 1, 3],
463
- [1, 2, 3],
464
- [1, 1, 0],
465
- [1, 2, 0],
466
- [1, 0, 1], // deleted, unstaged
467
- ].some((a) => a.every((val, index) => val === row.slice(1)[index])))
468
- .map((row) => join(dir, ensureOSPath(row[0])));
469
- const gitlines = statusMatrix
470
- .filter((row) => ![
471
- [0, 0, 0],
472
- [1, 1, 1],
473
- [0, 0, 3],
474
- [0, 2, 0],
475
- [1, 1, 3], // modified, staged, with unstaged original file
476
- ].some((a) => a.every((val, index) => val === row.slice(1)[index])))
477
- .map((row) => ({
478
- path: join(dir, ensureOSPath(row[0])),
479
- status: getStatus(row.slice(1)),
480
- }));
481
- return { warnings, lines: gitlines };
482
- }
483
- async function getGitDiff(ref1, ref2, dir) {
484
- let gitlines;
485
- let warnings = [];
486
- const proj = await SfProject.resolve();
487
- const resolveSourcePaths = proj.getUniquePackageDirectories().map((pDir) => pDir.fullPath);
488
- if (ref2) {
489
- gitlines = (await getFileStateChanges(ref1, ref2, dir)).filter((l) => resolveSourcePaths.some((f) => l.path.startsWith(f)));
490
- }
491
- else {
492
- const { warnings: warn, lines } = await getStatusMatrix(dir, ref1);
493
- warnings = warn.filter((l) => resolveSourcePaths.some((f) => l.startsWith(f)));
494
- gitlines = lines.filter((l) => resolveSourcePaths.some((f) => l.path.startsWith(f)));
495
- }
496
- gitlines = gitlines.filter((line) => {
497
- if (line.status === 'D') {
498
- for (const sourcePath of resolveSourcePaths) {
499
- const defaultFolder = join(sourcePath, 'main', 'default');
500
- const filePath = line.path.replace(line.path.startsWith(defaultFolder) ? defaultFolder : sourcePath, '');
501
- const target = gitlines.find((t) => t.path.endsWith(filePath) && t.status === 'A');
502
- if (target) {
503
- debug(`rename: ${line.path} -> ${target.path}`);
504
- return false;
505
- }
506
- }
507
- }
508
- return true;
509
- });
510
- debug({ gitlines, warnings });
511
- return { gitlines, warnings };
512
- }
513
- // eslint-disable-next-line complexity
514
- async function getGitResults(gitLines, ref1VirtualTreeContainer, ref2VirtualTreeContainer, destructiveChangesOnly, fsPaths) {
515
- const results = {
516
- manifest: new ComponentSet(undefined, registryAccess),
517
- output: {
518
- unchanged: [],
519
- ignored: { ref1: [], ref2: [] },
520
- counts: { added: 0, deleted: 0, modified: 0, unchanged: 0, ignored: 0, error: 0 },
521
- errors: [],
522
- },
523
- };
524
- const ref1Resolver = new MetadataResolver(registryAccess, ref1VirtualTreeContainer);
525
- const ref2Resolver = new MetadataResolver(registryAccess, ref2VirtualTreeContainer);
526
- const getComponentsFromPath = (resolver, path) => {
527
- let result = [];
528
- try {
529
- result = resolver.getComponentsFromPath(path);
530
- }
531
- catch (error) {
532
- results.output.counts.error++;
533
- results.output.errors.push(error.message);
534
- }
535
- return result;
536
- };
537
- const analyzedFilesPromises = [];
538
- for (const [, { status, path }] of gitLines.entries()) {
539
- if (!fsPaths || fsPaths.some((fsPath) => resolve(path).startsWith(fsPath))) {
540
- if (status === 'D') {
541
- for (const c of getComponentsFromPath(ref1Resolver, path)) {
542
- if (c.xml === path || gitLines.find((x) => x.path === c.xml)) {
543
- results.manifest.add(c, DestructiveChangesType.POST);
544
- results.output.counts.deleted++;
545
- }
546
- else {
547
- try {
548
- if (c.xml) {
549
- // in case a binary source file of a bundle was deleted, check if the bundle ist still valid and update instead of delete
550
- ref2Resolver.getComponentsFromPath(c.xml);
551
- }
552
- if (!destructiveChangesOnly) {
553
- results.manifest.add(c);
554
- results.output.counts.added++;
555
- }
556
- }
557
- catch (error) {
558
- results.output.counts.error++;
559
- results.output.errors.push(error.message);
560
- }
561
- }
562
- }
563
- }
564
- else if (status === 'A') {
565
- if (!destructiveChangesOnly) {
566
- for (const c of getComponentsFromPath(ref2Resolver, path)) {
567
- results.manifest.add(c);
568
- results.output.counts.added++;
569
- }
570
- }
571
- }
572
- else {
573
- analyzedFilesPromises.push(analyzeFile(path, ref1VirtualTreeContainer, ref2VirtualTreeContainer));
574
- }
575
- }
576
- else {
577
- debug(`${path} not included in sourcepath`);
578
- }
579
- }
580
- for await (const check of analyzedFilesPromises) {
581
- if (check.status === 0) {
582
- if (!destructiveChangesOnly) {
583
- for (const c of getComponentsFromPath(ref2Resolver, check.path)) {
584
- results.manifest.add(c);
585
- results.output.counts.modified++;
586
- }
587
- }
588
- }
589
- else if (check.status === -1) {
590
- results.output.unchanged.push(check.path);
591
- results.output.counts.unchanged++;
592
- }
593
- else if (check.status === -2) {
594
- results.output.counts.ignored++;
595
- results.output.ignored.ref2.push(check.path);
596
- }
597
- else {
598
- if ((check.toDestructiveChanges && check.toDestructiveChanges.length > 0) ||
599
- (check.toManifest && check.toManifest.length > 0 && !destructiveChangesOnly)) {
600
- results.output.counts.modified++;
601
- }
602
- if (check.toDestructiveChanges) {
603
- for (const c of check.toDestructiveChanges) {
604
- results.manifest.add(c, DestructiveChangesType.POST);
605
- }
606
- }
607
- if (!destructiveChangesOnly && check.toManifest) {
608
- for (const c of check.toManifest) {
609
- results.manifest.add(c);
610
- }
611
- }
612
- }
613
- }
614
- results.output.ignored = {
615
- ref1: Array.from(ref1Resolver.forceIgnoredPaths),
616
- ref2: results.output.ignored.ref2.concat(Array.from(ref2Resolver.forceIgnoredPaths)),
617
- };
618
- results.output.counts.ignored =
619
- results.output.counts.ignored + ref1Resolver.forceIgnoredPaths.size + ref2Resolver.forceIgnoredPaths.size;
620
- return results;
621
- }
622
- function fixComponentSetChilds(cs) {
623
- let sourceComponents = cs.getSourceComponents();
624
- // SDR library is more strict and avoids fixes like this
625
- const childsTobeReplacedByParent = [
626
- ...Object.keys(registry.types.workflow.children?.types ?? {}),
627
- ...Object.keys(registry.types.sharingrules.children?.types ?? {}),
628
- ...Object.keys(registry.types.customobjecttranslation.children?.types ?? {}),
629
- ...Object.keys(registry.types.bot.children?.types ?? {}),
630
- ];
631
- sourceComponents = sourceComponents.map((component) => {
632
- if (!component.isMarkedForDelete() && childsTobeReplacedByParent.includes(component.type.id) && component.parent) {
633
- debug(`replace: ${component.type.name}:${component.fullName} -> ${component.parent.type.name}:${component.parent.fullName}`);
634
- return component.parent;
635
- }
636
- return component;
637
- });
638
- return new ComponentSet(sourceComponents, registryAccess);
639
- }
640
143
  //# sourceMappingURL=diff.js.map