Skip to content

Commit

Permalink
feat: --reload flag to take arg for partial reload (#3109)
Browse files Browse the repository at this point in the history
Example: To reload only std modules --reload=https://deno.land/std/
  • Loading branch information
mhvsa authored and ry committed Oct 17, 2019
1 parent f51dcc1 commit 75ec942
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 3 deletions.
87 changes: 86 additions & 1 deletion cli/file_fetcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand All @@ -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,
};
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -636,6 +661,7 @@ mod tests {
DiskCache::new(&dir_path.to_path_buf().join("deps")),
Progress::new(),
true,
vec![],
false,
)
.expect("setup fail")
Expand All @@ -657,6 +683,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();
Expand Down
42 changes: 41 additions & 1 deletion cli/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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`.
Expand Down Expand Up @@ -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") {
Expand Down
1 change: 1 addition & 0 deletions cli/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ impl ThreadSafeState {
dir.deps_cache.clone(),
progress.clone(),
!flags.reload,
flags.cache_blacklist.clone(),
flags.no_fetch,
)?;

Expand Down
20 changes: 19 additions & 1 deletion website/manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 75ec942

Please sign in to comment.