commenter disabled: count transitive dependents

This commit is contained in:
Adam Bergmark 2022-01-17 01:42:01 +01:00
parent 4fe6e23bd4
commit 2984a8c1c7
3 changed files with 137 additions and 6 deletions

View File

@ -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

View File

@ -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<DisabledTransitively> {
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<Package, (Vec<VersionedPackage>, Option<usize>)>;
pub fn disabled() {
let mut disabled_transitively: Vec<DisabledTransitively> = vec![];
handle(false, |loc, lines| {
match loc {
Location::Lib => disabled_transitively.extend(
lines
.into_iter()
.map(|line| parse_disabled_transitviely(&line))
.flatten()
.collect::<Vec<_>>(),
),
Location::Test | Location::Bench => (),
}
vec![]
});
let mut packages: BTreeSet<Package> = 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<Package> = 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
}

View File

@ -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(),
}
}