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
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// 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::Parser;
|
||||||
use clap_derive::{Parser, Subcommand};
|
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"))]
|
#[cfg(not(target_os = "linux"))]
|
||||||
compile_error!("Only (Arch) linux is supported!");
|
compile_error!("Only (Arch) linux is supported!");
|
||||||
|
|
||||||
|
const PRIVLAGE_ESCELATE_COMMAND: &str = "sudo";
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
struct Args {
|
struct Args {
|
||||||
#[arg(long, global = true)]
|
#[arg(long, global = true)]
|
||||||
@@ -68,6 +75,10 @@ enum Commands {
|
|||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
/// When specified, the new world file content will be writen to stdout
|
/// When specified, the new world file content will be writen to stdout
|
||||||
stdout: bool,
|
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
|
/// Writes diffrents between the world file and the system
|
||||||
Diff,
|
Diff,
|
||||||
@@ -89,7 +100,77 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
match args.command {
|
match args.command {
|
||||||
Commands::Sync => todo!(),
|
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 => {
|
Commands::Diff => {
|
||||||
let world = World::load_from(world_path).unwrap_or(World::new_empty());
|
let world = World::load_from(world_path).unwrap_or(World::new_empty());
|
||||||
let world_state = world.get_packages();
|
let world_state = world.get_packages();
|
||||||
@@ -156,3 +237,16 @@ fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
Ok(())
|
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