Version 1.0 #14

Merged
luke merged 2 commits from development into main 2024-05-08 00:12:22 +00:00
6 changed files with 226 additions and 16 deletions
Showing only changes of commit 05de93b988 - Show all commits

2
Cargo.lock generated
View File

@ -20,7 +20,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "rust-archlinux-update" name = "rust-archlinux-update"
version = "0.1.1" version = "1.0.0"
dependencies = [ dependencies = [
"colored", "colored",
] ]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "rust-archlinux-update" name = "rust-archlinux-update"
version = "0.1.1" version = "1.0.0"
edition = "2021" edition = "2021"
license = "GPL-3" license = "GPL-3"

View File

@ -2,27 +2,42 @@
A program that automates the arch update process with cleanup and auto removal. A program that automates the arch update process with cleanup and auto removal.
***Currently, a WIP. USE AT OWN RISK***
## Setup ## Setup
The current state requires that you build it yourself. The most up-to-date version will be on the development branch. Download the binary from the releases tab. The pre-compiled binary works on x86_64 only.
Just run `cargo build --release` and copy the executable from `./target/release/rust-archlinux-update` to wherever you Recommended Installation:
need it.
Distribution on pre-built binaries, cargo, etc. is in the works. 1. Place the binary in the `~/local/bin` folder
2. Run `chmod +x` on the binary
3. Add `/home/<USER>/local/bin` to your PATH variable
This installation allows it to be run anywhere on your system.
If you need a different target please see the next section on compilation.
## Compilation
It's simple.
Steps:
1. Download the source code. (git clone or release tarball)
2. Ensure that rustup is up-to-date and has the correct toolchain installed and selected.
3. Run `cargo build --release` and find the binary at `./target/release/rust-archlinux-update`
## Usage ## Usage
The default behavior of the command is to use pacman to run a package update, auto-removal, and cache clear in that rust-archlinux-updater [OPTIONS]
order.
In the future the command will support AUR helpers like paru and those will need to be activated with a flag. Options:
-h, --help | Show this help message
-u | preform a regular update
-p | Use paru to update the AUR packages on your system
## Issue Reporting ## Issue Reporting
I don't allow random sign-ups on my gitea instance. Please email me at [luke@lukeh990.io](mailto:luke@lukeh990.io). I don't allow random sign-ups on my gitea instance. Please email me at <luke@lukeh990.io>.
If you have any suggestions for how to better handle issue reporting please email me. If you have any suggestions for how to better handle issue reporting please email me.

View File

