Skip to content

Commit

Permalink
refactor: move script_env into script (#392)
Browse files Browse the repository at this point in the history
  • Loading branch information
baszalmstra authored Dec 5, 2023
1 parent e10cac8 commit 49a0876
Show file tree
Hide file tree
Showing 12 changed files with 409 additions and 194 deletions.
107 changes: 73 additions & 34 deletions src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
use std::collections::HashSet;
use std::ffi::OsString;

use std::io::{BufRead, BufReader, Write};
use std::io::{BufRead, BufReader, ErrorKind, Write};

use fs_err as fs;
use fs_err::File;
use std::borrow::Cow;
use std::path::Path;
use std::path::PathBuf;
use std::process::{Command, Stdio};
use std::{io::Read, path::PathBuf};

use itertools::Itertools;
use miette::IntoDiagnostic;
Expand All @@ -17,6 +19,7 @@ use rattler_shell::shell;
use crate::env_vars::write_env_script;
use crate::metadata::{Directories, Output};
use crate::packaging::{package_conda, record_files};
use crate::recipe::parser::ScriptContent;
use crate::render::resolved_dependencies::{install_environments, resolve_dependencies};
use crate::source::fetch_sources;
use crate::test::TestConfiguration;
Expand All @@ -39,44 +42,80 @@ pub fn get_conda_build_script(
) -> Result<PathBuf, std::io::Error> {
let recipe = &output.recipe;

let default_script = if output.build_configuration.target_platform.is_windows() {
["build.bat".to_owned()]
let script = recipe.build().script();
let default_extension = if output.build_configuration.target_platform.is_windows() {
"bat"
} else {
["build.sh".to_owned()]
"sh"
};
let script_content = match script.contents() {
// No script was specified, so we try to read the default script. If the file cannot be
// found we return an empty string.
ScriptContent::Default => {
let recipe_file = directories
.recipe_dir
.join(Path::new("build").with_extension(default_extension));
match std::fs::read_to_string(recipe_file) {
Err(err) if err.kind() == ErrorKind::NotFound => String::new(),
Err(e) => {
return Err(e);
}
Ok(content) => content,
}
}

let script = if recipe.build().scripts().is_empty() {
&default_script
} else {
recipe.build().scripts()
};

let script = script.iter().join("\n");

let script = if script.ends_with(".sh") || script.ends_with(".bat") {
let recipe_file = directories.recipe_dir.join(script);
tracing::info!("Reading recipe file: {:?}", recipe_file);

if !recipe_file.exists() {
if recipe.build().scripts().is_empty() {
tracing::info!("Empty build script");
String::new()
// The scripts path was explicitly specified. If the file cannot be found we error out.
ScriptContent::Path(path) => {
let path_with_ext = if path.extension().is_none() {
Cow::Owned(path.with_extension(default_extension))
} else {
return Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("Recipe file {:?} does not exist", recipe_file),
));
Cow::Borrowed(path.as_path())
};
let recipe_file = directories.recipe_dir.join(path_with_ext);
match std::fs::read_to_string(&recipe_file) {
Err(err) if err.kind() == ErrorKind::NotFound => {
return Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("recipe file {:?} does not exist", recipe_file.display()),
));
}
Err(e) => {
return Err(e);
}
Ok(content) => content,
}
} else {
let mut orig_build_file = File::open(recipe_file)?;
let mut orig_build_file_text = String::new();
orig_build_file.read_to_string(&mut orig_build_file_text)?;
orig_build_file_text
}
} else {
script
// The scripts content was specified but it is still ambiguous whether it is a path or the
// contents of the string. Try to read the file as a script but fall back to using the string
// as the contents itself if the file is missing.
ScriptContent::CommandOrPath(path) => {
let content =
if !path.contains('\n') && (path.ends_with(".bat") || path.ends_with(".sh")) {
let recipe_file = directories.recipe_dir.join(Path::new(path));
match std::fs::read_to_string(recipe_file) {
Err(err) if err.kind() == ErrorKind::NotFound => None,
Err(e) => {
return Err(e);
}
Ok(content) => Some(content),
}
} else {
None
};
match content {
Some(content) => content,
None => path.to_owned(),
}
}
ScriptContent::Commands(commands) => commands.iter().join("\n"),
ScriptContent::Command(command) => command.to_owned(),
};

if script.interpreter().is_some() {
// We don't support an interpreter yet
tracing::error!("build.script.interpreter is not supported yet");
}

if cfg!(unix) {
let build_env_script_path = directories.work_dir.join("build_env.sh");
let preamble =
Expand All @@ -89,7 +128,7 @@ pub fn get_conda_build_script(
format!("Failed to write build env script: {}", e),
)
})?;
let full_script = format!("{}\n{}", preamble, script);
let full_script = format!("{}\n{}", preamble, script_content);
let build_script_path = directories.work_dir.join("conda_build.sh");

let mut build_script_file = File::create(&build_script_path)?;
Expand All @@ -110,7 +149,7 @@ pub fn get_conda_build_script(
)
})?;

let full_script = format!("{}\n{}", preamble, script);
let full_script = format!("{}\n{}", preamble, script_content);
let build_script_path = directories.work_dir.join("conda_build.bat");

let mut build_script_file = File::create(&build_script_path)?;
Expand Down
16 changes: 2 additions & 14 deletions src/env_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,23 +377,11 @@ pub fn write_env_script<T: Shell + Clone>(
shell_type.set_env_var(&mut s, &k, &v)?;
}

for env_key in output.recipe.build().script_env().passthrough() {
let var = std::env::var(env_key);
if let Ok(var) = var {
shell_type.set_env_var(&mut s, env_key, var.as_str())?;
} else {
tracing::warn!(
"Could not find passthrough environment variable: {}",
env_key
);
}
}

for (k, v) in output.recipe.build().script_env().env() {
for (k, v) in output.recipe.build().script().env() {
shell_type.set_env_var(&mut s, k, v)?;
}

if !output.recipe.build().script_env().secrets().is_empty() {
if !output.recipe.build().script().secrets().is_empty() {
tracing::error!("Secrets are not supported yet");
}

Expand Down
8 changes: 5 additions & 3 deletions src/recipe/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ mod build;
mod output;
mod package;
mod requirements;
mod script;
mod source;
mod test;

pub use self::{
about::About,
build::{Build, RunExports, ScriptEnv},
build::{Build, RunExports},
output::find_outputs_from_src,
package::{OutputPackage, Package},
requirements::{Compiler, Dependency, PinSubpackage, Requirements},
script::{Script, ScriptContent},
source::{Checksum, GitSource, GitUrl, PathSource, Source, UrlSource},
test::{PackageContent, Test},
};
Expand Down Expand Up @@ -133,7 +135,7 @@ impl Recipe {
ErrorKind::InvalidField("recipe".to_string().into()),
help =
"The recipe field is only allowed in conjunction with multiple outputs"
))
));
}
"source" => source = value.try_convert(key_str)?,
"build" => build = value.try_convert(key_str)?,
Expand All @@ -146,7 +148,7 @@ impl Recipe {
return Err(_partialerror!(
*key.span(),
ErrorKind::InvalidField(invalid_key.to_string().into()),
))
));
}
}
}
Expand Down
Loading

0 comments on commit 49a0876

Please sign in to comment.