Skip to content

Commit 94e5998

Browse files
committed
Fix self updating on unix-like systems, clippy warns
Also updated the readme. Hopefully I don't forget to update it for months like all my other abandoned projects.
1 parent 3a4d0ad commit 94e5998

File tree

4 files changed

+87
-47
lines changed

4 files changed

+87
-47
lines changed

README.md

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
`qud` is a command-line tool that **automatically detects and updates** various package managers across Linux, Windows,
44
macOS, and more.
55

6-
> **Latest Version:** **v1.5.0**
6+
> **Latest Version:** **v1.5.1**
77
88
## Table of Contents
99

@@ -33,7 +33,7 @@ macOS, and more.
3333

3434
**Linux:** `pacman`, `yay`, `apt`, `apt-get`, `dnf`, `zypper`, `snap`, `flatpak`, `xbps-install`, `apk`, `emerge`,
3535
`guix`, `nix`, `yum`, `eopkg`, `cave`, `sbopkg`, `scratch`
36-
**Windows:** `choco`, `scoop`, `winget`
36+
**Windows:** `choco`, `scoop`, `winget`, `Windows`
3737
**General/Other:** `rustup`, `brew`, `port`, `pkg`, `cargo`, `npm`, `pip`, `composer`, `gem`, `conda`, `poetry`,
3838
`nuget`, `asdf`, `vcpkg`, `conan`, `stack`, `opam`, `mix`, `sdkman`, `gvm`, `pnpm`, `yarn`, `maven`, `go`
3939

@@ -59,7 +59,7 @@ sudo pacman -U qud-<version>-x86_64.pkg.tar.zst
5959
#### Debian-based:
6060

6161
```bash
62-
sudo apt install ./qud_v1.5.0_amd64.deb
62+
sudo apt install ./qud_v1.5.1_amd64.deb
6363
```
6464

6565
## Usage
@@ -78,19 +78,21 @@ It will:
7878

7979
## Command-Line Options
8080

81-
| Option | Alias | Description |
82-
|---------------|-------|--------------------------------------------------------------------------------|
83-
| `--dry` | `-d` | Print update commands without executing. |
84-
| `--excl <s>` | `-e` | Exclude a package (`pm::pkg`) or a package manager (`pm`). Repeatable. |
85-
| `--auto` | `-a` | Run updates in non-interactive mode. |
86-
| `--verbose` | `-v` | Enable detailed logging. |
87-
| `--list` | `-l` | List detected package managers without updating. |
88-
| `--only <pm>` | `-o` | Update only the specified package manager(s). Repeatable. |
89-
| `--spec <s>` | `-s` | Override package manager executable (`pm::/path/to/executable`). |
90-
| `--ext <s>` | `-E` | Add extra flags (`pm::"<flags>"`). |
91-
| `--ord [s]` | `-O` | Set update order (e.g., `pm1,pm2,pm3`). Interactive mode if no value provided. |
92-
| `--help` | `-h` | Display help. |
93-
| `--version` | `-V` | Show version. |
81+
| Option | Alias | Description |
82+
|-----------------|-------|-------------------------------------------------------------------------------------------|
83+
| `--dry` | `-d` | Print update commands without executing. |
84+
| `--excl <s>` | `-e` | Exclude a package (`pm::pkg`) or a package manager (`pm`). Repeatable. |
85+
| `--auto` | `-a` | Run updates in non-interactive mode. |
86+
| `--verbose` | `-v` | Enable detailed logging. |
87+
| `--list` | `-l` | List detected package managers without updating. |
88+
| `--only <pm>` | `-o` | Update only the specified package manager(s). Repeatable. |
89+
| `--spec <s>` | `-s` | Override package manager executable (`pm::/path/to/executable`). |
90+
| `--ext <s>` | `-E` | Add extra flags (`pm::"<flags>"`). |
91+
| `--ord [s]` | `-O` | Set update order (e.g., `pm1,pm2,pm3`). Interactive mode if no value provided. |
92+
| `--help` | `-h` | Display help. |
93+
| `--version` | `-V` | Show version. |
94+
| `--self-update` | `-S` | Update qud itself. |
95+
| `--noconfirm` | `-n` | Do not confirm before updating. Does not stop package managers from prompting, only qud. |
9496

9597
## Examples
9698

