wpt_interop/
results_cache.rs1use crate::{Error, Result, Results};
2use git2;
3use serde_json;
4use std::collections::{BTreeMap, BTreeSet};
5use std::path::Path;
6use urlencoding;
7
8pub struct ResultsCache {
9 repo: git2::Repository,
10}
11
12impl ResultsCache {
13 pub fn new(path: &Path) -> Result<ResultsCache> {
14 Ok(ResultsCache {
15 repo: git2::Repository::open(path)?,
16 })
17 }
18
19 fn tag(run_id: u64) -> String {
20 format!("refs/tags/run/{}/results", run_id)
21 }
22
23 pub fn results(
24 &self,
25 run_id: u64,
26 include_tests: Option<&BTreeSet<String>>,
27 ) -> Result<BTreeMap<String, Results>> {
28 let mut results_data = BTreeMap::new();
29 let run_ref = self.repo.find_reference(&ResultsCache::tag(run_id))?;
30 if !run_ref.is_tag() {
31 return Err(Error::String(format!(
32 "{} is not a tag",
33 ResultsCache::tag(run_id)
34 )));
35 }
36 let root = run_ref.peel_to_tree()?;
37 let mut stack: Vec<(git2::Tree, String)> = vec![(root, "".to_string())];
38 while let Some((tree, path)) = stack.pop() {
39 for tree_entry in tree.iter() {
40 match tree_entry.kind() {
41 Some(git2::ObjectType::Tree) => {
42 let name = tree_entry.name().ok_or_else(|| {
43 Error::String(format!("Tree has non-utf8 name {:?}", tree_entry.name()))
44 })?;
45 stack.push((
46 tree_entry.to_object(&self.repo)?.peel_to_tree()?,
47 format!("{}/{}", path, name),
48 ));
49 }
50 Some(git2::ObjectType::Blob) => {
51 let name = tree_entry.name().ok_or_else(|| {
52 Error::String(format!("Tree has non-utf8 name {:?}", tree_entry.name()))
53 })?;
54 let test_name = match name.rsplit_once('.') {
55 Some((test_name, "json")) => urlencoding::decode(test_name),
56 Some((_, _)) | None => {
57 return Err(Error::String(format!(
58 "Expected a name ending .json(), got {}",
59 name
60 )));
61 }
62 }
63 .expect("Test name is valid utf8");
64 let path = format!("{}/{}", path, test_name);
65 if let Some(include) = include_tests {
66 if !include.contains(&path) {
67 continue;
68 }
69 }
70 let blob = tree_entry.to_object(&self.repo)?.peel_to_blob()?;
71 let results: Results = serde_json::from_slice(blob.content())?;
72 results_data.insert(path, results);
73 }
74 _ => {
75 return Err(Error::String(format!(
76 "Unexpected object while walking tree {}",
77 tree_entry.id()
78 )));
79 }
80 }
81 }
82 }
83 Ok(results_data)
84 }
85}