feat(tvix/cli): add helper for populating derivation outputs
Adds a small helper function which uses a Nix value supplied to
`builtins.derivation{Strict}` to populate the `outputs` field of the
`Derivation` struct.
Change-Id: Iccc7a4f293b3d913140aed576a573a8992241e46
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7898
Reviewed-by: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
			
			
This commit is contained in:
		
							parent
							
								
									1028aff105
								
							
						
					
					
						commit
						c6811f0cea
					
				
					 2 changed files with 89 additions and 0 deletions
				
			
		
							
								
								
									
										88
									
								
								tvix/cli/src/derivation.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								tvix/cli/src/derivation.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,88 @@ | |||
| //! Implements `builtins.derivation`, the core of what makes Nix build packages.
 | ||||
| 
 | ||||
| use tvix_derivation::Derivation; | ||||
| use tvix_eval::{AddContext, ErrorKind, NixList, VM}; | ||||
| 
 | ||||
| use crate::errors::Error; | ||||
| 
 | ||||
| /// Helper function for populating the `drv.outputs` field from a
 | ||||
| /// manually specified set of outputs, instead of the default
 | ||||
| /// `outputs`.
 | ||||
| fn populate_outputs(vm: &mut VM, drv: &mut Derivation, outputs: NixList) -> Result<(), ErrorKind> { | ||||
|     // Remove the original default `out` output.
 | ||||
|     drv.outputs.clear(); | ||||
| 
 | ||||
|     for output in outputs { | ||||
|         let output_name = output | ||||
|             .force(vm)? | ||||
|             .to_str() | ||||
|             .context("determining output name")?; | ||||
| 
 | ||||
|         if drv | ||||
|             .outputs | ||||
|             .insert(output_name.as_str().into(), Default::default()) | ||||
|             .is_some() | ||||
|         { | ||||
|             return Err(Error::DuplicateOutput(output_name.as_str().into()).into()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use super::*; | ||||
|     use tvix_eval::observer::NoOpObserver; | ||||
|     use tvix_eval::Value; | ||||
| 
 | ||||
|     static mut OBSERVER: NoOpObserver = NoOpObserver {}; | ||||
| 
 | ||||
|     // Creates a fake VM for tests, which can *not* actually be
 | ||||
|     // used to force (most) values but can satisfy the type
 | ||||
|     // parameter.
 | ||||
|     fn fake_vm() -> VM<'static> { | ||||
|         // safe because accessing the observer doesn't actually do anything
 | ||||
|         unsafe { | ||||
|             VM::new( | ||||
|                 Default::default(), | ||||
|                 Box::new(tvix_eval::DummyIO), | ||||
|                 &mut OBSERVER, | ||||
|                 Default::default(), | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn populate_outputs_ok() { | ||||
|         let mut vm = fake_vm(); | ||||
|         let mut drv = Derivation::default(); | ||||
|         drv.outputs.insert("out".to_string(), Default::default()); | ||||
| 
 | ||||
|         let outputs = NixList::construct( | ||||
|             2, | ||||
|             vec![Value::String("foo".into()), Value::String("bar".into())], | ||||
|         ); | ||||
| 
 | ||||
|         populate_outputs(&mut vm, &mut drv, outputs).expect("populate_outputs should succeed"); | ||||
| 
 | ||||
|         assert_eq!(drv.outputs.len(), 2); | ||||
|         assert!(drv.outputs.contains_key("bar")); | ||||
|         assert!(drv.outputs.contains_key("foo")); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn populate_outputs_duplicate() { | ||||
|         let mut vm = fake_vm(); | ||||
|         let mut drv = Derivation::default(); | ||||
|         drv.outputs.insert("out".to_string(), Default::default()); | ||||
| 
 | ||||
|         let outputs = NixList::construct( | ||||
|             2, | ||||
|             vec![Value::String("foo".into()), Value::String("foo".into())], | ||||
|         ); | ||||
| 
 | ||||
|         populate_outputs(&mut vm, &mut drv, outputs) | ||||
|             .expect_err("supplying duplicate outputs should fail"); | ||||
|     } | ||||
| } | ||||
|  | @ -1,3 +1,4 @@ | |||
| mod derivation; | ||||
| mod errors; | ||||
| mod known_paths; | ||||
| mod nix_compat; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue