hunk.code_window:   static assertCompatibleAngularVersion(projectRoot: string) {
       let angularPkgJson;
       let rxjsPkgJson;
       try {
         const resolveOptions = {
           basedir: projectRoot,
           checkGlobal: false,
           checkLocal: true,
         };
         const angularPackagePath = resolve('@angular/core/package.json', resolveOptions);
         const rxjsPackagePath = resolve('rxjs/package.json', resolveOptions);
         angularPkgJson = require(angularPackagePath);
         rxjsPkgJson = require(rxjsPackagePath);
       } catch {
  
hunk.labels: keep keep keep keep keep replace replace replace replace replace replace replace keep keep keep keep
hunk.after_edit:       const resolveOptions = { paths: [projectRoot] };
         const angularPackagePath = require.resolve('@angular/core/package.json', resolveOptions);
         const rxjsPackagePath = require.resolve('rxjs/package.json', resolveOptions);
  
hunk.file_path: packages/angular/cli/upgrade/version.ts
hunk.type: replace
file: /**
   * @license
   * Copyright Google Inc. 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 { Architect } from '@angular-devkit/architect/src/index2';
  import { normalize } from '@angular-devkit/core';
  import { browserBuild, createArchitect, host, lazyModuleFiles, lazyModuleImport } from '../utils';
  
  describe('Browser Builder output hashing', () => {
    const target = { project: 'app', target: 'build' };
    let architect: Architect;
  
    beforeEach(async () => {
      await host.initialize().toPromise();
      architect = (await createArchitect(host.root())).architect;
    });
    afterEach(async () => host.restore().toPromise());
  
    it('updates hash as content changes', async () => {
      const OUTPUT_RE = /(main|styles|lazy\.module)\.([a-z0-9]+)\.(chunk|bundle)\.(js|css)$/;
  
      function generateFileHashMap(): Map<string, string> {
        const hashes = new Map<string, string>();
  
        host.scopedSync().list(normalize('./dist')).forEach(name => {
          const matches = name.match(OUTPUT_RE);
          if (matches) {
            const [, module, hash] = matches;
            hashes.set(module, hash);
          }
        });
  
        return hashes;
      }
  
      function validateHashes(
        oldHashes: Map<string, string>,
        newHashes: Map<string, string>,
        shouldChange: Array<string>,
      ): void {
        newHashes.forEach((hash, module) => {
          if (hash == oldHashes.get(module)) {
            if (shouldChange.includes(module)) {
              throw new Error(
                `Module "${module}" did not change hash (${hash}), but was expected to.`);
            }
          } else if (!shouldChange.includes(module)) {
            throw new Error(`Module "${module}" changed hash (${hash}), but was not expected to.`);
          }
        });
      }
  
      let oldHashes: Map<string, string>;
      let newHashes: Map<string, string>;
  
      host.writeMultipleFiles(lazyModuleFiles);
      host.writeMultipleFiles(lazyModuleImport);
  
      const overrides = { outputHashing: 'all', extractCss: true };
  
      // We must do several builds instead of a single one in watch mode, so that the output
      // path is deleted on each run and only contains the most recent files.
      await browserBuild(architect, host, target, overrides);
  
      // Save the current hashes.
      oldHashes = generateFileHashMap();
      host.writeMultipleFiles(lazyModuleFiles);
      host.writeMultipleFiles(lazyModuleImport);
  
      await browserBuild(architect, host, target, overrides);
      newHashes = generateFileHashMap();
      validateHashes(oldHashes, newHashes, []);
      oldHashes = newHashes;
      host.writeMultipleFiles({ 'src/styles.css': 'body { background: blue; }' });
  
      // Style hash should change.
      await browserBuild(architect, host, target, overrides);
      newHashes = generateFileHashMap();
      validateHashes(oldHashes, newHashes, ['styles']);
      oldHashes = newHashes;
      host.writeMultipleFiles({ 'src/app/app.component.css': 'h1 { margin: 10px; }' });
  
      // Main hash should change, since inline styles go in the main bundle.
      await browserBuild(architect, host, target, overrides);
      newHashes = generateFileHashMap();
      validateHashes(oldHashes, newHashes, ['main']);
      oldHashes = newHashes;
      host.appendToFile('src/app/lazy/lazy.module.ts', `console.log(1);`);
  
      // Lazy loaded bundle should change, and so should inline.
      await browserBuild(architect, host, target, overrides);
      newHashes = generateFileHashMap();
      validateHashes(oldHashes, newHashes, ['lazy.module']);
      oldHashes = newHashes;
      host.appendToFile('src/main.ts', '');
  
      // Nothing should have changed.
      await browserBuild(architect, host, target, overrides);
      newHashes = generateFileHashMap();
      validateHashes(oldHashes, newHashes, []);
    });
  
    it('supports options', async () => {
      host.writeMultipleFiles({ 'src/styles.css': `h1 { background: url('./spectrum.png')}` });
      host.writeMultipleFiles(lazyModuleFiles);
      host.writeMultipleFiles(lazyModuleImport);
  
      // We must do several builds instead of a single one in watch mode, so that the output
      // path is deleted on each run and only contains the most recent files.
      // 'all' should hash everything.
      await browserBuild(architect, host, target, { outputHashing: 'all', extractCss: true });
  
      expect(host.fileMatchExists('dist', /runtime\.[0-9a-f]{20}\.js/)).toBeTruthy();
      expect(host.fileMatchExists('dist', /main\.[0-9a-f]{20}\.js/)).toBeTruthy();
      expect(host.fileMatchExists('dist', /polyfills\.[0-9a-f]{20}\.js/)).toBeTruthy();
      expect(host.fileMatchExists('dist', /vendor\.[0-9a-f]{20}\.js/)).toBeTruthy();
      expect(host.fileMatchExists('dist', /styles\.[0-9a-f]{20}\.css/)).toBeTruthy();
      expect(host.fileMatchExists('dist', /spectrum\.[0-9a-f]{20}\.png/)).toBeTruthy();
  
      // 'none' should hash nothing.
      await browserBuild(architect, host, target, { outputHashing: 'none', extractCss: true });
  
      expect(host.fileMatchExists('dist', /runtime\.[0-9a-f]{20}\.js/)).toBeFalsy();
      expect(host.fileMatchExists('dist', /main\.[0-9a-f]{20}\.js/)).toBeFalsy();
      expect(host.fileMatchExists('dist', /polyfills\.[0-9a-f]{20}\.js/)).toBeFalsy();
      expect(host.fileMatchExists('dist', /vendor\.[0-9a-f]{20}\.js/)).toBeFalsy();
      expect(host.fileMatchExists('dist', /styles\.[0-9a-f]{20}\.css/)).toBeFalsy();
      expect(host.fileMatchExists('dist', /spectrum\.[0-9a-f]{20}\.png/)).toBeFalsy();
  
      // 'media' should hash css resources only.
      await browserBuild(architect, host, target, { outputHashing: 'media', extractCss: true });
  
      expect(host.fileMatchExists('dist', /runtime\.[0-9a-f]{20}\.js/)).toBeFalsy();
      expect(host.fileMatchExists('dist', /main\.[0-9a-f]{20}\.js/)).toBeFalsy();
      expect(host.fileMatchExists('dist', /polyfills\.[0-9a-f]{20}\.js/)).toBeFalsy();
      expect(host.fileMatchExists('dist', /vendor\.[0-9a-f]{20}\.js/)).toBeFalsy();
      expect(host.fileMatchExists('dist', /styles\.[0-9a-f]{20}\.css/)).toBeFalsy();
      expect(host.fileMatchExists('dist', /spectrum\.[0-9a-f]{20}\.png/)).toBeTruthy();
  
      // 'bundles' should hash bundles only.
      await browserBuild(architect, host, target, { outputHashing: 'bundles', extractCss: true });
      expect(host.fileMatchExists('dist', /runtime\.[0-9a-f]{20}\.js/)).toBeTruthy();
      expect(host.fileMatchExists('dist', /main\.[0-9a-f]{20}\.js/)).toBeTruthy();
      expect(host.fileMatchExists('dist', /polyfills\.[0-9a-f]{20}\.js/)).toBeTruthy();
      expect(host.fileMatchExists('dist', /vendor\.[0-9a-f]{20}\.js/)).toBeTruthy();
      expect(host.fileMatchExists('dist', /styles\.[0-9a-f]{20}\.css/)).toBeTruthy();
      expect(host.fileMatchExists('dist', /spectrum\.[0-9a-f]{20}\.png/)).toBeFalsy();
    });
  
    it('does not hash lazy styles', async () => {
      const overrides = {
        outputHashing: 'all',
        extractCss: true,
        styles: [{ input: 'src/styles.css', lazy: true }],
      };
  
      await browserBuild(architect, host, target, overrides);
  
      expect(host.fileMatchExists('dist', /styles\.[0-9a-f]{20}\.js/)).toBeFalsy();
      expect(host.fileMatchExists('dist', /styles\.[0-9a-f]{20}\.js.map/)).toBeFalsy();
      expect(host.scopedSync().exists(normalize('dist/styles.css'))).toBe(true);
      expect(host.scopedSync().exists(normalize('dist/styles.css.map'))).toBe(true);
    });
  
    it('does not hash lazy styles when optimization is enabled', async () => {
      const overrides = {
        outputHashing: 'all',
        extractCss: true,
        optimization: true,
        styles: [{ input: 'src/styles.css', lazy: true }],
      };
  
      await browserBuild(architect, host, target, overrides);
      expect(host.fileMatchExists('dist', /styles\.[0-9a-f]{20}\.js/)).toBeFalsy();
      expect(host.fileMatchExists('dist', /styles\.[0-9a-f]{20}\.js.map/)).toBeFalsy();
      expect(host.scopedSync().exists(normalize('dist/styles.css'))).toBe(true);
      expect(host.scopedSync().exists(normalize('dist/styles.css.map'))).toBe(true);
    });
  });
  