@ -11,33 +11,142 @@
This file contains the primary logic of the application This file contains the primary logic of the application
*/ */
use std::{env, error};
use colored::{ColoredString, Colorize}; use colored::{ColoredString, Colorize};
use wrappers::pacman; use wrappers::pacman;
use crate::wrappers::paru;
mod shell_commands; mod shell_commands;
mod wrappers; mod wrappers;
#[derive(Debug, Clone)]
struct RunOptions {
pub help: bool,
pub update: bool,
pub paru: bool,
}
fn main() { fn main() {
println!("{}", copyright_notice()); println!("{}", copyright_notice());
update(); match get_run_options() {
Ok(options) => {
if options.help {
print_help_text();
return;
} }
fn update() { if options.update {
update(options.paru);
return;
}
print_help_text();
}
Err(e) => {
error_println("Failed to detect arguments.");
eprintln!("{}", e);
}
}
}
fn get_run_options() -> Result<RunOptions, Box<dyn error::Error>> {
let mut args = env::args();
// Remove unneeded first entry
if args.next().is_none() {
return Err("No args found".into());
}
let args: Vec<String> = args.collect();
let blank_options = RunOptions {
help: false,
update: false,
paru: false,
};
let mut options = blank_options.clone();
if args.is_empty() {
return Ok(blank_options);
}
for arg in args {
if arg[..2].eq("--") {
let flag = &arg[2..];
if flag.eq("help") {
options.help = true;
} else {
return Ok(blank_options);
}
} else if arg[..1].eq("-") {
let mut selected: Vec<&str> = arg[1..].split("").collect();
selected.retain_mut(|x| !x.is_empty());
for selected_option in selected {
match selected_option {
"h" => options.help = true,
"u" => options.update = true,
"p" => options.paru = true,
_ => return Ok(blank_options),
}
}
} else {
return Ok(blank_options);
}
}
Ok(options)
}
fn print_help_text() {
println!(
"rust-archlinux-updater [OPTIONS]\n\n\
Options:\n\
-h, --help | Show this help message\n\
-u | preform a regular update\n\
-p | Use paru to update the AUR packages on your system"
);
}
fn update(paru: bool) {
if let Err(e) = pacman::check() { if let Err(e) = pacman::check() {
error_println(e.to_string()); error_println(e.to_string());
return; return;
} else { } else {
notice_println("Pacman is installed\n") notice_println("Pacman is installed")
} }
if paru {
if let Err(e) = paru::check() {
error_println(e.to_string());
return;
} else {
notice_println("Paru is installed")
}
}
println!();
notice_println("Running pacman update"); notice_println("Running pacman update");
if let Err(e) = pacman::update_all() { if let Err(e) = pacman::update_all() {
error_println(e.to_string()); error_println(e.to_string());
return; return;
} }
if paru {
notice_println("Updating AUR with paru");
if let Err(e) = paru::update_aur() {
error_println(e.to_string());
return;
}
}
notice_println("Getting orphaned packages"); notice_println("Getting orphaned packages");
let result = match pacman::get_unused() { let result = match pacman::get_unused() {
Ok(result) => result, Ok(result) => result,
@ -64,7 +173,10 @@ fn update() {
} }
fn copyright_notice() -> ColoredString { fn copyright_notice() -> ColoredString {
"Rust Arch Linux Updater Copyright (C) 2024 Luke Harding <luke@lukeh990.io>\nThis program comes with ABSOLUTELY NO WARRANTY\nThis is free software, and you are welcome to redistribute it under certain conditions\n".italic() "Rust Arch Linux Updater Copyright (C) 2024 Luke Harding <luke@lukeh990.io>\
\nThis program comes with ABSOLUTELY NO WARRANTY\
\nThis is free software, and you are welcome to redistribute it under certain conditions\n"
.italic()
} }
pub fn error_println(msg: impl Into<String>) { pub fn error_println(msg: impl Into<String>) {

View File

@ -12,3 +12,4 @@
*/ */
pub mod pacman; pub mod pacman;
pub mod paru;

82
src/wrappers/paru.rs Normal file
View File

@ -0,0 +1,82 @@
/*
Rust Arch Linux Updater
Copyright (C) 2024 Luke Harding <luke@lukeh990.io>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/*
wrappers/paru.rs
This module provides a wrapper to make working with paru much easier.
*/
use std::{error, fmt, result};
use std::fmt::Formatter;
use std::path::Path;
use std::process::ExitStatus;
use crate::shell_commands;
type Result<T> = result::Result<T, Box<dyn error::Error>>;
#[derive(Debug, Clone)]
enum ParuError {
NotInstalled,
ExitCode(i32),
Other(&'static str),
}
impl fmt::Display for ParuError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let out = match self {
ParuError::NotInstalled => "Paru not installed.".to_string(),
ParuError::ExitCode(code) => format!("Paru exited with an exit code: {}", code),
ParuError::Other(msg) => msg.to_string(),
};
write!(f, "ParuError: {}", out)
}
}
impl error::Error for ParuError {}
pub fn check() -> Result<()> {
let out = shell_commands::execute_quiet("which", ["paru"])?;
let path = if out.status.success() {
let mut stdout = out.stdout;
stdout.pop(); // Remove \n from stdout
String::from_utf8(stdout)?
} else {
String::from("/usr/bin/paru")
};
let path = Path::new(&path);
if !path.exists() {
return Err(ParuError::NotInstalled.into());
}
Ok(())
}
pub fn update_aur() -> Result<()> {
let exit_status = shell_commands::execute_in_sh("paru -Sua")?;
check_exit_code(exit_status)
}
fn check_exit_code(exit_status: ExitStatus) -> Result<()> {
if !exit_status.success() {
let exit_code = match exit_status.code() {
Some(exit_code) => exit_code,
None => return Err(ParuError::Other("No Exit Code Found").into()),
};
return Err(ParuError::ExitCode(exit_code).into());
}
Ok(())
}