about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/branches.rs196
-rw-r--r--src/github.rs2
-rw-r--r--src/main.rs4
-rw-r--r--src/nixpkgs.rs8
-rw-r--r--src/tree.rs18
5 files changed, 201 insertions, 27 deletions
diff --git a/src/branches.rs b/src/branches.rs
index 3ca3d0d..b6e3d45 100644
--- a/src/branches.rs
+++ b/src/branches.rs
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: AGPL-3.0-or-later WITH GPL-3.0-linking-exception
-// SPDX-FileCopyrightText: 2021 Alyssa Ross <hi@alyssa.is>
+// SPDX-FileCopyrightText: 2021, 2023 Alyssa Ross <hi@alyssa.is>
+// SPDX-FileCopyrightText: 2022 Arnout Engelen <arnout@bzzt.net>
 
 use std::borrow::Cow;
 use std::collections::BTreeMap;
@@ -7,10 +8,12 @@ use std::collections::BTreeMap;
 use once_cell::sync::Lazy;
 use regex::{Regex, RegexSet};
 
-const NEXT_BRANCH_TABLE: [(&str, &str); 10] = [
+const NEXT_BRANCH_TABLE: [(&str, &str); 12] = [
+    (r"\Apython-updates\z", "staging"),
     (r"\Astaging\z", "staging-next"),
     (r"\Astaging-next\z", "master"),
     (r"\Astaging-next-([\d.]+)\z", "release-$1"),
+    (r"\Ahaskell-updates\z", "master"),
     (r"\Amaster\z", "nixpkgs-unstable"),
     (r"\Amaster\z", "nixos-unstable-small"),
     (r"\Anixos-(.*)-small\z", "nixos-$1"),
@@ -20,6 +23,25 @@ const NEXT_BRANCH_TABLE: [(&str, &str); 10] = [
     (r"\Astaging-((2[1-9]|[3-90].)\.\d{2})\z", "staging-next-$1"),
 ];
 
+const BRANCH_HYDRA_LINK_TABLE: [(&str, &str); 5] = [
+    (r"\Apython-updates\z", "nixpkgs/python-updates"),
+    (r"\Astaging-next\z", "nixpkgs/staging-next"),
+    // There's no staging-next-21.11 for some reason.
+    (
+        r"\Astaging-next-([013-9]\d\.\d{2}|2(1\.05|[2-90]\.\d{2}))\z",
+        "nixpkgs/staging-next-$1",
+    ),
+    (r"\Ahaskell-updates\z", "nixpkgs/haskell-updates"),
+    (r"\Amaster\z", "nixpkgs/trunk"),
+];
+
+const CHANNEL_HYDRA_LINK_TABLE: [(&str, &str); 4] = [
+    (r"\Anixpkgs-unstable\z", "nixpkgs/trunk/unstable"),
+    (r"\Anixos-unstable-small\z", "nixos/unstable-small/tested"),
+    (r"\Anixos-unstable\z", "nixos/trunk-combined/tested"),
+    (r"\Anixos-(\d.*)\z", "nixos/release-$1/tested"),
+];
+
 static BRANCH_NEXTS: Lazy<BTreeMap<&str, Vec<&str>>> = Lazy::new(|| {
     NEXT_BRANCH_TABLE
         .iter()
@@ -57,49 +79,191 @@ pub fn next_branches(branch: &str) -> Vec<Cow<str>> {
         .collect()
 }
 
+static BRANCH_HYDRA_LINK_PATTERNS: Lazy<Vec<Regex>> = Lazy::new(|| {
+    BRANCH_HYDRA_LINKS
+        .keys()
+        .copied()
+        .map(Regex::new)
+        .map(Result::unwrap)
+        .collect()
+});
+
+static BRANCH_HYDRA_LINKS: Lazy<BTreeMap<&str, String>> = Lazy::new(|| {
+    let branch_links = BRANCH_HYDRA_LINK_TABLE.iter().map(|(pattern, jobset)| {
+        (
+            *pattern,
+            format!("https://hydra.nixos.org/jobset/{jobset}#tabs-jobs"),
+        )
+    });
+    let channel_links = CHANNEL_HYDRA_LINK_TABLE.iter().map(|(pattern, job)| {
+        (
+            *pattern,
+            format!("https://hydra.nixos.org/job/{job}#tabs-constituents"),
+        )
+    });
+    branch_links.chain(channel_links).collect()
+});
+
+static BRANCH_HYDRA_LINKS_BY_INDEX: Lazy<Vec<String>> =
+    Lazy::new(|| BRANCH_HYDRA_LINKS.values().cloned().collect());
+
+static BRANCH_HYDRA_LINK_REGEXES: Lazy<RegexSet> =
+    Lazy::new(|| RegexSet::new(BRANCH_HYDRA_LINKS.keys()).unwrap());
+
+pub fn branch_hydra_link(branch: &str) -> Option<String> {
+    BRANCH_HYDRA_LINK_REGEXES
+        .matches(branch)
+        .iter()
+        .next()
+        .and_then(|index| {
+            let regex = BRANCH_HYDRA_LINK_PATTERNS.get(index).unwrap();
+            BRANCH_HYDRA_LINKS_BY_INDEX
+                .get(index)
+                .map(move |link| regex.replace(branch, link).to_string())
+        })
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
 
     #[test]
+    fn python_updates() {
+        let res = next_branches("python-updates");
+        assert_eq!(res, vec!["staging"]);
+    }
+
+    #[test]
+    fn staging_next() {
+        let branch = "staging-next";
+        let res = next_branches(branch);
+        assert_eq!(res, vec!["master"]);
+        let link = branch_hydra_link(branch);
+        let expected = "https://hydra.nixos.org/jobset/nixpkgs/staging-next#tabs-jobs";
+        assert_eq!(link.unwrap(), expected);
+    }
+
+    #[test]
     fn staging_18_03() {
-	let res = next_branches("staging-18.03");
-	assert_eq!(res, vec!["release-18.03"]);
+        let branch = "staging-18.03";
+        let next = next_branches(branch);
+        assert_eq!(next, vec!["release-18.03"]);
+        let link = branch_hydra_link(branch);
+        assert_eq!(link, None);
     }
 
     #[test]
     fn staging_20_09() {
-	let res = next_branches("staging-20.09");
-	assert_eq!(res, vec!["release-20.09"]);
+        let res = next_branches("staging-20.09");
+        assert_eq!(res, vec!["release-20.09"]);
     }
 
     #[test]
     fn staging_21_05() {
-	let res = next_branches("staging-21.05");
-	assert_eq!(res, vec!["staging-next-21.05"]);
+        let res = next_branches("staging-21.05");
+        assert_eq!(res, vec!["staging-next-21.05"]);
     }
 
     #[test]
     fn staging_30_05() {
-	let res = next_branches("staging-30.05");
-	assert_eq!(res, vec!["staging-next-30.05"]);
+        let res = next_branches("staging-30.05");
+        assert_eq!(res, vec!["staging-next-30.05"]);
     }
 
     #[test]
     fn staging_00_11() {
-	let res = next_branches("staging-00.11");
-	assert_eq!(res, vec!["staging-next-00.11"]);
+        let res = next_branches("staging-00.11");
+        assert_eq!(res, vec!["staging-next-00.11"]);
     }
 
     #[test]
     fn staging_next_21_05() {
-	let res = next_branches("staging-next-21.05");
-	assert_eq!(res, vec!["release-21.05"]);
+        let branch = "staging-next-21.05";
+        let res = next_branches(branch);
+        assert_eq!(res, vec!["release-21.05"]);
+        let link = branch_hydra_link(branch);
+        let expected = "https://hydra.nixos.org/jobset/nixpkgs/staging-next-21.05#tabs-jobs";
+        assert_eq!(link.unwrap(), expected);
+    }
+
+    #[test]
+    fn staging_next_21_11() {
+        let branch = "staging-next-21.11";
+        let next = next_branches(branch);
+        assert_eq!(next, vec!["release-21.11"]);
+        assert!(branch_hydra_link(branch).is_none());
+    }
+
+    #[test]
+    fn staging_next_22_05() {
+        let branch = "staging-next-22.05";
+        let next = next_branches(branch);
+        assert_eq!(next, vec!["release-22.05"]);
+        let link = branch_hydra_link(branch);
+        let expected = "https://hydra.nixos.org/jobset/nixpkgs/staging-next-22.05#tabs-jobs";
+        assert_eq!(link.unwrap(), expected);
+    }
+
+    #[test]
+    fn staging_next_30_05() {
+        let branch = "staging-next-30.05";
+        let next = next_branches(branch);
+        assert_eq!(next, vec!["release-30.05"]);
+        let link = branch_hydra_link(branch);
+        let expected = "https://hydra.nixos.org/jobset/nixpkgs/staging-next-30.05#tabs-jobs";
+        assert_eq!(link.unwrap(), expected);
+    }
+
+    #[test]
+    fn haskell_updates() {
+        let branch = "haskell-updates";
+        let next = next_branches(branch);
+        assert_eq!(next, vec!["master"]);
+    }
+
+    #[test]
+    fn master() {
+        let branch = "master";
+        let next = next_branches(branch);
+        assert_eq!(next, vec!["nixpkgs-unstable", "nixos-unstable-small"]);
+        let link = branch_hydra_link(branch);
+        let expected = "https://hydra.nixos.org/jobset/nixpkgs/trunk#tabs-jobs";
+        assert_eq!(link.unwrap(), expected);
     }
 
     #[test]
     fn release_20_09() {
-	let res = next_branches("release-20.09");
-	assert_eq!(res, vec!["nixpkgs-20.09-darwin", "nixos-20.09-small"]);
+        let res = next_branches("release-20.09");
+        assert_eq!(res, vec!["nixpkgs-20.09-darwin", "nixos-20.09-small"]);
+    }
+
+    #[test]
+    fn nixpkgs_unstable() {
+        let branch = "nixpkgs-unstable";
+        let next = next_branches(branch);
+        assert!(next.is_empty());
+        let link = branch_hydra_link(branch);
+        let expected = "https://hydra.nixos.org/job/nixpkgs/trunk/unstable#tabs-constituents";
+        assert_eq!(link.unwrap(), expected);
+    }
+
+    #[test]
+    fn nixos_unstable_small() {
+        let branch = "nixos-unstable-small";
+        let next = next_branches(branch);
+        assert_eq!(next, vec!["nixos-unstable"]);
+        let link = branch_hydra_link(branch);
+        let expected = "https://hydra.nixos.org/job/nixos/unstable-small/tested#tabs-constituents";
+        assert_eq!(link.unwrap(), expected);
+    }
+
+    #[test]
+    fn nixos_unstable() {
+        let branch = "nixos-unstable";
+        let next = next_branches(branch);
+        assert_eq!(next.len(), 0);
+        let link = branch_hydra_link(branch);
+        let expected = "https://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents";
+        assert_eq!(link.unwrap(), expected);
     }
 }
diff --git a/src/github.rs b/src/github.rs
index 1128f95..e5be0d3 100644
--- a/src/github.rs
+++ b/src/github.rs
@@ -117,7 +117,7 @@ impl<'a> GitHub<'a> {
     fn authorization_header(&self) -> Result<HeaderValue, surf::Error> {
         let mut value = b"bearer ".to_vec();
         value.extend_from_slice(self.token.as_bytes());
-        Ok(HeaderValue::from_bytes(value)?)
+        HeaderValue::from_bytes(value)
     }
 
     pub async fn pr_info_for_nixpkgs_pr(&self, pr: i64) -> Result<PrInfo, Error> {
diff --git a/src/main.rs b/src/main.rs
index 0b70a15..b088e1f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -162,7 +162,7 @@ async fn main() {
         E: std::error::Error,
     {
         match result {
-            Ok(v) => return v,
+            Ok(v) => v,
             Err(e) => {
                 eprintln!("pr-tracker: {}: {}", message.as_ref(), e);
                 exit(code);
@@ -188,7 +188,7 @@ async fn main() {
 
     let mut listeners: Vec<Pin<Box<dyn Future<Output = _>>>> = Vec::new();
 
-    for fd in (3..).into_iter().take(fd_count as usize) {
+    for fd in (3..).take(fd_count as usize) {
         let s = server.clone();
         if handle_error(is_socket_inet(fd), 74, "sd_is_socket_inet") {
             listeners.push(Box::pin(s.listen(unsafe { TcpListener::from_raw_fd(fd) })));
diff --git a/src/nixpkgs.rs b/src/nixpkgs.rs
index 7e622c2..6656543 100644
--- a/src/nixpkgs.rs
+++ b/src/nixpkgs.rs
@@ -56,7 +56,7 @@ impl<'a> Nixpkgs<'a> {
     fn git_command(&self, subcommand: impl AsRef<OsStr>) -> Command {
         let mut command = Command::new("git");
         command.arg("-C");
-        command.arg(&self.path);
+        command.arg(self.path);
         command.arg(subcommand);
         command
     }
@@ -64,7 +64,7 @@ impl<'a> Nixpkgs<'a> {
     async fn git_branch_contains(&self, commit: &str) -> Result<Vec<u8>> {
         let output = self
             .git_command("branch")
-            .args(&["-r", "--format=%(refname)", "--contains"])
+            .args(["-r", "--format=%(refname)", "--contains"])
             .arg(commit)
             .stderr(Stdio::inherit())
             .output()
@@ -79,7 +79,7 @@ impl<'a> Nixpkgs<'a> {
     async fn git_fetch_nixpkgs(&self) -> Result<()> {
         // TODO: add refspecs
         self.git_command("fetch")
-            .arg(&self.remote_name)
+            .arg(self.remote_name)
             .status()
             .await
             .map_err(Error::Io)
@@ -109,7 +109,7 @@ impl<'a> Nixpkgs<'a> {
         };
 
         let mut prefix = PathBuf::from("refs/remotes/");
-        prefix.push(&self.remote_name);
+        prefix.push(self.remote_name);
 
         for branch_name in output
             .split(|byte| *byte == b'\n')
diff --git a/src/tree.rs b/src/tree.rs
index f569dba..91dc05d 100644
--- a/src/tree.rs
+++ b/src/tree.rs
@@ -1,11 +1,13 @@
 // SPDX-License-Identifier: AGPL-3.0-or-later WITH GPL-3.0-linking-exception
 // SPDX-FileCopyrightText: 2021 Alyssa Ross <hi@alyssa.is>
+// SPDX-FileCopyrightText: 2022 Arnout Engelen <arnout@bzzt.net>
 
 use std::collections::BTreeSet;
 use std::ffi::{OsStr, OsString};
 
 use askama::Template;
 
+use crate::branches::branch_hydra_link;
 use crate::branches::next_branches;
 use crate::github;
 use crate::nixpkgs::Nixpkgs;
@@ -15,6 +17,7 @@ use crate::nixpkgs::Nixpkgs;
 pub struct Tree {
     branch_name: String,
     accepted: Option<bool>,
+    hydra_link: Option<String>,
     children: Vec<Tree>,
 }
 
@@ -27,9 +30,12 @@ impl Tree {
             .map(|b| Self::generate(b.to_string(), found_branches))
             .collect();
 
+        let link = branch_hydra_link(&branch);
+
         Tree {
             accepted: None,
             branch_name: branch,
+            hydra_link: link,
             children: nexts,
         }
     }
@@ -46,7 +52,11 @@ impl Tree {
         }
     }
 
-    pub async fn make(base_branch: String, merge_status: &github::PullRequestStatus, nixpkgs: &Nixpkgs<'_>) -> Tree {
+    pub async fn make(
+        base_branch: String,
+        merge_status: &github::PullRequestStatus,
+        nixpkgs: &Nixpkgs<'_>,
+    ) -> Tree {
         let mut missing_means_absent = true;
         let mut branches = BTreeSet::new();
 
@@ -59,9 +69,9 @@ impl Tree {
             if let Some(merge_commit) = merge_commit_oid {
                 let mut containing_commits = BTreeSet::new();
 
-                if let Err(e) =
-                    nixpkgs.branches_containing_commit(&merge_commit, &mut containing_commits)
-                        .await
+                if let Err(e) = nixpkgs
+                    .branches_containing_commit(merge_commit, &mut containing_commits)
+                    .await
                 {
                     eprintln!("pr-tracker: branches_containing_commit: {}", e);
                     missing_means_absent = false;