Skip to content

Commit

Permalink
Initial draft to implement downloading rust toolchain during sdist
Browse files Browse the repository at this point in the history
Initial draft to implement downloading rust toolchain during sdist
  • Loading branch information
Owen-CH-Leung committed Aug 8, 2024
1 parent d2e3861 commit 57f35c9
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 2 deletions.
31 changes: 30 additions & 1 deletion src/build_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::module_writer::{
};
use crate::project_layout::ProjectLayout;
use crate::python_interpreter::InterpreterKind;
use crate::source_distribution::source_distribution;
use crate::source_distribution::{download_and_execute_rustup, source_distribution};
use crate::target::{Arch, Os};
use crate::{
compile, pyproject_toml::Format, BuildArtifact, Metadata23, ModuleWriter, PyProjectToml,
Expand Down Expand Up @@ -273,6 +273,22 @@ impl BuildContext {
let sdist_path =
source_distribution(self, pyproject, self.excludes(Format::Sdist)?)
.context("Failed to build source distribution")?;
if self.require_rust_toolchain() {
let mut target_path = sdist_path.clone().to_path_buf();
target_path.pop();
target_path.pop();
target_path.push("bin");

fs::create_dir_all(&target_path)
.context("Fail to create directory for installing rust toolchain")?;

let target_path_str = target_path
.to_str()
.context("Fail to construct target path for installing rust toolchain")?;

download_and_execute_rustup(target_path_str, target_path_str)
.context("Failed to download rust toolchain")?;
}
Ok(Some((sdist_path, "source".to_string())))
}
None => Ok(None),
Expand Down Expand Up @@ -1132,6 +1148,19 @@ impl BuildContext {
}
Ok(wheels)
}
/// Check if user requires to install rust toolchain
///
/// Loop over `build-system.requires` defined in pyproject.toml and see if `rust-toolchain` is provided
pub fn require_rust_toolchain(&self) -> bool {
match &self.pyproject_toml {
Some(pyproject_toml) => pyproject_toml
.build_system
.requires
.iter()
.any(|req| req.name.as_ref() == "rust-toolchain"),
None => false,
}
}
}

/// Calculate the sha256 of a file
Expand Down
36 changes: 36 additions & 0 deletions src/source_distribution.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::module_writer::{add_data, ModuleWriter};
use crate::pyproject_toml::SdistGenerator;
use crate::upload::http_agent;
use crate::{pyproject_toml::Format, BuildContext, PyProjectToml, SDistWriter};
use anyhow::{bail, Context, Result};
use cargo_metadata::{Metadata, MetadataCommand, PackageId};
Expand All @@ -8,9 +9,11 @@ use ignore::overrides::Override;
use normpath::PathExt as _;
use path_slash::PathExt as _;
use std::collections::HashMap;
use std::io::copy;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str;
use tempfile::NamedTempFile;
use tracing::debug;

/// Path dependency information.
Expand Down Expand Up @@ -735,3 +738,36 @@ where
None
}
}

/// Downloads the rustup installer script and executes it to install rustup
///
/// Inspired by https://github.com/chriskuehl/rustenv
pub fn download_and_execute_rustup(rustup_home: &str, cargo_home: &str) -> Result<()> {
let mut tf = NamedTempFile::new()?;
let agent = http_agent()?;
let response = agent.get("https://sh.rustup.rs").call()?.into_string()?;

copy(&mut response.as_bytes(), &mut tf)?;

#[cfg(unix)]
{
Command::new("sh")
.arg(tf.path())
.arg("-y")
.arg("--no-modify-path")
.env("RUSTUP_HOME", rustup_home)
.env("CARGO_HOME", cargo_home)
.status()?;
}

#[cfg(windows)]
{
Command::new("cmd")
.args(&["/C", tf.path(), "-y", "--no-modify-path"])
.env("RUSTUP_HOME", rustup_home)
.env("CARGO_HOME", cargo_home)
.status()?;
}

Ok(())
}
2 changes: 1 addition & 1 deletion src/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ fn http_agent() -> Result<ureq::Agent, UploadError> {

#[cfg(feature = "rustls")]
#[allow(clippy::result_large_err)]
fn http_agent() -> Result<ureq::Agent, UploadError> {
pub fn http_agent() -> Result<ureq::Agent, UploadError> {
use std::sync::Arc;

let builder = ureq::builder().try_proxy_from_env(true);
Expand Down

0 comments on commit 57f35c9

Please sign in to comment.