use super::update_config_builder as builder;
use crate::github::{Error, Release, UpdateConfig, UpdateConfigBuilder, UpdateInfo};
use crate::http::BlockingHttp;
pub struct UpdateChecker {
inner: UpdateConfig,
}
impl UpdateChecker {
pub fn new(config: UpdateConfig) -> Self {
Self { inner: config }
}
pub fn fetch_latest(&self) -> Result<Release, Error> {
let res = BlockingHttp::get(
self.inner.client_builder(),
self.inner.releases_latest_path(),
)?;
let status = res.status();
let body = res.bytes()?;
Release::parse(status, body)
}
pub fn fetch(&self, n: usize) -> Result<Vec<Release>, Error> {
debug_assert!(n <= 100);
let res = BlockingHttp::get(
self.inner.client_builder(),
self.inner.releases_path(n as u8),
)?;
let status = res.status();
let body = res.bytes()?;
Release::parse_array(status, body)
}
pub fn fetch_latest_prerelease(&self) -> Result<Release, Error> {
let releases = self.fetch(1)?;
releases.into_iter().next().ok_or(Error::NO_RELEASE)
}
pub fn check(&self) -> Result<UpdateInfo, Error> {
self.check_prerelease(false)
}
pub fn check_prerelease(&self, prerelease: bool) -> Result<UpdateInfo, Error> {
let release = if prerelease {
self.fetch_latest_prerelease()
} else {
self.fetch_latest()
}?;
Ok(UpdateInfo::new(
self.inner.current_version.as_deref(),
release,
))
}
}
impl<S: builder::State> UpdateConfigBuilder<S> {
pub fn build_blocking(self) -> UpdateChecker
where
S: builder::IsComplete,
{
let config = self.build();
UpdateChecker::new(config)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::github::tests::{TEST_OWNER, TEST_REPO};
#[test]
fn fetch_latest() {
let config = UpdateConfig::builder()
.owner(TEST_OWNER)
.repo(TEST_REPO)
.build();
let release = UpdateChecker::new(config).fetch_latest().unwrap();
assert!(release.tag.starts_with('v'));
assert!(!release.assets.is_empty());
}
#[test]
fn fetch() {
let config = UpdateConfig::builder()
.owner(TEST_OWNER)
.repo(TEST_REPO)
.build();
let releases = UpdateChecker::new(config).fetch(5).unwrap();
assert!(!releases.is_empty(), "should have at least one release");
for release in &releases {
assert!(!release.tag.is_empty());
}
}
#[test]
fn fetch_latest_prerelease() {
let config = UpdateConfig::builder()
.owner(TEST_OWNER)
.repo(TEST_REPO)
.build();
let release = UpdateChecker::new(config)
.fetch_latest_prerelease()
.unwrap();
assert!(!release.tag.is_empty());
}
#[test]
fn check_has_update() {
let info = UpdateConfig::builder()
.owner(TEST_OWNER)
.repo(TEST_REPO)
.current_version("0.1.0")
.build_blocking()
.check()
.unwrap();
assert!(info.has_update());
assert_eq!(info.current_version(), Some("0.1.0"));
}
#[test]
fn current_version() {
let latest = UpdateConfig::builder()
.owner(TEST_OWNER)
.repo(TEST_REPO)
.build_blocking()
.fetch_latest()
.unwrap();
let info = UpdateConfig::builder()
.owner(TEST_OWNER)
.repo(TEST_REPO)
.current_version(&latest.tag)
.build_blocking()
.check()
.unwrap();
assert!(
!info.has_update(),
"checking against the latest tag ({}) should not need an update",
latest.tag
);
}
}