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

feat: Connection newtype

This commit is contained in:
RGBCube 2025-05-08 22:22:43 +03:00 committed by bloxx12
parent db09147da6
commit 574142c4a0
2 changed files with 125 additions and 116 deletions

View file

@ -1,4 +1,24 @@
use std::path::{
Path,
PathBuf,
};
use derive_more::Deref;
use ref_cast::RefCast;
pub mod error; pub mod error;
pub mod print; pub mod print;
pub mod store; pub mod store;
pub mod util; pub mod util;
#[derive(Deref, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DerivationId(i64);
#[derive(RefCast, Deref, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct StorePath(Path);
#[derive(Deref, Debug, Clone, PartialEq, Eq)]
pub struct StorePathBuf(PathBuf);

View file

@ -1,23 +1,21 @@
use std::{ use std::result;
path::{
Path,
PathBuf,
},
result,
};
use anyhow::{ use anyhow::{
Context as _, Context as _,
Result, Result,
}; };
use derive_more::Deref; use derive_more::Deref;
use ref_cast::RefCast;
use rusqlite::Connection;
use rustc_hash::{ use rustc_hash::{
FxBuildHasher, FxBuildHasher,
FxHashMap, FxHashMap,
}; };
use crate::{
DerivationId,
StorePath,
StorePathBuf,
};
macro_rules! path_to_str { macro_rules! path_to_str {
($path:ident) => { ($path:ident) => {
let $path = $path.canonicalize().with_context(|| { let $path = $path.canonicalize().with_context(|| {
@ -36,50 +34,43 @@ macro_rules! path_to_str {
}; };
} }
#[derive(Deref, Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Deref)]
pub struct DerivationId(i64); pub struct Connection(rusqlite::Connection);
#[expect(clippy::module_name_repetitions)]
#[derive(RefCast, Deref, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct StorePath(Path);
#[expect(clippy::module_name_repetitions)]
#[derive(Deref, Debug, Clone, PartialEq, Eq)]
pub struct StorePathBuf(PathBuf);
/// Connects to the Nix database. /// Connects to the Nix database.
pub fn connect() -> Result<Connection> { pub fn connect() -> Result<Connection> {
const DATABASE_PATH: &str = "/nix/var/nix/db/db.sqlite"; const DATABASE_PATH: &str = "/nix/var/nix/db/db.sqlite";
Connection::open(DATABASE_PATH).with_context(|| { let inner = rusqlite::Connection::open(DATABASE_PATH).with_context(|| {
format!("failed to connect to Nix database at {DATABASE_PATH}") format!("failed to connect to Nix database at {DATABASE_PATH}")
}) })?;
Ok(Connection(inner))
} }
/// Gathers all derivations that the given store path depends on. impl Connection {
pub fn query_depdendents( /// Gathers all derivations that the given store path depends on.
connection: &mut Connection, pub fn query_depdendents(
path: &StorePath, &mut self,
) -> Result<Vec<(DerivationId, StorePathBuf)>> { path: &StorePath,
const QUERY: &str = " ) -> Result<Vec<(DerivationId, StorePathBuf)>> {
WITH RECURSIVE const QUERY: &str = "
graph(p) AS ( WITH RECURSIVE
SELECT id graph(p) AS (
FROM ValidPaths SELECT id
WHERE path = ? FROM ValidPaths
UNION WHERE path = ?
SELECT reference FROM Refs UNION
JOIN graph ON referrer = p SELECT reference FROM Refs
) JOIN graph ON referrer = p
SELECT id, path from graph )
JOIN ValidPaths ON id = p; SELECT id, path from graph
"; JOIN ValidPaths ON id = p;
";
path_to_str!(path); path_to_str!(path);
let packages: result::Result<Vec<(DerivationId, StorePathBuf)>, _> = let packages: result::Result<Vec<(DerivationId, StorePathBuf)>, _> = self
connection
.prepare_cached(QUERY)? .prepare_cached(QUERY)?
.query_map([path], |row| { .query_map([path], |row| {
Ok(( Ok((
@ -89,79 +80,77 @@ pub fn query_depdendents(
})? })?
.collect(); .collect();
Ok(packages?) Ok(packages?)
}
/// Gets the total closure size of the given store path by summing up the nar
/// size of all depdendent derivations.
pub fn query_closure_size(
connection: &mut Connection,
path: &StorePath,
) -> Result<usize> {
const QUERY: &str = "
WITH RECURSIVE
graph(p) AS (
SELECT id
FROM ValidPaths
WHERE path = ?
UNION
SELECT reference FROM Refs
JOIN graph ON referrer = p
)
SELECT SUM(narSize) as sum from graph
JOIN ValidPaths ON p = id;
";
path_to_str!(path);
let closure_size = connection
.prepare_cached(QUERY)?
.query_row([path], |row| row.get(0))?;
Ok(closure_size)
}
/// Gathers the complete dependency graph of of the store path as an adjacency
/// list.
///
/// 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.
pub fn query_dependency_graph(
connection: &mut Connection,
path: &StorePath,
) -> Result<FxHashMap<DerivationId, Vec<DerivationId>>> {
const QUERY: &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;
";
path_to_str!(path);
let mut adj =
FxHashMap::<DerivationId, Vec<DerivationId>>::with_hasher(FxBuildHasher);
let mut statement = connection.prepare_cached(QUERY)?;
let edges = statement.query_map([path], |row| {
Ok((DerivationId(row.get(0)?), DerivationId(row.get(1)?)))
})?;
for row in edges {
let (from, to) = row?;
adj.entry(from).or_default().push(to);
adj.entry(to).or_default();
} }
Ok(adj) /// Gets the total closure size of the given store path by summing up the nar
/// size of all depdendent derivations.
pub fn query_closure_size(&mut self, path: &StorePath) -> Result<usize> {
const QUERY: &str = "
WITH RECURSIVE
graph(p) AS (
SELECT id
FROM ValidPaths
WHERE path = ?
UNION
SELECT reference FROM Refs
JOIN graph ON referrer = p
)
SELECT SUM(narSize) as sum from graph
JOIN ValidPaths ON p = id;
";
path_to_str!(path);
let closure_size = self
.prepare_cached(QUERY)?
.query_row([path], |row| row.get(0))?;
Ok(closure_size)
}
/// Gathers the complete dependency graph of of the store path as an adjacency
/// list.
///
/// 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.
pub fn query_dependency_graph(
&mut self,
path: &StorePath,
) -> Result<FxHashMap<DerivationId, Vec<DerivationId>>> {
const QUERY: &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;
";
path_to_str!(path);
let mut adj =
FxHashMap::<DerivationId, Vec<DerivationId>>::with_hasher(FxBuildHasher);
let mut statement = self.prepare_cached(QUERY)?;
let edges = statement.query_map([path], |row| {
Ok((DerivationId(row.get(0)?), DerivationId(row.get(1)?)))
})?;
for row in edges {
let (from, to) = row?;
adj.entry(from).or_default().push(to);
adj.entry(to).or_default();
}
Ok(adj)
}
} }