Skip to content

Commit 0518a0d

Browse files
committed
Use different library for mime on windows
1 parent 1b47c15 commit 0518a0d

File tree

4 files changed

+108
-39
lines changed

4 files changed

+108
-39
lines changed

Cargo.lock

Lines changed: 15 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@ reqwest = "0.9"
1818
semver = "0.9"
1919
slug = "=0.1.1"
2020
env_logger = "0.6"
21-
magic = "0.12"
2221
r2d2 = "0.8"
2322
r2d2_postgres = "0.14"
2423
url = "1.4"
25-
libc = "0.2"
2624
badge = { version = "0", path = "src/web/badge" }
2725
failure = "0.1.3"
2826
comrak = { version = "0.3", default-features = false }
@@ -48,8 +46,13 @@ handlebars-iron = "0.22"
4846
params = "0.6"
4947
staticfile = { version = "0.4", features = [ "cache" ] }
5048

49+
[target.'cfg(not(windows))'.dependencies]
50+
libc = "0.2"
51+
magic = "0.12"
52+
5153
[target.'cfg(windows)'.dependencies]
5254
path-slash = "0.1.1"
55+
mime_guess = "2.0.1"
5356

5457
[dependencies.postgres]
5558
version = "0.15"

src/db/file.rs

Lines changed: 81 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ use failure::err_msg;
1616
use rusoto_s3::{S3, PutObjectRequest, GetObjectRequest, S3Client};
1717
use rusoto_core::region::Region;
1818
use rusoto_credential::DefaultCredentialsProvider;
19+
#[cfg(not(windows))]
20+
use magic::{Cookie, flags};
21+
#[cfg(not(windows))]
22+
use std::ffi::OsStr;
1923

2024

