Skip to content

Commit c20dc30

Browse files
committed
feat: add GitLab update info support
Add gl-releases-zsync update info type for fetching releases from GitLab. Refactors the forge module to use a generic ForgeUpdateInfo with a ForgeKind enum to avoid duplicating release resolution logic. Format: gl-releases-zsync|<owner>|<repo>|<tag>|<filename>
1 parent ad1465c commit c20dc30

File tree

3 files changed

+76
-30
lines changed

3 files changed

+76
-30
lines changed

src/update_info/forge.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,39 @@
11
use std::cell::OnceCell;
22

33
use releasekit::client::UreqClient;
4-
use releasekit::platform::GitHub;
4+
use releasekit::platform::{GitHub, GitLab};
55
use releasekit::{Filter, Forge, Release};
66

77
use crate::config;
88
use crate::error::{Error, Result};
99

1010
#[derive(Debug, Clone)]
11-
pub struct GitHubUpdateInfo {
12-
pub username: String,
11+
pub enum ForgeKind {
12+
GitHub,
13+
GitLab,
14+
}
15+
16+
#[derive(Debug, Clone)]
17+
pub struct ForgeUpdateInfo {
18+
pub kind: ForgeKind,
19+
pub owner: String,
1320
pub repo: String,
1421
pub tag: String,
1522
pub filename: String,
1623
resolved_url: OnceCell<String>,
1724
}
1825

19-
impl GitHubUpdateInfo {
20-
pub fn new(username: String, repo: String, tag: String, filename: String) -> Self {
26+
impl ForgeUpdateInfo {
27+
pub fn new(
28+
kind: ForgeKind,
29+
owner: String,
30+
repo: String,
31+
tag: String,
32+
filename: String,
33+
) -> Self {
2134
Self {
22-
username,
35+
kind,
36+
owner,
2337
repo,
2438
tag,
2539
filename,
@@ -36,6 +50,16 @@ impl GitHubUpdateInfo {
3650
}
3751

3852
fn resolve_url(&self) -> Result<String> {
53+
match &self.kind {
54+
ForgeKind::GitHub => self.resolve_github(),
55+
ForgeKind::GitLab => {
56+
let gl = GitLab::new(UreqClient).with_token_from_env(&["GITLAB_TOKEN", "GL_TOKEN"]);
57+
self.fetch_with_forge(gl)
58+
}
59+
}
60+
}
61+
62+
fn resolve_github(&self) -> Result<String> {
3963
let proxies = config::get_proxies();
4064

4165
if proxies.is_empty() {
@@ -58,7 +82,7 @@ impl GitHubUpdateInfo {
5882
}
5983

6084
fn fetch_with_forge(&self, forge: impl Forge) -> Result<String> {
61-
let project = format!("{}/{}", self.username, self.repo);
85+
let project = format!("{}/{}", self.owner, self.repo);
6286

6387
let (tag, find_prerelease) = match self.tag.as_str() {
6488
"latest" | "latest-pre" | "latest-all" => (None, self.tag == "latest-pre"),

src/update_info/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mod forge;
22
mod generic;
33
mod parser;
44

5-
pub use forge::GitHubUpdateInfo;
5+
pub use forge::ForgeUpdateInfo;
66
pub use generic::GenericUpdateInfo;
77

88
use crate::error::Result;
@@ -16,7 +16,7 @@ pub struct UpdateInfo {
1616
#[derive(Debug, Clone)]
1717
enum UpdateInfoInner {
1818
Generic(GenericUpdateInfo),
19-
GitHub(GitHubUpdateInfo),
19+
Forge(ForgeUpdateInfo),
2020
}
2121

2222
impl UpdateInfo {
@@ -35,7 +35,7 @@ impl UpdateInfo {
3535
pub fn zsync_url(&self) -> Result<String> {
3636
match &self.inner {
3737
UpdateInfoInner::Generic(g) => Ok(g.zsync_url().to_owned()),
38-
UpdateInfoInner::GitHub(g) => g.zsync_url().map(|s| s.to_owned()),
38+
UpdateInfoInner::Forge(f) => f.zsync_url().map(|s| s.to_owned()),
3939
}
4040
}
4141
}

src/update_info/parser.rs

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

3-
use super::{GenericUpdateInfo, GitHubUpdateInfo, UpdateInfoInner};
3+
use super::forge::{ForgeKind, ForgeUpdateInfo};
4+
use super::{GenericUpdateInfo, UpdateInfoInner};
45

56
pub fn parse(s: &str) -> Result<UpdateInfoInner> {
67
let parts: Vec<&str> = s.split('|').collect();
@@ -20,26 +21,30 @@ pub fn parse(s: &str) -> Result<UpdateInfoInner> {
2021
url: parts[1].into(),
2122
}))
2223
}
23-
"gh-releases-zsync" => {
24-
if parts.len() != 5 {
25-
return Err(Error::InvalidUpdateInfo(
26-
"gh-releases-zsync format requires 4 parameters: gh-releases-zsync|<username>|<repo>|<tag>|<filename>".into(),
27-
));
28-
}
29-
Ok(UpdateInfoInner::GitHub(GitHubUpdateInfo::new(
30-
parts[1].into(),
31-
parts[2].into(),
32-
parts[3].into(),
33-
parts[4].into(),
34-
)))
35-
}
24+
"gh-releases-zsync" => parse_forge(ForgeKind::GitHub, &parts, "gh-releases-zsync"),
25+
"gl-releases-zsync" => parse_forge(ForgeKind::GitLab, &parts, "gl-releases-zsync"),
3626
_ => Err(Error::InvalidUpdateInfo(format!(
3727
"Unknown update information type: {}",
3828
parts[0]
3929
))),
4030
}
4131
}
4232

33+
fn parse_forge(kind: ForgeKind, parts: &[&str], prefix: &str) -> Result<UpdateInfoInner> {
34+
if parts.len() != 5 {
35+
return Err(Error::InvalidUpdateInfo(format!(
36+
"{prefix} format requires 4 parameters: {prefix}|<owner>|<repo>|<tag>|<filename>"
37+
)));
38+
}
39+
Ok(UpdateInfoInner::Forge(ForgeUpdateInfo::new(
40+
kind,
41+
parts[1].into(),
42+
parts[2].into(),
43+
parts[3].into(),
44+
parts[4].into(),
45+
)))
46+
}
47+
4348
#[cfg(test)]
4449
mod tests {
4550
use super::*;
@@ -59,13 +64,29 @@ mod tests {
5964
fn parse_github_releases() {
6065
let info = parse("gh-releases-zsync|user|repo|latest|app-*.AppImage").unwrap();
6166
match info {
62-
UpdateInfoInner::GitHub(g) => {
63-
assert_eq!(g.username, "user");
64-
assert_eq!(g.repo, "repo");
65-
assert_eq!(g.tag, "latest");
66-
assert_eq!(g.filename, "app-*.AppImage");
67+
UpdateInfoInner::Forge(f) => {
68+
assert!(matches!(f.kind, ForgeKind::GitHub));
69+
assert_eq!(f.owner, "user");
70+
assert_eq!(f.repo, "repo");
71+
assert_eq!(f.tag, "latest");
72+
assert_eq!(f.filename, "app-*.AppImage");
73+
}
74+
_ => panic!("Expected Forge variant"),
75+
}
76+
}
77+
78+
#[test]
79+
fn parse_gitlab_releases() {
80+
let info = parse("gl-releases-zsync|owner|repo|latest|app-*.AppImage").unwrap();
81+
match info {
82+
UpdateInfoInner::Forge(f) => {
83+
assert!(matches!(f.kind, ForgeKind::GitLab));
84+
assert_eq!(f.owner, "owner");
85+
assert_eq!(f.repo, "repo");
86+
assert_eq!(f.tag, "latest");
87+
assert_eq!(f.filename, "app-*.AppImage");
6788
}
68-
_ => panic!("Expected GitHub variant"),
89+
_ => panic!("Expected Forge variant"),
6990
}
7091
}
7192

@@ -78,5 +99,6 @@ mod tests {
7899
fn parse_missing_params() {
79100
assert!(parse("zsync").is_err());
80101
assert!(parse("gh-releases-zsync|user|repo").is_err());
102+
assert!(parse("gl-releases-zsync|user|repo").is_err());
81103
}
82104
}

0 commit comments

Comments
 (0)