|
1 | 1 | use std::hash::Hasher;
|
2 | 2 | use std::path::PathBuf;
|
3 | 3 |
|
4 |
| -use anyhow::bail; |
5 | 4 | use anyhow::Context;
|
6 | 5 | use deno_core::error::AnyError;
|
7 | 6 | use futures::io::AllowStdIo;
|
8 | 7 | use futures::StreamExt;
|
9 | 8 | use reqwest::Url;
|
10 | 9 | use tokio::io::AsyncWriteExt;
|
11 | 10 | use tokio_util::compat::FuturesAsyncWriteCompatExt;
|
12 |
| -use tracing::debug; |
13 |
| -use tracing::error; |
14 | 11 | use tracing::info;
|
15 | 12 | use tracing::info_span;
|
16 | 13 | use tracing::instrument;
|
@@ -82,85 +79,69 @@ pub async fn fetch_and_cache_from_url(
|
82 | 79 |
|
83 | 80 | let span = info_span!("download", filepath = %filepath.to_string_lossy());
|
84 | 81 | async move {
|
85 |
| - if is_filepath_exists && is_checksum_valid { |
86 |
| - info!("binary already exists, skipping download"); |
87 |
| - Ok(filepath.clone()) |
88 |
| - } else { |
89 |
| - info!("downloading binary"); |
90 |
| - |
91 |
| - if is_filepath_exists { |
92 |
| - let _ = tokio::fs::remove_file(&filepath).await; |
93 |
| - } |
94 |
| - |
95 |
| - use reqwest::*; |
96 |
| - |
97 |
| - let resp = Client::builder() |
98 |
| - .http1_only() |
99 |
| - .build() |
100 |
| - .context("failed to create http client")? |
101 |
| - .get(url.clone()) |
102 |
| - .send() |
103 |
| - .await |
104 |
| - .context("failed to download")?; |
105 |
| - |
106 |
| - let len = resp |
107 |
| - .headers() |
108 |
| - .get(header::CONTENT_LENGTH) |
109 |
| - .map(|it| it.to_str().map_err(AnyError::new)) |
110 |
| - .transpose()? |
111 |
| - .map(|it| it.parse::<usize>().map_err(AnyError::new)) |
112 |
| - .transpose()? |
113 |
| - .context("invalid Content-Length header")?; |
114 |
| - |
115 |
| - debug!(total_bytes = len); |
116 |
| - |
117 |
| - let file = tokio::fs::File::create(&filepath) |
118 |
| - .await |
119 |
| - .context("failed to create file")?; |
120 |
| - |
121 |
| - let mut stream = resp.bytes_stream(); |
122 |
| - let mut writer = tokio::io::BufWriter::new(file); |
123 |
| - let mut hasher = AllowStdIo::new(Xxh3::new()).compat_write(); |
124 |
| - let mut written = 0; |
125 |
| - |
126 |
| - while let Some(chunk) = stream.next().await { |
127 |
| - let chunk = chunk.context("failed to get chunks")?; |
128 |
| - |
129 |
| - written += tokio::io::copy(&mut chunk.as_ref(), &mut writer) |
130 |
| - .await |
131 |
| - .context("failed to store chunks to file")?; |
132 |
| - |
133 |
| - let _ = tokio::io::copy(&mut chunk.as_ref(), &mut hasher) |
134 |
| - .await |
135 |
| - .context("failed to calculate checksum")?; |
136 |
| - |
137 |
| - trace!(bytes_written = written); |
138 |
| - } |
139 |
| - |
140 |
| - let checksum_str = { |
141 |
| - let hasher = hasher.into_inner().into_inner(); |
142 |
| - faster_hex::hex_string(&hasher.finish().to_be_bytes()) |
143 |
| - }; |
144 |
| - |
145 |
| - if written == len as u64 { |
146 |
| - info!({ bytes_written = written, checksum = &checksum_str }, "done"); |
147 |
| - |
148 |
| - let mut checksum_file = tokio::fs::File::create(&checksum_path) |
149 |
| - .await |
150 |
| - .context("failed to create checksum file")?; |
151 |
| - |
152 |
| - let _ = checksum_file |
153 |
| - .write(checksum_str.as_bytes()) |
154 |
| - .await |
155 |
| - .context("failed to write checksum to file system")?; |
156 |
| - |
157 |
| - Ok(filepath) |
158 |
| - } else { |
159 |
| - error!({ expected = len, got = written }, "bytes mismatch"); |
160 |
| - bail!("error copying data to file: expected {len} length, but got {written}"); |
161 |
| - } |
162 |
| - } |
| 82 | + if is_filepath_exists && is_checksum_valid { |
| 83 | + info!("binary already exists, skipping download"); |
| 84 | + Ok(filepath.clone()) |
| 85 | + } else { |
| 86 | + info!("downloading binary"); |
| 87 | + |
| 88 | + if is_filepath_exists { |
| 89 | + let _ = tokio::fs::remove_file(&filepath).await; |
| 90 | + } |
| 91 | + |
| 92 | + use reqwest::*; |
| 93 | + |
| 94 | + let resp = Client::builder() |
| 95 | + .http1_only() |
| 96 | + .build() |
| 97 | + .context("failed to create http client")? |
| 98 | + .get(url.clone()) |
| 99 | + .send() |
| 100 | + .await |
| 101 | + .context("failed to download")?; |
| 102 | + |
| 103 | + let file = tokio::fs::File::create(&filepath) |
| 104 | + .await |
| 105 | + .context("failed to create file")?; |
| 106 | + |
| 107 | + let mut stream = resp.bytes_stream(); |
| 108 | + let mut writer = tokio::io::BufWriter::new(file); |
| 109 | + let mut hasher = AllowStdIo::new(Xxh3::new()).compat_write(); |
| 110 | + let mut written = 0; |
| 111 | + |
| 112 | + while let Some(chunk) = stream.next().await { |
| 113 | + let chunk = chunk.context("failed to get chunks")?; |
| 114 | + |
| 115 | + written += tokio::io::copy(&mut chunk.as_ref(), &mut writer) |
| 116 | + .await |
| 117 | + .context("failed to store chunks to file")?; |
| 118 | + |
| 119 | + let _ = tokio::io::copy(&mut chunk.as_ref(), &mut hasher) |
| 120 | + .await |
| 121 | + .context("failed to calculate checksum")?; |
| 122 | + |
| 123 | + trace!(bytes_written = written); |
| 124 | + } |
| 125 | + |
| 126 | + let checksum_str = { |
| 127 | + let hasher = hasher.into_inner().into_inner(); |
| 128 | + faster_hex::hex_string(&hasher.finish().to_be_bytes()) |
| 129 | + }; |
| 130 | + |
| 131 | + info!({ bytes_written = written, checksum = &checksum_str }, "done"); |
| 132 | + |
| 133 | + let mut checksum_file = tokio::fs::File::create(&checksum_path) |
| 134 | + .await |
| 135 | + .context("failed to create checksum file")?; |
| 136 | + |
| 137 | + let _ = checksum_file |
| 138 | + .write(checksum_str.as_bytes()) |
| 139 | + .await |
| 140 | + .context("failed to write checksum to file system")?; |
| 141 | + |
| 142 | + Ok(filepath) |
163 | 143 | }
|
164 |
| - .instrument(span) |
165 |
| - .await |
| 144 | + } |
| 145 | + .instrument(span) |
| 146 | + .await |
166 | 147 | }
|
0 commit comments