1_CAPTURED_ENV_VARS = [
2    "PWD",
3    "TARGET_PRODUCT",
4    "TARGET_BUILD_VARIANT",
5    "COMBINED_NINJA",
6    "KATI_NINJA",
7    "PACKAGE_NINJA",
8    "SOONG_NINJA",
9]
10
11_ALLOWED_SPECIAL_CHARACTERS = [
12    "/",
13    "_",
14    "-",
15    "'",
16    ".",
17]
18
19# Since we write the env var value literally into a .bzl file, ensure that the string
20# does not contain special characters like '"', '\n' and '\'. Use an allowlist approach
21# and check that the remaining string is alphanumeric.
22def _validate_env_value(env_var, env_value):
23    if env_value == None:
24        fail("The env var " + env_var + " is not defined.")
25
26    for allowed_char in _ALLOWED_SPECIAL_CHARACTERS:
27        env_value = env_value.replace(allowed_char, "")
28    if not env_value.isalnum():
29        fail("The value of " +
30             env_var +
31             " can only consist of alphanumeric and " +
32             str(_ALLOWED_SPECIAL_CHARACTERS) +
33             " characters: " +
34             str(env_value))
35
36def _lunch_impl(rctx):
37    env_vars = {}
38    for env_var in _CAPTURED_ENV_VARS:
39        env_value = rctx.os.environ.get(env_var)
40        _validate_env_value(env_var, env_value)
41        env_vars[env_var] = env_value
42
43    rctx.file("BUILD.bazel", """
44exports_files(["env.bzl"])
45""")
46
47    # Re-export captured environment variables in a .bzl file.
48    rctx.file("env.bzl", "\n".join([
49        item[0] + " = \"" + str(item[1]) + "\""
50        for item in env_vars.items()
51    ]))
52
53_lunch = repository_rule(
54    implementation = _lunch_impl,
55    configure = True,
56    environ = _CAPTURED_ENV_VARS,
57    doc = "A repository rule to capture environment variables based on the lunch choice.",
58)
59
60def lunch():
61    # Hardcode repository name to @lunch.
62    _lunch(name = "lunch")
63