diff --git a/src/completion.rs b/src/completion.rs index 486c143..263c54e 100644 --- a/src/completion.rs +++ b/src/completion.rs @@ -8,7 +8,7 @@ use crate::*; impl interface::CompletionArgs { #[instrument(ret, level = "trace")] pub fn run(&self) -> Result<()> { - let mut cmd = <Main as clap::CommandFactory>::command(); + let mut cmd = <Main<Installable2ContextOs> as clap::CommandFactory>::command(); generate(self.shell, &mut cmd, "nh", &mut std::io::stdout()); Ok(()) } diff --git a/src/installable.rs b/src/installable.rs index 307585b..71d7079 100644 --- a/src/installable.rs +++ b/src/installable.rs @@ -1,3 +1,4 @@ +use std::marker::PhantomData; use std::path::PathBuf; use std::{env, fs}; @@ -252,3 +253,66 @@ fn test_join_attribute() { assert_eq!(join_attribute(vec!["foo", "bar"]), "foo.bar"); assert_eq!(join_attribute(vec!["foo", "bar.baz"]), r#"foo."bar.baz""#); } + +#[derive(Debug)] +pub struct Installable2<C: Installable2Context> { + pub data: Installable2Data, + _marker: PhantomData<C>, +} + +#[derive(Debug)] +pub enum Installable2Data { + Flake, + File, +} + +pub trait Installable2Context { + fn context() -> Installable2ContextValue; +} + +pub enum Installable2ContextValue { + Home, + Os, +} + +pub struct Installable2ContextHome; +impl Installable2Context for Installable2ContextHome { + fn context() -> Installable2ContextValue { + Installable2ContextValue::Home + } +} + +#[derive(Debug)] +pub struct Installable2ContextOs; +impl Installable2Context for Installable2ContextOs { + fn context() -> Installable2ContextValue { + Installable2ContextValue::Os + } +} + +impl<C: Installable2Context> FromArgMatches for Installable2<C> { + fn from_arg_matches(matches: &clap::ArgMatches) -> Result<Self, clap::Error> { + let mut matches = matches.clone(); + Self::from_arg_matches_mut(&mut matches) + } + + fn from_arg_matches_mut(matches: &mut clap::ArgMatches) -> Result<Self, clap::Error> { + todo!(); + } + + fn update_from_arg_matches(&mut self, matches: &clap::ArgMatches) -> Result<(), clap::Error> { + todo!() + } +} + +impl<C: Installable2Context> Args for Installable2<C> { + fn augment_args(cmd: clap::Command) -> clap::Command { + let context = C::context(); + + cmd.arg(Arg::new("installable")) + } + + fn augment_args_for_update(cmd: clap::Command) -> clap::Command { + Self::augment_args(cmd) + } +} diff --git a/src/interface.rs b/src/interface.rs index e9a3dc6..bde91cf 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -4,7 +4,7 @@ use anstyle::Style; use clap::ValueEnum; use clap::{builder::Styles, Args, Parser, Subcommand}; -use crate::installable::Installable; +use crate::installable::{Installable, Installable2, Installable2Context}; use crate::Result; fn make_style() -> Styles { @@ -31,19 +31,19 @@ fn make_style() -> Styles { " )] /// Yet another nix helper -pub struct Main { +pub struct Main<C: Installable2Context> { #[arg(short, long, global = true)] /// Show debug logs pub verbose: bool, #[command(subcommand)] - pub command: NHCommand, + pub command: NHCommand<C>, } #[derive(Subcommand, Debug)] #[command(disable_help_subcommand = true)] -pub enum NHCommand { - Os(OsArgs), +pub enum NHCommand<C: Installable2Context> { + Os(OsArgs<C>), Home(HomeArgs), Darwin(DarwinArgs), Search(SearchArgs), @@ -52,7 +52,7 @@ pub enum NHCommand { Completions(CompletionArgs), } -impl NHCommand { +impl<C: Installable2Context> NHCommand<C> { pub fn run(self) -> Result<()> { match self { NHCommand::Os(args) => args.run(), @@ -70,13 +70,13 @@ impl NHCommand { /// NixOS functionality /// /// Implements functionality mostly around but not exclusive to nixos-rebuild -pub struct OsArgs { +pub struct OsArgs<C: Installable2Context> { #[command(subcommand)] - pub subcommand: OsSubcommand, + pub subcommand: OsSubcommand<C>, } #[derive(Debug, Subcommand)] -pub enum OsSubcommand { +pub enum OsSubcommand<C: Installable2Context> { /// Build and activate the new configuration, and make it the boot default Switch(OsRebuildArgs), @@ -90,7 +90,7 @@ pub enum OsSubcommand { Build(OsRebuildArgs), /// Load system in a repl - Repl(OsReplArgs), + Repl(OsReplArgs<C>), } #[derive(Debug, Args)] @@ -142,9 +142,9 @@ pub struct CommonRebuildArgs { } #[derive(Debug, Args)] -pub struct OsReplArgs { +pub struct OsReplArgs<C: Installable2Context> { #[command(flatten)] - pub installable: Installable, + pub installable: Installable2<C>, /// When using a flake installable, select this hostname from nixosConfigurations #[arg(long, short = 'H', global = true)] diff --git a/src/main.rs b/src/main.rs index 93368d9..61c2406 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,8 @@ mod util; use color_eyre::Result; use tracing::debug; +use crate::installable::Installable2ContextOs; + const NH_VERSION: &str = env!("CARGO_PKG_VERSION"); fn main() -> Result<()> { @@ -25,7 +27,7 @@ fn main() -> Result<()> { } } - let args = <crate::interface::Main as clap::Parser>::parse(); + let args = <crate::interface::Main<Installable2ContextOs> as clap::Parser>::parse(); crate::logging::setup_logging(args.verbose)?; tracing::debug!("{args:#?}"); tracing::debug!(%NH_VERSION); diff --git a/src/nixos.rs b/src/nixos.rs index 21df571..30e3c62 100644 --- a/src/nixos.rs +++ b/src/nixos.rs @@ -4,7 +4,7 @@ use tracing::{debug, info, warn}; use crate::commands; use crate::commands::Command; -use crate::installable::Installable; +use crate::installable::{Installable, Installable2Context}; use crate::interface::OsSubcommand::{self}; use crate::interface::{self, OsRebuildArgs, OsReplArgs}; @@ -13,7 +13,7 @@ const CURRENT_PROFILE: &str = "/run/current-system"; const SPEC_LOCATION: &str = "/etc/specialisation"; -impl interface::OsArgs { +impl<C: Installable2Context> interface::OsArgs<C> { pub fn run(self) -> Result<()> { use OsRebuildVariant::*; match self.subcommand { @@ -190,32 +190,9 @@ pub fn toplevel_for<S: AsRef<str>>(hostname: S, installable: Installable) -> Ins res } -impl OsReplArgs { +impl<C: Installable2Context> OsReplArgs<C> { fn run(self) -> Result<()> { - let mut target_installable = self.installable; - - if matches!(target_installable, Installable::Store { .. }) { - bail!("Nix doesn't support nix store installables."); - } - - let hostname = self - .hostname - .unwrap_or_else(|| hostname::get().unwrap().to_str().unwrap().to_string()); - - if let Installable::Flake { - ref mut attribute, .. - } = target_installable - { - if attribute.is_empty() { - attribute.push(String::from("nixosConfigurations")); - attribute.push(hostname); - } - } - - Command::new("nix") - .arg("repl") - .args(target_installable.to_args()) - .run()?; + todo!(); Ok(()) }