|
1 | 1 | use crate::config::Config;
|
2 | 2 | use crate::crates::Crate;
|
| 3 | +use crate::dirs::WORK_DIR; |
3 | 4 | use crate::experiments::Experiment;
|
4 | 5 | use crate::prelude::*;
|
5 | 6 | use crate::report::analyzer::{analyze_report, ReportConfig, ToolchainSelect};
|
6 | 7 | use crate::results::{EncodedLog, EncodingType, FailureReason, ReadResults, TestResult};
|
7 | 8 | use crate::toolchain::Toolchain;
|
8 | 9 | use crate::utils;
|
| 10 | +use crates_index::Index; |
9 | 11 | use mime::{self, Mime};
|
10 | 12 | use percent_encoding::{utf8_percent_encode, AsciiSet};
|
11 | 13 | use std::borrow::Cow;
|
@@ -53,10 +55,19 @@ pub struct CrateResult {
|
53 | 55 | name: String,
|
54 | 56 | url: String,
|
55 | 57 | krate: Crate,
|
| 58 | + #[serde(skip_serializing_if = "Option::is_none")] |
| 59 | + status: Option<CrateVersionStatus>, |
56 | 60 | pub res: Comparison,
|
57 | 61 | runs: [Option<BuildTestResult>; 2],
|
58 | 62 | }
|
59 | 63 |
|
| 64 | +string_enum!(enum CrateVersionStatus { |
| 65 | + Yanked => "yanked", |
| 66 | + Outdated => "outdated", |
| 67 | + UpToDate => "", |
| 68 | + MissingFromIndex => "missing from the index", |
| 69 | +}); |
| 70 | + |
60 | 71 | string_enum!(pub enum Comparison {
|
61 | 72 | Regressed => "regressed",
|
62 | 73 | Fixed => "fixed",
|
@@ -172,13 +183,42 @@ fn crate_to_path_fragment(
|
172 | 183 | path
|
173 | 184 | }
|
174 | 185 |
|
| 186 | +fn get_crate_version_status(index: &Index, krate: &Crate) -> Fallible<Option<CrateVersionStatus>> { |
| 187 | + if let Crate::Registry(krate) = krate { |
| 188 | + let index_krate = index |
| 189 | + .crate_(&krate.name) |
| 190 | + .ok_or_else(|| err_msg(format!("no crate found in index {:?}", &krate)))?; |
| 191 | + |
| 192 | + let outdated = index_krate.latest_version().version() != krate.version; |
| 193 | + |
| 194 | + for version in index_krate.versions().iter().rev() { |
| 195 | + // Check if the tested version is yanked |
| 196 | + if version.version() == krate.version { |
| 197 | + if version.is_yanked() { |
| 198 | + return Ok(Some(CrateVersionStatus::Yanked)); |
| 199 | + } else if outdated { |
| 200 | + return Ok(Some(CrateVersionStatus::Outdated)); |
| 201 | + } else { |
| 202 | + return Ok(Some(CrateVersionStatus::UpToDate)); |
| 203 | + } |
| 204 | + } |
| 205 | + } |
| 206 | + |
| 207 | + bail!("version not found"); |
| 208 | + } else { |
| 209 | + // we do not check versions for other crates |
| 210 | + Ok(None) |
| 211 | + } |
| 212 | +} |
| 213 | + |
175 | 214 | pub fn generate_report<DB: ReadResults>(
|
176 | 215 | db: &DB,
|
177 | 216 | config: &Config,
|
178 | 217 | ex: &Experiment,
|
179 | 218 | crates: &[Crate],
|
180 | 219 | ) -> Fallible<RawTestResults> {
|
181 | 220 | let mut crates = crates.to_vec();
|
| 221 | + let index = Index::new(WORK_DIR.join("crates.io-index")); |
182 | 222 | //crate ids are unique so unstable sort is equivalent to stable sort but is generally faster
|
183 | 223 | crates.sort_unstable_by(|a, b| a.id().cmp(&b.id()));
|
184 | 224 | let res = crates
|
@@ -212,6 +252,8 @@ pub fn generate_report<DB: ReadResults>(
|
212 | 252 | Ok(CrateResult {
|
213 | 253 | name: crate_to_name(&krate)?,
|
214 | 254 | url: crate_to_url(&krate)?,
|
| 255 | + status: get_crate_version_status(&index, &krate) |
| 256 | + .unwrap_or(Some(CrateVersionStatus::MissingFromIndex)), |
215 | 257 | krate: krate.clone(),
|
216 | 258 | res: comp,
|
217 | 259 | runs: [crate1, crate2],
|
@@ -584,9 +626,11 @@ mod tests {
|
584 | 626 | use super::*;
|
585 | 627 | use crate::config::{Config, CrateConfig};
|
586 | 628 | use crate::crates::{Crate, GitHubRepo, RegistryCrate};
|
| 629 | + use crate::dirs::WORK_DIR; |
587 | 630 | use crate::experiments::{CapLints, Experiment, Mode, Status};
|
588 | 631 | use crate::results::{BrokenReason, DummyDB, FailureReason, TestResult};
|
589 | 632 | use crate::toolchain::{MAIN_TOOLCHAIN, TEST_TOOLCHAIN};
|
| 633 | + use crates_index::Index; |
590 | 634 |
|
591 | 635 | #[test]
|
592 | 636 | fn test_crate_to_path_fragment() {
|
@@ -652,6 +696,39 @@ mod tests {
|
652 | 696 | );
|
653 | 697 | }
|
654 | 698 |
|
| 699 | + #[test] |
| 700 | + fn test_crate_version_status() { |
| 701 | + let reg = Crate::Registry(RegistryCrate { |
| 702 | + name: "lazy_static".into(), |
| 703 | + version: "0.1.0".into(), |
| 704 | + }); |
| 705 | + |
| 706 | + let yanked = Crate::Registry(RegistryCrate { |
| 707 | + name: "structopt".into(), |
| 708 | + version: "0.3.6".into(), |
| 709 | + }); |
| 710 | + |
| 711 | + let repo = GitHubRepo { |
| 712 | + org: "brson".into(), |
| 713 | + name: "hello-rs".into(), |
| 714 | + sha: None, |
| 715 | + }; |
| 716 | + let gh = Crate::GitHub(repo.clone()); |
| 717 | + |
| 718 | + let index = Index::new(WORK_DIR.join("crates.io-index")); |
| 719 | + index.retrieve_or_update().unwrap(); |
| 720 | + |
| 721 | + assert_eq!( |
| 722 | + get_crate_version_status(&index, ®).unwrap().unwrap(), |
| 723 | + CrateVersionStatus::Outdated |
| 724 | + ); |
| 725 | + assert_eq!( |
| 726 | + get_crate_version_status(&index, &yanked).unwrap().unwrap(), |
| 727 | + CrateVersionStatus::Yanked |
| 728 | + ); |
| 729 | + assert!(get_crate_version_status(&index, &gh).unwrap().is_none()); |
| 730 | + } |
| 731 | + |
655 | 732 | #[test]
|
656 | 733 | fn test_crate_to_url() {
|
657 | 734 | let reg = Crate::Registry(RegistryCrate {
|
|
0 commit comments