Pre-populate accepts either a store path or a flake URI.

This commit is contained in:
r-vdp 2023-05-16 12:00:30 +02:00
parent 2901945cfd
commit 7e78522c02
No known key found for this signature in database
2 changed files with 104 additions and 32 deletions

View file

@ -27,10 +27,8 @@ pub struct StorePath {
impl From<String> for StorePath { impl From<String> for StorePath {
fn from(path: String) -> Self { fn from(path: String) -> Self {
PathBuf::from(path.clone()).try_into().unwrap_or_else(|e| { PathBuf::from(path.clone()).try_into().unwrap_or_else(|e| {
panic!( log::error!("Error constructing store path: {}\n {:?}", path, e);
"Error constructing store path, path not in store: {}\n{:?}", panic!("Error constructing store path: {}: {:?}", path, e);
path, e
);
}) })
} }
} }

View file

@ -1,6 +1,5 @@
use anyhow::Result; use anyhow::Result;
use clap::Parser; use clap::Parser;
use std::borrow::Cow;
use std::ffi::OsString; use std::ffi::OsString;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::{self, ExitCode}; use std::process::{self, ExitCode};
@ -54,7 +53,7 @@ struct ActivationArgs {
} }
#[derive(clap::Args, Debug)] #[derive(clap::Args, Debug)]
struct OptionalStorePathArgs { struct OptionalStorePathArg {
#[arg(long = "store-path", name = "STORE_PATH")] #[arg(long = "store-path", name = "STORE_PATH")]
/// The store path for the system-manager profile. /// The store path for the system-manager profile.
/// You only need to specify this explicitly if it differs from the active /// You only need to specify this explicitly if it differs from the active
@ -62,6 +61,22 @@ struct OptionalStorePathArgs {
maybe_store_path: Option<StorePath>, maybe_store_path: Option<StorePath>,
} }
#[derive(clap::Args, Debug)]
struct OptionalFlakeUriArg {
#[arg(long = "flake", name = "FLAKE_URI")]
/// The flake URI defining the system-manager profile
maybe_flake_uri: Option<String>,
}
#[derive(clap::Args, Debug)]
struct StoreOrFlakeArgs {
#[command(flatten)]
optional_store_path_arg: OptionalStorePathArg,
#[command(flatten)]
optional_flake_uri_arg: OptionalFlakeUriArg,
}
#[derive(clap::Subcommand, Debug)] #[derive(clap::Subcommand, Debug)]
enum Action { enum Action {
/// Activate a given system-manager profile /// Activate a given system-manager profile
@ -76,7 +91,7 @@ enum Action {
/// services. Useful in build scripts. /// services. Useful in build scripts.
PrePopulate { PrePopulate {
#[command(flatten)] #[command(flatten)]
optional_store_path_args: OptionalStorePathArgs, store_or_flake_args: StoreOrFlakeArgs,
#[command(flatten)] #[command(flatten)]
activation_args: ActivationArgs, activation_args: ActivationArgs,
}, },
@ -88,13 +103,13 @@ enum Action {
/// Deactivate the active system-manager profile, removing all managed configuration /// Deactivate the active system-manager profile, removing all managed configuration
Deactivate { Deactivate {
#[command(flatten)] #[command(flatten)]
optional_store_path_args: OptionalStorePathArgs, optional_store_path_args: OptionalStorePathArg,
}, },
/// Generate a new system-manager profile and /// Generate a new system-manager profile and
/// register is as the active system-manager profile /// register is as the active system-manager profile
Generate { Generate {
#[command(flatten)] #[command(flatten)]
generate_args: GenerateArgs, store_or_flake_args: StoreOrFlakeArgs,
}, },
/// Generate a new system-manager profile and activate it /// Generate a new system-manager profile and activate it
Switch { Switch {
@ -127,21 +142,25 @@ fn go(args: Args) -> Result<()> {
activate(&store_path, ephemeral, &target_host, use_remote_sudo) activate(&store_path, ephemeral, &target_host, use_remote_sudo)
} }
Action::PrePopulate { Action::PrePopulate {
optional_store_path_args: OptionalStorePathArgs { maybe_store_path }, store_or_flake_args,
activation_args: ActivationArgs { ephemeral }, activation_args: ActivationArgs { ephemeral },
} => { } => prepopulate(
let store_path = store_path_or_active_profile(maybe_store_path).try_into()?; store_or_flake_args,
copy_closure(&store_path, &target_host)?; ephemeral,
prepopulate(&store_path, ephemeral, &target_host, use_remote_sudo) &target_host,
} use_remote_sudo,
)
.and_then(print_store_path),
Action::Build { Action::Build {
build_args: BuildArgs { flake_uri }, build_args: BuildArgs { flake_uri },
} => build(&flake_uri, &target_host).and_then(print_store_path), } => build(&flake_uri, &target_host).and_then(print_store_path),
Action::Deactivate { Action::Deactivate {
optional_store_path_args: OptionalStorePathArgs { maybe_store_path }, optional_store_path_args: OptionalStorePathArg { maybe_store_path },
} => deactivate(maybe_store_path, &target_host, use_remote_sudo), } => deactivate(maybe_store_path, &target_host, use_remote_sudo),
Action::Generate { generate_args } => { Action::Generate {
generate(&generate_args, &target_host, use_remote_sudo).and_then(print_store_path) store_or_flake_args,
} => {
generate(store_or_flake_args, &target_host, use_remote_sudo).and_then(print_store_path)
} }
Action::Switch { Action::Switch {
build_args: BuildArgs { flake_uri }, build_args: BuildArgs { flake_uri },
@ -171,28 +190,40 @@ fn do_build(flake_uri: &str) -> Result<StorePath> {
system_manager::generate::build(flake_uri) system_manager::generate::build(flake_uri)
} }
fn generate<'a>( fn generate(
args: &'a GenerateArgs, args: StoreOrFlakeArgs,
target_host: &Option<String>, target_host: &Option<String>,
use_remote_sudo: bool, use_remote_sudo: bool,
) -> Result<Cow<'a, StorePath>> { ) -> Result<StorePath> {
match args { match args {
GenerateArgs { StoreOrFlakeArgs {
flake_uri: Some(flake_uri), optional_store_path_arg:
store_path: None, OptionalStorePathArg {
maybe_store_path: None,
},
optional_flake_uri_arg:
OptionalFlakeUriArg {
maybe_flake_uri: Some(flake_uri),
},
} => { } => {
let store_path = do_build(flake_uri)?; let store_path = do_build(&flake_uri)?;
copy_closure(&store_path, target_host)?; copy_closure(&store_path, target_host)?;
do_generate(&store_path, target_host, use_remote_sudo)?; do_generate(&store_path, target_host, use_remote_sudo)?;
Ok(store_path.into()) Ok(store_path)
} }
GenerateArgs { StoreOrFlakeArgs {
flake_uri: None, optional_store_path_arg:
store_path: Some(store_path), OptionalStorePathArg {
maybe_store_path: Some(store_path),
},
optional_flake_uri_arg:
OptionalFlakeUriArg {
maybe_flake_uri: None,
},
} => { } => {
copy_closure(store_path, target_host)?; copy_closure(&store_path, target_host)?;
do_generate(store_path, target_host, use_remote_sudo)?; do_generate(&store_path, target_host, use_remote_sudo)?;
Ok(store_path.into()) Ok(store_path)
} }
_ => { _ => {
anyhow::bail!("Supply either a flake URI or a store path.") anyhow::bail!("Supply either a flake URI or a store path.")
@ -249,6 +280,49 @@ fn activate(
} }
fn prepopulate( fn prepopulate(
args: StoreOrFlakeArgs,
ephemeral: bool,
target_host: &Option<String>,
use_remote_sudo: bool,
) -> Result<StorePath> {
match args {
StoreOrFlakeArgs {
optional_store_path_arg:
OptionalStorePathArg {
maybe_store_path: None,
},
optional_flake_uri_arg:
OptionalFlakeUriArg {
maybe_flake_uri: Some(flake_uri),
},
} => {
let store_path = do_build(&flake_uri)?;
copy_closure(&store_path, target_host)?;
do_generate(&store_path, target_host, use_remote_sudo)?;
do_prepopulate(&store_path, ephemeral, target_host, use_remote_sudo)?;
Ok(store_path)
}
StoreOrFlakeArgs {
optional_store_path_arg: OptionalStorePathArg { maybe_store_path },
optional_flake_uri_arg:
OptionalFlakeUriArg {
maybe_flake_uri: None,
},
} => {
let store_path = StorePath::try_from(store_path_or_active_profile(maybe_store_path))?;
copy_closure(&store_path, target_host)?;
//TODO: this currently fails in the VM test, need to figure out why
//do_generate(&store_path, target_host, use_remote_sudo)?;
do_prepopulate(&store_path, ephemeral, target_host, use_remote_sudo)?;
Ok(store_path)
}
_ => {
anyhow::bail!("Supply either a flake URI or a store path.")
}
}
}
fn do_prepopulate(
store_path: &StorePath, store_path: &StorePath,
ephemeral: bool, ephemeral: bool,
target_host: &Option<String>, target_host: &Option<String>,