diff --git a/README.md b/README.md index 14d39d4ec..81f4bc062 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,12 @@ To rebuild the site, run `docker-compose build`. Note that docker-compose caches the build even if you change the source code, so this will be necessary anytime you make changes. +If you want to completely clean up the database, don't forget to remove the volumes too: + +``` +$ docker-compose down --volumes +``` + #### FAQ ##### I keep getting the error `standard_init_linux.go:211: exec user process caused "no such file or directory"` when I use docker-compose. diff --git a/src/db/add_package.rs b/src/db/add_package.rs index ed5e1bfb9..e693bdd7e 100644 --- a/src/db/add_package.rs +++ b/src/db/add_package.rs @@ -137,17 +137,24 @@ pub(crate) fn add_doc_coverage( ) -> Result { debug!("Adding doc coverage into database"); let rows = conn.query( - "INSERT INTO doc_coverage (release_id, total_items, documented_items) - VALUES ($1, $2, $3) + "INSERT INTO doc_coverage ( + release_id, total_items, documented_items, + total_items_needing_examples, items_with_examples + ) + VALUES ($1, $2, $3, $4, $5) ON CONFLICT (release_id) DO UPDATE SET total_items = $2, - documented_items = $3 + documented_items = $3, + total_items_needing_examples = $4, + items_with_examples = $5 RETURNING release_id", &[ &release_id, &doc_coverage.total_items, &doc_coverage.documented_items, + &doc_coverage.total_items_needing_examples, + &doc_coverage.items_with_examples, ], )?; Ok(rows[0].get(0)) diff --git a/src/db/migrate.rs b/src/db/migrate.rs index bb294bcbd..929f57de2 100644 --- a/src/db/migrate.rs +++ b/src/db/migrate.rs @@ -438,6 +438,25 @@ pub fn migrate(version: Option, conn: &mut Client) -> CratesfyiResult<( ALTER TABLE owners ALTER COLUMN name DROP NOT NULL; ALTER TABLE crates ALTER COLUMN github_stars DROP NOT NULL; " + ), + migration!( + context, + // version + 18, + // description + "Add more information into doc coverage", + // upgrade query + " + ALTER TABLE doc_coverage + ADD COLUMN total_items_needing_examples INT, + ADD COLUMN items_with_examples INT; + ", + // downgrade query + " + ALTER TABLE doc_coverage + DROP COLUMN total_items_needing_examples, + DROP COLUMN items_with_examples; + " ) ]; diff --git a/src/docbuilder/rustwide_builder.rs b/src/docbuilder/rustwide_builder.rs index e625e795a..0a4108155 100644 --- a/src/docbuilder/rustwide_builder.rs +++ b/src/docbuilder/rustwide_builder.rs @@ -455,11 +455,15 @@ impl RustwideBuilder { struct FileCoverage { total: i32, with_docs: i32, + total_examples: i32, + with_examples: i32, } let mut coverage = DocCoverage { total_items: 0, documented_items: 0, + total_items_needing_examples: 0, + items_with_examples: 0, }; self.prepare_command(build, target, metadata, limits, rustdoc_flags)? @@ -472,6 +476,8 @@ impl RustwideBuilder { for file in parsed.values() { coverage.total_items += file.total; coverage.documented_items += file.with_docs; + coverage.total_items_needing_examples += file.total_examples; + coverage.items_with_examples += file.with_examples; } } }) @@ -670,6 +676,11 @@ pub(crate) struct DocCoverage { pub(crate) total_items: i32, /// The items of the crate that are documented, used to calculate documentation coverage. pub(crate) documented_items: i32, + /// The total items that could have code examples in the current crate, used to calculate + /// documentation coverage. + pub(crate) total_items_needing_examples: i32, + /// The items of the crate that have a code example, used to calculate documentation coverage. + pub(crate) items_with_examples: i32, } pub(crate) struct BuildResult { diff --git a/src/test/fakes.rs b/src/test/fakes.rs index 15cc910c4..0134943dd 100644 --- a/src/test/fakes.rs +++ b/src/test/fakes.rs @@ -183,10 +183,18 @@ impl<'a> FakeRelease<'a> { self } - pub(crate) fn coverage(mut self, documented_items: i32, total_items: i32) -> Self { + pub(crate) fn coverage( + mut self, + documented_items: i32, + total_items: i32, + total_items_needing_examples: i32, + items_with_examples: i32, + ) -> Self { self.build_result.doc_coverage = Some(DocCoverage { total_items, documented_items, + total_items_needing_examples, + items_with_examples, }); self } diff --git a/src/web/crate_details.rs b/src/web/crate_details.rs index 5310ed833..4b2cd0d1b 100644 --- a/src/web/crate_details.rs +++ b/src/web/crate_details.rs @@ -45,6 +45,8 @@ pub struct CrateDetails { documentation_url: Option, total_items: Option, documented_items: Option, + total_items_needing_examples: Option, + items_with_examples: Option, } fn optional_markdown(markdown: &Option, serializer: S) -> Result @@ -100,7 +102,9 @@ impl CrateDetails { releases.documentation_url, releases.default_target, doc_coverage.total_items, - doc_coverage.documented_items + doc_coverage.documented_items, + doc_coverage.total_items_needing_examples, + doc_coverage.items_with_examples FROM releases INNER JOIN crates ON releases.crate_id = crates.id LEFT JOIN doc_coverage ON doc_coverage.release_id = releases.id @@ -156,6 +160,8 @@ impl CrateDetails { let documented_items: Option = krate.get("documented_items"); let total_items: Option = krate.get("total_items"); + let total_items_needing_examples: Option = krate.get("total_items_needing_examples"); + let items_with_examples: Option = krate.get("items_with_examples"); let mut crate_details = CrateDetails { name: krate.get("name"), @@ -189,6 +195,8 @@ impl CrateDetails { documentation_url: krate.get("documentation_url"), documented_items: documented_items.map(|v| v as f32), total_items: total_items.map(|v| v as f32), + total_items_needing_examples: total_items_needing_examples.map(|v| v as f32), + items_with_examples: items_with_examples.map(|v| v as f32), }; if let Some(repository_url) = crate_details.repository_url.clone() { diff --git a/src/web/mod.rs b/src/web/mod.rs index 98e3d5844..64136a08f 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -644,12 +644,12 @@ mod test { .name("foo") .version("0.0.1") .source_file("test.rs", &[]) - .coverage(6, 10) + .coverage(6, 10, 2, 1) .create()?; let web = env.frontend(); let foo_crate = kuchiki::parse_html().one(web.get("/crate/foo/0.0.1").send()?.text()?); - for value in &["60%", "6", "10"] { + for value in &["60%", "6", "10", "2", "1"] { assert!(foo_crate .select(".pure-menu-item b") .unwrap() diff --git a/templates/crate/details.html b/templates/crate/details.html index 8bf7db144..82b24ed94 100644 --- a/templates/crate/details.html +++ b/templates/crate/details.html @@ -20,7 +20,10 @@ {% set percent = details.documented_items * 100 / details.total_items %}
  • Coverage
  • {{ percent | round(precision=2) }}%
    - {{ details.documented_items }} out of {{ details.total_items }} items documented + {{ details.documented_items }} out of {{ details.total_items }} items documented + {%- if details.total_items_needing_examples and details.items_with_examples -%} + {{ details.items_with_examples }} out of {{ details.total_items_needing_examples }} items with examples + {%- endif -%}
  • {%- endif -%} {# List the release author's names and a link to their docs.rs profile #} diff --git a/templates/style/base.scss b/templates/style/base.scss index 7fda1a3d6..579ca2c98 100644 --- a/templates/style/base.scss +++ b/templates/style/base.scss @@ -311,6 +311,12 @@ div.package-page-container { margin: 20px 5px 15px 5px; } + li.pure-menu-item > .documented-info { + font-size: 13px; + display: block; + width: 100%; + } + li.pure-menu-heading:first-child { margin-top: 0; }