Skip to content

Commit 9aa74fc

Browse files
committed
feat: make CLI flags compatible with upstream appimageupdate
1 parent e016597 commit 9aa74fc

File tree

5 files changed

+114
-114
lines changed

5 files changed

+114
-114
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main.rs

Lines changed: 84 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,35 @@
11
use std::path::PathBuf;
22

33
use clap::Parser;
4-
use clap::Subcommand;
54

65
use appimageupdate::config;
76
use appimageupdate::{Error, Updater};
87

98
#[derive(Parser)]
109
#[command(name = "appimageupdate")]
11-
#[command(about = "Update AppImages using delta updates", long_about = None)]
10+
#[command(about = "AppImage companion tool taking care of updates for the commandline.", long_about = None)]
1211
#[command(version)]
1312
struct Cli {
14-
#[command(subcommand)]
15-
command: Commands,
16-
}
13+
#[arg(value_name = "APPIMAGE")]
14+
path: Option<PathBuf>,
1715

18-
#[derive(Subcommand)]
19-
enum Commands {
20-
Update {
21-
#[arg(value_name = "APPIMAGE")]
22-
path: PathBuf,
16+
#[arg(short = 'O', long)]
17+
overwrite: bool,
2318

24-
#[arg(short, long)]
25-
overwrite: bool,
19+
#[arg(short = 'r', long)]
20+
remove_old: bool,
2621

27-
#[arg(short, long, value_name = "DIR")]
28-
output: Option<PathBuf>,
22+
#[arg(short = 'u', long, value_name = "INFO")]
23+
update_info: Option<String>,
2924

30-
#[arg(long, value_name = "URL", env = "GITHUB_API_PROXY")]
31-
github_api_proxy: Option<String>,
32-
},
25+
#[arg(short = 'd', long)]
26+
describe: bool,
3327

34-
Check {
35-
#[arg(value_name = "APPIMAGE")]
36-
path: PathBuf,
28+
#[arg(short = 'j', long)]
29+
check_for_update: bool,
3730

38-
#[arg(long, value_name = "URL", env = "GITHUB_API_PROXY")]
39-
github_api_proxy: Option<String>,
40-
},
31+
#[arg(long, value_name = "URL", env = "GITHUB_API_PROXY")]
32+
github_api_proxy: Option<String>,
4133
}
4234

