diff --git a/src/fs.rs b/src/fs.rs new file mode 100644 index 0000000..1a76961 --- /dev/null +++ b/src/fs.rs @@ -0,0 +1,11 @@ +use std::{fs::read_link, path::PathBuf}; + +pub fn resolve_link(path: &PathBuf) -> PathBuf { + let mut location = path.clone(); + while let Ok(next) = read_link(&location) { + let base_path = location.parent().unwrap(); + let next_path = base_path.join(next); + location = next_path; + } + location +} diff --git a/src/gather.rs b/src/gather.rs index 04fb0ea..111506c 100644 --- a/src/gather.rs +++ b/src/gather.rs @@ -3,7 +3,7 @@ use std::{ path::{Path, PathBuf}, }; -use crate::{Session, User}; +use crate::{fs::resolve_link, Session, User}; #[derive(Debug)] struct PasswdUser { @@ -52,22 +52,11 @@ pub fn gather_sessions(user: &User) -> Vec { true => gather_hm_sessions(&hm_profile), false => vec![Session { name: String::from("Shell"), - init: user.shell.to_str().unwrap().to_owned(), + generation: user.shell.to_str().unwrap().to_owned(), }], } } -#[allow(clippy::ptr_arg)] -fn resolve_link(path: &PathBuf) -> PathBuf { - let mut location = path.clone(); - while let Ok(next) = read_link(&location) { - let base_path = location.parent().unwrap(); - let next_path = base_path.join(next); - location = next_path; - } - location -} - fn gather_hm_sessions(path: &PathBuf) -> Vec { let generation = resolve_link(path); let mut sessions = vec![gather_session_data(&generation, &generation)]; @@ -105,12 +94,13 @@ fn gather_session_data(path: &PathBuf, reset_path: &PathBuf) -> Session { let session_path = path.join("session"); let name = read_to_string(session_path.join("name")).unwrap(); - let init = format!( - "sh -c \"{} && {} && {}\"", - path.join("activate").display(), - session_path.join("init").display(), - reset_path.join("activate").display() - ); + // let init = format!( + // "sh -c \"{} && {} && {}\"", + // path.join("activate").display(), + // session_path.join("init").display(), + // reset_path.join("activate").display() + // ); + let generation = path.to_str().unwrap().to_owned(); - Session { name, init } + Session { name, generation } } diff --git a/src/greetd.rs b/src/greetd.rs index 9dd8ec4..782c125 100644 --- a/src/greetd.rs +++ b/src/greetd.rs @@ -30,8 +30,11 @@ pub fn login( return Ok(LoginResult::Success); } else { starting = true; - let cmd = vec![session.init.clone()]; - let env = vec![]; + let cmd = vec![String::from("nixgreety session")]; + let env = vec![format!( + "NIXGREETY_GENERATION={}", + session.generation.clone() + )]; Request::StartSession { cmd, env }.write_to(&mut stream)?; } } diff --git a/src/main.rs b/src/main.rs index 4a59177..cb7d17d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,6 @@ use std::{ env, fmt::Display, io, - os::unix::net::UnixStream, path::PathBuf, time::{Duration, Instant}, }; @@ -18,10 +17,27 @@ use ratatui::{ }; use tui_rain::Rain; +mod fs; mod gather; mod greetd; +mod session; fn main() -> io::Result<()> { + let mut args = env::args(); + let _ = args.next(); + let mode = args.next(); + + match mode { + Some(mode) => match mode.as_str() { + "greeter" => draw_app(), + "session" => session::handle_session(), + _ => panic!("Unrecognized mode: {}", mode), + }, + None => draw_app(), + } +} + +fn draw_app() -> io::Result<()> { let mut terminal = ratatui::init(); let app_result = App::default().run(&mut terminal); ratatui::restore(); @@ -111,7 +127,7 @@ impl Display for User { #[derive(PartialEq, Eq, Clone)] struct Session { name: String, - init: String, + generation: String, } impl Display for Session { @@ -329,7 +345,7 @@ impl App { LoginResult::Success => { self.error = false; self.status = Status::Success; - self.exit_time = Some(Instant::now() + Duration::from_millis(300)); + self.exit_time = Some(Instant::now() + Duration::from_millis(200)); } LoginResult::Failure => { self.error = true; diff --git a/src/session.rs b/src/session.rs new file mode 100644 index 0000000..fb2c024 --- /dev/null +++ b/src/session.rs @@ -0,0 +1,56 @@ +use std::{ + env, + fs::{read_dir, DirEntry}, + io, + path::PathBuf, + process::{Command, Stdio}, +}; + +use crate::fs::resolve_link; + +pub fn handle_session() -> io::Result<()> { + println!(">>> Activating environment <<<"); + let generation = env::var("NIXGREETY_GENERATION").unwrap(); + Command::new(format!("{}/activate", generation)) + .stdout(Stdio::inherit()) + .output() + .expect("Failed to activate environment"); + + println!(">>> Creating session <<<"); + Command::new(format!("{}/session/init", generation)) + .stdout(Stdio::inherit()) + .output() + .expect("Failed to create session"); + + println!(">>> Deactivating environment <<<"); + let home = env::var("HOME").unwrap(); + let profile_path = PathBuf::from(format!("{}/.local/state/nix/profiles/", home)); + let mut generations: Vec = read_dir(profile_path) + .expect("Failed to gather home-manager generations") + .flatten() + .collect(); + generations.sort_by_key(|entry| entry.file_name()); + let generation = generations + .into_iter() + .rev() + .filter(|entry| { + entry + .file_name() + .to_string_lossy() + .starts_with("home-manager-") + }) + .find(|entry| { + let entry_path = entry.path(); + let resolved_path = resolve_link(&entry_path); + let specialisation_path = resolved_path.join("specialisation"); + specialisation_path.exists() + }) + .map(|entry| entry.path()) + .unwrap_or(PathBuf::from("")); + Command::new(format!("{}/activate", generation.display())) + .stdout(Stdio::inherit()) + .output() + .unwrap(); + + Ok(()) +}