os_checker_plugin_cargo/crates_io/
release_tarball.rs

1use super::IndexFile;
2use crate::repo::local_base_dir;
3use cargo_metadata::semver::Version;
4use eyre::ContextCompat;
5use plugin::prelude::*;
6use std::os::linux::fs::MetadataExt;
7
8#[derive(Debug)]
9pub struct TarballInfo {
10    /// size in bytes
11    pub size: u64,
12    pub modified: Timestamp,
13}
14
15impl TarballInfo {
16    fn new(tarball: &Utf8Path) -> Result<Self> {
17        let meta = std::fs::metadata(tarball)?;
18        let size = meta.st_size();
19        let modified = Timestamp::from_second(meta.st_mtime())?;
20        Ok(Self { size, modified })
21    }
22}
23
24fn download_tarball(pkg: &str, version: &Version) -> Result<Utf8PathBuf> {
25    const TARBALL: &str = "download";
26
27    let url = url(pkg, version);
28    info!("wget {url}");
29
30    let dir = local_base_dir();
31
32    duct::cmd!("wget", url, "-O", TARBALL)
33        .dir(dir)
34        .stdout_null()
35        .stderr_null()
36        .run()?;
37
38    let tarball = dir.join(TARBALL);
39    Ok(tarball)
40}
41
42fn url(pkg: &str, version: &Version) -> String {
43    // wget https://static.crates.io/crates/os-checker/0.4.1/download
44    // for further use: tar xf download && cd os-checker-0.4.1
45    const PREFIX: &str = "https://static.crates.io/crates";
46    format!("{PREFIX}/{pkg}/{version}/download")
47}
48
49fn get_last_release_info(pkg: &str, version: &Version) -> Result<TarballInfo> {
50    let tarball = download_tarball(pkg, version)?;
51    TarballInfo::new(&tarball)
52}
53
54impl IndexFile {
55    pub fn get_last_release_info(&mut self) -> Result<()> {
56        let last = self.data.last();
57        let last = last.with_context(|| "index file is empty")?;
58        self.tarball = Some(get_last_release_info(&self.pkg, &last.vers)?);
59        Ok(())
60    }
61
62    pub fn last_release_size_and_time(&self) -> Option<(u64, Timestamp)> {
63        self.tarball
64            .as_ref()
65            .map(|tarball| (tarball.size, tarball.modified))
66    }
67}
68
69#[test]
70fn test_tarball_info() -> Result<()> {
71    // test on Cargo.toml instead of tarball for now
72    // dbg!(TarballInfo::new("Cargo.toml".into())?);
73
74    dbg!(get_last_release_info("os-checker", &Version::new(0, 4, 1))?);
75
76    Ok(())
77}