• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::splicing::SourceInfo;
2 use anyhow::{Context, Result};
3 use crates_index::IndexConfig;
4 use hex::ToHex;
5 
6 pub(crate) enum CrateIndexLookup {
7     Git(crates_index::GitIndex),
8     Http(crates_index::SparseIndex),
9 }
10 
11 impl CrateIndexLookup {
get_source_info(&self, pkg: &cargo_lock::Package) -> Result<Option<SourceInfo>>12     pub(crate) fn get_source_info(&self, pkg: &cargo_lock::Package) -> Result<Option<SourceInfo>> {
13         let index_config = self
14             .index_config()
15             .context("Failed to get crate index config")?;
16         let crate_ = match self {
17             // The crates we care about should all be in the cache already,
18             // because `cargo metadata` ran which should have fetched them.
19             Self::Http(index) => Some(
20                 index
21                     .crate_from_cache(pkg.name.as_str())
22                     .with_context(|| format!("Failed to get crate from cache for {pkg:?}"))?,
23             ),
24             Self::Git(index) => index.crate_(pkg.name.as_str()),
25         };
26         let source_info = crate_.and_then(|crate_idx| {
27             crate_idx
28                 .versions()
29                 .iter()
30                 .find(|v| v.version() == pkg.version.to_string())
31                 .and_then(|v| {
32                     v.download_url(&index_config).map(|url| {
33                         let sha256 = pkg
34                             .checksum
35                             .as_ref()
36                             .and_then(|sum| sum.as_sha256().map(|sum| sum.encode_hex::<String>()))
37                             .unwrap_or_else(|| v.checksum().encode_hex::<String>());
38                         SourceInfo { url, sha256 }
39                     })
40                 })
41         });
42         Ok(source_info)
43     }
44 
45     #[allow(clippy::result_large_err)]
index_config(&self) -> Result<IndexConfig, crates_index::Error>46     fn index_config(&self) -> Result<IndexConfig, crates_index::Error> {
47         match self {
48             Self::Git(index) => index.index_config(),
49             Self::Http(index) => index.index_config(),
50         }
51     }
52 }
53 
54 #[cfg(test)]
55 mod test {
56     use crate::splicing::crate_index_lookup::CrateIndexLookup;
57     use semver::Version;
58     use std::ffi::OsString;
59 
60     // TODO: Avoid global state (env vars) in these tests.
61     // TODO: These should be separate tests methods but they have conflicting state.
62 
63     #[test]
sparse_index()64     fn sparse_index() {
65         let runfiles = runfiles::Runfiles::create().unwrap();
66         {
67             let _e = EnvVarResetter::set(
68                 "CARGO_HOME",
69                 runfiles.rlocation(
70                     "rules_rust/crate_universe/test_data/crate_indexes/lazy_static/cargo_home",
71                 ),
72             );
73 
74             let index = CrateIndexLookup::Http(
75                 crates_index::SparseIndex::from_url("sparse+https://index.crates.io/").unwrap(),
76             );
77             let source_info = index
78                 .get_source_info(&cargo_lock::Package {
79                     name: "lazy_static".parse().unwrap(),
80                     version: Version::parse("1.4.0").unwrap(),
81                     source: None,
82                     checksum: None,
83                     dependencies: Vec::new(),
84                     replace: None,
85                 })
86                 .unwrap()
87                 .unwrap();
88             assert_eq!(
89                 source_info.url,
90                 "https://crates.io/api/v1/crates/lazy_static/1.4.0/download"
91             );
92             assert_eq!(
93                 source_info.sha256,
94                 "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
95             );
96         }
97         {
98             let _e = EnvVarResetter::set("CARGO_HOME", runfiles.rlocation("rules_rust/crate_universe/test_data/crate_indexes/rewritten_lazy_static/cargo_home"));
99 
100             let index = CrateIndexLookup::Http(
101                 crates_index::SparseIndex::from_url("sparse+https://index.crates.io/").unwrap(),
102             );
103             let source_info = index
104                 .get_source_info(&cargo_lock::Package {
105                     name: "lazy_static".parse().unwrap(),
106                     version: Version::parse("1.4.0").unwrap(),
107                     source: None,
108                     checksum: None,
109                     dependencies: Vec::new(),
110                     replace: None,
111                 })
112                 .unwrap()
113                 .unwrap();
114             assert_eq!(
115                 source_info.url,
116                 "https://some-mirror.com/api/v1/crates/lazy_static/1.4.0/download"
117             );
118             assert_eq!(
119                 source_info.sha256,
120                 "fffffffffbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
121             );
122         }
123     }
124 
125     struct EnvVarResetter {
126         key: OsString,
127         value: Option<OsString>,
128     }
129 
130     impl EnvVarResetter {
set<K: Into<OsString>, V: Into<OsString>>(key: K, value: V) -> EnvVarResetter131         fn set<K: Into<OsString>, V: Into<OsString>>(key: K, value: V) -> EnvVarResetter {
132             let key = key.into();
133             let value = value.into();
134             let old_value = std::env::var_os(&key);
135 
136             std::env::set_var(&key, value);
137 
138             EnvVarResetter {
139                 key,
140                 value: old_value,
141             }
142         }
143     }
144 
145     impl Drop for EnvVarResetter {
drop(&mut self)146         fn drop(&mut self) {
147             if let Some(old_value) = self.value.as_ref() {
148                 std::env::set_var(&self.key, old_value);
149             } else {
150                 std::env::remove_var(&self.key);
151             }
152         }
153     }
154 }
155