From e4b82cea26ab4b5d0cc0abfca1ac8df4fa213d30 Mon Sep 17 00:00:00 2001 From: Derek Cormier Date: Thu, 22 Sep 2022 14:15:08 -0700 Subject: [PATCH] build(bazel): clean up pathing in aio build tooling Make use of process.env.RUNFILES. --- WORKSPACE | 3 + aio/BUILD.bazel | 4 - aio/content/examples/examples.bzl | 5 +- aio/scripts/run-with-local-server.mjs | 2 +- aio/tools/examples/BUILD.bazel | 1 + aio/tools/examples/constants.js | 16 +- aio/tools/examples/create-example.js | 11 +- aio/tools/examples/example-boilerplate.js | 19 ++- .../examples/example-boilerplate.spec.js | 48 +++--- aio/tools/transforms/config.js | 8 +- .../rules_nodejs__b02128b178.patch | 148 ++++++++++++++++++ tools/esm-loader/esm-loader.mjs | 4 +- 12 files changed, 216 insertions(+), 53 deletions(-) create mode 100644 tools/bazel-repo-patches/rules_nodejs__b02128b178.patch diff --git a/WORKSPACE b/WORKSPACE index 987590ef0a8..aa7393f6893 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -25,6 +25,9 @@ http_archive( http_archive( name = "build_bazel_rules_nodejs", + patches = [ + "//:tools/bazel-repo-patches/rules_nodejs__b02128b178.patch", + ], sha256 = "b011d6206e4e76696eda8287618a2b6375ff862317847cdbe38f8d0cd206e9ce", urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/5.6.0/rules_nodejs-5.6.0.tar.gz"], ) diff --git a/aio/BUILD.bazel b/aio/BUILD.bazel index 6709f44a93a..ac5bbdf55c1 100644 --- a/aio/BUILD.bazel +++ b/aio/BUILD.bazel @@ -291,7 +291,6 @@ architect( nodejs_binary( name = "docs-watch", - chdir = package_name(), data = APPLICATION_FILES + [ "//aio/scripts:fast-serve-and-watch", ] + select({ @@ -301,9 +300,6 @@ nodejs_binary( enable_linker = True, entry_point = "//aio/scripts:fast-serve-and-watch.js", env = { - # Tell dgeni packages where the project root is since we used chdir - "PROJECT_ROOT": "../", - # Have the authors package output its low-fi dgeni build # to a different directory in the runfiles tree because bazel # write-protects original dgeni runfiles. Then in angular.json diff --git a/aio/content/examples/examples.bzl b/aio/content/examples/examples.bzl index e65cbfa9a13..d205a05ce24 100644 --- a/aio/content/examples/examples.bzl +++ b/aio/content/examples/examples.bzl @@ -121,10 +121,7 @@ def docs_example(name, test = True, test_tags = [], test_exec_properties = {}): # Generate example boilerplate npm_package_bin( name = "boilerplate", - args = ["add", native.package_name()], - env = { - "BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH": "$(@D)", - }, + args = ["add", native.package_name(), "$(@D)"], data = [":files"], output_dir = True, tool = "//aio/tools/examples:example-boilerplate", diff --git a/aio/scripts/run-with-local-server.mjs b/aio/scripts/run-with-local-server.mjs index e7414388619..384d4fce020 100644 --- a/aio/scripts/run-with-local-server.mjs +++ b/aio/scripts/run-with-local-server.mjs @@ -3,7 +3,7 @@ import path from 'node:path'; import sh from 'shelljs'; import treeKill from 'tree-kill'; -const RUNFILES_ROOT = path.resolve('.'); +const RUNFILES_ROOT = path.resolve(process.env.RUNFILES, 'angular'); sh.set('-e'); diff --git a/aio/tools/examples/BUILD.bazel b/aio/tools/examples/BUILD.bazel index e126a5447cb..96b8ab57761 100644 --- a/aio/tools/examples/BUILD.bazel +++ b/aio/tools/examples/BUILD.bazel @@ -8,6 +8,7 @@ EXAMPLE_BOILERPLATE_SRCS = [ "example-boilerplate.js", "constants.js", "//aio/tools/examples/shared", + "//aio/content/examples", ] EXAMPLE_BOILERPLATE_DEPS = [ diff --git a/aio/tools/examples/constants.js b/aio/tools/examples/constants.js index c24dc03f9a2..8214abaad4a 100644 --- a/aio/tools/examples/constants.js +++ b/aio/tools/examples/constants.js @@ -1,12 +1,14 @@ const path = require('canonical-path'); -// Bazel sets the environment variable BUILD_WORKSPACE_DIRECTORY when calling bazel run, -// which points to the root of the source tree. When running create-example we want to -// point to the source tree. In build and test cases we want to point to the output tree. -exports.PROJECT_ROOT = process.env.BUILD_WORKSPACE_DIRECTORY || path.resolve(__dirname, '../../../'); -exports.EXAMPLES_BASE_PATH = path.resolve(this.PROJECT_ROOT, 'aio', 'content', 'examples'); -exports.SHARED_PATH = path.resolve(this.PROJECT_ROOT, 'aio', 'tools', 'examples', 'shared'); +exports.RUNFILES_ROOT = path.resolve(process.env.RUNFILES, 'angular'); +exports.getExamplesBasePath = function(root) { + return path.join(root, 'aio', 'content', 'examples'); +} + +exports.getSharedPath = function(root) { + return path.join(root, 'aio', 'tools', 'examples', 'shared'); +} + exports.EXAMPLE_CONFIG_FILENAME = 'example-config.json'; exports.STACKBLITZ_CONFIG_FILENAME = 'stackblitz.json'; -exports.BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH = process.env.BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH || process.env.TEST_TMPDIR; diff --git a/aio/tools/examples/create-example.js b/aio/tools/examples/create-example.js index cb4d7105f63..3033ca3a5a4 100644 --- a/aio/tools/examples/create-example.js +++ b/aio/tools/examples/create-example.js @@ -5,9 +5,16 @@ const path = require('canonical-path'); const shelljs = require('shelljs'); const yargs = require('yargs'); const buildozer = require('@bazel/buildozer'); - -const {EXAMPLES_BASE_PATH, EXAMPLE_CONFIG_FILENAME, PROJECT_ROOT, SHARED_PATH, STACKBLITZ_CONFIG_FILENAME} = +const {RUNFILES_ROOT, getExamplesBasePath, getSharedPath, EXAMPLE_CONFIG_FILENAME, STACKBLITZ_CONFIG_FILENAME} = require('./constants'); + +// BUILD_WORKSPACE_DIRECTORY is set by Bazel when calling `bazel run` and points to the +// root of the source tree (e.g., for creating a new example in the source tree). Otherwise, +// we are in a test so use the runfiles root. +const PROJECT_ROOT = path.resolve(process.env.BUILD_WORKSPACE_DIRECTORY || RUNFILES_ROOT); +const EXAMPLES_BASE_PATH = getExamplesBasePath(PROJECT_ROOT); +const SHARED_PATH = getSharedPath(PROJECT_ROOT); + const BASIC_SOURCE_PATH = path.resolve(SHARED_PATH, 'example-scaffold'); shelljs.set('-e'); diff --git a/aio/tools/examples/example-boilerplate.js b/aio/tools/examples/example-boilerplate.js index 79cfb28ea98..f2ee0821870 100644 --- a/aio/tools/examples/example-boilerplate.js +++ b/aio/tools/examples/example-boilerplate.js @@ -4,7 +4,11 @@ const ignore = require('ignore'); const path = require('canonical-path'); const shelljs = require('shelljs'); const yargs = require('yargs'); -const {EXAMPLES_BASE_PATH, BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH, EXAMPLE_CONFIG_FILENAME, SHARED_PATH} = require('./constants'); +const {RUNFILES_ROOT, getExamplesBasePath, getSharedPath, EXAMPLE_CONFIG_FILENAME} = require('./constants'); + +const PROJECT_ROOT = RUNFILES_ROOT; +const EXAMPLES_BASE_PATH = getExamplesBasePath(PROJECT_ROOT); +const SHARED_PATH = getSharedPath(PROJECT_ROOT); const BOILERPLATE_BASE_PATH = path.resolve(SHARED_PATH, 'boilerplate'); const BOILERPLATE_CLI_PATH = path.resolve(BOILERPLATE_BASE_PATH, 'cli'); @@ -14,7 +18,7 @@ class ExampleBoilerPlate { /** * Add boilerplate files to an example */ - add(exampleFolder) { + add(exampleFolder, outputDir) { const gitignore = ignore().add(fs.readFileSync(path.resolve(BOILERPLATE_BASE_PATH, '.gitignore'), 'utf8')); const exampleConfig = this.loadJsonFile(path.resolve(exampleFolder, EXAMPLE_CONFIG_FILENAME)); @@ -31,22 +35,21 @@ class ExampleBoilerPlate { const boilerPlateType = exampleConfig.projectType || 'cli'; const boilerPlateBasePath = path.resolve(BOILERPLATE_BASE_PATH, boilerPlateType); - const outputPath = BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH; - shelljs.mkdir('-p', outputPath); + shelljs.mkdir('-p', outputDir); // All example types other than `cli` and `systemjs` are based on `cli`. Copy over the `cli` // boilerplate files first. // (Some of these files might be later overwritten by type-specific files.) if (boilerPlateType !== 'cli' && boilerPlateType !== 'systemjs') { - this.copyDirectoryContents(BOILERPLATE_CLI_PATH, outputPath, isPathIgnored); + this.copyDirectoryContents(BOILERPLATE_CLI_PATH, outputDir, isPathIgnored); } // Copy the type-specific boilerplate files. - this.copyDirectoryContents(boilerPlateBasePath, outputPath, isPathIgnored); + this.copyDirectoryContents(boilerPlateBasePath, outputDir, isPathIgnored); // Copy the common boilerplate files (unless explicitly not used). if (exampleConfig.useCommonBoilerplate !== false) { - this.copyDirectoryContents(BOILERPLATE_COMMON_PATH, outputPath, isPathIgnored); + this.copyDirectoryContents(BOILERPLATE_COMMON_PATH, outputDir, isPathIgnored); } } @@ -80,7 +83,7 @@ class ExampleBoilerPlate { main() { yargs.usage('$0 [args]') - .command('add', 'add the boilerplate to each example', yrgs => this.add(yrgs.argv._[1])) + .command('add ', 'create boilerplate for an example', yrgs => this.add(yrgs.argv._[1], yrgs.argv._[2])) .command('list-overrides', 'list all the boilerplate files that have been overridden in examples', () => this.listOverrides()) .demandCommand(1, 'Please supply a command from the list above') .argv; diff --git a/aio/tools/examples/example-boilerplate.spec.js b/aio/tools/examples/example-boilerplate.spec.js index bfa151e254f..bb06e4d3d47 100644 --- a/aio/tools/examples/example-boilerplate.spec.js +++ b/aio/tools/examples/example-boilerplate.spec.js @@ -3,12 +3,18 @@ const fs = require('fs-extra'); const glob = require('glob'); const shelljs = require('shelljs'); -const {BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH, EXAMPLES_BASE_PATH} = require("./constants"); +const {RUNFILES_ROOT, getExamplesBasePath, getSharedPath} = require("./constants"); + +const PROJECT_ROOT = RUNFILES_ROOT; +const EXAMPLES_BASE_PATH = getExamplesBasePath(PROJECT_ROOT); +const SHARED_PATH = getSharedPath(PROJECT_ROOT); + const exampleBoilerPlate = require('./example-boilerplate'); +const outputDir = process.env.TEST_TMPDIR; // Bazel-provided temp dir describe('example-boilerplate tool', () => { describe('add', () => { - const sharedDir = path.resolve(__dirname, 'shared'); + const sharedDir = SHARED_PATH; const exampleFolder = 'a'; beforeEach(() => { @@ -21,12 +27,12 @@ describe('example-boilerplate tool', () => { const boilerplateDir = path.resolve(sharedDir, 'boilerplate'); exampleBoilerPlate.loadJsonFile.and.returnValue({ projectType: 'systemjs' }); - exampleBoilerPlate.add(exampleFolder); + exampleBoilerPlate.add(exampleFolder, outputDir); expect(exampleBoilerPlate.copyDirectoryContents).toHaveBeenCalledTimes(2); expect(exampleBoilerPlate.copyDirectoryContents.calls.allArgs()).toEqual([ - [`${boilerplateDir}/systemjs`, BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH, jasmine.any(Function)], - [`${boilerplateDir}/common`, BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH, jasmine.any(Function)], + [`${boilerplateDir}/systemjs`, outputDir, jasmine.any(Function)], + [`${boilerplateDir}/common`, outputDir, jasmine.any(Function)], ]); }); @@ -34,12 +40,12 @@ describe('example-boilerplate tool', () => { const boilerplateDir = path.resolve(sharedDir, 'boilerplate'); exampleBoilerPlate.loadJsonFile.and.returnValue({ projectType: 'cli' }); - exampleBoilerPlate.add(exampleFolder); + exampleBoilerPlate.add(exampleFolder, outputDir); expect(exampleBoilerPlate.copyDirectoryContents).toHaveBeenCalledTimes(2); expect(exampleBoilerPlate.copyDirectoryContents.calls.allArgs()).toEqual([ - [`${boilerplateDir}/cli`, BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH, jasmine.any(Function)], - [`${boilerplateDir}/common`, BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH, jasmine.any(Function)], + [`${boilerplateDir}/cli`, outputDir, jasmine.any(Function)], + [`${boilerplateDir}/common`, outputDir, jasmine.any(Function)], ]); }); @@ -47,12 +53,12 @@ describe('example-boilerplate tool', () => { const boilerplateDir = path.resolve(sharedDir, 'boilerplate'); exampleBoilerPlate.loadJsonFile.and.returnValue({}); - exampleBoilerPlate.add(exampleFolder); + exampleBoilerPlate.add(exampleFolder, outputDir); expect(exampleBoilerPlate.copyDirectoryContents).toHaveBeenCalledTimes(2); expect(exampleBoilerPlate.copyDirectoryContents.calls.allArgs()).toEqual([ - [`${boilerplateDir}/cli`, BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH, jasmine.any(Function)], - [`${boilerplateDir}/common`, BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH, jasmine.any(Function)], + [`${boilerplateDir}/cli`, outputDir, jasmine.any(Function)], + [`${boilerplateDir}/common`, outputDir, jasmine.any(Function)], ]); }); @@ -60,13 +66,13 @@ describe('example-boilerplate tool', () => { const boilerplateDir = path.resolve(sharedDir, 'boilerplate'); exampleBoilerPlate.loadJsonFile.and.returnValue({ projectType: 'i18n' }); - exampleBoilerPlate.add(exampleFolder); + exampleBoilerPlate.add(exampleFolder, outputDir); expect(exampleBoilerPlate.copyDirectoryContents).toHaveBeenCalledTimes(3); expect(exampleBoilerPlate.copyDirectoryContents.calls.allArgs()).toEqual([ - [`${boilerplateDir}/cli`, BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH, jasmine.any(Function)], - [`${boilerplateDir}/i18n`, BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH, jasmine.any(Function)], - [`${boilerplateDir}/common`, BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH, jasmine.any(Function)], + [`${boilerplateDir}/cli`, outputDir, jasmine.any(Function)], + [`${boilerplateDir}/i18n`, outputDir, jasmine.any(Function)], + [`${boilerplateDir}/common`, outputDir, jasmine.any(Function)], ]); }); @@ -74,13 +80,13 @@ describe('example-boilerplate tool', () => { const boilerplateDir = path.resolve(sharedDir, 'boilerplate'); exampleBoilerPlate.loadJsonFile.and.returnValue({ projectType: 'universal' }); - exampleBoilerPlate.add(exampleFolder); + exampleBoilerPlate.add(exampleFolder, outputDir); expect(exampleBoilerPlate.copyDirectoryContents).toHaveBeenCalledTimes(3); expect(exampleBoilerPlate.copyDirectoryContents.calls.allArgs()).toEqual([ - [`${boilerplateDir}/cli`, BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH, jasmine.any(Function)], - [`${boilerplateDir}/universal`, BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH, jasmine.any(Function)], - [`${boilerplateDir}/common`, BAZEL_EXAMPLE_BOILERPLATE_OUTPUT_PATH, jasmine.any(Function)], + [`${boilerplateDir}/cli`, outputDir, jasmine.any(Function)], + [`${boilerplateDir}/universal`, outputDir, jasmine.any(Function)], + [`${boilerplateDir}/common`, outputDir, jasmine.any(Function)], ]); }); @@ -90,7 +96,7 @@ describe('example-boilerplate tool', () => { 'overrideBoilerplate': [ 'c/d' ] }); - exampleBoilerPlate.add(exampleFolder); + exampleBoilerPlate.add(exampleFolder, outputDir); const isPathIgnored = exampleBoilerPlate.copyDirectoryContents.calls.first().args[2]; expect(isPathIgnored(`${boilerplateDir}/cli/a/b`)).toBe(false); @@ -98,7 +104,7 @@ describe('example-boilerplate tool', () => { }); it('should try to load the example config file', () => { - exampleBoilerPlate.add(exampleFolder); + exampleBoilerPlate.add(exampleFolder, outputDir); expect(exampleBoilerPlate.loadJsonFile).toHaveBeenCalledTimes(1); expect(exampleBoilerPlate.loadJsonFile).toHaveBeenCalledWith(path.resolve(`${exampleFolder}/example-config.json`)); }); diff --git a/aio/tools/transforms/config.js b/aio/tools/transforms/config.js index e5c729ee72b..410ef5a28fe 100644 --- a/aio/tools/transforms/config.js +++ b/aio/tools/transforms/config.js @@ -5,9 +5,10 @@ const { readdirSync } = require('fs'); // directory (TEST_TMPDIR) that bazel provides for tests. const BAZEL_OUTPUT_PATH = process.env.BAZEL_DGENI_OUTPUT_PATH || process.env.TEST_TMPDIR; -// During a bazel build this script executes in the execroot, so assume -// the root is the current directory unless overridden. -const PROJECT_ROOT = resolve(process.env.PROJECT_ROOT || '.'); +// The current directory is always the correct project root. During a build, this evalutates +// to the exec root. During the "fast-serve" bazel run mode, it resolves to the runfiles root +// of the fast serve binary. +const PROJECT_ROOT = resolve('.'); const AIO_PATH = resolve(PROJECT_ROOT, 'aio'); const TEMPLATES_PATH = resolve(AIO_PATH, 'tools/transforms/templates'); @@ -26,4 +27,3 @@ function requireFolder(dirname, folderPath) { .map(p => require(resolve(absolutePath, p))); } module.exports = { BAZEL_OUTPUT_PATH, PROJECT_ROOT, AIO_PATH, TEMPLATES_PATH, API_TEMPLATES_PATH, CONTENTS_PATH, GUIDE_EXAMPLES_PATH, SRC_PATH, OUTPUT_PATH, DOCS_OUTPUT_PATH, API_SOURCE_PATH, requireFolder }; - diff --git a/tools/bazel-repo-patches/rules_nodejs__b02128b178.patch b/tools/bazel-repo-patches/rules_nodejs__b02128b178.patch new file mode 100644 index 00000000000..fc8b53ab5f3 --- /dev/null +++ b/tools/bazel-repo-patches/rules_nodejs__b02128b178.patch @@ -0,0 +1,148 @@ +diff --git internal/node/launcher.sh internal/node/launcher.sh +index d0e8df9..a830907 100755 +--- internal/node/launcher.sh ++++ internal/node/launcher.sh +@@ -14,7 +14,7 @@ + # limitations under the License. + + # It helps to determine if we are running on a Windows environment (excludes WSL as it acts like Unix) +-function isWindows { ++function is_windows { + case "$(uname -s)" in + CYGWIN*) local IS_WINDOWS=1 ;; + MINGW*) local IS_WINDOWS=1 ;; +@@ -29,14 +29,13 @@ function isWindows { + # It helps to normalizes paths when running on Windows. + # + # Example: +-# C:/Users/XUser/_bazel_XUser/7q7kkv32/execroot/A/b/C -> /c/users/xuser/_bazel_xuser/7q7kkv32/execroot/a/b/c +-function normalizeWindowsPath { +- # Apply the followings paths transformations to normalize paths on Windows +- # -process driver letter +- # -convert path separator +- # -lowercase everything +- echo $(sed -e 's#^\(.\):#/\L\1#' -e 's#\\#/#g' -e 's/[A-Z]/\L&/g' <<< "$1") +- return ++# C:/Users/XUser/_bazel_XUser/7q7kkv32/execroot/A/b/C -> /c/Users/XUser/_bazel_XUser/7q7kkv32/execroot/A/b/C ++function normalize_windows_path { ++ # Apply the followings paths transformations to normalize paths on Windows ++ # -process driver letter ++ # -convert path separator ++ sed -e 's#^\(.\):#/\L\1#' -e 's#\\#/#g' <<< "$1" ++ return + } + + # --- begin runfiles.bash initialization v2 --- +@@ -73,51 +72,71 @@ source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \ + # blaze. + # Case 5a is handled like case 1. + # Case 6a is handled like case 3. +-if [[ -n "${RUNFILES_MANIFEST_ONLY:-}" ]]; then +- # Windows only has a manifest file instead of symlinks. +- if [[ $(isWindows) -eq "1" ]]; then +- # If Windows normalizing the path and case insensitive removing the `/MANIFEST` part of the path +- NORMALIZED_RUNFILES_MANIFEST_FILE_PATH=$(normalizeWindowsPath $RUNFILES_MANIFEST_FILE) +- RUNFILES=$(sed 's|\/MANIFEST$||i' <<< $NORMALIZED_RUNFILES_MANIFEST_FILE_PATH) +- else +- RUNFILES=${RUNFILES_MANIFEST_FILE%/MANIFEST} +- fi +-elif [[ -n "${TEST_SRCDIR:-}" ]]; then +- # Case 4, bazel has identified runfiles for us. +- RUNFILES="${TEST_SRCDIR:-}" +-else +- case "$0" in +- /*) self="$0" ;; +- *) self="$PWD/$0" ;; +- esac +- while true; do +- if [[ -e "$self.runfiles" ]]; then +- RUNFILES="$self.runfiles" +- break +- fi +- +- if [[ $self == *.runfiles/* ]]; then +- RUNFILES="${self%%.runfiles/*}.runfiles" +- # don't break; this is a last resort for case 6b ++if [ "${TEST_SRCDIR:-}" ]; then ++ # Case 4, bazel has identified runfiles for us. ++ if [ "$(is_windows)" -eq "1" ]; then ++ # If Windows, normalize the path ++ RUNFILES=$(normalize_windows_path "$TEST_SRCDIR") ++ else ++ RUNFILES="$TEST_SRCDIR" + fi +- +- if [[ ! -L "$self" ]]; then +- break; ++elif [ "${RUNFILES_MANIFEST_FILE:-}" ]; then ++ if [ "$(is_windows)" -eq "1" ]; then ++ # If Windows, normalize the path ++ NORMALIZED_RUNFILES_MANIFEST_FILE=$(normalize_windows_path "$RUNFILES_MANIFEST_FILE") ++ else ++ NORMALIZED_RUNFILES_MANIFEST_FILE="$RUNFILES_MANIFEST_FILE" + fi +- +- readlink="$(readlink "$self")" +- if [[ "$readlink" = /* ]]; then +- self="$readlink" ++ if [[ "${NORMALIZED_RUNFILES_MANIFEST_FILE}" == *.runfiles_manifest ]]; then ++ # Newer versions of Bazel put the manifest besides the runfiles with the suffix .runfiles_manifest. ++ # For example, the runfiles directory is named my_binary.runfiles then the manifest is beside the ++ # runfiles directory and named my_binary.runfiles_manifest ++ RUNFILES=${NORMALIZED_RUNFILES_MANIFEST_FILE%_manifest} ++ elif [[ "${NORMALIZED_RUNFILES_MANIFEST_FILE}" == */MANIFEST ]]; then ++ # Older versions of Bazel put the manifest file named MANIFEST in the runfiles directory ++ RUNFILES=${NORMALIZED_RUNFILES_MANIFEST_FILE%/MANIFEST} + else +- # resolve relative symlink +- self="${self%%/*}/$readlink" ++ echo "\n>>>> FAIL: Unexpected RUNFILES_MANIFEST_FILE value $RUNFILES_MANIFEST_FILE. <<<<\n\n" >&2 ++ exit 1 + fi +- done +- +- if [[ -z "$RUNFILES" ]]; then +- echo " >>>> FAIL: RUNFILES environment variable is not set. <<<<" >&2 +- exit 1 +- fi ++else ++ case "$0" in ++ /*) self="$0" ;; ++ *) self="$PWD/$0" ;; ++ esac ++ while true; do ++ if [ -e "$self.runfiles" ]; then ++ RUNFILES="$self.runfiles" ++ break ++ fi ++ ++ if [[ "$self" == *.runfiles/* ]]; then ++ RUNFILES="${self%%.runfiles/*}.runfiles" ++ # don't break; this is a last resort for case 6b ++ fi ++ ++ if [ ! -L "$self" ]; then ++ break; ++ fi ++ ++ readlink="$(readlink "$self")" ++ if [[ "$readlink" == /* ]]; then ++ self="$readlink" ++ else ++ # resolve relative symlink ++ self="${self%%/*}/$readlink" ++ fi ++ done ++ ++ if [ -z "${RUNFILES:-}" ]; then ++ echo "\n>>>> FAIL: RUNFILES environment variable is not set. <<<<\n\n" >&2 ++ exit 1 ++ fi ++fi ++if [ "${RUNFILES:0:1}" != "/" ]; then ++ # Ensure RUNFILES set above is an absolute path. It may be a path relative ++ # to the PWD in case where RUNFILES_MANIFEST_FILE is used above. ++ RUNFILES="$PWD/$RUNFILES" + fi + export RUNFILES + # --- end RUNFILES initialization --- diff --git a/tools/esm-loader/esm-loader.mjs b/tools/esm-loader/esm-loader.mjs index f42e0bc1fb6..2ed1fc9ef75 100644 --- a/tools/esm-loader/esm-loader.mjs +++ b/tools/esm-loader/esm-loader.mjs @@ -25,8 +25,8 @@ export async function resolve(specifier, context, defaultResolve) { return defaultResolve(specifier, context, defaultResolve); } - const runfilesWorkspaceRoot = path.resolve(process.env.RUNFILES_DIR || path.join(process.env.RUNFILES, 'angular')); - const nodeModules = path.join(runfilesWorkspaceRoot, process.env.NODE_MODULES_WORKSPACE_NAME, 'node_modules'); + const runfilesRoot = path.resolve(process.env.RUNFILES, 'angular'); + const nodeModules = path.join(runfilesRoot, process.env.NODE_MODULES_WORKSPACE_NAME, 'node_modules'); const packageImport = parsePackageImport(specifier); const pathToNodeModule = path.join(nodeModules, packageImport.packageName);