1use eggup_core::{
9 AbsentPolicy, AllValidators, ArtifactMember, ArtifactSet, CommitOwnership, ExactDigestVerifier,
10 InstallPlan, IntegrityRequirement, MemberId, ProductId, ReleaseId, TransactionDisposition,
11};
12use std::fs;
13use std::path::PathBuf;
14use std::time::{SystemTime, UNIX_EPOCH};
15
16fn temp_root(prefix: &str) -> PathBuf {
17 let nanos = SystemTime::now()
18 .duration_since(UNIX_EPOCH)
19 .map(|d| d.as_nanos())
20 .unwrap_or(0);
21 std::env::temp_dir().join(format!("{prefix}-{}-{nanos}", std::process::id()))
22}
23
24fn main() -> Result<(), Box<dyn std::error::Error>> {
25 let base = temp_root("eggup-ownership");
26 let inputs = base.join("inputs");
27 let root = base.join("install");
28 fs::create_dir_all(&inputs)?;
29 fs::create_dir_all(root.join("bin"))?;
30 fs::write(inputs.join("app"), b"new-app")?;
31 fs::write(root.join("bin/app"), b"old-app")?;
32 let new_digest = eggup_core::hash_file(&inputs.join("app"))?;
33 let old_digest = eggup_core::hash_file(&root.join("bin/app"))?;
34 let member = ArtifactMember::new(MemberId::new("main")?, inputs.join("app"), "bin/app")?
35 .with_integrity(IntegrityRequirement::Sha256(new_digest));
36 let plan = InstallPlan::new(
37 ProductId::new("demo")?,
38 ReleaseId::new("4.0.0")?,
39 &root,
40 ArtifactSet::single(member)?,
41 )?;
42 let verifier = ExactDigestVerifier::new(vec![(MemberId::new("main")?, old_digest)]);
45 let receipt = plan
46 .prepare()?
47 .verify_integrity()?
48 .validate(&AllValidators::new())?
49 .commit(CommitOwnership::new(&verifier, AbsentPolicy::DenyCreate))?;
50 assert_eq!(receipt.disposition(), TransactionDisposition::Committed);
51 assert_eq!(fs::read(root.join("bin/app"))?, b"new-app");
52 let _ = fs::remove_dir_all(&base);
53 println!("ownership-verified commit: {:?}", receipt.disposition());
54 Ok(())
55}