feat: export subcommand
This commit is contained in:
+96
-2
@@ -13,7 +13,12 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
io::Write,
|
||||
path::PathBuf,
|
||||
process::{Command, Stdio},
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
use clap_derive::{Parser, Subcommand};
|
||||
@@ -35,6 +40,8 @@ compile_error!("'yay' and 'paru' are mutually exclusive and cannot be enabled to
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
compile_error!("Only (Arch) linux is supported!");
|
||||
|
||||
const PRIVLAGE_ESCELATE_COMMAND: &str = "sudo";
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Args {
|
||||
#[arg(long, global = true)]
|
||||
@@ -68,6 +75,10 @@ enum Commands {
|
||||
#[arg(short, long)]
|
||||
/// When specified, the new world file content will be writen to stdout
|
||||
stdout: bool,
|
||||
|
||||
#[arg(short, long)]
|
||||
/// When given will transfer ignore values to the new world file
|
||||
persist_ignore: bool,
|
||||
},
|
||||
/// Writes diffrents between the world file and the system
|
||||
Diff,
|
||||
@@ -89,7 +100,77 @@ fn main() -> Result<()> {
|
||||
|
||||
match args.command {
|
||||
Commands::Sync => todo!(),
|
||||
Commands::Export { overwrite, stdout } => todo!(),
|
||||
Commands::Export {
|
||||
overwrite,
|
||||
stdout,
|
||||
persist_ignore,
|
||||
} => {
|
||||
let mut world = match World::load_from(world_path.clone()) {
|
||||
Ok(x) => x,
|
||||
Err(_) => World::new_empty(),
|
||||
};
|
||||
|
||||
let mut state = get_system_state()?;
|
||||
|
||||
if persist_ignore {
|
||||
state.ignore = world.get_packages().ignore.clone();
|
||||
}
|
||||
|
||||
let world_state = world.get_mut_packages();
|
||||
|
||||
*world_state = state;
|
||||
|
||||
let text_world = toml::to_string_pretty(&world)?;
|
||||
|
||||
if stdout {
|
||||
println!("{}", &text_world);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if !overwrite && root_file_exists(world_path.as_os_str())? {
|
||||
eprintln!("File Already exists!");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(parent_path) = world_path.parent() {
|
||||
let status = Command::new(PRIVLAGE_ESCELATE_COMMAND)
|
||||
.arg("mkdir")
|
||||
.arg("-p")
|
||||
.arg(parent_path)
|
||||
.stdin(Stdio::inherit())
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.status()?;
|
||||
|
||||
if !status.success() {
|
||||
return Err("Making directories for the world file went unsuccessful!".into());
|
||||
}
|
||||
}
|
||||
|
||||
let mut child = Command::new(PRIVLAGE_ESCELATE_COMMAND)
|
||||
.arg("tee")
|
||||
.arg(world_path)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::inherit())
|
||||
.spawn()?;
|
||||
|
||||
let c_stdin = child.stdin.as_mut();
|
||||
if c_stdin.is_none() {
|
||||
return Err("Unabled to pass data to file!".into());
|
||||
}
|
||||
c_stdin.unwrap().write_all(text_world.as_bytes())?;
|
||||
|
||||
let status = child.wait()?;
|
||||
|
||||
if !status.success() {
|
||||
return Err("Couldn't write to a file!".into());
|
||||
}
|
||||
|
||||
if !args.quiet {
|
||||
println!("State succesfully saved in the world file!");
|
||||
}
|
||||
}
|
||||
Commands::Diff => {
|
||||
let world = World::load_from(world_path).unwrap_or(World::new_empty());
|
||||
let world_state = world.get_packages();
|
||||
@@ -156,3 +237,16 @@ fn main() -> Result<()> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn root_file_exists(path: &OsStr) -> std::io::Result<bool> {
|
||||
let status = Command::new(PRIVLAGE_ESCELATE_COMMAND)
|
||||
.arg("test")
|
||||
.arg("-e")
|
||||
.arg(path)
|
||||
.stdin(Stdio::inherit())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.status()?;
|
||||
|
||||
Ok(status.success())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user