@@ -174,7 +176,7 @@ Submit issues or pull requests on [GitHub](https://github.com/barely-a-dev/qud).
174176

175177
## Version
176178

177-
**v1.5.0**
179+
**v1.5.1**
178180

179181
For assistance, visit [GitHub](https://github.com/barely-a-dev/qud). Happy updating!
180182

src/conf.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,9 @@ impl Config {
4949
std::process::exit(0);
5050
}
5151
if pargs.contains(["-V", "--version"]) {
52-
println!("qud v1.5.0");
52+
println!("qud v1.5.1");
5353
std::process::exit(0);
5454
}
55-
if pargs.contains(["-S", "--self-update"]) {
56-
if !self_up::perm::is_elevated() {
57-
eprintln!("Program must be run as root to update.");
58-
std::process::exit(2);
59-
}
60-
println!("Updating qud...");
61-
match self_up::self_update() {
62-
Ok(()) => println!("qud updated successfully, exiting."),
63-
Err(e) => eprintln!("qud failed to update: {e}, exiting."),
64-
}
65-
std::process::exit(-1);
66-
}
6755

6856
let dry_run = pargs.contains(["-d", "--dry"]);
6957
let excl_values: Vec<String> = pargs
@@ -75,6 +63,18 @@ impl Config {
7563
}
7664
let auto = pargs.contains(["-a", "--auto"]);
7765
let noconfirm = pargs.contains(["-n", "--noconfirm"]);
66+
if pargs.contains(["-S", "--self-update"]) {
67+
if !self_up::perm::is_elevated() {
68+
eprintln!("Program must be run as root to update.");
69+
std::process::exit(2);
70+
}
71+
println!("Updating qud...");
72+
match self_up::self_update(noconfirm) {
73+
Ok(()) => println!("qud updated successfully, exiting."),
74+
Err(e) => eprintln!("qud failed to update: {e}, exiting."),
75+
}
76+
std::process::exit(-1);
77+
}
7878
let verbose = pargs.contains(["-v", "--verbose"]);
7979
let list = pargs.contains(["-l", "--list"]);
8080
let only_values: Vec<String> = pargs
@@ -164,7 +164,7 @@ impl Config {
164164

165165
fn print_help() {
166166
println!(
167-
r#"qud v1.5.0
167+
r#"qud v1.5.1
168168
169169
Usage:
170170
qud [options]

src/main.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ fn main() {
8282
.map(PathBuf::from)
8383
{
8484
if let Some(pm_name) = candidate.file_name().and_then(|s| s.to_str()) {
85-
if let Some(_) = seen.get(pm_name) {
86-
duplicates.entry(pm_name.to_string()).or_insert_with(Vec::new).push(candidate.clone());
85+
if seen.contains_key(pm_name) {
86+
duplicates.entry(pm_name.to_string()).or_default().push(candidate.clone());
8787
} else {
8888
seen.insert(pm_name.to_string(), candidate.clone());
8989
candidates.push(candidate);
@@ -638,7 +638,12 @@ fn process_pm(pm_name: &str, auto: bool, current_dir: &Path, extra_args: &[Strin
638638
upd("scratch", args, true, extra_args, dry_run);
639639
}
640640
"qud" => {
641-
upd("qud", &["--self-update"], true, extra_args, dry_run);
641+
let args: &[&str] = if auto {
642+
&["--self-update", "--noconfirm"]
643+
} else {
644+
&["--self-update"]
645+
};
646+
upd("qud", args, true, extra_args, dry_run);
642647
}
643648
_ => eprintln!(
644649
"{} Unknown package manager: {}",

src/self_up.rs

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
1-
use std::{
2-
error::Error,
3-
fs,
4-
path::PathBuf,
5-
process::Command,
6-
};
7-
8-
pub fn self_update() -> Result<(), Box<dyn Error>> {
1+
use std::io::Write;
2+
use std::{error::Error, fs, path::PathBuf, process::Command};
3+
4+
pub fn self_update(noconfirm: bool) -> Result<(), Box<dyn Error>> {
95
let repo_url = "https://github.com/barely-a-dev/qud.git";
106

7+
if !noconfirm {
8+
println!("Are you sure you want to update qud v1.5.1? (Y/n)");
9+
std::io::stdout().flush().unwrap();
10+
let mut confirm = String::new();
11+
std::io::stdin()
12+
.read_line(&mut confirm)
13+
.expect("Failed to read line");
14+
let confirm = confirm.trim().to_lowercase();
15+
if confirm == "n" || confirm == "no" {
16+
println!("Update cancelled by user.");
17+
std::process::exit(0);
18+
}
19+
}
20+
1121
let temp_dir = std::env::temp_dir().join("qud_temp");
1222
if temp_dir.exists() {
1323
fs::remove_dir_all(&temp_dir)?;
@@ -51,6 +61,7 @@ pub fn self_update() -> Result<(), Box<dyn Error>> {
5161
fs::set_permissions(&binary_path, perms)?;
5262
}
5363

64+
// Define the installation path.
5465
#[cfg(not(target_family = "windows"))]
5566
let install_path = PathBuf::from("/usr/bin/qud");
5667

@@ -61,13 +72,35 @@ pub fn self_update() -> Result<(), Box<dyn Error>> {
6172
target_dir.join("qud.exe")
6273
};
6374

64-
println!(
65-
"Copying built binary from {binary_path:?} to {install_path:?}",
66-
);
67-
fs::copy(&binary_path, &install_path)?;
75+
#[cfg(not(target_family = "windows"))]
76+
{
77+
let temp_install_path = install_path.with_extension("new");
78+
println!(
79+
"Copying built binary from {binary_path:?} to temporary location {temp_install_path:?}"
80+
);
81+
fs::copy(&binary_path, &temp_install_path)?;
82+
83+
println!("Spawning updater process to replace the binary after exit.");
84+
Command::new("sh")
85+
.arg("-c")
86+
.arg(format!(
87+
"sleep 10 && mv {} {}",
88+
temp_install_path.display(),
89+
install_path.display()
90+
))
91+
.spawn()?;
92+
93+
println!("Self-update scheduled.");
94+
}
6895

69-
println!("Self-update successful!");
96+
#[cfg(target_family = "windows")]
97+
{
98+
println!("Copying built binary from {binary_path:?} to {install_path:?}");
99+
fs::copy(&binary_path, &install_path)?;
100+
println!("Self-update successful!");
101+
}
70102

103+
// Clean up temporary directory.
71104
fs::remove_dir_all(&temp_dir)?;
72105

73106
Ok(())

0 commit comments

Comments
 (0)