Skip to content

Commit e0f67b6

Browse files
Koenraad VerheydenJoshua Nelson
authored andcommitted
Add blacklist functionality
Changes: - add a table blacklisted_crates to keep track of crate names - add a new module db::blacklist to interact with blacklisted_crates - expose blacklist functionality in the cratesfyi CLI - check if a crate is on the blacklist before building its docs and return Err if so
1 parent 242dc33 commit e0f67b6

File tree

5 files changed

+131
-0
lines changed

5 files changed

+131
-0
lines changed

src/bin/cratesfyi.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,21 @@ pub fn main() {
7777
.subcommand(SubCommand::with_name("unlock")
7878
.about("Unlocks cratesfyi daemon to continue building new crates"))
7979
.subcommand(SubCommand::with_name("print-options")))
80+
.subcommand(SubCommand::with_name("blacklist")
81+
.about("Blacklist operations")
82+
.setting(AppSettings::ArgRequiredElseHelp)
83+
.subcommand(SubCommand::with_name("add")
84+
.about("Add a crate to the blacklist")
85+
.arg(Arg::with_name("CRATE_NAME")
86+
.index(1)
87+
.required(true)
88+
.help("Crate name")))
89+
.subcommand(SubCommand::with_name("remove")
90+
.about("Remove a crate from the blacklist")
91+
.arg(Arg::with_name("CRATE_NAME")
92+
.index(1)
93+
.required(true)
94+
.help("Crate name"))))
8095
.subcommand(SubCommand::with_name("start-web-server")
8196
.about("Starts web server")
8297
.arg(Arg::with_name("SOCKET_ADDR")
@@ -200,6 +215,18 @@ pub fn main() {
200215
println!("{:?}", docbuilder.options());
201216
}
202217

218+
} else if let Some(matches) = matches.subcommand_matches("blacklist") {
219+
let conn = db::connect_db().expect("Failed to connect to the database");
220+
221+
if let Some(matches) = matches.subcommand_matches("add") {
222+
let crate_name = matches.value_of("CRATE_NAME").expect("Verified by clap");
223+
db::blacklist::add_crate(&conn, crate_name).expect("Failed to add crate to blacklist");
224+
225+
} else if let Some(matches) = matches.subcommand_matches("remove") {
226+
let crate_name = matches.value_of("CRATE_NAME").expect("Verified by clap");
227+
db::blacklist::remove_crate(&conn, crate_name).expect("Failed to remove crate from blacklist");
228+
}
229+
203230
} else if let Some(matches) = matches.subcommand_matches("database") {
204231
if let Some(matches) = matches.subcommand_matches("migrate") {
205232
let version = matches.value_of("VERSION").map(|v| v.parse::<i64>()

src/db/blacklist.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use failure::Error;
2+
use postgres::Connection;
3+
4+
#[derive(Debug, Fail)]
5+
enum BlacklistError {
6+
#[fail(display = "crate {} is already on the blacklist", _0)]
7+
CrateAlreadyOnBlacklist(String),
8+
9+
#[fail(display = "crate {} is not on the blacklist", _0)]
10+
CrateNotOnBlacklist(String),
11+
}
12+
13+
pub fn is_blacklisted(conn: &Connection, name: &str) -> Result<bool, Error> {
14+
let rows = conn.query(
15+
"SELECT COUNT(*) FROM blacklisted_crates WHERE crate_name = $1;",
16+
&[&name],
17+
)?;
18+
let count: i64 = rows.get(0).get(0);
19+
20+
Ok(count != 0)
21+
}
22+
23+
pub fn add_crate(conn: &Connection, name: &str) -> Result<(), Error> {
24+
if is_blacklisted(conn, name)? {
25+
return Err(BlacklistError::CrateAlreadyOnBlacklist(name.into()).into());
26+
}
27+
28+
conn.execute(
29+
"INSERT INTO blacklisted_crates (crate_name) VALUES ($1);",
30+
&[&name],
31+
)?;
32+
33+
Ok(())
34+
}
35+
36+
pub fn remove_crate(conn: &Connection, name: &str) -> Result<(), Error> {
37+
if !is_blacklisted(conn, name)? {
38+
return Err(BlacklistError::CrateNotOnBlacklist(name.into()).into());
39+
}
40+
41+
conn.execute(
42+
"DELETE FROM blacklisted_crates WHERE crate_name = $1;",
43+
&[&name],
44+
)?;
45+
46+
Ok(())
47+
}
48+
49+
#[cfg(test)]
50+
mod tests {
51+
use super::*;
52+
53+
#[test]
54+
fn test_add_to_and_remove_from_blacklist() {
55+
crate::test::with_database(|db| {
56+
assert!(is_blacklisted(db.conn(), "crate foo")? == false);
57+
add_crate(db.conn(), "crate foo")?;
58+
assert!(is_blacklisted(db.conn(), "crate foo")? == true);
59+
remove_crate(db.conn(), "crate foo")?;
60+
assert!(is_blacklisted(db.conn(), "crate foo")? == false);
61+
Ok(())
62+
});
63+
}
64+
65+
#[test]
66+
fn test_add_twice_to_blacklist() {
67+
crate::test::with_database(|db| {
68+
add_crate(db.conn(), "crate foo")?;
69+
assert!(add_crate(db.conn(), "crate foo").is_err());
70+
add_crate(db.conn(), "crate bar")?;
71+
72+
Ok(())
73+
});
74+
}
75+
76+
#[test]
77+
fn test_remove_non_existing_crate() {
78+
crate::test::with_database(|db| {
79+
assert!(remove_crate(db.conn(), "crate foo").is_err());
80+
81+
Ok(())
82+
});
83+
}
84+
}

src/db/migrate.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,19 @@ fn migrate_inner(version: Option<Version>, conn: &Connection, apply_mode: ApplyM
256256
// downgrade query
257257
"ALTER TABLE releases ALTER COLUMN target_name DROP NOT NULL",
258258
),
259+
migration!(
260+
context,
261+
// version
262+
6,
263+
// description
264+
"Added blacklisted_crates table",
265+
// upgrade query
266+
"CREATE TABLE blacklisted_crates (
267+
crate_name VARCHAR NOT NULL PRIMARY KEY
268+
);",
269+
// downgrade query
270+
"DROP TABLE blacklisted_crates;"
271+
),
259272
];
260273

261274
for migration in migrations {

src/db/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ mod add_package;
1717
pub mod file;
1818
mod migrate;
1919
mod delete_crate;
20+
pub mod blacklist;
2021

2122

2223
/// Connects to database

src/docbuilder/rustwide_builder.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::DocBuilder;
2+
use db::blacklist::is_blacklisted;
23
use db::file::add_path_into_database;
34
use db::{add_build_into_database, add_package_into_database, connect_db, CratesIoData};
45
use docbuilder::{crates::crates_from_path, Limits};
@@ -242,6 +243,11 @@ impl RustwideBuilder {
242243
info!("building package {} {}", name, version);
243244

244245
let conn = connect_db()?;
246+
247+
if is_blacklisted(&conn, name)? {
248+
return Err(::failure::err_msg("crate is on the blacklist"));
249+
}
250+
245251
let limits = Limits::for_crate(&conn, name)?;
246252

247253
let mut build_dir = self.workspace.build_dir(&format!("{}-{}", name, version));

0 commit comments

Comments
 (0)