|
1 | 1 | use crate::compare::{assert_match_exact, find_json_mismatch};
|
2 |
| -use crate::registry::{self, alt_api_path}; |
| 2 | +use crate::registry::{self, alt_api_path, FeatureMap}; |
3 | 3 | use flate2::read::GzDecoder;
|
4 | 4 | use std::collections::{HashMap, HashSet};
|
| 5 | +use std::fs; |
5 | 6 | use std::fs::File;
|
6 | 7 | use std::io::{self, prelude::*, SeekFrom};
|
7 | 8 | use std::path::{Path, PathBuf};
|
@@ -155,3 +156,90 @@ pub fn validate_crate_contents(
|
155 | 156 | }
|
156 | 157 | }
|
157 | 158 | }
|
| 159 | + |
| 160 | +pub(crate) fn create_index_line( |
| 161 | + name: serde_json::Value, |
| 162 | + vers: &str, |
| 163 | + deps: Vec<serde_json::Value>, |
| 164 | + cksum: &str, |
| 165 | + features: crate::registry::FeatureMap, |
| 166 | + yanked: bool, |
| 167 | + links: Option<String>, |
| 168 | + v: Option<u32>, |
| 169 | +) -> String { |
| 170 | + // This emulates what crates.io does to retain backwards compatibility. |
| 171 | + let (features, features2) = split_index_features(features.clone()); |
| 172 | + let mut json = serde_json::json!({ |
| 173 | + "name": name, |
| 174 | + "vers": vers, |
| 175 | + "deps": deps, |
| 176 | + "cksum": cksum, |
| 177 | + "features": features, |
| 178 | + "yanked": yanked, |
| 179 | + "links": links, |
| 180 | + }); |
| 181 | + if let Some(f2) = &features2 { |
| 182 | + json["features2"] = serde_json::json!(f2); |
| 183 | + json["v"] = serde_json::json!(2); |
| 184 | + } |
| 185 | + if let Some(v) = v { |
| 186 | + json["v"] = serde_json::json!(v); |
| 187 | + } |
| 188 | + |
| 189 | + json.to_string() |
| 190 | +} |
| 191 | + |
| 192 | +pub(crate) fn write_to_index(registry_path: &PathBuf, name: &str, line: String, local: bool) { |
| 193 | + let file = cargo_util::registry::make_dep_path(name, false); |
| 194 | + |
| 195 | + // Write file/line in the index. |
| 196 | + let dst = if local { |
| 197 | + registry_path.join("index").join(&file) |
| 198 | + } else { |
| 199 | + registry_path.join(&file) |
| 200 | + }; |
| 201 | + let prev = fs::read_to_string(&dst).unwrap_or_default(); |
| 202 | + t!(fs::create_dir_all(dst.parent().unwrap())); |
| 203 | + t!(fs::write(&dst, prev + &line[..] + "\n")); |
| 204 | + |
| 205 | + // Add the new file to the index. |
| 206 | + if !local { |
| 207 | + let repo = t!(git2::Repository::open(®istry_path)); |
| 208 | + let mut index = t!(repo.index()); |
| 209 | + t!(index.add_path(Path::new(&file))); |
| 210 | + t!(index.write()); |
| 211 | + let id = t!(index.write_tree()); |
| 212 | + |
| 213 | + // Commit this change. |
| 214 | + let tree = t!(repo.find_tree(id)); |
| 215 | + let sig = t!(repo.signature()); |
| 216 | + let parent = t!(repo.refname_to_id("refs/heads/master")); |
| 217 | + let parent = t!(repo.find_commit(parent)); |
| 218 | + t!(repo.commit( |
| 219 | + Some("HEAD"), |
| 220 | + &sig, |
| 221 | + &sig, |
| 222 | + "Another commit", |
| 223 | + &tree, |
| 224 | + &[&parent] |
| 225 | + )); |
| 226 | + } |
| 227 | +} |
| 228 | + |
| 229 | +fn split_index_features(mut features: FeatureMap) -> (FeatureMap, Option<FeatureMap>) { |
| 230 | + let mut features2 = FeatureMap::new(); |
| 231 | + for (feat, values) in features.iter_mut() { |
| 232 | + if values |
| 233 | + .iter() |
| 234 | + .any(|value| value.starts_with("dep:") || value.contains("?/")) |
| 235 | + { |
| 236 | + let new_values = values.drain(..).collect(); |
| 237 | + features2.insert(feat.clone(), new_values); |
| 238 | + } |
| 239 | + } |
| 240 | + if features2.is_empty() { |
| 241 | + (features, None) |
| 242 | + } else { |
| 243 | + (features, Some(features2)) |
| 244 | + } |
| 245 | +} |
0 commit comments