Skip to content

Commit a4a29da

Browse files
committed
Auto merge of #529 - Zeegomo:check-crates-version, r=pietroalbini
Check crates version Checks if a crate has been updated before report creation
2 parents a86c11e + a59f0e5 commit a4a29da

File tree

4 files changed

+91
-3
lines changed

4 files changed

+91
-3
lines changed

src/report/html.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ struct CrateResultHTML {
8484
name: String,
8585
url: String,
8686
res: Comparison,
87+
#[serde(skip_serializing_if = "Option::is_none")]
88+
status: Option<String>,
8789
runs: [Option<BuildTestResultHTML>; 2],
8890
}
8991

@@ -130,6 +132,7 @@ fn write_report<W: ReportWriter>(
130132
CrateResultHTML {
131133
name: result.name.clone(),
132134
url: result.url.clone(),
135+
status: result.status.map(|status| status.to_string()),
133136
res: result.res,
134137
runs,
135138
}

src/report/markdown.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ fn write_crate(
6464
];
6565

6666
let prefix = if is_child { " * " } else { "* " };
67+
let status_warning = krate
68+
.status
69+
.map(|status| format!(" ({})", status.to_string()))
70+
.unwrap_or_default();
6771

6872
if let ReportConfig::Complete(toolchain) = comparison.report_config() {
6973
let (conj, run) = match toolchain {
@@ -73,9 +77,10 @@ fn write_crate(
7377

7478
writeln!(
7579
&mut rendered,
76-
"{}[{}]({}) {} {} **{}** [start]({}/log.txt) | [end]({}/log.txt)",
80+
"{}[{}{}]({}) {} {} **{}** [start]({}/log.txt) | [end]({}/log.txt)",
7781
prefix,
7882
krate.name,
83+
status_warning,
7984
krate.url,
8085
comparison.to_string(),
8186
conj,
@@ -86,9 +91,10 @@ fn write_crate(
8691
} else {
8792
writeln!(
8893
&mut rendered,
89-
"{}[{}]({}) {} [start]({}/log.txt) | [end]({}/log.txt)",
94+
"{}[{}{}]({}) {} [start]({}/log.txt) | [end]({}/log.txt)",
9095
prefix,
9196
krate.name,
97+
status_warning,
9298
krate.url,
9399
comparison.to_string(),
94100
runs[1],

src/report/mod.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
use crate::config::Config;
22
use crate::crates::Crate;
3+
use crate::dirs::WORK_DIR;
34
use crate::experiments::Experiment;
45
use crate::prelude::*;
56
use crate::report::analyzer::{analyze_report, ReportConfig, ToolchainSelect};
67
use crate::results::{EncodedLog, EncodingType, FailureReason, ReadResults, TestResult};
78
use crate::toolchain::Toolchain;
89
use crate::utils;
10+
use crates_index::Index;
911
use mime::{self, Mime};
1012
use percent_encoding::{utf8_percent_encode, AsciiSet};
1113
use std::borrow::Cow;
@@ -53,10 +55,19 @@ pub struct CrateResult {
5355
name: String,
5456
url: String,
5557
krate: Crate,
58+
#[serde(skip_serializing_if = "Option::is_none")]
59+
status: Option<CrateVersionStatus>,
5660
pub res: Comparison,
5761
runs: [Option<BuildTestResult>; 2],
5862
}
5963

64+
string_enum!(enum CrateVersionStatus {
65+
Yanked => "yanked",
66+
Outdated => "outdated",
67+
UpToDate => "",
68+
MissingFromIndex => "missing from the index",
69+
});
70+
6071
string_enum!(pub enum Comparison {
6172
Regressed => "regressed",
6273
Fixed => "fixed",
@@ -172,13 +183,42 @@ fn crate_to_path_fragment(
172183
path
173184
}
174185

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+
175214
pub fn generate_report<DB: ReadResults>(
176215
db: &DB,
177216
config: &Config,
178217
ex: &Experiment,
179218
crates: &[Crate],
180219
) -> Fallible<RawTestResults> {
181220
let mut crates = crates.to_vec();
221+
let index = Index::new(WORK_DIR.join("crates.io-index"));
182222
//crate ids are unique so unstable sort is equivalent to stable sort but is generally faster
183223
crates.sort_unstable_by(|a, b| a.id().cmp(&b.id()));
184224
let res = crates
@@ -212,6 +252,8 @@ pub fn generate_report<DB: ReadResults>(
212252
Ok(CrateResult {
213253
name: crate_to_name(&krate)?,
214254
url: crate_to_url(&krate)?,
255+
status: get_crate_version_status(&index, &krate)
256+
.unwrap_or(Some(CrateVersionStatus::MissingFromIndex)),
215257
krate: krate.clone(),
216258
res: comp,
217259
runs: [crate1, crate2],
@@ -584,9 +626,11 @@ mod tests {
584626
use super::*;
585627
use crate::config::{Config, CrateConfig};
586628
use crate::crates::{Crate, GitHubRepo, RegistryCrate};
629+
use crate::dirs::WORK_DIR;
587630
use crate::experiments::{CapLints, Experiment, Mode, Status};
588631
use crate::results::{BrokenReason, DummyDB, FailureReason, TestResult};
589632
use crate::toolchain::{MAIN_TOOLCHAIN, TEST_TOOLCHAIN};
633+
use crates_index::Index;
590634

591635
#[test]
592636
fn test_crate_to_path_fragment() {
@@ -652,6 +696,39 @@ mod tests {
652696
);
653697
}
654698

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, &reg).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+
655732
#[test]
656733
fn test_crate_to_url() {
657734
let reg = Crate::Registry(RegistryCrate {

templates/macros.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222

2323
{% macro crate_div(crate) %}
2424
<div class="crate">
25-
<a href="{{ crate.url|safe }}" target="_blank" rel="noopener">{{ crate.name }}</a>
25+
<a href="{{ crate.url|safe }}" target="_blank" rel="noopener">
26+
{{ crate.name }} {% if crate.status %} ({{ crate.status }}) {% endif %}
27+
</a>
2628
{% for run in crate.runs %}
2729
<span class="run">
2830
{% if run %}

0 commit comments

Comments
 (0)