use crate::command_runner::CommandRunner; use crate::symbols::Symbol; use async_trait::async_trait; use std::borrow::Borrow; use std::error::Error; use std::fs; use std::marker::PhantomData; use std::os::unix::fs::MetadataExt; use std::path::Path; use users::get_user_by_name; #[derive(Debug)] pub struct Owner<_C, C, P, U> { path: P, user_name: U, command_runner: C, phantom: PhantomData<_C>, } impl<_C, C, P, U> Owner<_C, C, P, U> { pub fn new(path: P, user_name: U, command_runner: C) -> Self { Self { path, user_name, command_runner, phantom: PhantomData::default(), } } } #[async_trait(?Send)] impl<_C: CommandRunner, C: Borrow<_C>, P: AsRef, U: AsRef> Symbol for Owner<_C, C, P, U> { async fn target_reached(&self) -> Result> { if !self.path.as_ref().exists() { return Ok(false); } let actual_uid = fs::metadata(self.path.as_ref()).unwrap().uid(); let target_uid = get_user_by_name(self.user_name.as_ref()).unwrap().uid(); Ok(actual_uid == target_uid) } async fn execute(&self) -> Result<(), Box> { self .command_runner .borrow() .run_successfully( "chown", args!["-R", self.user_name.as_ref(), self.path.as_ref()], ) .await } }