Skip to content

Commit 6c6cad5

Browse files
authored
Merge pull request #27 from Profpatsch/improve-symlink-and-refactor
Improve symlink and refactor
2 parents fb89dc9 + b8a32b6 commit 6c6cad5

File tree

1 file changed

+60
-18
lines changed

1 file changed

+60
-18
lines changed

nixpkgs/nixpkgs.bzl

+60-18
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ def _nixpkgs_package_impl(ctx):
5757
"-A", ctx.attr.attribute_path
5858
if ctx.attr.nix_file or ctx.attr.nix_file_content
5959
else ctx.attr.attribute_path or ctx.attr.name,
60+
# Creating an out link prevents nix from garbage collecting the store path.
61+
# nixpkgs uses `nix-support/` for such house-keeping files, so we mirror them
62+
# and use `bazel-support/`, under the assumption that no nix package has
63+
# a file named `bazel-support` in its root.
64+
# A `bazel clean` deletes the symlink and thus nix is free to garbage collect
65+
# the store path.
66+
"--out-link", "bazel-support/nix-out-link"
6067
])
6168

6269
# If neither repository or path are set, leave empty which will use
@@ -75,10 +82,10 @@ def _nixpkgs_package_impl(ctx):
7582
elif not (ctx.attr.nix_file or ctx.attr.nix_file_content):
7683
fail(strFailureImplicitNixpkgs)
7784

78-
nix_build_path = ctx.which("nix-build")
79-
if nix_build_path == None:
80-
fail("Could not find nix-build on the path. Please install it. See: https://nixos.org/nix/")
81-
85+
nix_build_path = _executable_path(
86+
"nix-build", ctx,
87+
extra_msg = "See: https://nixos.org/nix/"
88+
)
8289
nix_build = [nix_build_path] + expr_args
8390

8491
# Large enough integer that Bazel can still parse. We don't have
@@ -91,24 +98,13 @@ def _nixpkgs_package_impl(ctx):
9198
if res.return_code == 0:
9299
output_path = res.stdout.splitlines()[-1]
93100
else:
94-
fail("Cannot build Nix attribute %s.\nstdout:\n%s\n\nstderr:\n%s\n" %
95-
(ctx.attr.name, res.stdout, res.stderr)
96-
)
101+
_execute_error(res, "Cannot build Nix attribute `{}`"
102+
.format(ctx.attr.attribute_path))
97103

98104
# Build a forest of symlinks (like new_local_package() does) to the
99105
# Nix store.
106+
_symlink_children(output_path, ctx)
100107

101-
find_path = ctx.which("find")
102-
if find_path == None:
103-
fail("Could not find the 'find' command. Please ensure it is in your PATH.")
104-
105-
res = ctx.execute(["find", output_path, "-maxdepth", "1"])
106-
if res.return_code == 0:
107-
for i in res.stdout.splitlines():
108-
basename = i.rpartition("/")[-1]
109-
ctx.symlink(i, ctx.path(basename))
110-
else:
111-
fail(res.stderr)
112108

113109
nixpkgs_package = repository_rule(
114110
implementation = _nixpkgs_package_impl,
@@ -124,3 +120,49 @@ nixpkgs_package = repository_rule(
124120
},
125121
local = True,
126122
)
123+
124+
125+
def _symlink_children(target_dir, rep_ctx):
126+
"""Create a symlink to all children of `target_dir` in the current
127+
build directory."""
128+
find_args = [
129+
_executable_path("find", rep_ctx),
130+
target_dir,
131+
"-maxdepth", "1",
132+
# otherwise the directory is printed as well
133+
"-mindepth", "1",
134+
# filenames can contain \n
135+
"-print0",
136+
]
137+
find_res = rep_ctx.execute(find_args)
138+
if find_res.return_code == 0:
139+
for target in find_res.stdout.rstrip("\0").split("\0"):
140+
basename = target.rpartition("/")[-1]
141+
rep_ctx.symlink(target, basename)
142+
else:
143+
_execute_error(find_res)
144+
145+
146+
def _executable_path(exe_name, rep_ctx, extra_msg=""):
147+
"""Try to find the executable, fail with an error."""
148+
path = rep_ctx.which(exe_name)
149+
if path == None:
150+
fail("Could not find the `{}` executable in PATH.{}\n"
151+
.format(exe_name, " " + extra_msg if extra_msg else ""))
152+
return path
153+
154+
155+
def _execute_error(exec_result, msg):
156+
"""Print a nice error message for a failed `execute`."""
157+
fail("""
158+
execute() error: {msg}
159+
status code: {code}
160+
stdout:
161+
{stdout}
162+
stderr:
163+
{stderr}
164+
""".format(
165+
msg=msg,
166+
code=exec_result.return_code,
167+
stdout=exec_result.stdout,
168+
stderr=exec_result.stderr))

0 commit comments

Comments
 (0)