Skip to content

Commit

Permalink
Invert order of path manipulations
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Jul 29, 2024
1 parent 5508f23 commit 2c80308
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 40 deletions.
58 changes: 20 additions & 38 deletions crates/install-wheel-rs/src/wheel.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::{env, io};
use std::collections::HashMap;
use std::io::{BufRead, BufReader, Cursor, Read, Seek, Write};
use std::path::{Path, PathBuf};

use data_encoding::BASE64URL_NOPAD;
use fs_err as fs;
use fs_err::{DirEntry, File};
use rustc_hash::FxHashMap;
use sha2::{Digest, Sha256};
use std::borrow::Cow;
use std::collections::HashMap;
use std::io::{BufRead, BufReader, Cursor, Read, Seek, Write};
use std::path::{Path, PathBuf};
use std::{env, io};
use tracing::{instrument, warn};
use walkdir::WalkDir;
use zip::write::FileOptions;
Expand All @@ -17,9 +17,9 @@ use pypi_types::DirectUrl;
use uv_fs::{relative_to, Simplified};
use uv_normalize::PackageName;

use crate::{Error, Layout};
use crate::record::RecordEntry;
use crate::script::Script;
use crate::{Error, Layout};

const LAUNCHER_MAGIC_NUMBER: [u8; 4] = [b'U', b'V', b'U', b'V'];

Expand Down Expand Up @@ -300,8 +300,8 @@ pub(crate) fn write_script_entrypoints(
})?;

// Generate the launcher script.
let python_executable = get_python_executable(layout, relocatable)?;
let launcher_executable = get_script_executable(&python_executable, is_gui);
let launcher_executable = get_script_executable(&layout.sys_executable, is_gui);
let launcher_executable = get_relocatable_executable(launcher_executable, layout, relocatable)?;
let launcher_python_script = get_script_launcher(
entrypoint,
&format_shebang(&launcher_executable, &layout.os_name, relocatable),
Expand Down Expand Up @@ -514,8 +514,8 @@ fn install_script(
false
}
};
let python_executable = get_python_executable(layout, relocatable)?;
let executable = get_script_executable(&python_executable, is_gui);
let executable = get_script_executable(&layout.sys_executable, is_gui);
let executable = get_relocatable_executable(executable, layout, relocatable)?;
let start = format_shebang(&executable, &layout.os_name, relocatable)
.as_bytes()
.to_vec();
Expand Down Expand Up @@ -710,26 +710,27 @@ pub(crate) fn extra_dist_info(
///
/// Returns `sys.executable` if the wheel is not relocatable; otherwise, returns a path relative
/// to the scripts directory.
pub(crate) fn get_python_executable(
pub(crate) fn get_relocatable_executable(
executable: PathBuf,
layout: &Layout,
relocatable: bool,
) -> Result<Cow<'_, Path>, Error> {
) -> Result<PathBuf, Error> {
Ok(if relocatable {
Cow::Owned(
pathdiff::diff_paths(&layout.sys_executable, &layout.scheme.scripts).ok_or_else(

pathdiff::diff_paths(&executable, &layout.scheme.scripts).ok_or_else(
|| {
Error::Io(io::Error::new(
io::ErrorKind::Other,
format!(
"Could not find relative path for: {}",
layout.sys_executable.simplified_display()
executable.simplified_display()
),
))
},
)?,
)
)?

} else {
Cow::Borrowed(&layout.sys_executable)
executable
})
}

Expand Down Expand Up @@ -787,8 +788,8 @@ mod test {
use assert_fs::prelude::*;
use indoc::{formatdoc, indoc};

use crate::wheel::format_shebang;
use crate::Error;
use crate::wheel::format_shebang;

use super::{
get_script_executable, parse_key_value_file, parse_wheel_file, read_record_file, Script,
Expand Down Expand Up @@ -1067,25 +1068,6 @@ mod test {
let script_path = get_script_executable(&dot_python_exe, false);
assert_eq!(script_path, dot_python_exe.to_path_buf());

// Test with relocatable executable.
let temp_dir = assert_fs::TempDir::new()?;
let python_exe = temp_dir.child("python.exe");
let pythonw_exe = temp_dir.child("pythonw.exe");
python_exe.write_str("")?;
pythonw_exe.write_str("")?;

// Truncate to a relative path.
let python_exe = python_exe.path().strip_prefix(temp_dir.path()).unwrap();

let script_path = get_script_executable(python_exe, true);
#[cfg(windows)]
assert_eq!(script_path, Path::new("pythonw.exe").to_path_buf());
#[cfg(not(windows))]
assert_eq!(script_path, Path::new("python.exe").to_path_buf());

let script_path = get_script_executable(python_exe, false);
assert_eq!(script_path, Path::new("python.exe").to_path_buf());

Ok(())
}
}
9 changes: 7 additions & 2 deletions crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1745,12 +1745,17 @@ pub struct VenvArgs {

/// Make the virtual environment relocatable.
///
/// A relocatable virtual environment can be moved around and redistributed with its
/// associated entrypoint and activation scripts functioning as usual.
/// A relocatable virtual environment can be moved around and redistributed without
/// invalidating its associated entrypoint and activation scripts.
///
/// Note that this can only be guaranteed for standard `console_scripts` and `gui_scripts`.
/// Other scripts may be adjusted if they ship with a generic `#!python[w]` shebang,
/// and binaries are left as-is.
///
/// As a result of making the environment relocatable (by way of writing relative, rather than
/// absolute paths), the entrypoints and scripts themselves will _not_ be relocatable. In other
/// words, copying those entrypoints and scripts to a location outside the environment will not
/// work, as they reference paths relative to the environment itself.
#[arg(long)]
pub relocatable: bool,

Expand Down

0 comments on commit 2c80308

Please sign in to comment.