Skip to content

Commit 9ddd617

Browse files
committed
Work in terms of bytes when patching shebang lines
As [Uv's implementation](https://github.com/astral-sh/uv/blob/db14cc3005d2cd53802cb04c2f1e177a22c934ac/crates/uv-install-wheel/src/wheel.rs#L425) notes: > scripts might be binaries, so we read an exact number of bytes instead of the first line as string Indeed, one wheel that contains a binary "script" is [`uv` itself](https://pypi.org/project/uv/). Constructing a venv that happens to include `uv` was previously failing with: ``` ERROR: /Users/peter/tecton/sdk/pypi/BUILD.bazel:97:8: Action sdk/pypi/.venv failed: (Exit 1): sandbox-exec failed: error executing Action command (cd /private/var/tmp/_bazel_peter/dfecb8ec3f6f433d8509be7ebe017232/sandbox/darwin-sandbox/589/execroot/_main && \ exec env - \ TMPDIR=/var/folders/9_/p2d_shr10b91_464_3jfl5t80000gn/T/ \ /usr/bin/sandbox-exec -f /private/var/tmp/_bazel_peter/dfecb8ec3f6f433d8509be7ebe017232/sandbox/darwin-sandbox/589/sandbox.sb /var/tmp/_bazel_peter/install/96e26d97222159f904e14600d7490eb0/process-wrapper '--timeout=0' '--kill_delay=15' '--stats=/private/var/tmp/_bazel_peter/dfecb8ec3f6f433d8509be7ebe017232/sandbox/darwin-sandbox/589/stats.out' bazel-out/darwin_arm64-opt-exec-ST-2adb5a2e0ae2/bin/external/aspect_rules_py~/py/tools/venv_bin/venv_macos_aarch64_build '--location=bazel-out/darwin_arm64-fastbuild/bin/sdk/pypi/.venv' '--venv-shim=bazel-out/darwin_arm64-fastbuild-ST-2adb5a2e0ae2/bin/external/aspect_rules_py~/py/tools/venv_shim/shim_macos_aarch64_build' '--python=python_3.8_macos_aarch64_runtime/python/install/bin/python3.8' '--pth-file=bazel-out/darwin_arm64-fastbuild/bin/sdk/pypi/venv.pth' '--env-file=bazel-out/darwin_arm64-fastbuild/bin/sdk/pypi/venv.env' '--bin-dir=bazel-out/darwin_arm64-fastbuild/bin' '--collision-strategy=error' '--venv-name=.venv' '--mode=static-copy' '--version=3.8') Error: × Unable to run command: ╰─▶ stream did not contain valid UTF-8 ```
1 parent 5968bcb commit 9ddd617

File tree

1 file changed

+30
-7
lines changed

1 file changed

+30
-7
lines changed

py/tools/py/src/venv.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use sha256::try_digest;
88
use std::{
99
env::current_dir,
1010
fs::{self, File},
11-
io::{BufRead, BufReader, BufWriter, Write},
11+
io::{self, BufRead, BufReader, BufWriter, Read, Write, Seek},
1212
os::unix::fs::{MetadataExt, PermissionsExt},
1313
path::{Path, PathBuf},
1414
};
@@ -172,7 +172,34 @@ fn copy(original: &PathBuf, link: &PathBuf) -> miette::Result<()> {
172172
));
173173
}
174174

175-
const RELOCATABLE_SHEBANG: &str = "\
175+
fn copy_and_patch_shebang(original: &PathBuf, link: &PathBuf) -> miette::Result<()> {
176+
let mut src = File::open(original.as_path()).into_diagnostic()?;
177+
178+
let mut buf = [0u8; PLACEHOLDER_SHEBANG.len()];
179+
let found_shebang = match src.read_exact(&mut buf) {
180+
Ok(()) => buf == PLACEHOLDER_SHEBANG,
181+
Err(error) => match error.kind() {
182+
io::ErrorKind::UnexpectedEof => false, // File too short to contain shebang.
183+
_ => Err(error).into_diagnostic()?,
184+
},
185+
};
186+
187+
if found_shebang {
188+
let mut dst = File::create(link.as_path()).into_diagnostic()?;
189+
dst.write_all(RELOCATABLE_SHEBANG).into_diagnostic()?;
190+
src.rewind().into_diagnostic()?;
191+
io::copy(&mut src, &mut dst).into_diagnostic()?;
192+
}
193+
else {
194+
copy(original, link)?;
195+
}
196+
197+
Ok(())
198+
}
199+
200+
const PLACEHOLDER_SHEBANG: &[u8] = b"#!/dev/null";
201+
202+
const RELOCATABLE_SHEBANG: &[u8] = b"\
176203
#!/bin/sh
177204
'''exec' \"$(dirname -- \"$(realpath -- \"$0\")\")\"/'python3' \"$0\" \"$@\"
178205
' '''
@@ -619,11 +646,7 @@ pub fn create_tree(
619646

620647
// In the case of copying bin entries, we need to patch them. Yay.
621648
if link_dir.file_name() == Some(OsStr::new("bin")) {
622-
let mut content = fs::read_to_string(original_entry).into_diagnostic()?;
623-
if content.starts_with("#!/dev/null") {
624-
content.replace_range(..0, &RELOCATABLE_SHEBANG);
625-
}
626-
fs::write(&link_entry, content).into_diagnostic()?;
649+
copy_and_patch_shebang(&original_entry, &link_entry)?;
627650
}
628651
// Normal case of needing to link a file :smile:
629652
else {

0 commit comments

Comments
 (0)