Skip to content
Closed
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions src/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ java_binary(
py_library(
name = "plantuml_for_python",
srcs = ["@score_docs_as_code//src:dummy.py"],
#deps = ["@score_docs_as_code//src/find_runfiles"],
data = ["@score_docs_as_code//src:plantuml"],
visibility = ["//visibility:public"],
)
Expand Down
1 change: 1 addition & 0 deletions src/extensions/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ py_library(
srcs = ["@score_docs_as_code//src/extensions:score_plantuml.py"],
imports = ["."],
visibility = ["//visibility:public"],
deps = ["@score_docs_as_code//src/find_runfiles"],
)
5 changes: 4 additions & 1 deletion src/extensions/score_metamodel/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ py_library(
imports = ["."],
visibility = ["//visibility:public"],
# TODO: Figure out if all requirements are needed or if we can break it down a bit
deps = all_requirements + ["@score_docs_as_code//src/helper_lib"],
deps = all_requirements + [
"@score_docs_as_code//src/find_runfiles",
"@score_docs_as_code//src/helper_lib",
],
)

score_py_pytest(
Expand Down
35 changes: 10 additions & 25 deletions src/extensions/score_metamodel/external_needs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
# *******************************************************************************

import json
import os
import subprocess
import sys
from dataclasses import dataclass
from pathlib import Path

Expand All @@ -23,6 +21,8 @@
from sphinx.util import logging
from sphinx_needs.needsfile import NeedsList

from src.find_runfiles import get_runfiles_dir

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -138,7 +138,7 @@ def temp(self: NeedsList):


def get_external_needs_source(external_needs_source: str) -> list[ExternalNeedsSource]:
bazel = external_needs_source or os.getenv("RUNFILES_DIR")
bazel = external_needs_source or get_runfiles_dir()

if bazel:
external_needs = parse_external_needs_sources_from_DATA(external_needs_source)
Expand All @@ -149,25 +149,10 @@ def get_external_needs_source(external_needs_source: str) -> list[ExternalNeedsS


def add_external_needs_json(e: ExternalNeedsSource, config: Config):
json_file = f"{e.bazel_module}+/{e.target}/_build/needs/needs.json"
if r := os.getenv("RUNFILES_DIR"):
logger.debug("Using runfiles to determine external needs JSON file.")
fixed_json_file = Path(r) / json_file
else:
logger.debug(
"Running outside bazel. "
+ "Determining git root for external needs JSON file."
)
git_root = Path.cwd().resolve()
while not (git_root / ".git").exists():
git_root = git_root.parent
if git_root == Path("/"):
sys.exit("Could not find git root.")
logger.debug(f"Git root found: {git_root}")
fixed_json_file = git_root / "bazel-bin" / "ide_support.runfiles" / json_file

logger.debug(f"Fixed JSON file path: {json_file} -> {fixed_json_file}")
json_file = fixed_json_file
json_file_raw = f"{e.bazel_module}+/{e.target}/_build/needs/needs.json"
r = get_runfiles_dir()
json_file = r / json_file_raw
logger.debug(f"Fixed JSON file path: {json_file_raw} -> {json_file}")

try:
needs_json_data = json.loads(Path(json_file).read_text(encoding="utf-8")) # pyright: ignore[reportAny]
Expand All @@ -192,11 +177,11 @@ def add_external_needs_json(e: ExternalNeedsSource, config: Config):
def add_external_docs_sources(e: ExternalNeedsSource, config: Config):
# Note that bazel does NOT write the files under e.target!
# {e.bazel_module}+ matches the original git layout!
if r := os.getenv("RUNFILES_DIR"):
docs_source_path = Path(r) / f"{e.bazel_module}+"
else:
r = get_runfiles_dir()
if "ide_support.runfiles" in str(r):
logger.error("Combo builds are currently only supported with Bazel.")
return
docs_source_path = Path(r) / f"{e.bazel_module}+"

if "collections" not in config:
config.collections = {}
Expand Down
68 changes: 34 additions & 34 deletions src/extensions/score_plantuml.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,48 +24,48 @@
In addition it sets common PlantUML options, like output to svg_obj.
"""

import os
import sys
from pathlib import Path

from sphinx.application import Sphinx
from sphinx.util import logging

logger = logging.getLogger(__name__)

from src.find_runfiles import get_runfiles_dir

def get_runfiles_dir() -> Path:
if r := os.getenv("RUNFILES_DIR"):
# Runfiles are only available when running in Bazel.
# bazel build and bazel run are both supported.
# i.e. `bazel build //:docs` and `bazel run //:docs`.
logger.debug("Using runfiles to determine plantuml path.")
logger = logging.getLogger(__name__)

runfiles_dir = Path(r)

else:
# The only way to land here is when running from within the virtual
# environment created by the `:ide_support` rule in the BUILD file.
# i.e. esbonio or manual sphinx-build execution within the virtual
# environment.
# We'll still use the plantuml binary from the bazel build.
# But we need to find it first.
logger.debug("Running outside bazel.")

git_root = Path.cwd().resolve()
while not (git_root / ".git").exists():
git_root = git_root.parent
if git_root == Path("/"):
sys.exit("Could not find git root.")

runfiles_dir = git_root / "bazel-bin" / "ide_support.runfiles"

if not runfiles_dir.exists():
sys.exit(
f"Could not find runfiles_dir at {runfiles_dir}. "
"Have a look at README.md for instructions on how to build docs."
)
return runfiles_dir
# def get_runfiles_dir() -> Path:
# if r := os.getenv("RUNFILES_DIR"):
# # Runfiles are only available when running in Bazel.
# # bazel build and bazel run are both supported.
# # i.e. `bazel build //:docs` and `bazel run //:docs`.
# logger.debug("Using runfiles to determine plantuml path.")
#
# runfiles_dir = Path(r)
#
# else:
# # The only way to land here is when running from within the virtual
# # environment created by the `:ide_support` rule in the BUILD file.
# # i.e. esbonio or manual sphinx-build execution within the virtual
# # environment.
# # We'll still use the plantuml binary from the bazel build.
# # But we need to find it first.
# logger.debug("Running outside bazel.")
#
# git_root = Path.cwd().resolve()
# while not (git_root / ".git").exists():
# git_root = git_root.parent
# if git_root == Path("/"):
# sys.exit("Could not find git root.")
#
# runfiles_dir = git_root / "bazel-bin" / "ide_support.runfiles"
#
# if not runfiles_dir.exists():
# sys.exit(
# f"Could not find runfiles_dir at {runfiles_dir}. "
# "Have a look at README.md for instructions on how to build docs."
# )
# return runfiles_dir


def find_correct_path(runfiles: Path) -> Path:
Expand Down
126 changes: 64 additions & 62 deletions src/find_runfiles/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,17 @@ def _log_debug(message: str):
print(message)


def find_git_root() -> Path:
# TODO: is __file__ ever resolved into the bazel cache directories?
# Then this function will not work!
def find_git_root(starting_path: Path | None = None) -> Path:
# 1. Highest priority: Bazel environment variable
workspace = os.getenv("BUILD_WORKSPACE_DIRECTORY")
if workspace:
return Path(workspace)

for parent in Path(__file__).resolve().parents:
# 2. Traversal logic: use starting_path (for tests) or __file__ (for prod)
# We resolve it to ensure we aren't dealing with symlinks in the bazel cache
current: Path = (starting_path or Path(__file__)).resolve()

for parent in current.parents:
if (parent / ".git").exists():
return parent

Expand All @@ -44,74 +47,73 @@ def find_git_root() -> Path:
)


def get_runfiles_dir_impl(
cwd: Path,
conf_dir: Path,
env_runfiles: Path | None,
git_root: Path,
) -> Path:
"""Functional (and therefore testable) logic to determine the runfiles directory."""

_log_debug(
f"get_runfiles_dir_impl(\n cwd={cwd},\n conf_dir={conf_dir},\n"
f" env_runfiles={env_runfiles},\n git_root={git_root}\n)"
)

if env_runfiles:
def get_runfiles_dir() -> Path:
"""Runfiles directory relative to conf.py"""
if r := os.getenv("RUNFILES_DIR"):
# Runfiles are only available when running in Bazel.
# Both `bazel build` and `bazel run` are supported.
# bazel build and bazel run are both supported.
# i.e. `bazel build //:docs` and `bazel run //:docs`.
_log_debug("Using env[RUNFILES_DIR] to find the runfiles...")

if env_runfiles.is_absolute() and "bazel-out" in env_runfiles.parts:
# In case of `bazel run` it will point to the global cache directory,
# which has a new hash every time. And it's not pretty.
# However, `bazel-out` is a symlink to that same cache directory!
try:
idx = env_runfiles.parts.index("bazel-out")
runfiles_dir = git_root.joinpath(*env_runfiles.parts[idx:])
_log_debug(f"Made runfiles dir pretty: {runfiles_dir}")
except ValueError:
sys.exit("Could not find bazel-out in runfiles path.")
else:
runfiles_dir = git_root / env_runfiles
logger.debug("Using runfiles to determine plantuml path.")

runfiles_dir = Path(r)

else:
# The only way to land here is when running from within the virtual
# environment created by the `:ide_support` rule.
# environment created by the `:ide_support` rule in the BUILD file.
# i.e. esbonio or manual sphinx-build execution within the virtual
# environment.
_log_debug("Running outside bazel.")

# TODO: "process-docs" is in SOURCE_DIR!!
runfiles_dir = git_root / "bazel-bin" / "process-docs" / "ide_support.runfiles"

return runfiles_dir


def get_runfiles_dir() -> Path:
"""Runfiles directory relative to conf.py"""
# We'll still use the plantuml binary from the bazel build.
# But we need to find it first.
logger.debug("Running outside bazel.")

# FIXME CONF_DIRECTORY is our invention. When running from esbonio, this is not
# set. It seems to provide app.confdir instead...
conf_dir = os.getenv("CONF_DIRECTORY")
assert conf_dir
git_root = Path.cwd().resolve()
while not (git_root / ".git").exists():
git_root = git_root.parent
if git_root == Path("/"):
sys.exit("Could not find git root.")

env_runfiles = os.getenv("RUNFILES_DIR")
runfiles_dir = git_root / "bazel-bin" / "ide_support.runfiles"

runfiles = Path(
get_runfiles_dir_impl(
cwd=Path(os.getcwd()),
conf_dir=Path(conf_dir),
env_runfiles=Path(env_runfiles) if env_runfiles else None,
git_root=find_git_root(),
)
)

if not runfiles.exists():
if not runfiles_dir.exists():
sys.exit(
f"Could not find runfiles at {runfiles}. Have a look at "
"README.md for instructions on how to build docs."
f"Could not find runfiles_dir at {runfiles_dir}. "
"Have a look at README.md for instructions on how to build docs."
)
return runfiles_dir

return runfiles
# _log_debug(
# f"get_runfiles_dir_impl(\n cwd={cwd},\n "
# f" env_runfiles={env_runfiles},\n git_root={git_root}\n)"
# )
#
# if env_runfiles:
# # Runfiles are only available when running in Bazel.
# # Both `bazel build` and `bazel run` are supported.
# # i.e. `bazel build //:docs` and `bazel run //:docs`.
# _log_debug("Using env[RUNFILES_DIR] to find the runfiles...")
#
# if env_runfiles.is_absolute() and "bazel-out" in env_runfiles.parts:
# # In case of `bazel run` it will point to the global cache directory,
# # which has a new hash every time. And it's not pretty.
# # However, `bazel-out` is a symlink to that same cache directory!
# try:
# idx = env_runfiles.parts.index("bazel-out")
# runfiles_dir = git_root.joinpath(*env_runfiles.parts[idx:])
# _log_debug(f"Made runfiles dir pretty: {runfiles_dir}")
# except ValueError:
# sys.exit("Could not find bazel-out in runfiles path.")
# else:
# runfiles_dir = git_root / env_runfiles
#
# else:
# # The only way to land here is when running from within the virtual
# # environment created by the `:ide_support` rule.
# # i.e. esbonio or manual sphinx-build execution within the virtual
# # environment.
# _log_debug("Running outside bazel.")
#
# # TODO: "process-docs" is in SOURCE_DIR!!
# runfiles_dir = git_root / "bazel-bin" /
# "process-docs" / "ide_support.runfiles"
#
# return runfiles_dir
Loading
Loading