From 416bda9f710e5a06e499851ad6060b0315093a4c Mon Sep 17 00:00:00 2001 From: Matthias Endler Date: Thu, 17 May 2018 21:03:39 +0200 Subject: [PATCH] Add ci (#160) --- .travis.yml | 6 ++ ci/.gitignore | 3 + ci/Cargo.lock | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++ ci/Cargo.toml | 9 ++ ci/README.md | 2 + ci/src/lib.rs | 181 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 432 insertions(+) create mode 100644 .travis.yml create mode 100644 ci/.gitignore create mode 100644 ci/Cargo.lock create mode 100644 ci/Cargo.toml create mode 100644 ci/README.md create mode 100644 ci/src/lib.rs diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..db6d2cc1f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: rust +rust: + - stable +cache: cargo +before_install: + - cd ci \ No newline at end of file diff --git a/ci/.gitignore b/ci/.gitignore new file mode 100644 index 000000000..48d269417 --- /dev/null +++ b/ci/.gitignore @@ -0,0 +1,3 @@ +/target/ +**/*.rs.bk +.env diff --git a/ci/Cargo.lock b/ci/Cargo.lock new file mode 100644 index 000000000..0d4d49f98 --- /dev/null +++ b/ci/Cargo.lock @@ -0,0 +1,231 @@ +[[package]] +name = "aho-corasick" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cc" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ci" +version = "0.2.0" +dependencies = [ + "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.40" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ucd-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf8-ranges" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" +"checksum backtrace 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea58cd16fd6c9d120b5bcb01d63883ae4cc7ba2aed35c1841b862a3c7ef6639" +"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" +"checksum cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebb87d1116151416c0cf66a0e3fb6430cccd120fd6300794b4dfaa050ac40ba" +"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18" +"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" +"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" +"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" +"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" +"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" +"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" +"checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" +"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" +"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/ci/Cargo.toml b/ci/Cargo.toml new file mode 100644 index 000000000..41e3d98bb --- /dev/null +++ b/ci/Cargo.toml @@ -0,0 +1,9 @@ +[package] +authors = ["Matthias Endler "] +name = "ci" +version = "0.2.0" + +[dependencies] +lazy_static = "0.2.9" +regex = "0.2.2" +failure = "0.1.1" diff --git a/ci/README.md b/ci/README.md new file mode 100644 index 000000000..e91622417 --- /dev/null +++ b/ci/README.md @@ -0,0 +1,2 @@ +This is the CI environment for awesome-static-analysis. +Read more about the tooling here: https://matthias-endler.de/2017/obsolete/ \ No newline at end of file diff --git a/ci/src/lib.rs b/ci/src/lib.rs new file mode 100644 index 000000000..5137a4db1 --- /dev/null +++ b/ci/src/lib.rs @@ -0,0 +1,181 @@ +// `error_chain!` can recurse deeply +#![recursion_limit = "1024"] + +#[macro_use] +extern crate failure; + +#[macro_use] +extern crate lazy_static; + +extern crate regex; + +use failure::{Error, err_msg}; +use regex::Regex; +use std::fmt; +use std::cmp::Ordering; + +lazy_static! { + static ref TOOL_REGEX: Regex = Regex::new(r"\*\s\[(?P.*)\]\((?Phttp[s]?://.*)\)\s(:copyright:\s)?\-\s(?P.*)").unwrap(); + static ref SUBSECTION_HEADLINE_REGEX: Regex = Regex::new(r"[A-Za-z\s]*").unwrap(); +} + +struct Tool { + name: String, + link: String, + desc: String, +} + +impl Tool { + fn new>(name: T, link: T, desc: T) -> Self { + Tool { + name: name.into(), + link: link.into(), + desc: desc.into(), + } + } +} + +impl PartialEq for Tool { + fn eq(&self, other: &Tool) -> bool { + self.name.to_lowercase() == other.name.to_lowercase() + } +} + +impl Eq for Tool {} + +impl PartialOrd for Tool { + fn partial_cmp(&self, other: &Tool) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Tool { + fn cmp(&self, other: &Tool) -> Ordering { + self.name.to_lowercase().cmp(&other.name.to_lowercase()) + } +} + +fn check_tool(tool: &str) -> Result { + println!("Checking `{}`", tool); + // NoneError can not implement Fail at this time. That's why we use ok_or + // See https://github.com/rust-lang-nursery/failure/issues/61 + let captures = TOOL_REGEX.captures(tool).ok_or(err_msg(format!("Tool does not match regex: {}", tool)))?; + + let name = captures["name"].to_string(); + let link = captures["link"].to_string(); + let desc = captures["desc"].to_string(); + + if name.len() > 50 { + bail!("Name of tool is suspiciously long: `{}`", name); + } + + // A somewhat arbitrarily chosen description length. + // Note that this includes any markdown formatting + // like links. Therefore we are quite generous for now. + if desc.len() > 200 { + bail!("Desription of `{}` is too long: {}", name, desc); + } + + Ok(Tool::new(name, link, desc)) +} + +fn check_section(section: String) -> Result<(), Error> { + // Ignore license section + if section.starts_with("License") { + return Ok(()); + } + + // Skip section headline + let lines: Vec<_> = section.split('\n').skip(1).collect(); + if lines.is_empty() { + bail!("Empty section: {}", section) + }; + + let mut tools = vec![]; + for line in lines { + if line.is_empty() { + continue; + } + // Exception for subsection headlines + if !line.starts_with("*") && line.ends_with(":") && + SUBSECTION_HEADLINE_REGEX.is_match(line) + { + continue; + } + tools.push(check_tool(line)?); + } + // Tools need to be alphabetically ordered + check_ordering(tools) +} + +fn check_ordering(tools: Vec) -> Result<(), Error> { + match tools.windows(2).find(|t| t[0] > t[1]) { + Some(tools) => bail!("`{}` does not conform to alphabetical ordering", tools[0].name), + None => Ok(()), + } +} + +fn check(text: String) -> Result<(), Error> { + let sections = text.split("\n# "); + + // Skip first two sections, + // as they contain the prelude and the table of contents. + for section in sections.skip(2) { + let subsections = section.split("## "); + for subsection in subsections.skip(1) { + check_section(subsection.into())?; + } + } + Ok(()) +} + +mod tests { + use super::*; + use std::fs::File; + use std::io::Read; + + #[test] + fn test_complete_file() { + let mut file = File::open("../README.md").expect("Can't open testfile"); + let mut contents = String::new(); + file.read_to_string(&mut contents).expect("Can't read testfile contents"); + let result = check(contents); + if result.is_err() { + println!("Error: {:?}", result.err()); + assert!(false); + } else { + assert!(true); + } + } + + + #[test] + fn test_correct_ordering() { + assert!(check_ordering(vec![]).is_ok()); + + assert!(check_ordering(vec![Tool::new("a", "url", "desc")]).is_ok()); + + assert!( + check_ordering(vec![ + Tool::new("0", "", ""), + Tool::new("1", "", ""), + Tool::new("a", "", ""), + Tool::new("Axx", "", ""), + Tool::new("B", "", ""), + Tool::new("b", "", ""), + Tool::new("c", "", ""), + ]).is_ok() + ); + } + + #[test] + fn test_incorrect_ordering() { + assert!( + check_ordering(vec![ + Tool::new("b", "", ""), + Tool::new("a", "", ""), + Tool::new("c", "", ""), + ]).is_err() + ); + } +}