2125
const MAX_CONCURRENT_UPLOADS: usize = 1000;
@@ -155,12 +159,9 @@ pub fn add_path_into_database<P: AsRef<Path>>(conn: &Connection,
155159
prefix: &str,
156160
path: P)
157161
-> Result<Json> {
158-
use magic::{Cookie, flags};
159-
let cookie = Cookie::open(flags::MIME_TYPE)?;
160-
cookie.load::<&str>(&[])?;
161-
162162
let trans = conn.transaction()?;
163-
163+
#[cfg(not(windows))]
164+
let mime_data = load_mime_data()?;
164165
use std::collections::HashMap;
165166
let mut file_paths_and_mimes: HashMap<PathBuf, String> = HashMap::new();
166167
use futures::future::Future;
@@ -195,25 +196,10 @@ pub fn add_path_into_database<P: AsRef<Path>>(conn: &Connection,
195196
#[cfg(not(windows))]
196197
let bucket_path = bucket_path.into_os_string().into_string().unwrap();
197198

198-
let mime = {
199-
let mime = cookie.buffer(&content)?;
200-
// css's are causing some problem in browsers
201-
// magic will return text/plain for css file types
202-
// convert them to text/css
203-
// do the same for javascript files
204-
if mime == "text/plain" {
205-
let e = file_path.extension().unwrap_or_default();
206-
if e == "css" {
207-
"text/css".to_owned()
208-
} else if e == "js" {
209-
"application/javascript".to_owned()
210-
} else {
211-
mime.to_owned()
212-
}
213-
} else {
214-
mime.to_owned()
215-
}
216-
};
199+
#[cfg(windows)]
200+
let mime = detect_mime(&content, &file_path)?;
201+
#[cfg(not(windows))]
202+
let mime = detect_mime(&content, &file_path, &mime_data)?;
217203

218204
if let Some(client) = &client {
219205
futures.push(client.put_object(PutObjectRequest {
@@ -276,6 +262,51 @@ pub fn add_path_into_database<P: AsRef<Path>>(conn: &Connection,
276262
file_list_to_json(file_list_with_mimes)
277263
}
278264

265+
#[cfg(not(windows))]
266+
fn load_mime_data() -> Result<Cookie> {
267+
let cookie = Cookie::open(flags::MIME_TYPE)?;
268+
cookie.load::<&str>(&[])?;
269+
Ok(cookie)
270+
}
271+
272+
#[cfg(not(windows))]
273+
fn detect_mime(content: &Vec<u8>, file_path: &Path, cookie: &Cookie) -> Result<String> {
274+
let mime = cookie.buffer(&content)?;
275+
276+
// magic is not specific enough sometimes
277+
match mime.as_str() {
278+
"text/plain" => {
279+
match file_path.extension().and_then(OsStr::to_str) {
280+
Some("md") => Ok("text/markdown".to_owned()),
281+
Some("rs") => Ok("text/rust".to_owned()),
282+
Some("markdown") => Ok("text/markdown".to_owned()),
283+
Some("css") => Ok("text/css".to_owned()),
284+
Some("toml") => Ok("text/x-toml".to_owned()),
285+
Some("js") => Ok("application/javascript".to_owned()),
286+
Some("json") => Ok("application/json".to_owned()),
287+
_ => Ok(mime.to_owned())
288+
}
289+
}
290+
"text/troff" => {
291+
match file_path.extension().and_then(OsStr::to_str) {
292+
Some("css") => Ok("text/css".to_owned()),
293+
_ => Ok(mime.to_owned())
294+
}
295+
}
296+
_ => Ok(mime.to_owned())
297+
}
298+
}
299+
300+
#[cfg(windows)]
301+
fn detect_mime(_content: &Vec<u8>, file_path: &Path) -> Result<String> {
302+
let file_ext = file_path.extension().map(|ext| ext.to_str()).unwrap_or_default();
303+
Ok(match file_ext {
304+
Some("md") => "text/markdown".to_owned(),
305+
Some("rs") => "text/rust".to_owned(),
306+
None => "text/plain".to_owned(),
307+
_ => mime_guess::from_path(file_path).first_raw().map(|m| m.to_owned()).unwrap_or("text/plain".to_owned())
308+
})
309+
}
279310

280311

281312
fn file_list_to_json(file_list: Vec<(String, PathBuf)>) -> Result<Json> {
@@ -343,7 +374,7 @@ pub fn move_to_s3(conn: &Connection, n: usize) -> Result<usize> {
343374
mod test {
344375
extern crate env_logger;
345376
use std::env;
346-
use super::get_file_list;
377+
use super::*;
347378

348379
#[test]
349380
fn test_get_file_list() {
@@ -356,4 +387,29 @@ mod test {
356387
let files = get_file_list(env::current_dir().unwrap().join("Cargo.toml")).unwrap();
357388
assert_eq!(files[0], std::path::Path::new("Cargo.toml"));
358389
}
390+
#[test]
391+
fn test_mime_types() {
392+
check_mime("/ignored", ".gitignore", "text/plain");
393+
check_mime("[package]", "hello.toml","text/x-toml");
394+
check_mime(".ok { color:red; }", "hello.css","text/css");
395+
check_mime("var x = 1", "hello.js","application/javascript");
396+
check_mime("<html>", "hello.html","text/html");
397+
check_mime("## HELLO", "hello.hello.md","text/markdown");
398+
check_mime("## WORLD", "hello.markdown","text/markdown");
399+
check_mime("{}", "hello.json","application/json");
400+
check_mime("hello world", "hello.txt","text/plain");
401+
check_mime("//! Simple module to ...", "file.rs", "text/rust");
402+
}
403+
404+
fn check_mime(content: &str, path: &str, expected_mime: &str) {
405+
#[cfg(not(windows))]
406+
let mime_data = load_mime_data().unwrap();
407+
#[cfg(windows)]
408+
let detected_mime = detect_mime(&content.as_bytes().to_vec(), Path::new(&path));
409+
#[cfg(not(windows))]
410+
let detected_mime = detect_mime(&content.as_bytes().to_vec(), Path::new(&path), &mime_data);
411+
let detected_mime = detected_mime.expect("no mime was given");
412+
assert_eq!(detected_mime, expected_mime);
413+
}
359414
}
415+

src/lib.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ extern crate reqwest;
1616
extern crate time;
1717
extern crate semver;
1818
extern crate slug;
19-
extern crate magic;
2019
extern crate iron;
2120
extern crate router;
2221
extern crate staticfile;
@@ -26,7 +25,6 @@ extern crate r2d2;
2625
extern crate r2d2_postgres;
2726
extern crate url;
2827
extern crate params;
29-
extern crate libc;
3028
extern crate badge;
3129
extern crate crates_index_diff;
3230
extern crate toml;
@@ -42,8 +40,15 @@ extern crate systemstat;
4240
extern crate rustwide;
4341
extern crate tempdir;
4442

43+
#[cfg(not(windows))]
44+
extern crate magic;
45+
#[cfg(not(windows))]
46+
extern crate libc;
47+
4548
#[cfg(windows)]
4649
extern crate path_slash;
50+
#[cfg(windows)]
51+
extern crate mime_guess;
4752

4853
#[cfg(test)]
4954
extern crate once_cell;

0 commit comments

Comments
 (0)