summaryrefslogtreecommitdiff
path: root/src/deno_dir.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/deno_dir.rs')
-rw-r--r--src/deno_dir.rs160
1 files changed, 117 insertions, 43 deletions
diff --git a/src/deno_dir.rs b/src/deno_dir.rs
index 72e75bf5b..b8573a018 100644
--- a/src/deno_dir.rs
+++ b/src/deno_dir.rs
@@ -1,6 +1,8 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
use errors::DenoError;
+use errors::DenoResult;
use fs;
+use net;
use sha1;
use std;
use std::fs::File;
@@ -25,12 +27,17 @@ pub struct DenoDir {
// This is where we cache compilation outputs. Example:
// /Users/rld/.deno/gen/f39a473452321cacd7c346a870efb0e3e1264b43.js
pub deps: PathBuf,
+ // If remote resources should be reloaded.
+ reload: bool,
}
impl DenoDir {
// Must be called before using any function from this module.
// https://github.com/denoland/deno/blob/golang/deno_dir.go#L99-L111
- pub fn new(custom_root: Option<&Path>) -> std::io::Result<DenoDir> {
+ pub fn new(
+ reload: bool,
+ custom_root: Option<&Path>,
+ ) -> std::io::Result<DenoDir> {
// Only setup once.
let home_dir = std::env::home_dir().expect("Could not get home directory.");
let default = home_dir.join(".deno");
@@ -42,7 +49,12 @@ impl DenoDir {
let gen = root.as_path().join("gen");
let deps = root.as_path().join("deps");
- let deno_dir = DenoDir { root, gen, deps };
+ let deno_dir = DenoDir {
+ root,
+ gen,
+ deps,
+ reload,
+ };
fs::mkdir(deno_dir.gen.as_ref())?;
fs::mkdir(deno_dir.deps.as_ref())?;
@@ -93,6 +105,50 @@ impl DenoDir {
}
}
+ // Prototype https://github.com/denoland/deno/blob/golang/deno_dir.go#L37-L73
+ fn fetch_remote_source(
+ self: &DenoDir,
+ module_name: &str,
+ filename: &str,
+ ) -> DenoResult<String> {
+ let p = Path::new(filename);
+
+ let src = if self.reload || !p.exists() {
+ println!("Downloading {}", module_name);
+ let source = net::fetch_sync_string(module_name)?;
+ match p.parent() {
+ Some(ref parent) => std::fs::create_dir_all(parent),
+ None => Ok(()),
+ }?;
+ fs::write_file_sync(&p, source.as_bytes())?;
+ source
+ } else {
+ let source = fs::read_file_sync_string(&p)?;
+ source
+ };
+ Ok(src)
+ }
+
+ // Prototype: https://github.com/denoland/deno/blob/golang/os.go#L122-L138
+ fn get_source_code(
+ self: &DenoDir,
+ module_name: &str,
+ filename: &str,
+ ) -> DenoResult<String> {
+ if is_remote(module_name) {
+ self.fetch_remote_source(module_name, filename)
+ } else if module_name.starts_with(ASSET_PREFIX) {
+ panic!("Asset resolution should be done in JS, not Rust.");
+ } else {
+ assert!(
+ module_name == filename,
+ "if a module isn't remote, it should have the same filename"
+ );
+ let src = fs::read_file_sync_string(Path::new(filename))?;
+ Ok(src)
+ }
+ }
+
pub fn code_fetch(
self: &DenoDir,
module_specifier: &str,
@@ -106,7 +162,8 @@ impl DenoDir {
module_name, module_specifier, containing_file, filename
);
- let out = get_source_code(module_name.as_str(), filename.as_str())
+ let out = self
+ .get_source_code(module_name.as_str(), filename.as_str())
.and_then(|source_code| {
Ok(CodeFetchOutput {
module_name,
@@ -154,6 +211,9 @@ impl DenoDir {
module_specifier: &str,
containing_file: &str,
) -> Result<(String, String), url::ParseError> {
+ let module_name;
+ let filename;
+
debug!(
"resolve_module before module_specifier {} containing_file {}",
module_specifier, containing_file
@@ -165,12 +225,11 @@ impl DenoDir {
let j: Url =
if containing_file == "." || Path::new(module_specifier).is_absolute() {
- let r = Url::from_file_path(module_specifier);
- // TODO(ry) Properly handle error.
- if r.is_err() {
- error!("Url::from_file_path error {}", module_specifier);
+ if module_specifier.starts_with("http://") {
+ Url::parse(module_specifier)?
+ } else {
+ Url::from_file_path(module_specifier).unwrap()
}
- r.unwrap()
} else if containing_file.ends_with("/") {
let r = Url::from_directory_path(&containing_file);
// TODO(ry) Properly handle error.
@@ -189,27 +248,59 @@ impl DenoDir {
base.join(module_specifier)?
};
- let mut p = j
- .to_file_path()
- .unwrap()
- .into_os_string()
- .into_string()
- .unwrap();
+ match j.scheme() {
+ "file" => {
+ let mut p = j
+ .to_file_path()
+ .unwrap()
+ .into_os_string()
+ .into_string()
+ .unwrap();
+
+ if cfg!(target_os = "windows") {
+ // On windows, replace backward slashes to forward slashes.
+ // TODO(piscisaureus): This may not me be right, I just did it to make
+ // the tests pass.
+ p = p.replace("\\", "/");
+ }
- if cfg!(target_os = "windows") {
- // On windows, replace backward slashes to forward slashes.
- // TODO(piscisaureus): This may not me be right, I just did it to make
- // the tests pass.
- p = p.replace("\\", "/");
+ module_name = p.to_string();
+ filename = p.to_string();
+ }
+ _ => {
+ module_name = module_specifier.to_string();
+ filename = get_cache_filename(self.deps.as_path(), j)
+ .to_str()
+ .unwrap()
+ .to_string();
+ }
}
- let module_name = p.to_string();
- let filename = p.to_string();
-
+ debug!("module_name: {}, filename: {}", module_name, filename);
Ok((module_name, filename))
}
}
+fn get_cache_filename(basedir: &Path, url: Url) -> PathBuf {
+ let mut out = basedir.to_path_buf();
+ out.push(url.host_str().unwrap());
+ for path_seg in url.path_segments().unwrap() {
+ out.push(path_seg);
+ }
+ out
+}
+
+#[test]
+fn test_get_cache_filename() {
+ let url = Url::parse("http://example.com:1234/path/to/file.ts").unwrap();
+ let basedir = Path::new("/cache/dir/");
+ let cache_file = get_cache_filename(&basedir, url);
+ assert_eq!(
+ cache_file,
+ Path::new("/cache/dir/example.com/path/to/file.ts")
+ );
+}
+
#[derive(Debug)]
pub struct CodeFetchOutput {
pub module_name: String,
@@ -221,7 +312,8 @@ pub struct CodeFetchOutput {
#[cfg(test)]
pub fn test_setup() -> (TempDir, DenoDir) {
let temp_dir = TempDir::new().expect("tempdir fail");
- let deno_dir = DenoDir::new(Some(temp_dir.path())).expect("setup fail");
+ let deno_dir =
+ DenoDir::new(false, Some(temp_dir.path())).expect("setup fail");
(temp_dir, deno_dir)
}
@@ -395,24 +487,6 @@ fn test_resolve_module() {
const ASSET_PREFIX: &str = "/$asset$/";
-fn is_remote(_module_name: &str) -> bool {
- false
-}
-
-fn get_source_code(
- module_name: &str,
- filename: &str,
-) -> std::io::Result<String> {
- if is_remote(module_name) {
- unimplemented!();
- } else if module_name.starts_with(ASSET_PREFIX) {
- assert!(false, "Asset resolution should be done in JS, not Rust.");
- unimplemented!();
- } else {
- assert!(
- module_name == filename,
- "if a module isn't remote, it should have the same filename"
- );
- fs::read_file_sync_string(Path::new(filename))
- }
+fn is_remote(module_name: &str) -> bool {
+ module_name.starts_with("http")
}