Calculate maintainers

This commit is contained in:
Graham Christensen 2019-01-01 15:44:22 -05:00
parent 789e0d81bd
commit 5b6a387fee
No known key found for this signature in database
GPG key ID: ACA1C1D120C83D5C
3 changed files with 195 additions and 0 deletions

View file

@ -39,6 +39,7 @@ pub mod evalchecker;
pub mod files;
pub mod ghevent;
pub mod locks;
pub mod maintainers;
pub mod message;
pub mod nix;
pub mod notifyworker;

110
ofborg/src/maintainers.nix Normal file
View file

@ -0,0 +1,110 @@
{ changedattrsjson, changedpathsjson }:
let
pkgs = import ./. {};
changedattrs = builtins.fromJSON changedattrsjson;
changedpaths = builtins.fromJSON changedpathsjson;
anyMatchingFile = filename:
let
matching = builtins.filter
(changed: pkgs.lib.strings.hasSuffix changed filename)
changedpaths;
in (builtins.length matching) > 0;
anyMatchingFiles = files:
(builtins.length (builtins.filter anyMatchingFile files)) > 0;
enrichedAttrs = builtins.map
(path: {
path = path;
name = "pkgs.${builtins.concatStringsSep "." path}";
})
changedattrs;
validPackageAttributes = builtins.filter
(pkg:
if (pkgs.lib.attrsets.hasAttrByPath pkg.path pkgs) then
(if (builtins.tryEval (pkgs.lib.attrsets.attrByPath pkg.path null pkgs)).success
then true
else builtins.trace "Failed to access ${pkg.name} even though it exists" false)
else builtins.trace "Failed to locate ${pkg.name}." false
)
enrichedAttrs;
attrsWithPackages = builtins.map
(pkg: pkg // { package = pkgs.lib.attrsets.attrByPath pkg.path null pkgs; })
validPackageAttributes;
attrsWithMaintainers = builtins.map
(pkg: pkg // { maintainers = (pkg.package.meta or {}).maintainers or []; })
attrsWithPackages;
attrsWeCanPing = builtins.filter
(pkg: if (builtins.length pkg.maintainers) > 0
then true
else builtins.trace "Package has no maintainers: ${pkg.name}" false
)
attrsWithMaintainers;
relevantFilenames = drv:
(pkgs.lib.lists.unique
(builtins.map
(pos: pos.file)
(builtins.filter (x: x != null)
[
(builtins.unsafeGetAttrPos "maintainers" (drv.meta or {}))
(builtins.unsafeGetAttrPos "src" drv)
# broken because name is always set in stdenv:
# # A hack to make `nix-env -qa` and `nix search` ignore broken packages.
# # TODO(@oxij): remove this assert when something like NixOS/nix#1771 gets merged into nix.
# name = assert validity.handled; name + lib.optionalString
#(builtins.unsafeGetAttrPos "name" drv)
(builtins.unsafeGetAttrPos "pname" drv)
(builtins.unsafeGetAttrPos "version" drv)
]
)));
attrsWithFilenames = builtins.map
(pkg: pkg // { filenames = relevantFilenames pkg.package; })
attrsWithMaintainers;
attrsWithModifiedFiles = builtins.filter
(pkg: anyMatchingFiles pkg.filenames)
attrsWithFilenames;
listToPing = pkgs.lib.lists.flatten
(builtins.map
(pkg:
builtins.map
(maintainer: {
handle = maintainer.github;
packageName = pkg.name;
dueToFiles = pkg.filenames;
})
pkg.maintainers
)
attrsWithModifiedFiles);
byMaintainer = pkgs.lib.lists.foldr
(ping: collector: collector // { "${ping.handle}" = [ { inherit (ping) packageName dueToFiles; } ] ++ (collector."${ping.handle}" or []); })
{}
listToPing;
textForPackages = packages:
pkgs.lib.strings.concatStringsSep ", " (
builtins.map
(pkg: pkg.packageName)
packages);
textPerMaintainer = pkgs.lib.attrsets.mapAttrs
(maintainer: packages: "- @${maintainer} for ${textForPackages packages}")
byMaintainer;
packagesPerMaintainer = pkgs.lib.attrsets.mapAttrs
(maintainer: packages:
builtins.map
(pkg: pkg.packageName)
packages)
byMaintainer;
in packagesPerMaintainer

84
ofborg/src/maintainers.rs Normal file
View file

@ -0,0 +1,84 @@
use std::collections::HashMap;
#[derive(Deserialize, Debug, Eq, PartialEq)]
struct ImpactedMaintainers(HashMap<Maintainer, Vec<Package>>);
#[derive(Deserialize, Debug, Eq, PartialEq, Hash)]
struct Maintainer(String);
impl<'a> From<&'a str> for Maintainer {
fn from(name: &'a str) -> Maintainer {
Maintainer(name.to_owned())
}
}
#[derive(Deserialize, Debug, Eq, PartialEq, Hash)]
struct Package(String);
impl<'a> From<&'a str> for Package {
fn from(name: &'a str) -> Package {
Package(name.to_owned())
}
}
#[cfg(test)]
mod tests {
use super::*;
use checkout::cached_cloner;
use clone::GitClonable;
use ofborg::nix::Nix;
use std::env;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
fn tpath(component: &str) -> PathBuf {
return Path::new(env!("CARGO_MANIFEST_DIR")).join(component);
}
#[test]
fn example() {
let attributes = vec![vec!["kgpg"], vec!["qrencode"], vec!["pass"]];
let cloner = cached_cloner(&tpath("nixpkgs"));
let project = cloner.project(
"commit-msg-list".to_owned(),
"https://github.com/nixos/nixpkgs.git".to_owned(),
);
let working_co = project
.clone_for("testing-commit-msgs".to_owned(), "123".to_owned())
.expect("clone should work");
working_co
.checkout_origin_ref(OsStr::new("master"))
.unwrap();
working_co.fetch_pr(53149).unwrap();
let paths = working_co.files_changed_from_head("pr").unwrap();
let pathstr = serde_json::to_string(&paths).unwrap();
let attrstr = serde_json::to_string(&attributes).unwrap();
let mut argstrs: HashMap<&str, &str> = HashMap::new();
argstrs.insert("changedattrsjson", &attrstr);
argstrs.insert("changedpathsjson", &pathstr);
let remote = env::var("NIX_REMOTE").unwrap_or("".to_owned());
let nix = Nix::new("x86_64-linux".to_owned(), remote, 1800, None);
let ret = nix
.safely_evaluate_expr_cmd(
&working_co.clone_to(),
include_str!("./maintainers.nix"),
argstrs,
)
.output()
.expect(":)");
let parsed: ImpactedMaintainers =
serde_json::from_str(&String::from_utf8(ret.stdout).unwrap()).unwrap();
let mut expect = ImpactedMaintainers(HashMap::new());
expect.0.insert(
Maintainer::from("yegortimoshenko"),
vec![Package::from("pkgs.qrencode")],
);
assert_eq!(parsed, expect);
}
}