diff --git a/packages/angular_devkit/build_angular/test/hello-world-lib/.gitignore b/packages/angular_devkit/build_angular/test/hello-world-lib/.gitignore index 54bfd2001e64..e0406551d1ea 100644 --- a/packages/angular_devkit/build_angular/test/hello-world-lib/.gitignore +++ b/packages/angular_devkit/build_angular/test/hello-world-lib/.gitignore @@ -25,6 +25,7 @@ !.vscode/extensions.json # misc +/.angular/cache /.sass-cache /connect.lock /coverage diff --git a/packages/angular_devkit/build_webpack/test/basic-app/.gitignore b/packages/angular_devkit/build_webpack/test/basic-app/.gitignore index 54bfd2001e64..e0406551d1ea 100644 --- a/packages/angular_devkit/build_webpack/test/basic-app/.gitignore +++ b/packages/angular_devkit/build_webpack/test/basic-app/.gitignore @@ -25,6 +25,7 @@ !.vscode/extensions.json # misc +/.angular/cache /.sass-cache /connect.lock /coverage diff --git a/packages/schematics/angular/migrations/migration-collection.json b/packages/schematics/angular/migrations/migration-collection.json index e73d4cd6891d..1df6534c049d 100644 --- a/packages/schematics/angular/migrations/migration-collection.json +++ b/packages/schematics/angular/migrations/migration-collection.json @@ -139,6 +139,11 @@ "version": "13.0.0", "factory": "./update-13/drop-ie-polyfills", "description": "Remove polyfills required only for Internet Explorer which is no longer supported." + }, + "update-gitignore": { + "version": "13.0.0", + "factory": "./update-13/update-gitignore", + "description": "Updating '.gitignore' to include '.angular/cache'." } } } diff --git a/packages/schematics/angular/migrations/update-13/update-gitignore.ts b/packages/schematics/angular/migrations/update-13/update-gitignore.ts new file mode 100644 index 000000000000..a91dcab07d91 --- /dev/null +++ b/packages/schematics/angular/migrations/update-13/update-gitignore.ts @@ -0,0 +1,51 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import { Rule } from '@angular-devkit/schematics'; + +export default function (): Rule { + return (tree, context) => { + const gitIgnoreEntry = '/.angular/cache'; + const gitIgnorePath = '.gitignore'; + + const contents = tree.read(gitIgnorePath)?.toString(); + if (!contents) { + context.logger.warn(`Could not find '${gitIgnorePath}'.`); + + return; + } + + if (contents.includes(gitIgnoreEntry)) { + // The migration has run already. + return; + } + + // Try to insert the new entry in the misc section. + const recorder = tree.beginUpdate(gitIgnorePath); + let idx = contents.indexOf('# misc'); + if (idx < 0) { + idx = 0; + } else { + switch (contents[idx + 6]) { + case '\n': + idx += 7; + break; + case '\r': + idx += 8; + break; + default: + // the word is something else. + idx = 0; + break; + } + } + + recorder.insertLeft(idx, `${gitIgnoreEntry}\n`); + tree.commitUpdate(recorder); + }; +} diff --git a/packages/schematics/angular/migrations/update-13/update-gitignore_spec.ts b/packages/schematics/angular/migrations/update-13/update-gitignore_spec.ts new file mode 100644 index 000000000000..d7a02d844d97 --- /dev/null +++ b/packages/schematics/angular/migrations/update-13/update-gitignore_spec.ts @@ -0,0 +1,128 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import { tags } from '@angular-devkit/core'; +import { EmptyTree } from '@angular-devkit/schematics'; +import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; + +describe('Migration to update "gitignore".', () => { + const schematicName = 'update-gitignore'; + const schematicRunner = new SchematicTestRunner( + 'migrations', + require.resolve('../migration-collection.json'), + ); + + let tree: UnitTestTree; + beforeEach(() => { + tree = new UnitTestTree(new EmptyTree()); + }); + + it(`should not modify '.gitignore' if '.angular/cache' is already present.`, async () => { + const input = tags.stripIndents` + # dependencies + /node_modules + + # profiling files + chrome-profiler-events*.json + + # misc + /.angular/cache + /.sass-cache + /connect.lock + /coverage + + # System Files + .DS_Store + Thumbs.db + `; + + tree.create('.gitignore', input); + const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise(); + expect(newTree.readContent('.gitignore')).toBe(input); + }); + + it(`should insert '.angular/cache' in '# misc' section when it exists.`, async () => { + const input = tags.stripIndents` + # dependencies + /node_modules + + # profiling files + chrome-profiler-events*.json + + # misc + /.sass-cache + /connect.lock + /coverage + + # System Files + .DS_Store + Thumbs.db + `; + + const output = tags.stripIndents` + # dependencies + /node_modules + + # profiling files + chrome-profiler-events*.json + + # misc + /.angular/cache + /.sass-cache + /connect.lock + /coverage + + # System Files + .DS_Store + Thumbs.db + `; + + tree.create('.gitignore', input); + const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise(); + expect(newTree.readContent('.gitignore')).toBe(output); + }); + + it(`should insert '.angular/cache' at the top when '# misc' section does not exist.`, async () => { + const input = tags.stripIndents` + # dependencies + /node_modules + + # profiling files + chrome-profiler-events*.json + + # miscs + /connect.lock + /coverage + + # System Files + .DS_Store + Thumbs.db + `; + + const output = tags.stripIndents` + /.angular/cache + # dependencies + /node_modules + + # profiling files + chrome-profiler-events*.json + + # miscs + /connect.lock + /coverage + + # System Files + .DS_Store + Thumbs.db + `; + + tree.create('.gitignore', input); + const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise(); + expect(newTree.readContent('.gitignore')).toBe(output); + }); +}); diff --git a/packages/schematics/angular/workspace/files/__dot__gitignore.template b/packages/schematics/angular/workspace/files/__dot__gitignore.template index de51f68a2cda..105c00f22e08 100644 --- a/packages/schematics/angular/workspace/files/__dot__gitignore.template +++ b/packages/schematics/angular/workspace/files/__dot__gitignore.template @@ -31,6 +31,7 @@ chrome-profiler-events*.json .history/* # misc +/.angular/cache /.sass-cache /connect.lock /coverage