aboutsummaryrefslogtreecommitdiff
path: root/nix-rust/src/store/store.rs
blob: c33dc4a90f1fc1bd205e9ada860d657d057a63a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
use super::{PathInfo, StorePath};
use crate::Error;
use std::collections::{BTreeMap, BTreeSet};
use std::path::Path;

pub trait Store: Send + Sync {
    fn store_dir(&self) -> &str {
        "/nix/store"
    }

    fn query_path_info(
        &self,
        store_path: &StorePath,
    ) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<PathInfo, Error>> + Send>>;
}

impl dyn Store {
    pub fn parse_store_path(&self, path: &Path) -> Result<StorePath, Error> {
        StorePath::new(path, self.store_dir())
    }

    pub async fn compute_path_closure(
        &self,
        roots: BTreeSet<StorePath>,
    ) -> Result<BTreeMap<StorePath, PathInfo>, Error> {
        let mut done = BTreeSet::new();
        let mut result = BTreeMap::new();
        let mut pending = vec![];

        for root in roots {
            pending.push(self.query_path_info(&root));
            done.insert(root);
        }

        while !pending.is_empty() {
            let (info, _, remaining) = futures::future::select_all(pending).await;
            pending = remaining;

            let info = info?;

            for path in &info.references {
                if !done.contains(path) {
                    pending.push(self.query_path_info(&path));
                    done.insert(path.clone());
                }
            }

            result.insert(info.path.clone(), info);
        }

        Ok(result)
    }
}