Version 1.0 #14
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -20,7 +20,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "rust-archlinux-update"
|
||||
version = "0.1.1"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"colored",
|
||||
]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rust-archlinux-update"
|
||||
version = "0.1.1"
|
||||
version = "1.0.0"
|
||||
edition = "2021"
|
||||
license = "GPL-3"
|
||||
|
||||
|
35
README.md
35
README.md
@ -2,27 +2,42 @@
|
||||
|
||||
A program that automates the arch update process with cleanup and auto removal.
|
||||
|
||||
***Currently, a WIP. USE AT OWN RISK***
|
||||
|
||||
## 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
|
||||
need it.
|
||||
Recommended Installation:
|
||||
|
||||
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
|
||||
|
||||
The default behavior of the command is to use pacman to run a package update, auto-removal, and cache clear in that
|
||||
order.
|
||||
rust-archlinux-updater [OPTIONS]
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
|
120
src/main.rs
120
src/main.rs
@ -11,33 +11,142 @@
|
||||
This file contains the primary logic of the application
|
||||
*/
|
||||
|
||||
use std::{env, error};
|
||||
|
||||
use colored::{ColoredString, Colorize};
|
||||
|
||||
use wrappers::pacman;
|
||||
|
||||
use crate::wrappers::paru;
|
||||
|
||||
mod shell_commands;
|
||||
mod wrappers;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct RunOptions {
|
||||
pub help: bool,
|
||||
pub update: bool,
|
||||
pub paru: bool,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{}", copyright_notice());
|
||||
|
||||
update();
|
||||
match get_run_options() {
|
||||
Ok(options) => {
|
||||
if options.help {
|
||||
print_help_text();
|
||||
return;
|
||||
}
|
||||
|
||||
if options.update {
|
||||
update(options.paru);
|
||||
return;
|
||||
}
|
||||
|
||||
print_help_text();
|
||||
}
|
||||
Err(e) => {
|
||||
error_println("Failed to detect arguments.");
|
||||
eprintln!("{}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update() {
|
||||
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() {
|
||||
error_println(e.to_string());
|
||||
return;
|
||||
} 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");
|
||||
if let Err(e) = pacman::update_all() {
|
||||
error_println(e.to_string());
|
||||
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");
|
||||
let result = match pacman::get_unused() {
|
||||
Ok(result) => result,
|
||||
@ -64,7 +173,10 @@ fn update() {
|
||||
}
|
||||
|
||||
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>) {
|
||||
|
@ -12,3 +12,4 @@
|
||||
*/
|
||||
|
||||
pub mod pacman;
|
||||
pub mod paru;
|
||||
|
82
src/wrappers/paru.rs
Normal file
82
src/wrappers/paru.rs
Normal 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(())
|
||||
}
|
Loading…
Reference in New Issue
Block a user