nix_data/cache/
nonnixos.rs

1use crate::CACHEDIR;
2use anyhow::{anyhow, Result};
3use log::{debug, info};
4use std::{
5    fs::{self, File},
6    io::{Read, Write},
7    path::Path,
8};
9
10
11/// Downloads the latest `packages.json` for the system from the Nix cache and returns the path to an SQLite database `nonnixospkgs.db` which contains package data.
12/// Mean for non-NixOS systems.
13pub async fn nixpkgs() -> Result<String> {
14    // If cache directory doesn't exist, create it
15    if !std::path::Path::new(&*CACHEDIR).exists() {
16        std::fs::create_dir_all(&*CACHEDIR)?;
17    }
18
19    let verurl = String::from(
20        "https://raw.githubusercontent.com/snowflakelinux/nix-data-db/main/nixpkgs-unstable/nixpkgs.ver"
21    );
22    debug!("Checking nixpkgs version");
23    let resp = reqwest::get(&verurl).await;
24    let resp = if let Ok(r) = resp {
25        r
26    } else {
27        // Internet connection failed
28        // Check if we can use the old database
29        let dbpath = format!("{}/nonnixospkgs.db", &*CACHEDIR);
30        if Path::new(&dbpath).exists() {
31            info!("Using old database");
32            return Ok(dbpath);
33        } else {
34            return Err(anyhow!("Could not find latest nixpkgs version"));
35        }
36    };
37    let latestnixpkgsver = if resp.status().is_success() {
38        resp.text().await?
39    } else {
40        return Err(anyhow!("Could not find latest nixpkgs version"));
41    };
42    debug!("Latest nixpkgs version: {}", latestnixpkgsver);
43
44    let latestnixpkgsver = latestnixpkgsver
45        .strip_prefix("nixos-")
46        .unwrap_or(&latestnixpkgsver);
47    info!("latestnixosver: {}", latestnixpkgsver);
48    // Check if latest version is already downloaded
49    if let Ok(prevver) = fs::read_to_string(&format!("{}/nonnixospkgs.ver", &*CACHEDIR)) {
50        if prevver == latestnixpkgsver
51            && Path::new(&format!("{}/nonnixospkgs.db", &*CACHEDIR)).exists()
52        {
53            debug!("No new version of nixpkgs found");
54            return Ok(format!("{}/nonnixospkgs.db", &*CACHEDIR));
55        }
56    }
57
58    let url = String::from(
59        "https://raw.githubusercontent.com/snowflakelinux/nix-data-db/main/nixpkgs-unstable/nixpkgs.db.br"
60    );
61    debug!("Downloading nix-data database");
62    let client = reqwest::Client::builder().brotli(true).build()?;
63    let resp = client.get(url).send().await?;
64    if resp.status().is_success() {
65        debug!("Writing nix-data database");
66        let mut out = File::create(&format!("{}/nonnixospkgs.db", &*CACHEDIR))?;
67        {
68            let bytes = resp.bytes().await?;
69            let mut reader = brotli::Decompressor::new(
70                bytes.as_ref(),
71                4096, // buffer size
72            );
73            let mut buf = [0u8; 4096];
74            loop {
75                match reader.read(&mut buf[..]) {
76                    Err(e) => {
77                        if let std::io::ErrorKind::Interrupted = e.kind() {
78                            continue;
79                        }
80                        panic!("{}", e);
81                    }
82                    Ok(size) => {
83                        if size == 0 {
84                            break;
85                        }
86                        if let Err(e) = out.write_all(&buf[..size]) {
87                            panic!("{}", e)
88                        }
89                    }
90                }
91            }
92        }
93        debug!("Writing nix-data version");
94        // Write version downloaded to file
95        File::create(format!("{}/nonnixospkgs.ver", &*CACHEDIR))?
96            .write_all(latestnixpkgsver.as_bytes())?;
97    } else {
98        return Err(anyhow!("Failed to download latest nonnixospkgs.db.br"));
99    }
100    Ok(format!("{}/nonnixospkgs.db", &*CACHEDIR))
101}