summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichaƂ Sabiniarz <31597105+mhvsa@users.noreply.github.com>2019-10-17 16:29:06 +0200
committerRyan Dahl <ry@tinyclouds.org>2019-10-17 10:29:06 -0400
commit75ec9426f3083bff0b0d64e8a7bd7352dfd7f67c (patch)
tree6cb9ee97f08b305a9bbd405943ce7516ea2fae47
parentf51dcc12d7a75a677529d63eb53d7a577d5b9289 (diff)
feat: --reload flag to take arg for partial reload (#3109)
Example: To reload only std modules --reload=https://deno.land/std/
-rw-r--r--cli/file_fetcher.rs87
-rw-r--r--cli/flags.rs42
-rw-r--r--cli/state.rs1
-rw-r--r--website/manual.md20
4 files changed, 147 insertions, 3 deletions
diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs
index 29fe04d8a..99ea61795 100644
--- a/cli/file_fetcher.rs
+++ b/cli/file_fetcher.rs
@@ -70,6 +70,7 @@ pub struct SourceFileFetcher {
deps_cache: DiskCache,
progress: Progress,
source_file_cache: SourceFileCache,
+ cache_blacklist: Vec<String>,
use_disk_cache: bool,
no_remote_fetch: bool,
}
@@ -79,12 +80,14 @@ impl SourceFileFetcher {
deps_cache: DiskCache,
progress: Progress,
use_disk_cache: bool,
+ cache_blacklist: Vec<String>,
no_remote_fetch: bool,
) -> std::io::Result<Self> {
let file_fetcher = Self {
deps_cache,
progress,
source_file_cache: SourceFileCache::default(),
+ cache_blacklist,
use_disk_cache,
no_remote_fetch,
};
@@ -308,8 +311,10 @@ impl SourceFileFetcher {
return Box::new(futures::future::err(too_many_redirects()));
}
+ let is_blacklisted =
+ check_cache_blacklist(module_url, self.cache_blacklist.as_ref());
// First try local cache
- if use_disk_cache {
+ if use_disk_cache && !is_blacklisted {
match self.fetch_cached_remote_source(&module_url) {
Ok(Some(source_file)) => {
return Box::new(futures::future::ok(source_file));
@@ -552,6 +557,26 @@ fn filter_shebang(bytes: Vec<u8>) -> Vec<u8> {
}
}
+fn check_cache_blacklist(url: &Url, black_list: &[String]) -> bool {
+ let mut url_without_fragmets = url.clone();
+ url_without_fragmets.set_fragment(None);
+ if black_list.contains(&String::from(url_without_fragmets.as_str())) {
+ return true;
+ }
+ let mut url_without_query_strings = url_without_fragmets;
+ url_without_query_strings.set_query(None);
+ let mut path_buf = PathBuf::from(url_without_query_strings.as_str());
+ loop {
+ if black_list.contains(&String::from(path_buf.to_str().unwrap())) {
+ return true;
+ }
+ if !path_buf.pop() {
+ break;
+ }
+ }
+ false
+}
+
#[derive(Debug, Default)]
/// Header metadata associated with a particular "symbolic" source code file.
/// (the associated source code file might not be cached, while remaining
@@ -636,6 +661,7 @@ mod tests {
DiskCache::new(&dir_path.to_path_buf().join("deps")),
Progress::new(),
true,
+ vec![],
false,
)
.expect("setup fail")
@@ -658,6 +684,65 @@ mod tests {
}
#[test]
+ fn test_cache_blacklist() {
+ let args = crate::flags::resolve_urls(vec![
+ String::from("http://deno.land/std"),
+ String::from("http://github.com/example/mod.ts"),
+ String::from("http://fragment.com/mod.ts#fragment"),
+ String::from("http://query.com/mod.ts?foo=bar"),
+ String::from("http://queryandfragment.com/mod.ts?foo=bar#fragment"),
+ ]);
+
+ let u: Url = "http://deno.land/std/fs/mod.ts".parse().unwrap();
+ assert_eq!(check_cache_blacklist(&u, &args), true);
+
+ let u: Url = "http://github.com/example/file.ts".parse().unwrap();
+ assert_eq!(check_cache_blacklist(&u, &args), false);
+
+ let u: Url = "http://github.com/example/mod.ts".parse().unwrap();
+ assert_eq!(check_cache_blacklist(&u, &args), true);
+
+ let u: Url = "http://github.com/example/mod.ts?foo=bar".parse().unwrap();
+ assert_eq!(check_cache_blacklist(&u, &args), true);
+
+ let u: Url = "http://github.com/example/mod.ts#fragment".parse().unwrap();
+ assert_eq!(check_cache_blacklist(&u, &args), true);
+
+ let u: Url = "http://fragment.com/mod.ts".parse().unwrap();
+ assert_eq!(check_cache_blacklist(&u, &args), true);
+
+ let u: Url = "http://query.com/mod.ts".parse().unwrap();
+ assert_eq!(check_cache_blacklist(&u, &args), false);
+
+ let u: Url = "http://fragment.com/mod.ts#fragment".parse().unwrap();
+ assert_eq!(check_cache_blacklist(&u, &args), true);
+
+ let u: Url = "http://query.com/mod.ts?foo=bar".parse().unwrap();
+ assert_eq!(check_cache_blacklist(&u, &args), true);
+
+ let u: Url = "http://queryandfragment.com/mod.ts".parse().unwrap();
+ assert_eq!(check_cache_blacklist(&u, &args), false);
+
+ let u: Url = "http://queryandfragment.com/mod.ts?foo=bar"
+ .parse()
+ .unwrap();
+ assert_eq!(check_cache_blacklist(&u, &args), true);
+
+ let u: Url = "http://queryandfragment.com/mod.ts#fragment"
+ .parse()
+ .unwrap();
+ assert_eq!(check_cache_blacklist(&u, &args), false);
+
+ let u: Url = "http://query.com/mod.ts?foo=bar#fragment".parse().unwrap();
+ assert_eq!(check_cache_blacklist(&u, &args), true);
+
+ let u: Url = "http://fragment.com/mod.ts?foo=bar#fragment"
+ .parse()
+ .unwrap();
+ assert_eq!(check_cache_blacklist(&u, &args), true);
+ }
+
+ #[test]
fn test_source_code_headers_get_and_save() {
let (_temp_dir, fetcher) = test_setup();
let url = Url::parse("http://example.com/f.js").unwrap();
diff --git a/cli/flags.rs b/cli/flags.rs
index 8690ac983..612415ec7 100644
--- a/cli/flags.rs
+++ b/cli/flags.rs
@@ -11,6 +11,7 @@ use log::Level;
use std;
use std::str;
use std::str::FromStr;
+use url::Url;
macro_rules! std_url {
($x:expr) => {
@@ -45,6 +46,7 @@ pub struct DenoFlags {
pub import_map_path: Option<String>,
pub allow_read: bool,
pub read_whitelist: Vec<String>,
+ pub cache_blacklist: Vec<String>,
pub allow_write: bool,
pub write_whitelist: Vec<String>,
pub allow_net: bool,
@@ -172,8 +174,20 @@ To get help on the another subcommands (run in this case):
).arg(
Arg::with_name("reload")
.short("r")
+ .min_values(0)
+ .takes_value(true)
+ .use_delimiter(true)
+ .require_equals(true)
.long("reload")
.help("Reload source code cache (recompile TypeScript)")
+ .value_name("CACHE_BLACKLIST")
+ .long_help("Reload source code cache (recompile TypeScript)
+ --reload
+ Reload everything
+ --reload=https://deno.land/std
+ Reload all standard modules
+ --reload=https://deno.land/std/fs/utils.ts,https://deno.land/std/fmt/colors.ts
+ Reloads specific modules")
.global(true),
).arg(
Arg::with_name("config")
@@ -509,6 +523,23 @@ fn resolve_paths(paths: Vec<String>) -> Vec<String> {
out
}
+pub fn resolve_urls(urls: Vec<String>) -> Vec<String> {
+ let mut out: Vec<String> = vec![];
+ for urlstr in urls.iter() {
+ let result = Url::from_str(urlstr);
+ if result.is_err() {
+ panic!("Bad Url: {}", urlstr);
+ }
+ let mut url = result.unwrap();
+ url.set_fragment(None);
+ let mut full_url = String::from(url.as_str());
+ if full_url.len() > 1 && full_url.ends_with('/') {
+ full_url.pop();
+ }
+ out.push(full_url);
+ }
+ out
+}
/// This function expands "bare port" paths (eg. ":8080")
/// into full paths with hosts. It expands to such paths
/// into 3 paths with following hosts: `0.0.0.0:port`, `127.0.0.1:port` and `localhost:port`.
@@ -566,7 +597,16 @@ pub fn parse_flags(
flags.version = true;
}
if matches.is_present("reload") {
- flags.reload = true;
+ if matches.value_of("reload").is_some() {
+ let cache_bl = matches.values_of("reload").unwrap();
+ let raw_cache_blacklist: Vec<String> =
+ cache_bl.map(std::string::ToString::to_string).collect();
+ flags.cache_blacklist = resolve_urls(raw_cache_blacklist);
+ debug!("cache blacklist: {:#?}", &flags.cache_blacklist);
+ flags.reload = false;
+ } else {
+ flags.reload = true;
+ }
}
flags.config_path = matches.value_of("config").map(ToOwned::to_owned);
if matches.is_present("v8-options") {
diff --git a/cli/state.rs b/cli/state.rs
index 70845fb8b..950bdba70 100644
--- a/cli/state.rs
+++ b/cli/state.rs
@@ -225,6 +225,7 @@ impl ThreadSafeState {
dir.deps_cache.clone(),
progress.clone(),
!flags.reload,
+ flags.cache_blacklist.clone(),
flags.no_fetch,
)?;
diff --git a/website/manual.md b/website/manual.md
index b56c93761..ec5612372 100644
--- a/website/manual.md
+++ b/website/manual.md
@@ -381,6 +381,24 @@ And if you ever want to upgrade to the latest published version:
$ file_server --reload
```
+### Reload specific modules
+
+Sometimes we want to upgrade only some modules. You can control it by passing an
+argument to a `--reload` flag.
+
+To reload everything
+
+`--reload`
+
+To reload all standard modules
+
+`--reload=https://deno.land/std`
+
+To reload specific modules (in this example - colors and file system utils) use
+a comma to separate URLs
+
+`--reload=https://deno.land/std/fs/utils.ts,https://deno.land/std/fmt/colors.ts`
+
### Permissions whitelist
Deno also provides permissions whitelist.
@@ -670,7 +688,7 @@ OPTIONS:
-L, --log-level <log-level> Set log level [possible values: debug, info]
--no-fetch Do not download remote modules
--no-prompt Do not use prompts
- -r, --reload Reload source code cache (recompile TypeScript)
+ -r, --reload=<CACHE_BLACKLIST> Reload source code cache (recompile TypeScript)
--seed <NUMBER> Seed Math.random()
--v8-flags=<v8-flags> Set V8 command line options
--v8-options Print V8 command line options