diff --git a/src/main.rs b/src/main.rs
index 6638b1e..0397493 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -13,7 +13,12 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-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 {
+ 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())
+}