Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions cli50/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,13 @@ def main():
if lang := os.getenv("LANG"):
options += ["--env", f"LANG={lang}"]

# Check for .env
try:
# Source and export any variables from DIRECTORY/.env.
options += env_options(directory)
except RuntimeError as e:
sys.exit(_("{}: unable to source").format(e))

# Validate ports
if not args["port"]:
args["port"] = PORTS
Expand Down Expand Up @@ -321,6 +328,34 @@ def ports(container):
return ", ".join(mappings)


def env_options(directory):
"""Return Docker options for .env in directory."""
dotenv = os.path.join(directory, ".env")
if not os.path.isfile(dotenv):
return []
try:
# Capture bash's baseline environment so shell defaults like PWD
# are not forwarded unless DIRECTORY/.env actually changes them.
before = subprocess.check_output([
"bash", "-c", "env -0"
], env={}, cwd=directory).decode("utf-8")

# Source and export DIRECTORY/.env, then emit the resulting environment.
after = subprocess.check_output([
"bash", "-c", 'set -a && source "$1" && env -0', "_", dotenv
], env={}, cwd=directory).decode("utf-8")
except subprocess.CalledProcessError:
raise RuntimeError(dotenv) from None

before = dict(entry.split("=", 1) for entry in before.rstrip("\0").split("\0") if entry)
after = dict(entry.split("=", 1) for entry in after.rstrip("\0").split("\0") if entry)
options = []
for key, value in after.items():
if before.get(key) != value:
options += ["--env", f"{key}={value}"]
return options


def pull(image, tag):
"""Pull image as needed."""
import json
Expand Down