1#![cfg_attr(not(doctest), doc = include_str!("../README.md"))]
18
19pub mod action;
20pub mod build;
21pub mod config;
22pub mod db;
23pub mod report;
24pub mod sandbox;
25pub mod scan;
26pub mod summary;
27
28mod init;
30pub mod logging;
31mod tui;
32
33use std::collections::{HashMap, VecDeque};
34use std::hash::Hash;
35use std::io::{self, Write};
36use std::sync::Arc;
37use std::sync::atomic::AtomicBool;
38
39pub fn build_order<K>(deps: &HashMap<K, Vec<K>>, weight: impl Fn(&K) -> usize) -> Vec<K>
47where
48 K: Eq + Hash + Clone + Ord,
49{
50 let mut rev: HashMap<&K, Vec<&K>> = HashMap::new();
51 for pkg in deps.keys() {
52 rev.entry(pkg).or_default();
53 }
54 for (pkg, d) in deps {
55 for dep in d {
56 rev.entry(dep).or_default().push(pkg);
57 }
58 }
59 let mut pending: HashMap<&K, usize> = deps.keys().map(|p| (p, rev[p].len())).collect();
60 let mut queue: VecDeque<&K> = pending
61 .iter()
62 .filter(|(_, c)| **c == 0)
63 .map(|(&p, _)| p)
64 .collect();
65 let mut weights: HashMap<&K, usize> = HashMap::new();
66 while let Some(pkg) = queue.pop_front() {
67 let w = rev[pkg]
68 .iter()
69 .fold(weight(pkg), |a, d| a + weights.get(d).copied().unwrap_or(0));
70 weights.insert(pkg, w);
71 for dep in deps[pkg].iter() {
72 if let Some(c) = pending.get_mut(dep) {
73 *c -= 1;
74 if *c == 0 {
75 queue.push_back(dep);
76 }
77 }
78 }
79 }
80 let mut result: Vec<K> = deps.keys().cloned().collect();
81 result.sort_by(|a, b| weights.get(b).cmp(&weights.get(a)).then_with(|| a.cmp(b)));
82 result
83}
84
85pub fn try_println(s: &str) -> bool {
91 let result = writeln!(io::stdout(), "{}", s);
92 !matches!(result, Err(e) if e.kind() == io::ErrorKind::BrokenPipe)
93}
94
95#[derive(Debug)]
97pub struct Interrupted;
98
99impl std::fmt::Display for Interrupted {
100 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101 write!(f, "Interrupted")
102 }
103}
104
105impl std::error::Error for Interrupted {}
106
107#[derive(Clone, Debug)]
109pub struct RunContext {
110 pub shutdown: Arc<AtomicBool>,
112}
113
114impl RunContext {
115 pub fn new(shutdown: Arc<AtomicBool>) -> Self {
122 Self { shutdown }
123 }
124}
125
126pub use action::{Action, ActionType, FSType};
133pub use build::{
134 Build, BuildCounts, BuildOutcome, BuildReason, BuildResult, BuildSummary, pkg_up_to_date,
135};
136pub use config::{Config, Options, Pkgsrc, PkgsrcEnv, Sandboxes};
137pub use db::Database;
138pub use init::Init;
139pub use report::write_html_report;
140pub use sandbox::Sandbox;
141pub use scan::{ResolvedPackage, Scan, ScanResult, ScanSummary, SkipReason, SkippedCounts};
142pub use summary::generate_pkg_summary;