Skip to content

Commit

Permalink
Refuse to remove the target directory if it is not a python installat…
Browse files Browse the repository at this point in the history
…ion (#921)
  • Loading branch information
j178 authored Mar 29, 2024
1 parent 09c8e07 commit c216b90
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 16 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ _Unreleased_

- Always create `.gitignore` file in `rye init`. #919

- Prevent `rye fetch --force` from removing a target directory that is not a Python installation. #921

- `rye list` always prints the currently installed packages even this project is not managed by Rye. #940

- Fix error on using -v or -q with `rye fmt` or `rye lint`. #959
- Fix error on using -v or -q with `rye fmt` or `rye lint`. #959

- Fix rye fetch detection of registered toolchain. #931

Expand Down
21 changes: 17 additions & 4 deletions rye/src/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ use tempfile::tempdir_in;
use crate::config::Config;
use crate::piptools::LATEST_PIP;
use crate::platform::{
get_app_dir, get_canonical_py_path, get_toolchain_python_bin, list_known_toolchains,
get_app_dir, get_canonical_py_path, get_python_bin_within, get_toolchain_python_bin,
list_known_toolchains,
};
use crate::pyproject::latest_available_python_version;
use crate::sources::py::{get_download_url, PythonVersion, PythonVersionRequest};
Expand Down Expand Up @@ -396,11 +397,23 @@ pub fn fetch(

let target_dir = match options.target_path {
Some(ref target_dir) => {
echo!(if options.output, "downloading to: {}", target_dir.display());
if target_dir.is_file() {
bail!("target directory '{}' is a file", target_dir.display());
}
echo!(if options.output, "Downloading to '{}'", target_dir.display());
if target_dir.is_dir() {
if options.force {
// Refuse to remove the target directory if it's not empty and not a python installation
if target_dir.read_dir()?.next().is_some()
&& !get_python_bin_within(target_dir).exists()
{
bail!(
"target directory '{}' exists and is not a Python installation",
target_dir.display()
);
}
fs::remove_dir_all(target_dir)
.path_context(target_dir, "could not remove target director")?;
.path_context(target_dir, "could not remove target directory")?;
} else {
bail!("target directory '{}' exists", target_dir.display());
}
Expand Down Expand Up @@ -449,7 +462,7 @@ pub fn fetch(
let with_build_info = options
.build_info
.unwrap_or_else(|| Config::current().fetch_with_build_info());
let temp_dir = tempdir_in(target_dir.parent().unwrap()).context("temporary unpack location")?;
let temp_dir = tempdir_in(parent).context("temporary unpack location")?;

unpack_archive(&archive_buffer, temp_dir.path(), 1).with_context(|| {
format!(
Expand Down
27 changes: 16 additions & 11 deletions rye/src/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub fn get_canonical_py_path(version: &PythonVersion) -> Result<PathBuf, Error>

/// Returns the path of the python binary for the given version.
pub fn get_toolchain_python_bin(version: &PythonVersion) -> Result<PathBuf, Error> {
let mut p = get_canonical_py_path(version)?;
let p = get_canonical_py_path(version)?;

// It's permissible to link Python binaries directly in two ways. It can either be
// a symlink in which case it's used directly, it can be a non-executable text file
Expand All @@ -83,26 +83,31 @@ pub fn get_toolchain_python_bin(version: &PythonVersion) -> Result<PathBuf, Erro
return Ok(PathBuf::from(contents.trim_end()));
}

Ok(get_python_bin_within(&p))
}

/// Returns the path to the python binary within the path.
pub fn get_python_bin_within(path: &Path) -> PathBuf {
let mut path = path.to_path_buf();
// we support install/bin/python, install/python and bin/python
p.push("install");
if !p.is_dir() {
p.pop();
path.push("install");
if !path.is_dir() {
path.pop();
}
p.push("bin");
if !p.is_dir() {
p.pop();
path.push("bin");
if !path.is_dir() {
path.pop();
}

#[cfg(unix)]
{
p.push("python3");
path.push("python3");
}
#[cfg(windows)]
{
p.push("python.exe");
path.push("python.exe");
}

Ok(p)
path
}

/// Returns a pinnable version for this version request.
Expand Down

0 comments on commit c216b90

Please sign in to comment.