ib_update/github/
blocking.rs1use super::update_config_builder as builder;
2use crate::github::{Error, Release, UpdateConfig, UpdateConfigBuilder, UpdateInfo};
3use crate::http::BlockingHttp;
4
5pub struct UpdateChecker {
26 inner: UpdateConfig,
27}
28
29impl UpdateChecker {
30 pub fn new(config: UpdateConfig) -> Self {
32 Self { inner: config }
33 }
34
35 pub fn fetch_latest(&self) -> Result<Release, Error> {
37 let res = BlockingHttp::get(
38 self.inner.client_builder(),
39 self.inner.releases_latest_path(),
40 )?;
41
42 let status = res.status();
43 let body = res.bytes()?;
44 Release::parse(status, body)
45 }
46
47 pub fn fetch(&self, n: usize) -> Result<Vec<Release>, Error> {
51 debug_assert!(n <= 100);
52 let res = BlockingHttp::get(
53 self.inner.client_builder(),
54 self.inner.releases_path(n as u8),
55 )?;
56
57 let status = res.status();
58 let body = res.bytes()?;
59 Release::parse_array(status, body)
60 }
61
62 pub fn fetch_latest_prerelease(&self) -> Result<Release, Error> {
64 let releases = self.fetch(1)?;
65 releases.into_iter().next().ok_or(Error::NO_RELEASE)
66 }
67
68 pub fn check(&self) -> Result<UpdateInfo, Error> {
73 self.check_prerelease(false)
74 }
75
76 pub fn check_prerelease(&self, prerelease: bool) -> Result<UpdateInfo, Error> {
80 let release = if prerelease {
81 self.fetch_latest_prerelease()
82 } else {
83 self.fetch_latest()
84 }?;
85 Ok(UpdateInfo::new(
86 self.inner.current_version.as_deref(),
87 release,
88 ))
89 }
90}
91
92impl<S: builder::State> UpdateConfigBuilder<S> {
93 pub fn build_blocking(self) -> UpdateChecker
112 where
113 S: builder::IsComplete,
114 {
115 let config = self.build();
116 UpdateChecker::new(config)
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123 use crate::github::tests::{TEST_OWNER, TEST_REPO};
124
125 #[test]
126 fn fetch_latest() {
127 let config = UpdateConfig::builder()
128 .owner(TEST_OWNER)
129 .repo(TEST_REPO)
130 .build();
131 let release = UpdateChecker::new(config).fetch_latest().unwrap();
132
133 assert!(release.tag.starts_with('v'));
134 assert!(!release.assets.is_empty());
135 }
136
137 #[test]
138 fn fetch() {
139 let config = UpdateConfig::builder()
140 .owner(TEST_OWNER)
141 .repo(TEST_REPO)
142 .build();
143 let releases = UpdateChecker::new(config).fetch(5).unwrap();
144
145 assert!(!releases.is_empty(), "should have at least one release");
146
147 for release in &releases {
148 assert!(!release.tag.is_empty());
149 }
150 }
151
152 #[test]
153 fn fetch_latest_prerelease() {
154 let config = UpdateConfig::builder()
155 .owner(TEST_OWNER)
156 .repo(TEST_REPO)
157 .build();
158 let release = UpdateChecker::new(config)
159 .fetch_latest_prerelease()
160 .unwrap();
161
162 assert!(!release.tag.is_empty());
163 }
164
165 #[test]
166 fn check_has_update() {
167 let info = UpdateConfig::builder()
168 .owner(TEST_OWNER)
169 .repo(TEST_REPO)
170 .current_version("0.1.0")
171 .build_blocking()
172 .check()
173 .unwrap();
174
175 assert!(info.has_update());
176 assert_eq!(info.current_version(), Some("0.1.0"));
177 }
178
179 #[test]
180 fn current_version() {
181 let latest = UpdateConfig::builder()
182 .owner(TEST_OWNER)
183 .repo(TEST_REPO)
184 .build_blocking()
185 .fetch_latest()
186 .unwrap();
187
188 let info = UpdateConfig::builder()
189 .owner(TEST_OWNER)
190 .repo(TEST_REPO)
191 .current_version(&latest.tag)
192 .build_blocking()
193 .check()
194 .unwrap();
195
196 assert!(
197 !info.has_update(),
198 "checking against the latest tag ({}) should not need an update",
199 latest.tag
200 );
201 }
202}