4335
fn main() {
@@ -66,100 +58,90 @@ fn format_size(bytes: u64) -> String {
6658
}
6759

6860
fn run(cli: Cli) -> Result<(), Error> {
69-
match cli.command {
70-
Commands::Update {
71-
path,
72-
overwrite,
73-
output,
74-
github_api_proxy,
75-
} => {
76-
config::init(github_api_proxy);
61+
config::init(cli.github_api_proxy);
7762

78-
let mut updater = Updater::new(&path)?;
63+
let path = cli.path.ok_or_else(|| {
64+
Error::AppImage("No AppImage path provided. Use --help for usage.".into())
65+
})?;
7966

80-
if overwrite {
81-
updater = updater.overwrite(true);
82-
}
67+
let updater = if let Some(ref update_info) = cli.update_info {
68+
Updater::with_update_info(&path, update_info)?
69+
} else {
70+
Updater::new(&path)?
71+
};
8372

84-
if let Some(dir) = output {
85-
updater = updater.output_dir(dir);
86-
}
73+
if cli.describe {
74+
let source_path = updater.source_path();
75+
let source_size = updater.source_size();
76+
let (target_path, target_size) = updater.target_info()?;
8777

88-
let source_path = updater.source_path();
89-
let source_size = updater.source_size();
90-
let (target_path, target_size) = updater.target_info()?;
78+
println!("Path: {}", source_path.display());
79+
println!("Size: {}", format_size(source_size));
80+
println!("Target: {}", target_path.display());
81+
println!("Target Size: {}", format_size(target_size));
82+
println!("Update Info: {}", updater.update_info());
9183

92-
println!(
93-
"Source: {} ({})",
94-
source_path.display(),
95-
format_size(source_size)
96-
);
97-
println!(
98-
"Target: {} ({})",
99-
target_path.display(),
100-
format_size(target_size)
101-
);
102-
println!();
84+
return Ok(());
85+
}
10386

104-
if updater.check_for_update()? {
105-
println!("Performing delta update...");
106-
let (new_path, stats) = updater.perform_update()?;
107-
108-
if stats.blocks_reused > 0 || stats.blocks_downloaded > 0 {
109-
println!();
110-
println!(
111-
"Reused: {:>10} ({} blocks)",
112-
format_size(stats.bytes_reused()),
113-
stats.blocks_reused
114-
);
115-
println!(
116-
"Downloaded: {:>10} ({} blocks)",
117-
format_size(stats.bytes_downloaded()),
118-
stats.blocks_downloaded
119-
);
120-
println!(
121-
"Saved: {:>10} ({}%)",
122-
format_size(stats.bytes_reused()),
123-
stats.saved_percentage()
124-
);
125-
}
126-
127-
println!();
128-
println!("Updated: {}", new_path.display());
129-
} else {
130-
println!("Already up to date!");
131-
}
132-
}
133-
Commands::Check {
134-
path,
135-
github_api_proxy,
136-
} => {
137-
config::init(github_api_proxy);
87+
if cli.check_for_update {
88+
let has_update = updater.check_for_update()?;
89+
std::process::exit(if has_update { 1 } else { 0 });
90+
}
13891

139-
let updater = Updater::new(&path)?;
92+
let source_path = updater.source_path().to_path_buf();
93+
let source_size = updater.source_size();
94+
let (target_path, target_size) = updater.target_info()?;
95+
96+
println!(
97+
"Source: {} ({})",
98+
source_path.display(),
99+
format_size(source_size)
100+
);
101+
println!(
102+
"Target: {} ({})",
103+
target_path.display(),
104+
format_size(target_size)
105+
);
106+
println!();
107+
108+
let mut updater = updater;
109+
if cli.overwrite {
110+
updater = updater.overwrite(true);
111+
}
140112

141-
let source_path = updater.source_path();
142-
let source_size = updater.source_size();
143-
let (target_path, target_size) = updater.target_info()?;
113+
if updater.check_for_update()? {
114+
println!("Performing delta update...");
115+
let (new_path, stats) = updater.perform_update()?;
144116

117+
if stats.blocks_reused > 0 || stats.blocks_downloaded > 0 {
118+
println!();
145119
println!(
146-
"Source: {} ({})",
147-
source_path.display(),
148-
format_size(source_size)
120+
"Reused: {:>10} ({} blocks)",
121+
format_size(stats.bytes_reused()),
122+
stats.blocks_reused
149123
);
150124
println!(
151-
"Target: {} ({})",
152-
target_path.display(),
153-
format_size(target_size)
125+
"Downloaded: {:>10} ({} blocks)",
126+
format_size(stats.bytes_downloaded()),
127+
stats.blocks_downloaded
154128
);
155-
println!();
129+
println!(
130+
"Saved: {:>10} ({}%)",
131+
format_size(stats.bytes_reused()),
132+
stats.saved_percentage()
133+
);
134+
}
156135

157-
if updater.check_for_update()? {
158-
println!("Status: Update available");
159-
} else {
160-
println!("Status: Up to date");
161-
}
136+
println!();
137+
println!("Updated: {}", new_path.display());
138+
139+
if cli.remove_old && new_path != source_path {
140+
std::fs::remove_file(source_path)?;
141+
println!("Removed old AppImage");
162142
}
143+
} else {
144+
println!("Already up to date!");
163145
}
164146

165147
Ok(())

src/update_info/mod.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,34 @@ pub use github::GitHubUpdateInfo;
88
use crate::error::Result;
99

1010
#[derive(Debug, Clone)]
11-
pub enum UpdateInfo {
11+
pub struct UpdateInfo {
12+
raw: String,
13+
inner: UpdateInfoInner,
14+
}
15+
16+
#[derive(Debug, Clone)]
17+
enum UpdateInfoInner {
1218
Generic(GenericUpdateInfo),
1319
GitHub(GitHubUpdateInfo),
1420
}
1521

1622
impl UpdateInfo {
1723
pub fn parse(s: &str) -> Result<Self> {
18-
parser::parse(s)
24+
let inner = parser::parse(s)?;
25+
Ok(Self {
26+
raw: s.to_owned(),
27+
inner,
28+
})
29+
}
30+
31+
pub fn raw(&self) -> &str {
32+
&self.raw
1933
}
2034

2135
pub fn zsync_url(&self) -> Result<String> {
22-
match self {
23-
UpdateInfo::Generic(g) => Ok(g.zsync_url().to_owned()),
24-
UpdateInfo::GitHub(g) => g.zsync_url().map(|s| s.to_owned()),
36+
match &self.inner {
37+
UpdateInfoInner::Generic(g) => Ok(g.zsync_url().to_owned()),
38+
UpdateInfoInner::GitHub(g) => g.zsync_url().map(|s| s.to_owned()),
2539
}
2640
}
2741
}

src/update_info/parser.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::error::{Error, Result};
22

3-
use super::{GenericUpdateInfo, GitHubUpdateInfo, UpdateInfo};
3+
use super::{GenericUpdateInfo, GitHubUpdateInfo, UpdateInfoInner};
44

5-
pub fn parse(s: &str) -> Result<UpdateInfo> {
5+
pub fn parse(s: &str) -> Result<UpdateInfoInner> {
66
let parts: Vec<&str> = s.split('|').collect();
77

88
if parts.is_empty() {
@@ -16,7 +16,7 @@ pub fn parse(s: &str) -> Result<UpdateInfo> {
1616
"zsync format requires exactly 1 parameter: zsync|<url>".into(),
1717
));
1818
}
19-
Ok(UpdateInfo::Generic(GenericUpdateInfo {
19+
Ok(UpdateInfoInner::Generic(GenericUpdateInfo {
2020
url: parts[1].into(),
2121
}))
2222
}
@@ -26,7 +26,7 @@ pub fn parse(s: &str) -> Result<UpdateInfo> {
2626
"gh-releases-zsync format requires 4 parameters: gh-releases-zsync|<username>|<repo>|<tag>|<filename>".into(),
2727
));
2828
}
29-
Ok(UpdateInfo::GitHub(GitHubUpdateInfo::new(
29+
Ok(UpdateInfoInner::GitHub(GitHubUpdateInfo::new(
3030
parts[1].into(),
3131
parts[2].into(),
3232
parts[3].into(),
@@ -48,7 +48,7 @@ mod tests {
4848
fn parse_generic_zsync() {
4949
let info = parse("zsync|https://example.com/app.AppImage.zsync").unwrap();
5050
match info {
51-
UpdateInfo::Generic(g) => {
51+
UpdateInfoInner::Generic(g) => {
5252
assert_eq!(g.url, "https://example.com/app.AppImage.zsync");
5353
}
5454
_ => panic!("Expected Generic variant"),
@@ -59,7 +59,7 @@ mod tests {
5959
fn parse_github_releases() {
6060
let info = parse("gh-releases-zsync|user|repo|latest|app-*.AppImage").unwrap();
6161
match info {
62-
UpdateInfo::GitHub(g) => {
62+
UpdateInfoInner::GitHub(g) => {
6363
assert_eq!(g.username, "user");
6464
assert_eq!(g.repo, "repo");
6565
assert_eq!(g.tag, "latest");

src/updater.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ impl Updater {
145145
.unwrap_or(0)
146146
}
147147

148+
pub fn update_info(&self) -> &str {
149+
self.update_info.raw()
150+
}
151+
148152
pub fn target_info(&self) -> Result<(PathBuf, u64)> {
149153
let (control, _zsync_url) = self.fetch_control_file()?;
150154
let output_path = self.resolve_output_path(&control)?;

0 commit comments

Comments
 (0)