From 5e2884174fa14115799aea89997153b32572bf58 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 26 Mar 2019 17:13:28 -0500 Subject: [PATCH 01/17] mark releases as yanked when a yank is detected --- src/docbuilder/queue.rs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/docbuilder/queue.rs b/src/docbuilder/queue.rs index f0f1df98f..54a5c8ecf 100644 --- a/src/docbuilder/queue.rs +++ b/src/docbuilder/queue.rs @@ -19,12 +19,26 @@ impl DocBuilder { // I belive this will fix ordering of queue if we get more than one crate from changes changes.reverse(); - for krate in changes.iter().filter(|k| k.kind != ChangeKind::Yanked) { - let priority = get_crate_priority(&conn, &krate.name)?; - add_crate_to_queue(&conn, &krate.name, &krate.version, priority).ok(); + for krate in &changes { + match krate.kind { + ChangeKind::Yanked => { + // FIXME: remove built doc files? set build as failed? + conn.execute( + "UPDATE releases SET yanked = TRUE FROM crates WHERE \ + crates.id = releases.crate_id AND name = $1 AND version = $2", + &[&krate.name, &krate.version], + ) + .ok(); + debug!("{}-{} yanked", krate.name, krate.version); + } + ChangeKind::Added => { + let priority = get_crate_priority(&conn, &krate.name)?; + add_crate_to_queue(&conn, &krate.name, &krate.version, priority).ok(); - debug!("{}-{} added into build queue", krate.name, krate.version); - add_count += 1; + debug!("{}-{} added into build queue", krate.name, krate.version); + add_count += 1; + } + } } Ok(add_count) From f1f99e7d9b4203359280df9ab6d61b46bdbabb1b Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Wed, 27 Mar 2019 09:45:20 -0500 Subject: [PATCH 02/17] show yanked status on crate details page --- src/web/crate_details.rs | 12 ++++++++---- templates/crate_details.hbs | 4 ++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/web/crate_details.rs b/src/web/crate_details.rs index e80e7c6e4..29b88b9e3 100644 --- a/src/web/crate_details.rs +++ b/src/web/crate_details.rs @@ -40,6 +40,7 @@ pub struct CrateDetails { github_issues: Option, pub(crate) metadata: MetaData, is_library: bool, + yanked: bool, pub(crate) doc_targets: Vec, license: Option, documentation_url: Option, @@ -83,6 +84,7 @@ impl ToJson for CrateDetails { m.insert("github_issues".to_string(), self.github_issues.to_json()); m.insert("metadata".to_string(), self.metadata.to_json()); m.insert("is_library".to_string(), self.is_library.to_json()); + m.insert("yanked".to_string(), self.yanked.to_json()); m.insert("doc_targets".to_string(), self.doc_targets.to_json()); m.insert("license".to_string(), self.license.to_json()); m.insert( @@ -134,6 +136,7 @@ impl CrateDetails { crates.github_forks, crates.github_issues, releases.is_library, + releases.yanked, releases.doc_targets, releases.license, releases.documentation_url, @@ -180,11 +183,11 @@ impl CrateDetails { description: rows.get(0).get(4), rustdoc_status: rows.get(0).get(11), target_name: rows.get(0).get(16), - default_target: rows.get(0).get(25), + default_target: rows.get(0).get(26), }; let doc_targets = { - let data: Json = rows.get(0).get(22); + let data: Json = rows.get(0).get(23); data.as_array() .map(|array| { array @@ -221,9 +224,10 @@ impl CrateDetails { github_issues: rows.get(0).get(20), metadata, is_library: rows.get(0).get(21), + yanked: rows.get(0).get(22), doc_targets, - license: rows.get(0).get(23), - documentation_url: rows.get(0).get(24), + license: rows.get(0).get(24), + documentation_url: rows.get(0).get(25), }; if let Some(repository_url) = crate_details.repository_url.clone() { diff --git a/templates/crate_details.hbs b/templates/crate_details.hbs index c9ed6093c..4757c5513 100644 --- a/templates/crate_details.hbs +++ b/templates/crate_details.hbs @@ -67,6 +67,9 @@ {{#unless is_library}}
{{name}}-{{version}} is not a library.
{{else}} + {{#if yanked}} +
{{name}}-{{version}} has been yanked.
+ {{else}} {{#unless build_status}}
docs.rs failed to build {{name}}-{{version}}
Please check the build logs and, if you believe this is docs.rs' fault, open an issue.
{{#if last_successful_build}} @@ -77,6 +80,7 @@
{{name}}-{{version}} doesn't have any documentation.
{{/unless}} {{/unless}} + {{/if}} {{/unless}} {{#if readme}} {{{readme}}} From 97572cb1327227431cbc147e47a56560823ea6aa Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Wed, 27 Mar 2019 11:43:38 -0500 Subject: [PATCH 03/17] don't redirect to a yanked version if it's the latest --- src/web/mod.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/web/mod.rs b/src/web/mod.rs index af4844cd9..ea1e4443c 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -259,8 +259,8 @@ fn match_version(conn: &Connection, name: &str, version: Option<&str>) -> Option .unwrap_or_else(|| "*".into()); let mut corrected_name = None; - let versions: Vec<(String, i32)> = { - let query = "SELECT name, version, releases.id + let versions: Vec<(String, i32, bool)> = { + let query = "SELECT name, version, releases.id, releases.yanked FROM releases INNER JOIN crates ON releases.crate_id = crates.id WHERE normalize_crate_name(name) = normalize_crate_name($1) AND yanked = false"; @@ -275,11 +275,12 @@ fn match_version(conn: &Connection, name: &str, version: Option<&str>) -> Option } }; - rows.map(|row| (row.get(1), row.get(2))).collect() + rows.map(|row| (row.get(1), row.get(2), row.get(3))) + .collect() }; // first check for exact match, we can't expect users to use semver in query - if let Some((version, id)) = versions.iter().find(|(vers, _)| vers == &req_version) { + if let Some((version, id, _)) = versions.iter().find(|(vers, _, _)| vers == &req_version) { return Some(MatchVersion { corrected_name, version: MatchSemver::Exact((version.to_owned(), *id)), @@ -293,7 +294,7 @@ fn match_version(conn: &Connection, name: &str, version: Option<&str>) -> Option let versions_sem = { let mut versions_sem: Vec<(Version, i32)> = Vec::new(); - for version in &versions { + for version in versions.iter().filter(|(_, _, yanked)| !yanked) { // in theory a crate must always have a semver compatible version, but check result just in case versions_sem.push((Version::parse(&version.0).ok()?, version.1)); } @@ -314,11 +315,11 @@ fn match_version(conn: &Connection, name: &str, version: Option<&str>) -> Option } // semver is acting weird for '*' (any) range if a crate only have pre-release versions - // return first version if requested version is '*' - if req_version == "*" && !versions_sem.is_empty() { - return Some(MatchVersion { + // return first non-yanked version if requested version is '*' + if req_version == "*" { + return versions_sem.first().map(|v| MatchVersion { corrected_name, - version: MatchSemver::Semver((versions_sem[0].0.to_string(), versions_sem[0].1)), + version: MatchSemver::Semver((v.0.to_string(), v.1)), }); } From cec4e57e2ffb4a2d34df9ae2520db66ed2819eaf Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Wed, 27 Mar 2019 14:22:30 -0500 Subject: [PATCH 04/17] add test to load handlebars templates --- src/web/mod.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/web/mod.rs b/src/web/mod.rs index ea1e4443c..2c80c9bdc 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -56,7 +56,7 @@ mod sitemap; mod source; use self::pool::Pool; -use handlebars_iron::{DirectorySource, HandlebarsEngine}; +use handlebars_iron::{DirectorySource, HandlebarsEngine, SourceError}; use iron::headers::{CacheControl, CacheDirective, ContentType, Expires, HttpDate}; use iron::modifiers::Redirect; use iron::prelude::*; @@ -87,6 +87,17 @@ const DEFAULT_BIND: &str = "0.0.0.0:3000"; type PoolFactoryFn = dyn Fn() -> Pool + Send + Sync; type PoolFactory = Box; +fn handlebars_engine() -> Result { + // TODO: Use DocBuilderOptions for paths + let mut hbse = HandlebarsEngine::new(); + hbse.add(Box::new(DirectorySource::new("./templates", ".hbs"))); + + // load templates + hbse.reload()?; + + Ok(hbse) +} + struct CratesfyiHandler { shared_resource_handler: Box, router_handler: Box, @@ -97,14 +108,7 @@ struct CratesfyiHandler { impl CratesfyiHandler { fn chain(pool_factory: &PoolFactoryFn, base: H) -> Chain { - // TODO: Use DocBuilderOptions for paths - let mut hbse = HandlebarsEngine::new(); - hbse.add(Box::new(DirectorySource::new("./templates", ".hbs"))); - - // load templates - if let Err(e) = hbse.reload() { - panic!("Failed to load handlebar templates: {}", e); - } + let hbse = handlebars_engine().expect("Failed to load handlebar templates"); let mut chain = Chain::new(base); chain.link_before(pool_factory()); @@ -572,7 +576,7 @@ impl ToJson for MetaData { #[cfg(test)] mod test { use crate::test::*; - use crate::web::match_version; + use crate::web::{handlebars_engine, match_version}; use html5ever::tendril::TendrilSink; fn release(version: &str, db: &TestDatabase) -> i32 { @@ -779,4 +783,9 @@ mod test { Ok(()) }); } + + #[test] + fn test_templates_are_valid() { + handlebars_engine().expect("Failed to load handlebar templates"); + } } From e43c50e4d015a4bae3db0c56645cd18e3eaa7423 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Fri, 1 May 2020 19:24:45 +0200 Subject: [PATCH 05/17] Don't show latest version redirect to yanked versions --- src/web/crate_details.rs | 71 ++++++++++++++++++++++++++++++++++++++-- src/web/rustdoc.rs | 49 +++++++++++++++++++++++++-- 2 files changed, 114 insertions(+), 6 deletions(-) diff --git a/src/web/crate_details.rs b/src/web/crate_details.rs index 29b88b9e3..38905346f 100644 --- a/src/web/crate_details.rs +++ b/src/web/crate_details.rs @@ -275,10 +275,15 @@ impl CrateDetails { Some(crate_details) } - /// Returns the version of the latest release of this crate. + /// Returns the version of the latest non-yanked release of this crate (or latest yanked if + /// they are all yanked). pub fn latest_version(&self) -> &str { - // releases will always contain at least one element - &self.releases[0].version + let release = self + .releases + .iter() + .find(|release| !release.yanked) + .unwrap_or(&self.releases[0]); + &release.version } } @@ -535,4 +540,64 @@ mod tests { Ok(()) }) } + + #[test] + fn test_latest_version_ignores_yanked() { + crate::test::wrapper(|env| { + let db = env.db(); + + db.fake_release().name("foo").version("0.0.1").create()?; + db.fake_release() + .name("foo") + .version("0.0.3") + .cratesio_data_yanked(true) + .create()?; + db.fake_release().name("foo").version("0.0.2").create()?; + + let details = CrateDetails::new(&db.conn(), "foo", "0.0.1").unwrap(); + assert_eq!(details.latest_version(), "0.0.2"); + + let details = CrateDetails::new(&db.conn(), "foo", "0.0.2").unwrap(); + assert_eq!(details.latest_version(), "0.0.2"); + + let details = CrateDetails::new(&db.conn(), "foo", "0.0.3").unwrap(); + assert_eq!(details.latest_version(), "0.0.2"); + + Ok(()) + }) + } + + #[test] + fn test_latest_version_only_yanked() { + crate::test::wrapper(|env| { + let db = env.db(); + + db.fake_release() + .name("foo") + .version("0.0.1") + .cratesio_data_yanked(true) + .create()?; + db.fake_release() + .name("foo") + .version("0.0.3") + .cratesio_data_yanked(true) + .create()?; + db.fake_release() + .name("foo") + .version("0.0.2") + .cratesio_data_yanked(true) + .create()?; + + let details = CrateDetails::new(&db.conn(), "foo", "0.0.1").unwrap(); + assert_eq!(details.latest_version(), "0.0.3"); + + let details = CrateDetails::new(&db.conn(), "foo", "0.0.2").unwrap(); + assert_eq!(details.latest_version(), "0.0.3"); + + let details = CrateDetails::new(&db.conn(), "foo", "0.0.3").unwrap(); + assert_eq!(details.latest_version(), "0.0.3"); + + Ok(()) + }) + } } diff --git a/src/web/rustdoc.rs b/src/web/rustdoc.rs index d7fb1d7ab..66386d5d7 100644 --- a/src/web/rustdoc.rs +++ b/src/web/rustdoc.rs @@ -537,7 +537,10 @@ mod test { use reqwest::StatusCode; use std::{collections::BTreeMap, iter::FromIterator}; - fn latest_version_redirect(path: &str, web: &TestFrontend) -> Result { + fn try_latest_version_redirect( + path: &str, + web: &TestFrontend, + ) -> Result, failure::Error> { use html5ever::tendril::TendrilSink; assert_success(path, web)?; let data = web.get(path).send()?.text()?; @@ -549,9 +552,15 @@ mod test { { let link = elem.attributes.borrow().get("href").unwrap().to_string(); assert_success(&link, web)?; - return Ok(link); + Ok(Some(link)) + } else { + Ok(None) } - panic!("no redirect found for {}", path); + } + + fn latest_version_redirect(path: &str, web: &TestFrontend) -> Result { + try_latest_version_redirect(path, web) + .and_then(|v| v.ok_or_else(|| failure::format_err!("no redirect found for {}", path))) } #[test] @@ -762,6 +771,40 @@ mod test { }) } + #[test] + fn redirect_latest_does_not_go_to_yanked_versions() { + wrapper(|env| { + let db = env.db(); + db.fake_release() + .name("dummy") + .version("0.1.0") + .rustdoc_file("dummy/index.html", b"lah") + .create() + .unwrap(); + db.fake_release() + .name("dummy") + .version("0.2.0") + .rustdoc_file("dummy/index.html", b"lah") + .create() + .unwrap(); + db.fake_release() + .name("dummy") + .version("0.2.1") + .rustdoc_file("dummy/index.html", b"lah") + .cratesio_data_yanked(true) + .create() + .unwrap(); + + let web = env.frontend(); + let redirect = latest_version_redirect("/dummy/0.1.0/dummy/", web)?; + assert_eq!(redirect, "/dummy/0.2.0/dummy/index.html"); + + let redirect = try_latest_version_redirect("/dummy/0.2.0/dummy/", web)?; + assert!(redirect.is_none()); + Ok(()) + }) + } + #[test] fn badges_are_urlencoded() { wrapper(|env| { From a1de62e7bef6d16542b3837bd5cab24a5e460226 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Fri, 1 May 2020 20:17:50 +0200 Subject: [PATCH 06/17] Allow loading yanked docs via exact version number --- src/web/mod.rs | 2 +- src/web/rustdoc.rs | 42 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/web/mod.rs b/src/web/mod.rs index 2c80c9bdc..9262977ad 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -266,7 +266,7 @@ fn match_version(conn: &Connection, name: &str, version: Option<&str>) -> Option let versions: Vec<(String, i32, bool)> = { let query = "SELECT name, version, releases.id, releases.yanked FROM releases INNER JOIN crates ON releases.crate_id = crates.id - WHERE normalize_crate_name(name) = normalize_crate_name($1) AND yanked = false"; + WHERE normalize_crate_name(name) = normalize_crate_name($1)"; let rows = conn.query(query, &[&name]).unwrap(); let mut rows = rows.iter().peekable(); diff --git a/src/web/rustdoc.rs b/src/web/rustdoc.rs index 66386d5d7..c588161af 100644 --- a/src/web/rustdoc.rs +++ b/src/web/rustdoc.rs @@ -799,8 +799,46 @@ mod test { let redirect = latest_version_redirect("/dummy/0.1.0/dummy/", web)?; assert_eq!(redirect, "/dummy/0.2.0/dummy/index.html"); - let redirect = try_latest_version_redirect("/dummy/0.2.0/dummy/", web)?; - assert!(redirect.is_none()); + let redirect = latest_version_redirect("/dummy/0.2.1/dummy/", web)?; + assert_eq!(redirect, "/dummy/0.2.0/dummy/index.html"); + + Ok(()) + }) + } + + #[test] + fn redirect_latest_with_all_yanked() { + wrapper(|env| { + let db = env.db(); + db.fake_release() + .name("dummy") + .version("0.1.0") + .rustdoc_file("dummy/index.html", b"lah") + .cratesio_data_yanked(true) + .create() + .unwrap(); + db.fake_release() + .name("dummy") + .version("0.2.0") + .rustdoc_file("dummy/index.html", b"lah") + .cratesio_data_yanked(true) + .create() + .unwrap(); + db.fake_release() + .name("dummy") + .version("0.2.1") + .rustdoc_file("dummy/index.html", b"lah") + .cratesio_data_yanked(true) + .create() + .unwrap(); + + let web = env.frontend(); + let redirect = latest_version_redirect("/dummy/0.1.0/dummy/", web)?; + assert_eq!(redirect, "/dummy/0.2.1/dummy/index.html"); + + let redirect = latest_version_redirect("/dummy/0.2.0/dummy/", web)?; + assert_eq!(redirect, "/dummy/0.2.1/dummy/index.html"); + Ok(()) }) } From a7c632f007173e09211c3eec951f319d21851f27 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Fri, 1 May 2020 21:21:53 +0200 Subject: [PATCH 07/17] Show yanked status in nav on rustdoc pages --- src/web/rustdoc.rs | 40 ++++++++++++++++++++++++++++++++ templates/navigation_rustdoc.hbs | 22 ++++++++++++++---- templates/style.scss | 6 ++--- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/web/rustdoc.rs b/src/web/rustdoc.rs index c588161af..4f9ae316f 100644 --- a/src/web/rustdoc.rs +++ b/src/web/rustdoc.rs @@ -843,6 +843,46 @@ mod test { }) } + #[test] + fn yanked_release_shows_warning_in_nav() { + fn has_yanked_warning(path: &str, web: &TestFrontend) -> Result { + use html5ever::tendril::TendrilSink; + assert_success(path, web)?; + let data = web.get(path).send()?.text()?; + Ok(kuchiki::parse_html() + .one(data) + .select("form > ul > li > .warn") + .expect("invalid selector") + .any(|el| el.text_contents().contains("yanked"))) + } + + wrapper(|env| { + let (db, web) = (env.db(), env.frontend()); + + db.fake_release() + .name("dummy") + .version("0.1.0") + .rustdoc_file("dummy/index.html", b"lah") + .cratesio_data_yanked(true) + .create() + .unwrap(); + + assert!(has_yanked_warning("/dummy/0.1.0/dummy/", web)?); + + db.fake_release() + .name("dummy") + .version("0.2.0") + .rustdoc_file("dummy/index.html", b"lah") + .cratesio_data_yanked(true) + .create() + .unwrap(); + + assert!(has_yanked_warning("/dummy/0.1.0/dummy/", web)?); + + Ok(()) + }) + } + #[test] fn badges_are_urlencoded() { wrapper(|env| { diff --git a/templates/navigation_rustdoc.hbs b/templates/navigation_rustdoc.hbs index 5f6f45f40..913ec112a 100644 --- a/templates/navigation_rustdoc.hbs +++ b/templates/navigation_rustdoc.hbs @@ -93,11 +93,23 @@ - {{#unless ../../varsb.is_latest_version}} -
  • - Go to latest version -
  • - {{/unless}} + {{#if ../../varsb.is_latest_version}} + {{#if yanked}} +
  • + This release has been yanked +
  • + {{/if}} + {{else}} + {{#if ../../content.crate_details.yanked}} +
  • + This release has been yanked, go to latest version +
  • + {{else}} +
  • + Go to latest version +
  • + {{/if}} + {{/if}}
  • Source
  • diff --git a/templates/style.scss b/templates/style.scss index d31bae130..7759788a6 100644 --- a/templates/style.scss +++ b/templates/style.scss @@ -160,7 +160,7 @@ div.nav-container { font-size: 0.8em; } - a { + .pure-menu-link { font-size: 0.8em; font-weight: 400; } @@ -220,11 +220,11 @@ div.nav-container { } // used for latest version warning - .warn { + .warn, .warn:hover { color: $color-type; } - .warn:hover { + a.warn:hover { color: darken($color-type, 10%); } From 39ab5aefc517b070237d03239fe505d40643636c Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Fri, 1 May 2020 21:39:14 +0200 Subject: [PATCH 08/17] Show yanked status in version drop down --- src/web/crate_details.rs | 1 + templates/navigation_rustdoc.hbs | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/web/crate_details.rs b/src/web/crate_details.rs index 38905346f..1e80bd07b 100644 --- a/src/web/crate_details.rs +++ b/src/web/crate_details.rs @@ -107,6 +107,7 @@ impl ToJson for Release { let mut m: BTreeMap = BTreeMap::new(); m.insert("version".to_string(), self.version.to_json()); m.insert("build_status".to_string(), self.build_status.to_json()); + m.insert("yanked".to_string(), self.yanked.to_json()); m.to_json() } } diff --git a/templates/navigation_rustdoc.hbs b/templates/navigation_rustdoc.hbs index 913ec112a..dff59f3cb 100644 --- a/templates/navigation_rustdoc.hbs +++ b/templates/navigation_rustdoc.hbs @@ -78,10 +78,14 @@
      {{#each releases}}
    • - {{#if this.build_status}} - {{this.version}} + {{#if this.yanked}} + {{this.version}} {{else}} - {{this.version}} + {{#if this.build_status}} + {{this.version}} + {{else}} + {{this.version}} + {{/if}} {{/if}}
    • {{/each}} From d99d03a04c7c0d050109c5d1c532fbe745820cb5 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Fri, 1 May 2020 21:40:06 +0200 Subject: [PATCH 09/17] Show yanked status on crate details version list --- templates/crate_details.hbs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/templates/crate_details.hbs b/templates/crate_details.hbs index 4757c5513..71b4c18bc 100644 --- a/templates/crate_details.hbs +++ b/templates/crate_details.hbs @@ -44,10 +44,14 @@
        {{#each releases}}
      • - {{#if this.build_status}} - {{this.version}} + {{#if this.yanked}} + {{this.version}} {{else}} - {{this.version}} + {{#if this.build_status}} + {{this.version}} + {{else}} + {{this.version}} + {{/if}} {{/if}}
      • {{/each}} From 4c67acd98b9d0a0f3043b754d051b7de6b75d853 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Fri, 1 May 2020 22:06:33 +0200 Subject: [PATCH 10/17] Make fake release more realistic on failure --- src/test/fakes.rs | 93 ++++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/src/test/fakes.rs b/src/test/fakes.rs index 61ae247ea..5d6a60045 100644 --- a/src/test/fakes.rs +++ b/src/test/fakes.rs @@ -139,55 +139,58 @@ impl<'a> FakeRelease<'a> { let package = self.package; let db = self.db; - let upload_files = |prefix: &str, files: &[(&str, &[u8])], target: Option<&str>| { - let mut path_prefix = tempdir.path().join(prefix); - if let Some(target) = target { - path_prefix.push(target); - } - fs::create_dir(&path_prefix)?; + let mut source_meta = None; + if self.build_result.successful { + let upload_files = |prefix: &str, files: &[(&str, &[u8])], target: Option<&str>| { + let mut path_prefix = tempdir.path().join(prefix); + if let Some(target) = target { + path_prefix.push(target); + } + fs::create_dir(&path_prefix)?; + + for (path, data) in files { + // allow `src/main.rs` + if let Some(parent) = Path::new(path).parent() { + fs::create_dir_all(path_prefix.join(parent))?; + } + let file = path_prefix.join(&path); + log::debug!("writing file {}", file.display()); + fs::write(file, data)?; + } - for (path, data) in files { - // allow `src/main.rs` - if let Some(parent) = Path::new(path).parent() { - fs::create_dir_all(path_prefix.join(parent))?; + let prefix = format!( + "{}/{}/{}/{}", + prefix, + package.name, + package.version, + target.unwrap_or("") + ); + log::debug!("adding directory {} from {}", prefix, path_prefix.display()); + crate::db::add_path_into_database(&db.conn(), &prefix, path_prefix) + }; + + let index = [&package.name, "index.html"].join("/"); + let mut rustdoc_files = self.rustdoc_files; + if package.is_library() && !rustdoc_files.iter().any(|(path, _)| path == &index) { + rustdoc_files.push((&index, b"default index content")); + } + for (source_path, data) in &self.source_files { + if source_path.starts_with("src/") { + let updated = ["src", &package.name, &source_path[4..]].join("/"); + rustdoc_files.push((Box::leak(Box::new(updated)), data)); } - let file = path_prefix.join(&path); - log::debug!("writing file {}", file.display()); - fs::write(file, data)?; } - - let prefix = format!( - "{}/{}/{}/{}", - prefix, - package.name, - package.version, - target.unwrap_or("") - ); - log::debug!("adding directory {} from {}", prefix, path_prefix.display()); - crate::db::add_path_into_database(&db.conn(), &prefix, path_prefix) - }; - - let index = [&package.name, "index.html"].join("/"); - let mut rustdoc_files = self.rustdoc_files; - if package.is_library() && !rustdoc_files.iter().any(|(path, _)| path == &index) { - rustdoc_files.push((&index, b"default index content")); - } - for (source_path, data) in &self.source_files { - if source_path.starts_with("src/") { - let updated = ["src", &package.name, &source_path[4..]].join("/"); - rustdoc_files.push((Box::leak(Box::new(updated)), data)); + let rustdoc_meta = upload_files("rustdoc", &rustdoc_files, None)?; + log::debug!("added rustdoc files {}", rustdoc_meta); + source_meta = Some(upload_files("source", &self.source_files, None)?); + log::debug!("added source files {}", source_meta.as_ref().unwrap()); + + for target in &package.targets[1..] { + let platform = target.src_path.as_ref().unwrap(); + upload_files("rustdoc", &rustdoc_files, Some(platform))?; + log::debug!("added platform files for {}", platform); } } - let rustdoc_meta = upload_files("rustdoc", &rustdoc_files, None)?; - log::debug!("added rustdoc files {}", rustdoc_meta); - let source_meta = upload_files("source", &self.source_files, None)?; - log::debug!("added source files {}", source_meta); - - for target in &package.targets[1..] { - let platform = target.src_path.as_ref().unwrap(); - upload_files("rustdoc", &rustdoc_files, Some(platform))?; - log::debug!("added platform files for {}", platform); - } let release_id = crate::db::add_package_into_database( &db.conn(), @@ -195,7 +198,7 @@ impl<'a> FakeRelease<'a> { tempdir.path(), &self.build_result, self.default_target.unwrap_or("x86_64-unknown-linux-gnu"), - Some(source_meta), + source_meta, self.doc_targets, &self.cratesio_data, self.has_docs, From ba46da78e1e45b1f735f2d2ba06362c79be1d0c2 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Fri, 1 May 2020 22:22:05 +0200 Subject: [PATCH 11/17] Fix latest_version_redirect test helper to get correct link and make link go direct to crate page on build failure --- src/web/crate_details.rs | 38 +++++++++++++++----------------- src/web/rustdoc.rs | 21 +++++++++++++----- templates/navigation_rustdoc.hbs | 4 ++-- 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/web/crate_details.rs b/src/web/crate_details.rs index 1e80bd07b..5a47ea217 100644 --- a/src/web/crate_details.rs +++ b/src/web/crate_details.rs @@ -96,10 +96,10 @@ impl ToJson for CrateDetails { } #[derive(Debug, Eq, PartialEq)] -struct Release { - version: String, - build_status: bool, - yanked: bool, +pub struct Release { + pub version: String, + pub build_status: bool, + pub yanked: bool, } impl ToJson for Release { @@ -276,15 +276,13 @@ impl CrateDetails { Some(crate_details) } - /// Returns the version of the latest non-yanked release of this crate (or latest yanked if - /// they are all yanked). - pub fn latest_version(&self) -> &str { - let release = self - .releases + /// Returns the latest non-yanked release of this crate (or latest yanked if they are all + /// yanked). + pub fn latest_release(&self) -> &Release { + self.releases .iter() .find(|release| !release.yanked) - .unwrap_or(&self.releases[0]); - &release.version + .unwrap_or(&self.releases[0]) } } @@ -530,13 +528,13 @@ mod tests { db.fake_release().name("foo").version("0.0.2").create()?; let details = CrateDetails::new(&db.conn(), "foo", "0.0.1").unwrap(); - assert_eq!(details.latest_version(), "0.0.3"); + assert_eq!(details.latest_release().version, "0.0.3"); let details = CrateDetails::new(&db.conn(), "foo", "0.0.2").unwrap(); - assert_eq!(details.latest_version(), "0.0.3"); + assert_eq!(details.latest_release().version, "0.0.3"); let details = CrateDetails::new(&db.conn(), "foo", "0.0.3").unwrap(); - assert_eq!(details.latest_version(), "0.0.3"); + assert_eq!(details.latest_release().version, "0.0.3"); Ok(()) }) @@ -556,13 +554,13 @@ mod tests { db.fake_release().name("foo").version("0.0.2").create()?; let details = CrateDetails::new(&db.conn(), "foo", "0.0.1").unwrap(); - assert_eq!(details.latest_version(), "0.0.2"); + assert_eq!(details.latest_release().version, "0.0.2"); let details = CrateDetails::new(&db.conn(), "foo", "0.0.2").unwrap(); - assert_eq!(details.latest_version(), "0.0.2"); + assert_eq!(details.latest_release().version, "0.0.2"); let details = CrateDetails::new(&db.conn(), "foo", "0.0.3").unwrap(); - assert_eq!(details.latest_version(), "0.0.2"); + assert_eq!(details.latest_release().version, "0.0.2"); Ok(()) }) @@ -590,13 +588,13 @@ mod tests { .create()?; let details = CrateDetails::new(&db.conn(), "foo", "0.0.1").unwrap(); - assert_eq!(details.latest_version(), "0.0.3"); + assert_eq!(details.latest_release().version, "0.0.3"); let details = CrateDetails::new(&db.conn(), "foo", "0.0.2").unwrap(); - assert_eq!(details.latest_version(), "0.0.3"); + assert_eq!(details.latest_release().version, "0.0.3"); let details = CrateDetails::new(&db.conn(), "foo", "0.0.3").unwrap(); - assert_eq!(details.latest_version(), "0.0.3"); + assert_eq!(details.latest_release().version, "0.0.3"); Ok(()) }) diff --git a/src/web/rustdoc.rs b/src/web/rustdoc.rs index 4f9ae316f..41ad59fae 100644 --- a/src/web/rustdoc.rs +++ b/src/web/rustdoc.rs @@ -320,15 +320,23 @@ pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult { content.full = file_content; - let latest_version = crate_details.latest_version().to_owned(); + let latest_release = crate_details.latest_release(); + let latest_version = latest_release.version.to_owned(); let is_latest_version = latest_version == version; - let path_in_latest = if !is_latest_version { + let latest_path = if is_latest_version { + format!("/{}/{}", name, latest_version) + } else if latest_release.build_status { let mut latest_path = req_path.clone(); latest_path[2] = &latest_version; - path_for_version(&latest_path, &crate_details.doc_targets, &conn) + format!( + "/{}/{}/{}", + name, + latest_version, + path_for_version(&latest_path, &crate_details.doc_targets, &conn) + ) } else { - Default::default() + format!("/crate/{}/{}", name, latest_version) }; // The path within this crate version's rustdoc output @@ -349,7 +357,7 @@ pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult { .set_true("package_navigation_documentation_tab") .set_true("package_navigation_show_platforms_tab") .set_bool("is_latest_version", is_latest_version) - .set("path_in_latest", &path_in_latest) + .set("latest_path", &latest_path) .set("latest_version", &latest_version) .set("inner_path", &inner_path) .to_resp("rustdoc") @@ -544,9 +552,10 @@ mod test { use html5ever::tendril::TendrilSink; assert_success(path, web)?; let data = web.get(path).send()?.text()?; + println!("{}", data); let dom = kuchiki::parse_html().one(data); if let Some(elem) = dom - .select("form ul li a.warn") + .select("form > ul > li > a.warn") .expect("invalid selector") .next() { diff --git a/templates/navigation_rustdoc.hbs b/templates/navigation_rustdoc.hbs index dff59f3cb..8d19de158 100644 --- a/templates/navigation_rustdoc.hbs +++ b/templates/navigation_rustdoc.hbs @@ -106,11 +106,11 @@ {{else}} {{#if ../../content.crate_details.yanked}}
      • - This release has been yanked, go to latest version + This release has been yanked, go to latest version
      • {{else}}
      • - Go to latest version + Go to latest version
      • {{/if}} {{/if}} From 0df4dd781e31c6830fc9e3ffcb1e2c2e48e0399e Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Fri, 1 May 2020 22:34:05 +0200 Subject: [PATCH 12/17] Simplify latest version tests --- src/web/crate_details.rs | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/src/web/crate_details.rs b/src/web/crate_details.rs index 5a47ea217..adf089a47 100644 --- a/src/web/crate_details.rs +++ b/src/web/crate_details.rs @@ -527,14 +527,10 @@ mod tests { db.fake_release().name("foo").version("0.0.3").create()?; db.fake_release().name("foo").version("0.0.2").create()?; - let details = CrateDetails::new(&db.conn(), "foo", "0.0.1").unwrap(); - assert_eq!(details.latest_release().version, "0.0.3"); - - let details = CrateDetails::new(&db.conn(), "foo", "0.0.2").unwrap(); - assert_eq!(details.latest_release().version, "0.0.3"); - - let details = CrateDetails::new(&db.conn(), "foo", "0.0.3").unwrap(); - assert_eq!(details.latest_release().version, "0.0.3"); + for version in &["0.0.1", "0.0.2", "0.0.3"] { + let details = CrateDetails::new(&db.conn(), "foo", version).unwrap(); + assert_eq!(details.latest_release().version, "0.0.3"); + } Ok(()) }) @@ -553,14 +549,10 @@ mod tests { .create()?; db.fake_release().name("foo").version("0.0.2").create()?; - let details = CrateDetails::new(&db.conn(), "foo", "0.0.1").unwrap(); - assert_eq!(details.latest_release().version, "0.0.2"); - - let details = CrateDetails::new(&db.conn(), "foo", "0.0.2").unwrap(); - assert_eq!(details.latest_release().version, "0.0.2"); - - let details = CrateDetails::new(&db.conn(), "foo", "0.0.3").unwrap(); - assert_eq!(details.latest_release().version, "0.0.2"); + for version in &["0.0.1", "0.0.2", "0.0.3"] { + let details = CrateDetails::new(&db.conn(), "foo", version).unwrap(); + assert_eq!(details.latest_release().version, "0.0.2"); + } Ok(()) }) @@ -587,14 +579,10 @@ mod tests { .cratesio_data_yanked(true) .create()?; - let details = CrateDetails::new(&db.conn(), "foo", "0.0.1").unwrap(); - assert_eq!(details.latest_release().version, "0.0.3"); - - let details = CrateDetails::new(&db.conn(), "foo", "0.0.2").unwrap(); - assert_eq!(details.latest_release().version, "0.0.3"); - - let details = CrateDetails::new(&db.conn(), "foo", "0.0.3").unwrap(); - assert_eq!(details.latest_release().version, "0.0.3"); + for version in &["0.0.1", "0.0.2", "0.0.3"] { + let details = CrateDetails::new(&db.conn(), "foo", version).unwrap(); + assert_eq!(details.latest_release().version, "0.0.3"); + } Ok(()) }) From 0f262019c6dec19c16a9e0886da4fa6afa0b47b4 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Fri, 1 May 2020 22:38:02 +0200 Subject: [PATCH 13/17] Remove unecessary unwraps in tests --- src/web/rustdoc.rs | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/src/web/rustdoc.rs b/src/web/rustdoc.rs index 41ad59fae..00f13791f 100644 --- a/src/web/rustdoc.rs +++ b/src/web/rustdoc.rs @@ -714,14 +714,12 @@ mod test { .version("0.1.0") .add_platform("x86_64-pc-windows-msvc") .rustdoc_file("dummy/struct.Blah.html", b"lah") - .create() - .unwrap(); + .create()?; db.fake_release() .name("dummy") .version("0.2.0") .add_platform("x86_64-pc-windows-msvc") - .create() - .unwrap(); + .create()?; let web = env.frontend(); @@ -763,14 +761,12 @@ mod test { .name("dummy") .version("0.1.0") .rustdoc_file("dummy/index.html", b"lah") - .create() - .unwrap(); + .create()?; db.fake_release() .name("dummy") .version("0.2.0") .build_result_successful(false) - .create() - .unwrap(); + .create()?; let web = env.frontend(); let redirect = latest_version_redirect("/dummy/0.1.0/dummy/", web)?; @@ -788,21 +784,18 @@ mod test { .name("dummy") .version("0.1.0") .rustdoc_file("dummy/index.html", b"lah") - .create() - .unwrap(); + .create()?; db.fake_release() .name("dummy") .version("0.2.0") .rustdoc_file("dummy/index.html", b"lah") - .create() - .unwrap(); + .create()?; db.fake_release() .name("dummy") .version("0.2.1") .rustdoc_file("dummy/index.html", b"lah") .cratesio_data_yanked(true) - .create() - .unwrap(); + .create()?; let web = env.frontend(); let redirect = latest_version_redirect("/dummy/0.1.0/dummy/", web)?; @@ -824,22 +817,19 @@ mod test { .version("0.1.0") .rustdoc_file("dummy/index.html", b"lah") .cratesio_data_yanked(true) - .create() - .unwrap(); + .create()?; db.fake_release() .name("dummy") .version("0.2.0") .rustdoc_file("dummy/index.html", b"lah") .cratesio_data_yanked(true) - .create() - .unwrap(); + .create()?; db.fake_release() .name("dummy") .version("0.2.1") .rustdoc_file("dummy/index.html", b"lah") .cratesio_data_yanked(true) - .create() - .unwrap(); + .create()?; let web = env.frontend(); let redirect = latest_version_redirect("/dummy/0.1.0/dummy/", web)?; @@ -873,8 +863,7 @@ mod test { .version("0.1.0") .rustdoc_file("dummy/index.html", b"lah") .cratesio_data_yanked(true) - .create() - .unwrap(); + .create()?; assert!(has_yanked_warning("/dummy/0.1.0/dummy/", web)?); @@ -883,8 +872,7 @@ mod test { .version("0.2.0") .rustdoc_file("dummy/index.html", b"lah") .cratesio_data_yanked(true) - .create() - .unwrap(); + .create()?; assert!(has_yanked_warning("/dummy/0.1.0/dummy/", web)?); @@ -919,8 +907,7 @@ mod test { .name("fake-crate") .version("0.0.1") .rustdoc_file("fake_crate/index.html", b"some content") - .create() - .unwrap(); + .create()?; let web = env.frontend(); assert_redirect("/fake%2Dcrate", "/fake-crate/0.0.1/fake_crate/", web)?; From d3d617914c71cb3f57aebb32f2fb6bf4dfa273b1 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Fri, 1 May 2020 22:49:34 +0200 Subject: [PATCH 14/17] Show both yanked and build status warnings --- templates/crate_details.hbs | 6 +++++- templates/navigation_rustdoc.hbs | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/templates/crate_details.hbs b/templates/crate_details.hbs index 71b4c18bc..1a1385708 100644 --- a/templates/crate_details.hbs +++ b/templates/crate_details.hbs @@ -45,7 +45,11 @@ {{#each releases}}
      • {{#if this.yanked}} - {{this.version}} + {{#if this.build_status}} + {{this.version}} + {{else}} + {{this.version}} + {{/if}} {{else}} {{#if this.build_status}} {{this.version}} diff --git a/templates/navigation_rustdoc.hbs b/templates/navigation_rustdoc.hbs index 8d19de158..ebeeb3707 100644 --- a/templates/navigation_rustdoc.hbs +++ b/templates/navigation_rustdoc.hbs @@ -79,7 +79,11 @@ {{#each releases}}
      • {{#if this.yanked}} - {{this.version}} + {{#if this.build_status}} + {{this.version}} + {{else}} + {{this.version}} + {{/if}} {{else}} {{#if this.build_status}} {{this.version}} From c875676a86e659b87f97aa306ae5f6dbb5764d60 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Fri, 1 May 2020 22:52:14 +0200 Subject: [PATCH 15/17] Rename cratesio_data_yanked to yanked --- src/test/fakes.rs | 2 +- src/web/crate_details.rs | 18 +++++++++--------- src/web/rustdoc.rs | 12 ++++++------ 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/test/fakes.rs b/src/test/fakes.rs index 5d6a60045..1189ad060 100644 --- a/src/test/fakes.rs +++ b/src/test/fakes.rs @@ -86,7 +86,7 @@ impl<'a> FakeRelease<'a> { self } - pub(crate) fn cratesio_data_yanked(mut self, new: bool) -> Self { + pub(crate) fn yanked(mut self, new: bool) -> Self { self.cratesio_data.yanked = new; self } diff --git a/src/web/crate_details.rs b/src/web/crate_details.rs index adf089a47..71fcdb033 100644 --- a/src/web/crate_details.rs +++ b/src/web/crate_details.rs @@ -375,13 +375,13 @@ mod tests { db.fake_release() .name("foo") .version("0.0.4") - .cratesio_data_yanked(true) + .yanked(true) .create()?; db.fake_release() .name("foo") .version("0.0.5") .build_result_successful(false) - .cratesio_data_yanked(true) + .yanked(true) .create()?; assert_last_successful_build_equals(&db, "foo", "0.0.1", None)?; @@ -411,7 +411,7 @@ mod tests { db.fake_release() .name("foo") .version("0.0.3") - .cratesio_data_yanked(true) + .yanked(true) .create()?; assert_last_successful_build_equals(&db, "foo", "0.0.1", None)?; @@ -435,7 +435,7 @@ mod tests { db.fake_release() .name("foo") .version("0.0.3") - .cratesio_data_yanked(true) + .yanked(true) .create()?; db.fake_release().name("foo").version("0.0.4").create()?; @@ -465,7 +465,7 @@ mod tests { db.fake_release() .name("foo") .version("0.2.0") - .cratesio_data_yanked(true) + .yanked(true) .create()?; db.fake_release() .name("foo") @@ -545,7 +545,7 @@ mod tests { db.fake_release() .name("foo") .version("0.0.3") - .cratesio_data_yanked(true) + .yanked(true) .create()?; db.fake_release().name("foo").version("0.0.2").create()?; @@ -566,17 +566,17 @@ mod tests { db.fake_release() .name("foo") .version("0.0.1") - .cratesio_data_yanked(true) + .yanked(true) .create()?; db.fake_release() .name("foo") .version("0.0.3") - .cratesio_data_yanked(true) + .yanked(true) .create()?; db.fake_release() .name("foo") .version("0.0.2") - .cratesio_data_yanked(true) + .yanked(true) .create()?; for version in &["0.0.1", "0.0.2", "0.0.3"] { diff --git a/src/web/rustdoc.rs b/src/web/rustdoc.rs index 00f13791f..5e03855fa 100644 --- a/src/web/rustdoc.rs +++ b/src/web/rustdoc.rs @@ -794,7 +794,7 @@ mod test { .name("dummy") .version("0.2.1") .rustdoc_file("dummy/index.html", b"lah") - .cratesio_data_yanked(true) + .yanked(true) .create()?; let web = env.frontend(); @@ -816,19 +816,19 @@ mod test { .name("dummy") .version("0.1.0") .rustdoc_file("dummy/index.html", b"lah") - .cratesio_data_yanked(true) + .yanked(true) .create()?; db.fake_release() .name("dummy") .version("0.2.0") .rustdoc_file("dummy/index.html", b"lah") - .cratesio_data_yanked(true) + .yanked(true) .create()?; db.fake_release() .name("dummy") .version("0.2.1") .rustdoc_file("dummy/index.html", b"lah") - .cratesio_data_yanked(true) + .yanked(true) .create()?; let web = env.frontend(); @@ -862,7 +862,7 @@ mod test { .name("dummy") .version("0.1.0") .rustdoc_file("dummy/index.html", b"lah") - .cratesio_data_yanked(true) + .yanked(true) .create()?; assert!(has_yanked_warning("/dummy/0.1.0/dummy/", web)?); @@ -871,7 +871,7 @@ mod test { .name("dummy") .version("0.2.0") .rustdoc_file("dummy/index.html", b"lah") - .cratesio_data_yanked(true) + .yanked(true) .create()?; assert!(has_yanked_warning("/dummy/0.1.0/dummy/", web)?); From a797fad22f2b1249ed04d2138ddf8a8cc426afba Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Fri, 1 May 2020 23:03:23 +0200 Subject: [PATCH 16/17] Add test for fully yanked crate --- src/web/rustdoc.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/web/rustdoc.rs b/src/web/rustdoc.rs index 5e03855fa..b37c4c26e 100644 --- a/src/web/rustdoc.rs +++ b/src/web/rustdoc.rs @@ -1318,4 +1318,29 @@ mod test { Ok(()) }); } + + #[test] + fn test_fully_yanked_crate_404s() { + crate::test::wrapper(|env| { + let db = env.db(); + + db.fake_release() + .name("dummy") + .version("1.0.0") + .yanked(true) + .create()?; + + assert_eq!( + env.frontend().get("/crate/dummy").send()?.status(), + StatusCode::NOT_FOUND + ); + + assert_eq!( + env.frontend().get("/dummy").send()?.status(), + StatusCode::NOT_FOUND + ); + + Ok(()) + }) + } } From d51802cd26d7f8b2af9628c1238810d94f0332b1 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Wed, 6 May 2020 10:50:20 +0200 Subject: [PATCH 17/17] Log errors while marking crates yanked --- src/docbuilder/queue.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/docbuilder/queue.rs b/src/docbuilder/queue.rs index 54a5c8ecf..ba9a73a8d 100644 --- a/src/docbuilder/queue.rs +++ b/src/docbuilder/queue.rs @@ -22,14 +22,24 @@ impl DocBuilder { for krate in &changes { match krate.kind { ChangeKind::Yanked => { - // FIXME: remove built doc files? set build as failed? - conn.execute( - "UPDATE releases SET yanked = TRUE FROM crates WHERE \ - crates.id = releases.crate_id AND name = $1 AND version = $2", + let res = conn.execute( + " + UPDATE releases + SET yanked = TRUE + FROM crates + WHERE crates.id = releases.crate_id + AND name = $1 + AND version = $2 + ", &[&krate.name, &krate.version], - ) - .ok(); - debug!("{}-{} yanked", krate.name, krate.version); + ); + match res { + Ok(_) => debug!("{}-{} yanked", krate.name, krate.version), + Err(err) => error!( + "error while setting {}-{} to yanked: {}", + krate.name, krate.version, err + ), + } } ChangeKind::Added => { let priority = get_crate_priority(&conn, &krate.name)?;