@@ -4,6 +4,7 @@ use crate::{
4
4
schema:: { crates, readme_renderings, versions} ,
5
5
uploaders:: Uploader ,
6
6
} ;
7
+ use anyhow:: { anyhow, Context } ;
7
8
use std:: { io:: Read , path:: Path , sync:: Arc , thread} ;
8
9
9
10
use cargo_registry_markdown:: text_to_html;
@@ -37,7 +38,7 @@ pub struct Opts {
37
38
crate_name : Option < String > ,
38
39
}
39
40
40
- pub fn run ( opts : Opts ) {
41
+ pub fn run ( opts : Opts ) -> anyhow :: Result < ( ) > {
41
42
let base_config = Arc :: new ( config:: Base :: from_environment ( ) ) ;
42
43
let conn = db:: connect_now ( ) . unwrap ( ) ;
43
44
@@ -102,21 +103,14 @@ pub fn run(opts: Opts) {
102
103
103
104
let mut tasks = Vec :: with_capacity ( page_size as usize ) ;
104
105
for ( version, krate_name) in versions {
105
- Version :: record_readme_rendering ( version. id , & conn) . unwrap_or_else ( |_| {
106
- panic ! (
107
- "[{}-{}] Couldn't record rendering time" ,
108
- krate_name, version. num
109
- )
110
- } ) ;
106
+ Version :: record_readme_rendering ( version. id , & conn)
107
+ . context ( "Couldn't record rendering time" ) ?;
108
+
111
109
let client = client. clone ( ) ;
112
110
let base_config = base_config. clone ( ) ;
113
- let handle = thread:: spawn ( move || {
111
+ let handle = thread:: spawn :: < _ , anyhow :: Result < ( ) > > ( move || {
114
112
println ! ( "[{}-{}] Rendering README..." , krate_name, version. num) ;
115
- let readme = get_readme ( base_config. uploader ( ) , & client, & version, & krate_name) ;
116
- if readme. is_none ( ) {
117
- return ;
118
- }
119
- let readme = readme. unwrap ( ) ;
113
+ let readme = get_readme ( base_config. uploader ( ) , & client, & version, & krate_name) ?;
120
114
let content_length = readme. len ( ) as u64 ;
121
115
let content = std:: io:: Cursor :: new ( readme) ;
122
116
let readme_path = format ! ( "readmes/{0}/{0}-{1}.html" , krate_name, version. num) ;
@@ -125,6 +119,7 @@ pub fn run(opts: Opts) {
125
119
header:: CACHE_CONTROL ,
126
120
header:: HeaderValue :: from_static ( CACHE_CONTROL_README ) ,
127
121
) ;
122
+
128
123
base_config
129
124
. uploader ( )
130
125
. upload (
@@ -135,21 +130,22 @@ pub fn run(opts: Opts) {
135
130
"text/html" ,
136
131
extra_headers,
137
132
)
138
- . unwrap_or_else ( |_| {
139
- panic ! (
140
- "[{}-{}] Couldn't upload file to S3" ,
141
- krate_name, version. num
142
- )
143
- } ) ;
133
+ . context ( "Failed to upload rendered README file to S3" ) ?;
134
+
135
+ Ok ( ( ) )
144
136
} ) ;
145
137
tasks. push ( handle) ;
146
138
}
147
139
for handle in tasks {
148
- if let Err ( err) = handle. join ( ) {
149
- println ! ( "Thread panicked: {:?}" , err) ;
140
+ match handle. join ( ) {
141
+ Err ( err) => println ! ( "Thread panicked: {:?}" , err) ,
142
+ Ok ( Err ( err) ) => println ! ( "Thread failed: {:?}" , err) ,
143
+ _ => { }
150
144
}
151
145
}
152
146
}
147
+
148
+ Ok ( ( ) )
153
149
}
154
150
155
151
/// Renders the readme of an uploaded crate version.
@@ -158,7 +154,7 @@ fn get_readme(
158
154
client : & Client ,
159
155
version : & Version ,
160
156
krate_name : & str ,
161
- ) -> Option < String > {
157
+ ) -> anyhow :: Result < String > {
162
158
let pkg_name = format ! ( "{}-{}" , krate_name, version. num) ;
163
159
164
160
let location = uploader. crate_location ( krate_name, & version. num . to_string ( ) ) ;
@@ -173,39 +169,30 @@ fn get_readme(
173
169
header:: USER_AGENT ,
174
170
header:: HeaderValue :: from_static ( USER_AGENT ) ,
175
171
) ;
176
- let response = match client. get ( & location) . headers ( extra_headers) . send ( ) {
177
- Ok ( r) => r,
178
- Err ( err) => {
179
- println ! ( "[{}] Unable to fetch crate: {}" , pkg_name, err) ;
180
- return None ;
181
- }
182
- } ;
172
+ let request = client. get ( & location) . headers ( extra_headers) ;
173
+ let response = request. send ( ) . context ( "Failed to fetch crate" ) ?;
183
174
184
175
if !response. status ( ) . is_success ( ) {
185
- println ! (
186
- "[{}] Failed to get a 200 response: {}" ,
187
- pkg_name,
176
+ return Err ( anyhow ! (
177
+ "Failed to get a 200 response: {}" ,
188
178
response. text( ) . unwrap( )
189
- ) ;
190
- return None ;
179
+ ) ) ;
191
180
}
192
181
193
182
let reader = GzDecoder :: new ( response) ;
194
183
let archive = Archive :: new ( reader) ;
195
184
render_pkg_readme ( archive, & pkg_name)
196
185
}
197
186
198
- fn render_pkg_readme < R : Read > ( mut archive : Archive < R > , pkg_name : & str ) -> Option < String > {
199
- let mut entries = archive
200
- . entries ( )
201
- . unwrap_or_else ( |_| panic ! ( "[{}] Invalid tar archive entries" , pkg_name) ) ;
187
+ fn render_pkg_readme < R : Read > ( mut archive : Archive < R > , pkg_name : & str ) -> anyhow:: Result < String > {
188
+ let mut entries = archive. entries ( ) . context ( "Invalid tar archive entries" ) ?;
202
189
203
190
let manifest: Manifest = {
204
191
let path = format ! ( "{}/Cargo.toml" , pkg_name) ;
205
- let contents = find_file_by_path ( & mut entries, Path :: new ( & path) , pkg_name )
206
- . unwrap_or_else ( || panic ! ( "[{}] couldn't open file: Cargo.toml" , pkg_name ) ) ;
207
- toml :: from_str ( & contents )
208
- . unwrap_or_else ( |_| panic ! ( "[{}] Syntax error in manifest file", pkg_name ) )
192
+ let contents = find_file_by_path ( & mut entries, Path :: new ( & path) )
193
+ . context ( "Failed to read Cargo.toml file" ) ? ;
194
+
195
+ toml :: from_str ( & contents ) . context ( "Failed to parse manifest file") ?
209
196
} ;
210
197
211
198
let rendered = {
@@ -215,14 +202,16 @@ fn render_pkg_readme<R: Read>(mut archive: Archive<R>, pkg_name: &str) -> Option
215
202
. clone ( )
216
203
. unwrap_or_else ( || "README.md" . into ( ) ) ;
217
204
let path = format ! ( "{}/{}" , pkg_name, readme_path) ;
218
- let contents = find_file_by_path ( & mut entries, Path :: new ( & path) , pkg_name) ?;
205
+ let contents = find_file_by_path ( & mut entries, Path :: new ( & path) )
206
+ . with_context ( || format ! ( "Failed to read {} file" , readme_path) ) ?;
207
+
219
208
text_to_html (
220
209
& contents,
221
210
& readme_path,
222
211
manifest. package . repository . as_deref ( ) ,
223
212
)
224
213
} ;
225
- return Some ( rendered) ;
214
+ return Ok ( rendered) ;
226
215
227
216
#[ derive( Debug , Deserialize ) ]
228
217
struct Package {
@@ -240,25 +229,20 @@ fn render_pkg_readme<R: Read>(mut archive: Archive<R>, pkg_name: &str) -> Option
240
229
fn find_file_by_path < R : Read > (
241
230
entries : & mut tar:: Entries < ' _ , R > ,
242
231
path : & Path ,
243
- pkg_name : & str ,
244
- ) -> Option < String > {
232
+ ) -> anyhow:: Result < String > {
245
233
let mut file = entries
246
- . find ( |entry| match * entry {
234
+ . filter_map ( |entry| entry. ok ( ) )
235
+ . find ( |file| match file. path ( ) {
236
+ Ok ( p) => p == path,
247
237
Err ( _) => false ,
248
- Ok ( ref file) => {
249
- let filepath = match file. path ( ) {
250
- Ok ( p) => p,
251
- Err ( _) => return false ,
252
- } ;
253
- filepath == path
254
- }
255
- } ) ?
256
- . unwrap_or_else ( |_| panic ! ( "[{}] file is not present: {}" , pkg_name, path. display( ) ) ) ;
238
+ } )
239
+ . ok_or_else ( || anyhow ! ( "Failed to find tarball entry: {}" , path. display( ) ) ) ?;
257
240
258
241
let mut contents = String :: new ( ) ;
259
242
file. read_to_string ( & mut contents)
260
- . unwrap_or_else ( |_| panic ! ( "[{}] Couldn't read file contents" , pkg_name) ) ;
261
- Some ( contents)
243
+ . context ( "Failed to read file contents" ) ?;
244
+
245
+ Ok ( contents)
262
246
}
263
247
264
248
#[ cfg( test) ]
@@ -304,7 +288,10 @@ readme = "README.md"
304
288
"# ,
305
289
) ;
306
290
let serialized_archive = pkg. into_inner ( ) . unwrap ( ) ;
307
- assert ! ( render_pkg_readme( tar:: Archive :: new( & * serialized_archive) , "foo-0.0.1" ) . is_none( ) ) ;
291
+ assert_err ! ( render_pkg_readme(
292
+ tar:: Archive :: new( & * serialized_archive) ,
293
+ "foo-0.0.1"
294
+ ) ) ;
308
295
}
309
296
310
297
#[ test]
0 commit comments