|
|
|
|
@@ -1,10 +1,31 @@
|
|
|
|
|
use crate::util;
|
|
|
|
|
use rust_util::util_time::get_current_millis;
|
|
|
|
|
use rust_util::XResult;
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
use std::fs;
|
|
|
|
|
use std::path::Path;
|
|
|
|
|
|
|
|
|
|
#[allow(unreachable_code)]
|
|
|
|
|
fn get_script_cache_dir() -> &'static str {
|
|
|
|
|
#[cfg(feature = "switch-rust-lang")]
|
|
|
|
|
{
|
|
|
|
|
return "runrs";
|
|
|
|
|
}
|
|
|
|
|
#[cfg(feature = "switch-ts-lang")]
|
|
|
|
|
{
|
|
|
|
|
return "runts";
|
|
|
|
|
}
|
|
|
|
|
failure_and_exit!("Only rust/ts script supported.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
|
struct HttpsScriptMeta {
|
|
|
|
|
url: String,
|
|
|
|
|
download_time: u128,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// download from internet if starts with https://
|
|
|
|
|
pub fn resolve_file(script_file: &str) -> XResult<String> {
|
|
|
|
|
pub fn resolve_file(script_file: &str, force_update: bool) -> XResult<String> {
|
|
|
|
|
if script_file.starts_with("http://") {
|
|
|
|
|
return simple_error!("Insecure script file: {}", script_file);
|
|
|
|
|
}
|
|
|
|
|
@@ -14,23 +35,55 @@ pub fn resolve_file(script_file: &str) -> XResult<String> {
|
|
|
|
|
let file_sha256 = sha256::digest(script_file);
|
|
|
|
|
let file_name = get_file_name(script_file)?;
|
|
|
|
|
let cache_file_path = format!(
|
|
|
|
|
"{}/.cache/runrs/{}/{}",
|
|
|
|
|
"{}/.cache/{}/{}/{}",
|
|
|
|
|
util::get_user_home_or_die(),
|
|
|
|
|
get_script_cache_dir(),
|
|
|
|
|
file_sha256,
|
|
|
|
|
file_name
|
|
|
|
|
);
|
|
|
|
|
let cache_file_path_url = format!(
|
|
|
|
|
"{}/.cache/runrs/{}.url",
|
|
|
|
|
let cache_file_path_meta = format!(
|
|
|
|
|
"{}/.cache/{}/{}.meta",
|
|
|
|
|
util::get_user_home_or_die(),
|
|
|
|
|
get_script_cache_dir(),
|
|
|
|
|
file_sha256
|
|
|
|
|
);
|
|
|
|
|
debugging!("Cache file: {}", cache_file_path);
|
|
|
|
|
if let Ok(metadata) = fs::metadata(&cache_file_path) {
|
|
|
|
|
if metadata.is_file() {
|
|
|
|
|
let is_script_path_latest_version = script_file.contains("/@latest/");
|
|
|
|
|
let cache_file_path_exists = fs::metadata(&cache_file_path).is_ok();
|
|
|
|
|
debugging!(
|
|
|
|
|
"Cache file: {}, is latest version: {}, cache file exists: {}",
|
|
|
|
|
cache_file_path,
|
|
|
|
|
is_script_path_latest_version,
|
|
|
|
|
cache_file_path_exists
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if force_update {
|
|
|
|
|
debugging!("Force update is on, skip cache file check");
|
|
|
|
|
} else if is_script_path_latest_version {
|
|
|
|
|
// force update is not on, and script file is @latest version
|
|
|
|
|
if let Ok(cache_file_path_meta_content) = fs::read_to_string(&cache_file_path_meta) {
|
|
|
|
|
if let Ok(http_script_meta) =
|
|
|
|
|
serde_json::from_str::<HttpsScriptMeta>(&cache_file_path_meta_content)
|
|
|
|
|
{
|
|
|
|
|
let current_millis = get_current_millis();
|
|
|
|
|
debugging!(
|
|
|
|
|
"Read from meta: {:?}, current millis: {}",
|
|
|
|
|
http_script_meta,
|
|
|
|
|
current_millis
|
|
|
|
|
);
|
|
|
|
|
if current_millis - http_script_meta.download_time < 12 * 60 * 60 * 1000
|
|
|
|
|
&& cache_file_path_exists
|
|
|
|
|
{
|
|
|
|
|
// script file is download in 12 hours
|
|
|
|
|
return Ok(cache_file_path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// force update is not on, and script is static version, check file existence only
|
|
|
|
|
if cache_file_path_exists {
|
|
|
|
|
debugging!("Found cache file: {}", cache_file_path);
|
|
|
|
|
return Ok(cache_file_path);
|
|
|
|
|
}
|
|
|
|
|
return simple_error!("Cache file is not a file: {}", cache_file_path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// create cache file parent path if not exists
|
|
|
|
|
@@ -59,13 +112,31 @@ pub fn resolve_file(script_file: &str) -> XResult<String> {
|
|
|
|
|
let get_script_response_result = reqwest::blocking::get(script_file);
|
|
|
|
|
debugging!("Get script response: {:#?}", &get_script_response_result);
|
|
|
|
|
let get_script_response = match get_script_response_result {
|
|
|
|
|
Err(e) => return simple_error!("Get script failed: {}", e),
|
|
|
|
|
Err(e) => {
|
|
|
|
|
if cache_file_path_exists {
|
|
|
|
|
warning!(
|
|
|
|
|
"Get script failed, reuse local cache file: {}",
|
|
|
|
|
cache_file_path
|
|
|
|
|
);
|
|
|
|
|
return Ok(cache_file_path);
|
|
|
|
|
}
|
|
|
|
|
return simple_error!("Get script failed: {}", e);
|
|
|
|
|
}
|
|
|
|
|
Ok(response) => response,
|
|
|
|
|
};
|
|
|
|
|
let get_script_response_status = get_script_response.status().as_u16();
|
|
|
|
|
if get_script_response_status == 404 {
|
|
|
|
|
// when 404 do not reuse local cache file
|
|
|
|
|
return simple_error!("Script not found!");
|
|
|
|
|
} else if get_script_response_status != 200 {
|
|
|
|
|
if cache_file_path_exists {
|
|
|
|
|
warning!(
|
|
|
|
|
"Get script failed, status: {}, reuse local cache file: {}",
|
|
|
|
|
get_script_response_status,
|
|
|
|
|
cache_file_path
|
|
|
|
|
);
|
|
|
|
|
return Ok(cache_file_path);
|
|
|
|
|
}
|
|
|
|
|
return simple_error!("Get script failed: {}", get_script_response_status);
|
|
|
|
|
}
|
|
|
|
|
let remote_script_content = match get_script_response.text() {
|
|
|
|
|
@@ -78,8 +149,14 @@ pub fn resolve_file(script_file: &str) -> XResult<String> {
|
|
|
|
|
if let Err(e) = fs::write(&cache_file_path, remote_script_content) {
|
|
|
|
|
return simple_error!("Write script: {} failed: {}", cache_file_path, e);
|
|
|
|
|
}
|
|
|
|
|
if let Err(_) = fs::write(&cache_file_path_url, script_file) {
|
|
|
|
|
// JUST IGNORE
|
|
|
|
|
let meta = HttpsScriptMeta {
|
|
|
|
|
url: script_file.to_string(),
|
|
|
|
|
download_time: get_current_millis(),
|
|
|
|
|
};
|
|
|
|
|
if let Ok(meta_json) = serde_json::to_string_pretty(&meta) {
|
|
|
|
|
if let Err(_) = fs::write(&cache_file_path_meta, &meta_json) {
|
|
|
|
|
// JUST IGNORE
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(cache_file_path)
|
|
|
|
|
|