42dc18353d
The primary constructor for this is now from_bytes, from_string is simply calling .as_bytes() on the string, passing it along. The InvalidName error now contains a Vec<u8>, to encode the invalid name (which might not be a string anymore). from_absolute_path now accepts a &[u8] (even though we might want to make this a OSString of some sort). StorePath::validate_name has been degraded to a pub(crate) function. It's still used in src/derivation, even though it probably shouldn't at all - that cleanup is left for cl/8412 though. Change-Id: I6b4e62a6fa5c4bec13b535279e73444f0b83ad35 Reviewed-on: https://cl.tvl.fyi/c/depot/+/8973 Autosubmit: flokli <flokli@flokli.de> Tested-by: BuildkiteCI Reviewed-by: raitobezarius <tvl@lahfa.xyz>
129 lines
4.9 KiB
Rust
129 lines
4.9 KiB
Rust
use crate::derivation::{Derivation, DerivationError};
|
|
use crate::store_path::{self, StorePath};
|
|
|
|
impl Derivation {
|
|
/// validate ensures a Derivation struct is properly populated,
|
|
/// and returns a [DerivationError] if not.
|
|
///
|
|
/// if `validate_output_paths` is set to false, the output paths are
|
|
/// excluded from validation.
|
|
///
|
|
/// This is helpful to validate struct population before invoking
|
|
/// [Derivation::calculate_output_paths].
|
|
pub fn validate(&self, validate_output_paths: bool) -> Result<(), DerivationError> {
|
|
// Ensure the number of outputs is > 1
|
|
if self.outputs.is_empty() {
|
|
return Err(DerivationError::NoOutputs());
|
|
}
|
|
|
|
// Validate all outputs
|
|
for (output_name, output) in &self.outputs {
|
|
// empty output names are invalid.
|
|
//
|
|
// `drv` is an invalid output name too, as this would cause
|
|
// a `builtins.derivation` call to return an attrset with a
|
|
// `drvPath` key (which already exists) and has a different
|
|
// meaning.
|
|
//
|
|
// Other output names that don't match the name restrictions from
|
|
// [StorePath] will fail the [store_path::validate_name] check.
|
|
if output_name.is_empty()
|
|
|| output_name == "drv"
|
|
|| store_path::validate_name(output_name.as_bytes()).is_err()
|
|
{
|
|
return Err(DerivationError::InvalidOutputName(output_name.to_string()));
|
|
}
|
|
|
|
if output.is_fixed() {
|
|
if self.outputs.len() != 1 {
|
|
return Err(DerivationError::MoreThanOneOutputButFixed());
|
|
}
|
|
if output_name != "out" {
|
|
return Err(DerivationError::InvalidOutputNameForFixed(
|
|
output_name.to_string(),
|
|
));
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if let Err(e) = output.validate(validate_output_paths) {
|
|
return Err(DerivationError::InvalidOutput(output_name.to_string(), e));
|
|
}
|
|
}
|
|
|
|
// Validate all input_derivations
|
|
for (input_derivation_path, output_names) in &self.input_derivations {
|
|
// Validate input_derivation_path
|
|
if let Err(e) = StorePath::from_absolute_path(input_derivation_path.as_bytes()) {
|
|
return Err(DerivationError::InvalidInputDerivationPath(
|
|
input_derivation_path.to_string(),
|
|
e,
|
|
));
|
|
}
|
|
|
|
if !input_derivation_path.ends_with(".drv") {
|
|
return Err(DerivationError::InvalidInputDerivationPrefix(
|
|
input_derivation_path.to_string(),
|
|
));
|
|
}
|
|
|
|
if output_names.is_empty() {
|
|
return Err(DerivationError::EmptyInputDerivationOutputNames(
|
|
input_derivation_path.to_string(),
|
|
));
|
|
}
|
|
|
|
for output_name in output_names.iter() {
|
|
// empty output names are invalid.
|
|
//
|
|
// `drv` is an invalid output name too, as this would cause
|
|
// a `builtins.derivation` call to return an attrset with a
|
|
// `drvPath` key (which already exists) and has a different
|
|
// meaning.
|
|
//
|
|
// Other output names that don't match the name restrictions from
|
|
// [StorePath] will fail the [StorePath::validate_name] check.
|
|
if output_name.is_empty()
|
|
|| output_name == "drv"
|
|
|| store_path::validate_name(output_name.as_bytes()).is_err()
|
|
{
|
|
return Err(DerivationError::InvalidInputDerivationOutputName(
|
|
input_derivation_path.to_string(),
|
|
output_name.to_string(),
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Validate all input_sources
|
|
for input_source in self.input_sources.iter() {
|
|
if let Err(e) = StorePath::from_absolute_path(input_source.as_bytes()) {
|
|
return Err(DerivationError::InvalidInputSourcesPath(
|
|
input_source.to_string(),
|
|
e,
|
|
));
|
|
}
|
|
}
|
|
|
|
// validate platform
|
|
if self.system.is_empty() {
|
|
return Err(DerivationError::InvalidPlatform(self.system.to_string()));
|
|
}
|
|
|
|
// validate builder
|
|
if self.builder.is_empty() {
|
|
return Err(DerivationError::InvalidBuilder(self.builder.to_string()));
|
|
}
|
|
|
|
// validate env, none of the keys may be empty.
|
|
// We skip the `name` validation seen in go-nix.
|
|
for k in self.environment.keys() {
|
|
if k.is_empty() {
|
|
return Err(DerivationError::InvalidEnvironmentKey(k.to_string()));
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|