Skip to content

Commit 78d3b89

Browse files
committed
feat: add --list-releases to show available versions
1 parent 513e522 commit 78d3b89

File tree

4 files changed

+76
-10
lines changed

4 files changed

+76
-10
lines changed

src/main.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ struct Cli {
3737
#[arg(short = 'j', long)]
3838
check_for_update: bool,
3939

40+
#[arg(short = 'l', long)]
41+
list_releases: bool,
42+
4043
#[arg(short = 't', long, value_name = "TAG")]
4144
target_tag: Option<String>,
4245

@@ -161,6 +164,35 @@ fn run(cli: Cli) -> Result<(), Error> {
161164
return Ok(());
162165
}
163166

167+
if cli.list_releases {
168+
for path in &appimages {
169+
let updater = create_updater(&cli, path)?;
170+
let name = path
171+
.file_name()
172+
.and_then(|n| n.to_str())
173+
.unwrap_or("unknown");
174+
match updater.list_releases() {
175+
Ok(releases) => {
176+
if appimages.len() > 1 {
177+
eprintln!("{}:", name);
178+
}
179+
let max_tag = releases.iter().map(|r| r.tag().len()).max().unwrap_or(0);
180+
for r in &releases {
181+
let date = r.published_at().split('T').next().unwrap_or("");
182+
let pre = if r.is_prerelease() {
183+
" [pre-release]"
184+
} else {
185+
""
186+
};
187+
eprintln!(" {:<width$} {}{}", r.tag(), date, pre, width = max_tag);
188+
}
189+
}
190+
Err(e) => eprintln!(" {} Error: {}", name, e),
191+
}
192+
}
193+
return Ok(());
194+
}
195+
164196
let totals: Arc<Mutex<Totals>> = Arc::new(Mutex::new(Totals::default()));
165197
let errors: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(Vec::new()));
166198

src/update_info/forge.rs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::cell::OnceCell;
22

3+
pub use releasekit::Release as ReleaseInfo;
34
use releasekit::client::UreqClient;
45
use releasekit::platform::{GitHub, GitLab, Gitea};
56
use releasekit::{Filter, Forge, Release};
@@ -56,64 +57,83 @@ impl ForgeUpdateInfo {
5657
Ok(self.resolved_url.get().unwrap())
5758
}
5859

60+
pub fn list_releases(&self) -> Result<Vec<Release>> {
61+
let project = format!("{}/{}", self.owner, self.repo);
62+
self.with_forge(|forge| {
63+
forge
64+
.fetch_releases(&project, None)
65+
.map_err(|e| Error::ForgeApi(e.to_string()))
66+
})
67+
}
68+
5969
fn resolve_url(&self) -> Result<String> {
70+
self.with_forge(|forge| self.fetch_with_forge(forge))
71+
}
72+
73+
fn with_forge<T>(&self, action: impl Fn(&dyn Forge) -> Result<T>) -> Result<T> {
6074
match &self.kind {
61-
ForgeKind::GitHub => self.resolve_with_proxies(
75+
ForgeKind::GitHub => self.with_forge_proxied(
6276
config::get_github_proxies(),
6377
|base| {
6478
GitHub::new(UreqClient)
6579
.with_base_url(base)
6680
.with_token_from_env(&["GITHUB_TOKEN", "GH_TOKEN"])
6781
},
6882
|| GitHub::new(UreqClient).with_token_from_env(&["GITHUB_TOKEN", "GH_TOKEN"]),
83+
&action,
6984
),
70-
ForgeKind::GitLab => self.resolve_with_proxies(
85+
ForgeKind::GitLab => self.with_forge_proxied(
7186
config::get_gitlab_proxies(),
7287
|base| {
7388
GitLab::new(UreqClient)
7489
.with_base_url(base)
7590
.with_token_from_env(&["GITLAB_TOKEN", "GL_TOKEN"])
7691
},
7792
|| GitLab::new(UreqClient).with_token_from_env(&["GITLAB_TOKEN", "GL_TOKEN"]),
93+
&action,
7894
),
79-
ForgeKind::Codeberg => self.resolve_with_proxies(
95+
ForgeKind::Codeberg => self.with_forge_proxied(
8096
config::get_codeberg_proxies(),
8197
|base| Gitea::new(UreqClient, base).with_token_from_env(&["CODEBERG_TOKEN"]),
8298
|| {
8399
Gitea::new(UreqClient, "https://codeberg.org")
84100
.with_token_from_env(&["CODEBERG_TOKEN"])
85101
},
102+
&action,
86103
),
87104
ForgeKind::Gitea { instance } => {
88105
let gt = Gitea::new(UreqClient, format!("https://{instance}"))
89106
.with_token_from_env(&["GITEA_TOKEN"]);
90-
self.fetch_with_forge(gt)
107+
action(&gt)
91108
}
92109
}
93110
}
94111

95-
fn resolve_with_proxies<F: Forge>(
112+
fn with_forge_proxied<F: Forge, T>(
96113
&self,
97114
proxies: Vec<String>,
98115
make_proxy: impl Fn(&str) -> F,
99116
make_default: impl FnOnce() -> F,
100-
) -> Result<String> {
117+
action: &impl Fn(&dyn Forge) -> Result<T>,
118+
) -> Result<T> {
101119
if proxies.is_empty() {
102-
return self.fetch_with_forge(make_default());
120+
let forge = make_default();
121+
return action(&forge);
103122
}
104123

105124
let mut last_error = None;
106125
for proxy in &proxies {
107-
match self.fetch_with_forge(make_proxy(proxy)) {
108-
Ok(url) => return Ok(url),
126+
let forge = make_proxy(proxy);
127+
match action(&forge) {
128+
Ok(v) => return Ok(v),
109129
Err(e) => last_error = Some(e),
110130
}
111131
}
112132

113133
Err(last_error.unwrap_or_else(|| Error::ForgeApi("All proxies failed".into())))
114134
}
115135

116-
fn fetch_with_forge(&self, forge: impl Forge) -> Result<String> {
136+
fn fetch_with_forge(&self, forge: &dyn Forge) -> Result<String> {
117137
let project = format!("{}/{}", self.owner, self.repo);
118138

119139
let (tag, find_prerelease) = match self.tag.as_str() {

src/update_info/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod generic;
33
mod parser;
44

55
pub use forge::ForgeUpdateInfo;
6+
pub use forge::ReleaseInfo;
67
pub use generic::GenericUpdateInfo;
78

89
use crate::error::Result;
@@ -43,6 +44,15 @@ impl UpdateInfo {
4344
matches!(self.inner, UpdateInfoInner::Forge(_))
4445
}
4546

47+
pub fn list_releases(&self) -> Result<Vec<ReleaseInfo>> {
48+
match &self.inner {
49+
UpdateInfoInner::Generic(_) => Err(crate::error::Error::InvalidUpdateInfo(
50+
"--list-releases is only supported for forge-based update info".into(),
51+
)),
52+
UpdateInfoInner::Forge(f) => f.list_releases(),
53+
}
54+
}
55+
4656
pub fn zsync_url(&self) -> Result<String> {
4757
match &self.inner {
4858
UpdateInfoInner::Generic(g) => Ok(g.zsync_url().to_owned()),

src/updater.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ impl Updater {
172172
self.update_info.raw()
173173
}
174174

175+
pub fn list_releases(&self) -> Result<Vec<crate::update_info::ReleaseInfo>> {
176+
self.update_info.list_releases()
177+
}
178+
175179
pub fn zsync_url(&self) -> Result<String> {
176180
self.update_info.zsync_url()
177181
}

0 commit comments

Comments
 (0)