summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/deno_dir.rs137
-rw-r--r--cli/http_util.rs7
2 files changed, 97 insertions, 47 deletions
diff --git a/cli/deno_dir.rs b/cli/deno_dir.rs
index 7e19209c0..6d7c04f7f 100644
--- a/cli/deno_dir.rs
+++ b/cli/deno_dir.rs
@@ -8,9 +8,10 @@ use crate::fs as deno_fs;
use crate::http_util;
use crate::js_errors::SourceMapGetter;
use crate::msg;
+use crate::tokio_util;
use crate::version;
-
use dirs;
+use futures::Future;
use ring;
use std;
use std::fmt::Write;
@@ -492,55 +493,64 @@ fn filter_shebang(bytes: Vec<u8>) -> Vec<u8> {
}
}
-// Prototype https://github.com/denoland/deno/blob/golang/deno_dir.go#L37-L73
-/// Fetch remote source code.
-fn fetch_remote_source(
+/// Asynchronously fetch remote source file specified by the URL `module_name`
+/// and write it to disk at `filename`.
+fn fetch_remote_source_async(
module_name: &str,
filename: &str,
-) -> DenoResult<Option<ModuleMetaData>> {
- let p = Path::new(&filename);
+) -> impl Future<Item = Option<ModuleMetaData>, Error = DenoError> {
+ let filename = filename.to_string();
+ let module_name = module_name.to_string();
+ let p = PathBuf::from(filename.clone());
// We write a special ".mime" file into the `.deno/deps` directory along side the
// cached file, containing just the media type.
let media_type_filename = [&filename, ".mime"].concat();
- let mt = Path::new(&media_type_filename);
+ let mt = PathBuf::from(&media_type_filename);
eprint!("Downloading {}...", &module_name); // no newline
- let maybe_source = http_util::fetch_sync_string(&module_name);
- if let Ok((source, content_type)) = maybe_source {
- eprintln!(""); // next line
- match p.parent() {
- Some(ref parent) => fs::create_dir_all(parent),
- None => Ok(()),
- }?;
- deno_fs::write_file(&p, &source, 0o666)?;
- // Remove possibly existing stale .mime file
- // may not exist. DON'T unwrap
- let _ = std::fs::remove_file(&media_type_filename);
- // Create .mime file only when content type different from extension
- let resolved_content_type = map_content_type(&p, Some(&content_type));
- let ext = p
- .extension()
- .map(|x| x.to_str().unwrap_or(""))
- .unwrap_or("");
- let media_type = extmap(&ext);
- if media_type == msg::MediaType::Unknown
- || media_type != resolved_content_type
- {
- deno_fs::write_file(&mt, content_type.as_bytes(), 0o666)?
- }
- return Ok(Some(ModuleMetaData {
- module_name: module_name.to_string(),
- filename: filename.to_string(),
- media_type: map_content_type(&p, Some(&content_type)),
- source_code: source.as_bytes().to_owned(),
- maybe_output_code_filename: None,
- maybe_output_code: None,
- maybe_source_map_filename: None,
- maybe_source_map: None,
- }));
- } else {
- eprintln!(" NOT FOUND");
- }
- Ok(None)
+ http_util::fetch_string(&module_name).and_then(
+ move |(source, content_type)| {
+ eprintln!(""); // next line
+ match p.parent() {
+ Some(ref parent) => fs::create_dir_all(parent),
+ None => Ok(()),
+ }?;
+ deno_fs::write_file(&p, &source, 0o666)?;
+ // Remove possibly existing stale .mime file
+ // may not exist. DON'T unwrap
+ let _ = std::fs::remove_file(&media_type_filename);
+ // Create .mime file only when content type different from extension
+ let resolved_content_type = map_content_type(&p, Some(&content_type));
+ let ext = p
+ .extension()
+ .map(|x| x.to_str().unwrap_or(""))
+ .unwrap_or("");
+ let media_type = extmap(&ext);
+ if media_type == msg::MediaType::Unknown
+ || media_type != resolved_content_type
+ {
+ deno_fs::write_file(&mt, content_type.as_bytes(), 0o666)?
+ }
+ Ok(Some(ModuleMetaData {
+ module_name: module_name.to_string(),
+ filename: filename.to_string(),
+ media_type: map_content_type(&p, Some(&content_type)),
+ source_code: source.as_bytes().to_owned(),
+ maybe_output_code_filename: None,
+ maybe_output_code: None,
+ maybe_source_map_filename: None,
+ maybe_source_map: None,
+ }))
+ },
+ )
+}
+
+// Prototype https://github.com/denoland/deno/blob/golang/deno_dir.go#L37-L73
+/// Fetch remote source code.
+fn fetch_remote_source(
+ module_name: &str,
+ filename: &str,
+) -> DenoResult<Option<ModuleMetaData>> {
+ tokio_util::block_on(fetch_remote_source_async(module_name, filename))
}
/// Fetch local or cached source code.
@@ -582,7 +592,6 @@ fn fetch_local_source(
#[cfg(test)]
mod tests {
use super::*;
- use crate::tokio_util;
use tempfile::TempDir;
fn test_setup(reload: bool, recompile: bool) -> (TempDir, DenoDir) {
@@ -817,6 +826,44 @@ mod tests {
}
#[test]
+ fn test_fetch_source_async_1() {
+ use crate::tokio_util;
+ // http_util::fetch_sync_string requires tokio
+ tokio_util::init(|| {
+ let (_temp_dir, deno_dir) = test_setup(false, false);
+ let module_name =
+ "http://127.0.0.1:4545/tests/subdir/mt_video_mp2t.t3.ts".to_string();
+ let filename = deno_fs::normalize_path(
+ deno_dir
+ .deps_http
+ .join("127.0.0.1_PORT4545/tests/subdir/mt_video_mp2t.t3.ts")
+ .as_ref(),
+ );
+ let mime_file_name = format!("{}.mime", &filename);
+
+ let result = tokio_util::block_on(fetch_remote_source_async(
+ &module_name,
+ &filename,
+ ));
+ assert!(result.is_ok());
+ let r = result.unwrap().unwrap();
+ assert_eq!(r.source_code, b"export const loaded = true;\n");
+ assert_eq!(&(r.media_type), &msg::MediaType::TypeScript);
+ // matching ext, no .mime file created
+ assert!(fs::read_to_string(&mime_file_name).is_err());
+
+ // Modify .mime, make sure read from local
+ let _ = fs::write(&mime_file_name, "text/javascript");
+ let result2 = fetch_local_source(&module_name, &filename);
+ assert!(result2.is_ok());
+ let r2 = result2.unwrap().unwrap();
+ assert_eq!(r2.source_code, b"export const loaded = true;\n");
+ // Not MediaType::TypeScript due to .mime modification
+ assert_eq!(&(r2.media_type), &msg::MediaType::JavaScript);
+ });
+ }
+
+ #[test]
fn test_fetch_source_1() {
use crate::tokio_util;
// http_util::fetch_sync_string requires tokio
diff --git a/cli/http_util.rs b/cli/http_util.rs
index 52be9d1bc..9c92c08eb 100644
--- a/cli/http_util.rs
+++ b/cli/http_util.rs
@@ -1,8 +1,6 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use crate::errors;
use crate::errors::DenoError;
-use crate::errors::DenoResult;
-use crate::tokio_util;
use futures::future::{loop_fn, Loop};
use futures::{future, Future, Stream};
use hyper;
@@ -53,6 +51,11 @@ fn resolve_uri_from_location(base_uri: &Uri, location: &str) -> Uri {
}
}
+#[cfg(test)]
+use crate::errors::DenoResult;
+#[cfg(test)]
+use crate::tokio_util;
+#[cfg(test)]
/// Synchronously fetchs the given HTTP URL. Returns (content, media_type).
pub fn fetch_sync_string(module_name: &str) -> DenoResult<(String, String)> {
tokio_util::block_on(fetch_string(module_name))