@@ -82,40 +82,34 @@ impl Uploader {
82
82
format ! ( "readmes/{}/{}-{}.html" , name, name, version)
83
83
}
84
84
85
+ /// Uploads a file using the configured uploader (either S3, Local or NoOp).
86
+ /// It returns a a tuple containing the path of the uploaded file
87
+ /// and its checksum.
85
88
pub fn upload (
86
89
& self ,
87
- req : & mut Request ,
88
- krate : & Crate ,
89
- readme : Option < String > ,
90
- max : u64 ,
91
- vers : & semver :: Version ,
92
- ) -> CargoResult < ( Vec < u8 > , Bomb , Bomb ) > {
90
+ app : Arc < App > ,
91
+ path : & str ,
92
+ body : & mut io :: Read ,
93
+ content_type : & str ,
94
+ content_length : u64 ,
95
+ ) -> CargoResult < ( Option < String > , Vec < u8 > ) > {
93
96
match * self {
94
97
Uploader :: S3 { ref bucket, .. } => {
95
- let mut handle = req. app ( ) . handle ( ) ;
96
- let crate_path =
97
- format ! ( "/{}" , Uploader :: crate_path( & krate. name, & vers. to_string( ) ) ) ;
98
+ let mut handle = app. handle ( ) ;
98
99
let ( response, cksum) = {
99
- let length = read_le_u32 ( req. body ( ) ) ?;
100
- let body = LimitErrorReader :: new ( req. body ( ) , max) ;
101
100
let mut body = HashingReader :: new ( body) ;
102
101
let mut response = Vec :: new ( ) ;
103
102
{
104
- let mut s3req = bucket. put (
105
- & mut handle,
106
- & crate_path,
107
- & mut body,
108
- "application/x-tar" ,
109
- length as u64 ,
110
- ) ;
103
+ let mut s3req =
104
+ bucket. put ( & mut handle, & path, & mut body, content_type, content_length) ;
111
105
s3req
112
106
. write_function ( |data| {
113
107
response. extend ( data) ;
114
108
Ok ( data. len ( ) )
115
109
} )
116
110
. unwrap ( ) ;
117
111
s3req. perform ( ) . chain_error ( || {
118
- internal ( & format_args ! ( "failed to upload to S3: `{}`" , crate_path ) )
112
+ internal ( & format_args ! ( "failed to upload to S3: `{}`" , path ) )
119
113
} ) ?;
120
114
}
121
115
( response, body. finalize ( ) )
@@ -127,134 +121,76 @@ impl Uploader {
127
121
response
128
122
) ) ) ;
129
123
}
130
- let readme_path = if let Some ( rendered) = readme {
131
- let mut handle = req. app ( ) . handle ( ) ;
132
- let readme_path =
133
- format ! ( "/{}" , Uploader :: readme_path( & krate. name, & vers. to_string( ) ) ) ;
134
- let response = {
135
- let mut response = Vec :: new ( ) ;
136
- {
137
- let readme_len = rendered. len ( ) ;
138
- let mut cursor = io:: Cursor :: new ( rendered. into_bytes ( ) ) ;
139
- let mut s3req = bucket. put (
140
- & mut handle,
141
- & readme_path,
142
- & mut cursor,
143
- "text/html" ,
144
- readme_len as u64 ,
145
- ) ;
146
- s3req
147
- . write_function ( |data| {
148
- response. extend ( data) ;
149
- Ok ( data. len ( ) )
150
- } )
151
- . unwrap ( ) ;
152
- s3req. perform ( ) . chain_error ( || {
153
- internal ( & format_args ! (
154
- "failed to upload readme to S3: `{}`" ,
155
- readme_path
156
- ) )
157
- } ) ?;
158
- }
159
- response
160
- } ;
161
- if handle. response_code ( ) . unwrap ( ) != 200 {
162
- if let Err ( e) = self . delete ( req. app ( ) . clone ( ) , & crate_path) {
163
- println ! ( "failed to delete crate from S3: `{}`, {:?}" , crate_path, e) ;
164
- }
165
- let response = String :: from_utf8_lossy ( & response) ;
166
- return Err ( internal ( & format_args ! (
167
- "failed to get a 200 response from S3: {}" ,
168
- response
169
- ) ) ) ;
170
- }
171
- Some ( readme_path)
172
- } else {
173
- None
174
- } ;
175
-
176
- Ok ( (
177
- cksum,
178
- Bomb {
179
- app : req. app ( ) . clone ( ) ,
180
- path : Some ( crate_path) ,
181
- } ,
182
- Bomb {
183
- app : req. app ( ) . clone ( ) ,
184
- path : readme_path,
185
- } ,
186
- ) )
124
+ Ok ( ( Some ( String :: from ( path) ) , cksum) )
187
125
}
188
126
Uploader :: Local => {
189
- use std:: io:: Write ;
190
-
191
- let crate_path = Uploader :: crate_path ( & krate. name , & vers. to_string ( ) ) ;
192
- let crate_filename = env:: current_dir ( )
127
+ let filename = env:: current_dir ( )
193
128
. unwrap ( )
194
129
. join ( "dist" )
195
130
. join ( "local_uploads" )
196
- . join ( crate_path) ;
197
-
198
- let crate_dir = crate_filename. parent ( ) . unwrap ( ) ;
199
- fs:: create_dir_all ( crate_dir) ?;
200
-
201
- let mut crate_file = File :: create ( & crate_filename) ?;
202
-
203
- let cksum = {
204
- read_le_u32 ( req. body ( ) ) ?;
205
- let body = LimitErrorReader :: new ( req. body ( ) , max) ;
206
- let mut body = HashingReader :: new ( body) ;
207
-
208
- io:: copy ( & mut body, & mut crate_file) ?;
209
- body. finalize ( )
210
- } ;
211
-
212
- let readme_filename = if let Some ( rendered) = readme {
213
- let readme_path = Uploader :: readme_path ( & krate. name , & vers. to_string ( ) ) ;
214
- let readme_filename = env:: current_dir ( )
215
- . unwrap ( )
216
- . join ( "dist" )
217
- . join ( "local_uploads" )
218
- . join ( readme_path) ;
219
-
220
- let readme_dir = readme_filename. parent ( ) . unwrap ( ) ;
221
- fs:: create_dir_all ( readme_dir) ?;
222
-
223
- let mut readme_file = File :: create ( & readme_filename) ?;
224
- readme_file. write_all ( rendered. as_ref ( ) ) ?;
225
- readme_filename. to_str ( ) . map ( String :: from)
226
- } else {
227
- None
228
- } ;
229
-
230
- Ok ( (
231
- cksum,
232
- Bomb {
233
- app : req. app ( ) . clone ( ) ,
234
- path : crate_filename. to_str ( ) . map ( String :: from) ,
235
- } ,
236
- Bomb {
237
- app : req. app ( ) . clone ( ) ,
238
- path : readme_filename,
239
- } ,
240
- ) )
241
- }
242
- Uploader :: NoOp => {
243
- Ok ( (
244
- vec ! [ ] ,
245
- Bomb {
246
- app : req. app ( ) . clone ( ) ,
247
- path : None ,
248
- } ,
249
- Bomb {
250
- app : req. app ( ) . clone ( ) ,
251
- path : None ,
252
- } ,
253
- ) )
131
+ . join ( path) ;
132
+ let dir = filename. parent ( ) . unwrap ( ) ;
133
+ fs:: create_dir_all ( dir) ?;
134
+ let mut file = File :: create ( & filename) ?;
135
+ let mut body = HashingReader :: new ( body) ;
136
+ io:: copy ( & mut body, & mut file) ?;
137
+ Ok ( ( filename. to_str ( ) . map ( String :: from) , body. finalize ( ) ) )
254
138
}
139
+ Uploader :: NoOp => Ok ( ( None , vec ! [ ] ) ) ,
255
140
}
256
141
}
257
142
143
+ /// Uploads a crate and its readme. Returns the checksum of the uploaded crate
144
+ /// file, and bombs for the uploaded crate and the uploaded readme.
145
+ pub fn upload_crate (
146
+ & self ,
147
+ req : & mut Request ,
148
+ krate : & Crate ,
149
+ readme : Option < String > ,
150
+ max : u64 ,
151
+ vers : & semver:: Version ,
152
+ ) -> CargoResult < ( Vec < u8 > , Bomb , Bomb ) > {
153
+ let app = req. app ( ) . clone ( ) ;
154
+ let ( crate_path, checksum) = {
155
+ let path = format ! ( "/{}" , Uploader :: crate_path( & krate. name, & vers. to_string( ) ) ) ;
156
+ let length = read_le_u32 ( req. body ( ) ) ?;
157
+ let mut body = LimitErrorReader :: new ( req. body ( ) , max) ;
158
+ self . upload (
159
+ app. clone ( ) ,
160
+ & path,
161
+ & mut body,
162
+ "application/x-tar" ,
163
+ length as u64 ,
164
+ ) ?
165
+ } ;
166
+ let crate_bomb = Bomb {
167
+ app : app. clone ( ) ,
168
+ path : crate_path,
169
+ } ;
170
+ let ( readme_path, _) = if let Some ( rendered) = readme {
171
+ let path = format ! ( "/{}" , Uploader :: readme_path( & krate. name, & vers. to_string( ) ) ) ;
172
+ let length = rendered. len ( ) ;
173
+ let mut body = io:: Cursor :: new ( rendered. into_bytes ( ) ) ;
174
+ self . upload (
175
+ app. clone ( ) ,
176
+ & path,
177
+ & mut body,
178
+ "text/html" ,
179
+ length as u64 ,
180
+ ) ?
181
+ } else {
182
+ ( None , vec ! [ ] )
183
+ } ;
184
+ Ok ( (
185
+ checksum,
186
+ crate_bomb,
187
+ Bomb {
188
+ app : app. clone ( ) ,
189
+ path : readme_path,
190
+ } ,
191
+ ) )
192
+ }
193
+
258
194
pub fn delete ( & self , app : Arc < App > , path : & str ) -> CargoResult < ( ) > {
259
195
match * self {
260
196
Uploader :: S3 { ref bucket, .. } => {
0 commit comments