|
1 | 1 | use crates::{lists::List, Crate}; |
2 | 2 | use crates_index::Index; |
3 | | -use dirs::LOCAL_DIR; |
| 3 | +use dirs::{LOCAL_DIR, SOURCE_CACHE_DIR}; |
4 | 4 | use flate2::read::GzDecoder; |
5 | 5 | use prelude::*; |
6 | 6 | use std::collections::HashMap; |
7 | | -use std::fs; |
8 | | -use std::io::Read; |
9 | | -use std::path::Path; |
| 7 | +use std::fs::{self, File}; |
| 8 | +use std::io::{BufReader, BufWriter, Read}; |
| 9 | +use std::path::{Path, PathBuf}; |
10 | 10 | use tar::Archive; |
11 | 11 |
|
12 | 12 | static CRATES_ROOT: &str = "https://crates-io.s3-us-west-1.amazonaws.com/crates"; |
@@ -67,40 +67,57 @@ pub struct RegistryCrate { |
67 | 67 | } |
68 | 68 |
|
69 | 69 | impl RegistryCrate { |
70 | | - pub(in crates) fn prepare(&self, dest: &Path) -> Fallible<()> { |
71 | | - dl_registry(&self.name, &self.version, &dest).with_context(|_| { |
72 | | - format!("unable to download {} version {}", self.name, self.version) |
73 | | - })?; |
74 | | - Ok(()) |
| 70 | + fn cached_path(&self) -> PathBuf { |
| 71 | + SOURCE_CACHE_DIR |
| 72 | + .join("reg") |
| 73 | + .join(&self.name) |
| 74 | + .join(format!("{}-{}.crate", self.name, self.version)) |
75 | 75 | } |
76 | | -} |
77 | 76 |
|
78 | | -fn dl_registry(name: &str, vers: &str, dir: &Path) -> Fallible<()> { |
79 | | - if dir.exists() { |
80 | | - info!( |
81 | | - "crate {}-{} exists at {}. skipping", |
82 | | - name, |
83 | | - vers, |
84 | | - dir.display() |
| 77 | + pub(in crates) fn fetch(&self) -> Fallible<()> { |
| 78 | + let local = self.cached_path(); |
| 79 | + if local.exists() { |
| 80 | + info!("crate {} {} is already in cache", self.name, self.version); |
| 81 | + return Ok(()); |
| 82 | + } |
| 83 | + |
| 84 | + info!("fetching crate {} {}...", self.name, self.version); |
| 85 | + if let Some(parent) = local.parent() { |
| 86 | + fs::create_dir_all(parent)?; |
| 87 | + } |
| 88 | + let remote = format!( |
| 89 | + "{0}/{1}/{1}-{2}.crate", |
| 90 | + CRATES_ROOT, self.name, self.version |
85 | 91 | ); |
86 | | - return Ok(()); |
87 | | - } |
88 | | - info!("downloading crate {}-{} to {}", name, vers, dir.display()); |
89 | | - let url = format!("{0}/{1}/{1}-{2}.crate", CRATES_ROOT, name, vers); |
90 | | - let bin = |
91 | | - ::utils::http::get_sync(&url).with_context(|_| format!("unable to download {}", url))?; |
| 92 | + let mut resp = ::utils::http::get_sync(&remote)?; |
| 93 | + resp.copy_to(&mut BufWriter::new(File::create(&local)?))?; |
92 | 94 |
|
93 | | - fs::create_dir_all(&dir)?; |
| 95 | + Ok(()) |
| 96 | + } |
94 | 97 |
|
95 | | - let mut tar = Archive::new(GzDecoder::new(bin)); |
96 | | - let r = |
97 | | - unpack_without_first_dir(&mut tar, dir).with_context(|_| "unable to unpack crate tarball"); |
| 98 | + pub(in crates) fn copy_to(&self, dest: &Path) -> Fallible<()> { |
| 99 | + let cached = self.cached_path(); |
| 100 | + let mut file = File::open(cached)?; |
| 101 | + let mut tar = Archive::new(GzDecoder::new(BufReader::new(&mut file))); |
98 | 102 |
|
99 | | - if r.is_err() { |
100 | | - let _ = ::utils::fs::remove_dir_all(dir); |
| 103 | + info!( |
| 104 | + "extracting crate {} {} into {}", |
| 105 | + self.name, |
| 106 | + self.version, |
| 107 | + dest.display() |
| 108 | + ); |
| 109 | + if let Err(err) = unpack_without_first_dir(&mut tar, dest) { |
| 110 | + let _ = ::utils::fs::remove_dir_all(dest); |
| 111 | + Err(err |
| 112 | + .context(format!( |
| 113 | + "unable to download {} version {}", |
| 114 | + self.name, self.version |
| 115 | + )) |
| 116 | + .into()) |
| 117 | + } else { |
| 118 | + Ok(()) |
| 119 | + } |
101 | 120 | } |
102 | | - |
103 | | - r.map_err(|e| e.into()) |
104 | 121 | } |
105 | 122 |
|
106 | 123 | fn unpack_without_first_dir<R: Read>(archive: &mut Archive<R>, path: &Path) -> Fallible<()> { |
|
0 commit comments