Repository: astral-sh/uv
File: crates/uv/src/commands/project/run.rs (Rust)

Code before:
        Err(VarError::NotPresent) => return Ok(0),
        Err(e) => {
            return Err(e)
                .with_context(|| format!("invalid value for {}", EnvVars::UV_RUN_RECURSION_DEPTH));
        }
    };

    envvar
        .parse::<u32>()
        .with_context(|| format!("invalid value for {}", EnvVars::UV_RUN_RECURSION_DEPTH))
}

#[cfg(unix)]
fn copy_entrypoint(
    source: &Path,
    target: &Path,
    previous_executable: &Path,
    python_executable: &Path,
) -> anyhow::Result<()> {
    use std::os::unix::fs::PermissionsExt;

    let contents = fs_err::read_to_string(source)?;
    let expected = r#"#!/bin/sh
'''exec' "$(dirname -- "$(realpath -- "$0")")"/'python' "$0" "$@"
' '''
"#;

    // Only rewrite entrypoints that use the expected shebang.
    let Some(contents) = contents
        .strip_prefix(expected)
        .or_else(|| contents.strip_prefix(&format!("#!{}", previous_executable.display())))
    else {
        debug!(
            "Skipping copy of entrypoint at {}: does not start with expected shebang",
            source.user_display()
        );
        return Ok(());
    };

    let contents = format!("#!{}\n{}", python_executable.display(), contents);
    fs_err::write(target, &contents)?;

    match fs_err::write(target, &contents) {
        Ok(()) => trace!("Updated entrypoint at {}", target.user_display()),
        Err(err) if err.kind() == std::io::ErrorKind::AlreadyExists => {}
        Err(err) => return Err(err.into()),
    }

    let mut perms = fs_err::metadata(target)?.permissions();
    perms.set_mode(0o755);
    fs_err::set_permissions(target, perms)?;

Review comment (suggestion):
I think we also need to check for absolute shebangs, because we use these in the `--with` environment, but we use standard absolute shebangs in the base environment.

Code after:
    envvar
        .parse::<u32>()
        .with_context(|| format!("invalid value for {}", EnvVars::UV_RUN_RECURSION_DEPTH))
}

#[derive(Error, Debug)]
enum CopyEntrypointError {
    #[error(transparent)]
    Io(#[from] std::io::Error),
    #[cfg(windows)]
    #[error(transparent)]
    Trampoline(#[from] uv_trampoline_builder::Error),
}

/// Create a copy of the entrypoint at `source` at `target`, if it has a Python shebang, replacing
/// the previous Python executable with a new one.
///
/// This is a no-op if the target already exists.
///
/// Note on Windows, the entrypoints do not use shebangs and require a rewrite of the trampoline.
#[cfg(unix)]
fn copy_entrypoint(
    source: &Path,
    target: &Path,
    previous_executable: &Path,
    python_executable: &Path,
) -> Result<(), CopyEntrypointError> {
    use std::io::Write;
    use std::os::unix::fs::PermissionsExt;

    use fs_err::os::unix::fs::OpenOptionsExt;

    let contents = fs_err::read_to_string(source)?;

    let Some(contents) = contents
        // Check for a relative path or relocatable shebang
        .strip_prefix(
            r#"#!/bin/sh
'''exec' "$(dirname -- "$(realpath -- "$0")")"/'python' "$0" "$@"
' '''
"#,
        )
        // Or an absolute path shebang
        .or_else(|| contents.strip_prefix(&format!("#!{}\n", previous_executable.display())))
    else {
        // If it's not a Python shebang, we'll skip it
        trace!(
            "Skipping copy of entrypoint `{}`: does not start with expected shebang",
            source.user_display()
        );
        return Ok(());