From 2984a8c1c78579e4b75fec39e05be5e9baeac1e0 Mon Sep 17 00:00:00 2001 From: Adam Bergmark Date: Mon, 17 Jan 2022 01:42:01 +0100 Subject: [PATCH] commenter disabled: count transitive dependents --- CURATORS.md | 14 +++++ etc/commenter/src/lib.rs | 119 +++++++++++++++++++++++++++++++++++++- etc/commenter/src/main.rs | 10 ++-- 3 files changed, 137 insertions(+), 6 deletions(-) diff --git a/CURATORS.md b/CURATORS.md index 0e3b25af..1bbbc442 100644 --- a/CURATORS.md +++ b/CURATORS.md @@ -533,6 +533,20 @@ TARGET=nightly-2021-01-14 \ # the date doesn't matter curator snapshot ``` +#### Finding disabled packages with lots of dependents + +`commenter disabled` prints the number of transitive dependents a disabled package has. Low hanging fruit to get a lot of packages included again. + +Example output: +``` +[...] +stringable is disabled with 10 dependents +llvm-hs is disabled with 12 dependents +th-data-compat is disabled with 12 dependents +amazonka-core is disabled with 96 dependents +gogol-core is disabled with 96 dependents +``` + ## Adding new curators 1. Add public ssh key to `~/.ssh/authorized_keys` on build server diff --git a/etc/commenter/src/lib.rs b/etc/commenter/src/lib.rs index 1f0f9431..afebf260 100644 --- a/etc/commenter/src/lib.rs +++ b/etc/commenter/src/lib.rs @@ -188,6 +188,7 @@ enum State { Done, } +#[derive(PartialEq, Eq, Debug)] struct VersionedPackage { package: Package, version: Version, @@ -352,7 +353,7 @@ struct SnapshotPackage { // pantry-tree } -#[derive(PartialOrd, Ord, PartialEq, Eq, Clone)] +#[derive(PartialOrd, Ord, PartialEq, Eq, Clone, Debug)] struct Package(String); impl fmt::Display for Package { @@ -361,7 +362,7 @@ impl fmt::Display for Package { } } -#[derive(Clone, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Debug)] struct Version(String); impl fmt::Display for Version { @@ -457,3 +458,117 @@ pub fn diff_snapshot(a: String, b: String) { println!("{s}"); } } + +#[derive(PartialEq, Eq, Debug)] +struct DisabledTransitively { + child: VersionedPackage, + parent: Package, +} + +fn parse_disabled_transitviely(s: &str) -> Option { + let r = regex!( + r#"- *([^ ]+) < *0 *# tried [^ ]+-([\d.]+), but its \*[^*]+\* requires the disabled package: ([^ ]+)"# + ); + if let Some(caps) = r.captures(s) { + let package = Package(caps.get(1).unwrap().as_str().to_owned()); + let version = Version(caps.get(2).unwrap().as_str().to_owned()); + let parent = Package(caps.get(3).unwrap().as_str().to_owned()); + Some(DisabledTransitively { + child: VersionedPackage { package, version }, + parent, + }) + } else { + None + } +} + +#[test] +fn test_parse_disabled_transitviely() { + let s = "- Network-NineP < 0 # tried Network-NineP-0.4.7.1, but its *library* requires the disabled package: mstate"; + assert_eq!( + parse_disabled_transitviely(s), + Some(DisabledTransitively { + child: VersionedPackage { + package: Package("Network-NineP".to_owned()), + version: Version("0.4.7.1".to_owned()) + }, + parent: Package("mstate".to_owned()), + }) + ) +} + +type M = BTreeMap, Option)>; + +pub fn disabled() { + let mut disabled_transitively: Vec = vec![]; + handle(false, |loc, lines| { + match loc { + Location::Lib => disabled_transitively.extend( + lines + .into_iter() + .map(|line| parse_disabled_transitviely(&line)) + .flatten() + .collect::>(), + ), + Location::Test | Location::Bench => (), + } + vec![] + }); + + let mut packages: BTreeSet = BTreeSet::new(); + let mut disabled: M = BTreeMap::new(); + + for DisabledTransitively { child, parent } in disabled_transitively { + packages.insert(child.package.clone()); + packages.insert(parent.clone()); + disabled + .entry(child.package.clone()) + .or_insert_with(|| (vec![], None)); + let t = disabled.entry(parent).or_insert_with(|| (vec![], None)); + t.0.push(child); + } + + let mut packages_len = packages.len(); + while packages_len > 0 { + let mut new_packages: BTreeSet = BTreeSet::new(); + for package in packages { + let (_, count) = disabled.get(&package).unwrap(); + if count.is_none() && !process(&package, &mut disabled) { + new_packages.insert(package.clone()); + } + } + packages = new_packages; + packages_len = packages.len(); + } + + let mut v: Vec<_> = disabled + .into_iter() + .map(|(package, (_, count))| (count, package)) + .collect(); + v.sort(); + for (count, package) in v { + let count = count.unwrap(); + if count != 0 { + println!("{package} is disabled with {count} dependents"); + } + } +} + +fn process(package: &Package, m: &mut M) -> bool { + let (children, count) = m.get(package).unwrap(); + assert!(count.is_none(), "{:?}", package); + let mut count = 0; + for child in children { + let (_, child_count) = m + .get(&child.package) + .unwrap_or_else(|| panic!("{}", child.package)); + match child_count { + None => return false, + Some(i) => count += 1 + i, + } + } + m.entry(package.clone()) + .and_modify(|tup| tup.1 = Some(count)) + .or_insert_with(|| panic!("{}", package)); + true +} diff --git a/etc/commenter/src/main.rs b/etc/commenter/src/main.rs index 25db2bbf..f34f753b 100644 --- a/etc/commenter/src/main.rs +++ b/etc/commenter/src/main.rs @@ -19,19 +19,21 @@ enum Header { about = "Automates generation of bounds in build-constraints.yaml" )] enum Opt { - Clear, Add, - Outdated, + Clear, DiffSnapshot { a: String, b: String }, + Disabled, + Outdated, } fn main() { let opt = Opt::from_args(); match opt { - Opt::Clear => commenter::clear(), Opt::Add => add(), - Opt::Outdated => commenter::outdated(), + Opt::Clear => commenter::clear(), Opt::DiffSnapshot { a, b } => commenter::diff_snapshot(a, b), + Opt::Disabled => commenter::disabled(), + Opt::Outdated => commenter::outdated(), } }