1
Fork 0
mirror of https://github.com/RGBCube/dix synced 2025-07-28 04:07:46 +00:00

store: Add derivation dependency graph query

This commit is contained in:
Dragyx 2025-05-06 14:46:50 +02:00
parent 719e6eca41
commit 9a2a5cb4ff
2 changed files with 56 additions and 6 deletions

View file

@ -97,6 +97,7 @@ fn main() {
println!("<<< {}", args.path.to_string_lossy());
println!(">>> {}", args.path2.to_string_lossy());
// handles to the threads collecting closure size information
// We do this as early as possible because nix is slow.
let closure_size_handles = if args.closure_size {
@ -115,7 +116,7 @@ fn main() {
let package_list_pre = match store::get_packages(&args.path) {
Ok(packages) => {
debug!("Found {} packages in first closure", packages.len());
packages
packages.into_iter().map(|(_, path)| path).collect()
}
Err(e) => {
error!(
@ -135,7 +136,7 @@ fn main() {
let package_list_post = match store::get_packages(&args.path2) {
Ok(packages) => {
debug!("Found {} packages in second closure", packages.len());
packages
packages.into_iter().map(|(_, path)| path).collect()
}
Err(e) => {
error!(
@ -184,6 +185,7 @@ fn main() {
// Difference gives us added and removed packages
let added: HashSet<&str> = &post_keys - &pre_keys;
let removed: HashSet<&str> = &pre_keys - &post_keys;
// Get the intersection of the package names for version changes
let changed: HashSet<&str> = &pre_keys & &post_keys;

View file

@ -1,3 +1,5 @@
use std::collections::HashMap;
use crate::error::AppError;
use rusqlite::Connection;
@ -14,7 +16,7 @@ WITH RECURSIVE
SELECT reference FROM Refs
JOIN graph ON referrer = p
)
SELECT path from graph
SELECT id, path from graph
JOIN ValidPaths ON id = p;
";
@ -32,18 +34,37 @@ SELECT SUM(narSize) as sum from graph
JOIN ValidPaths ON p = id;
";
const QUERY_DEPENDENCY_GRAPH: &str = "
WITH RECURSIVE
graph(p, c) AS (
SELECT id as par, reference as chd
FROM ValidPaths
JOIN Refs ON referrer = id
WHERE path = ?
UNION
SELECT referrer as par, reference as chd FROM Refs
JOIN graph ON referrer = c
)
SELECT p, c from graph;
";
/// executes a query on the nix db directly
/// to gather all derivations that the derivation given by the path
/// depends on
///
/// The ids of the derivations in the database are returned as well, since these
/// can be used to later convert nodes (represented by the the ids) of the
/// dependency graph to actual paths
///
/// in the future, we might wan't to switch to async
pub fn get_packages(path: &std::path::Path) -> Result<Vec<String>> {
pub fn get_packages(path: &std::path::Path) -> Result<Vec<(i64, String)>> {
let p: String = path.canonicalize()?.to_string_lossy().into_owned();
let conn = Connection::open("/nix/var/nix/db/db.sqlite")?;
let mut stmt = conn.prepare(QUERY_PKGS)?;
let queried_pkgs: std::result::Result<Vec<String>, _> =
stmt.query_map([p], |row| row.get(0))?.collect();
let queried_pkgs: std::result::Result<Vec<(i64, String)>, _> =
stmt.query_map([p], |row| Ok((row.get(0)?, row.get(1)?)))?
.collect();
Ok(queried_pkgs?)
}
@ -61,3 +82,30 @@ pub fn get_closure_size(path: &std::path::Path) -> Result<i64> {
let queried_sum = stmt.query_row([p], |row| row.get(0))?;
Ok(queried_sum)
}
/// returns the complete dependency graph of
/// of the derivation as an adjacency list. The nodes are
/// represented by the DB ids
///
/// We might want to collect the paths in the graph directly as
/// well in the future, depending on how much we use them
/// in the operations on the graph
///
/// The mapping from id to graph can be obtained by using [get_packages]
pub fn get_dependency_graph(path: &std::path::Path) -> Result<HashMap<i64, Vec<i64>>> {
let p: String = path.canonicalize()?.to_string_lossy().into_owned();
let conn = Connection::open("/nix/var/nix/db/db.sqlite")?;
let mut stmt = conn.prepare(QUERY_DEPENDENCY_GRAPH)?;
let mut adj = HashMap::<i64, Vec<i64>>::new();
let queried_sum = stmt.query_map(
[p],
|row| Ok::<(i64, i64), _>((row.get(0)?, row.get(1)?)))?;
for row in queried_sum {
let (from, to) = row?;
adj.entry(from).or_default().push(to);
}
Ok(adj)
}