feat: v0.2.5, support go scripts

This commit is contained in:
2024-12-29 17:13:41 +08:00
parent affcb233bd
commit 3ace53b509
11 changed files with 163 additions and 31 deletions

4
Cargo.lock generated
View File

@@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 4
[[package]] [[package]]
name = "addr2line" name = "addr2line"
@@ -710,7 +710,7 @@ dependencies = [
[[package]] [[package]]
name = "runrs" name = "runrs"
version = "0.2.4" version = "0.2.5"
dependencies = [ dependencies = [
"reqwest", "reqwest",
"rust_util", "rust_util",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "runrs" name = "runrs"
version = "0.2.4" version = "0.2.5"
edition = "2018" edition = "2018"
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "A Tool for Run Rust Scripts" description = "A Tool for Run Rust Scripts"
@@ -8,6 +8,10 @@ readme = "README.md"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = []
switch-go-lang = []
[dependencies] [dependencies]
reqwest = { version = "0.11.14", features = ["blocking"] } reqwest = { version = "0.11.14", features = ["blocking"] }
rust_util = "0.6.41" rust_util = "0.6.41"

View File

@@ -4,3 +4,6 @@ _:
install: install:
cargo install --path . cargo install --path .
build-run-go:
cargo build --release --features switch-go-lang

24
src/help_go.rs Normal file
View File

@@ -0,0 +1,24 @@
pub fn print_help() {
println!(r##"rungo v{} - A Tool for Run Go Scripts
Show help:
$ rungo -h|--help
Show template:
$ rungo -t|--template
Show scriptions:
$ rungo -l|--list
Install script:
$ rungo -i|--install <script.go>
Run script:
$ rungo <script.rs> [arguments]
Powered by gorun, know more reference: https://github.com/erning/gorun
"##,
env!("CARGO_PKG_VERSION")
);
}

View File

@@ -3,24 +3,28 @@ use std::os::unix::fs::PermissionsExt;
use std::path::PathBuf; use std::path::PathBuf;
use rust_util::util_os::get_user_home; use rust_util::util_os::get_user_home;
use crate::util::{SCRIPT_DOT_EXT, SCRIPT_HYPHEN_EXT};
#[cfg(not(feature = "switch-go-lang"))]
const SCRIPT_PATTERN: &'static str = "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/$NAME/src/main.rs"; const SCRIPT_PATTERN: &'static str = "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/$NAME/src/main.rs";
#[cfg(feature = "switch-go-lang")]
const SCRIPT_PATTERN: &'static str = "https://git.hatter.ink/hatter/go-scripts/raw/branch/main/$NAME/main.go";
pub fn install_script(args: Vec<&String>) { pub fn install_script(args: Vec<&String>) {
if args.is_empty() { if args.is_empty() {
failure_and_exit!("No script name assigned!"); failure_and_exit!("No script name assigned!");
} }
let script_name = &args[0]; let script_name = &args[0];
let normalized_script_name = if script_name.ends_with(".rs") { let normalized_script_name = if script_name.ends_with(SCRIPT_DOT_EXT) {
script_name.chars().take(script_name.len() - 3).collect::<String>() + "-rs" script_name.chars().take(script_name.len() - 3).collect::<String>() + SCRIPT_HYPHEN_EXT
} else if script_name.ends_with("-rs") { } else if script_name.ends_with(SCRIPT_HYPHEN_EXT) {
script_name.to_string() script_name.to_string()
} else { } else {
failure_and_exit!("Invalid script name: {}", script_name); failure_and_exit!("Invalid script name: {}", script_name);
}; };
let script_file_name = normalized_script_name let script_file_name = normalized_script_name
.chars().take(normalized_script_name.len() - 3).collect::<String>() + ".rs"; .chars().take(normalized_script_name.len() - 3).collect::<String>() + SCRIPT_DOT_EXT;
let user_home = get_user_home().expect("Get user home failed!"); let user_home = get_user_home().expect("Get user home failed!");
let output_file_name = PathBuf::from(&user_home).join("bin").join(&script_file_name); let output_file_name = PathBuf::from(&user_home).join("bin").join(&script_file_name);
if output_file_name.exists() { if output_file_name.exists() {

View File

@@ -3,8 +3,12 @@ use serde::Deserialize;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fs; use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
use crate::util::{SCRIPT_DOT_EXT, SCRIPT_HYPHEN_EXT};
#[cfg(not(feature = "switch-go-lang"))]
const FILE_META: &'static str = "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/script-meta.json"; const FILE_META: &'static str = "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/script-meta.json";
#[cfg(feature = "switch-go-lang")]
const FILE_META: &'static str = "https://git.hatter.ink/hatter/go-scripts/raw/branch/main/script-meta.json";
#[derive(Deserialize)] #[derive(Deserialize)]
struct ScriptMeta { struct ScriptMeta {
@@ -16,14 +20,14 @@ struct ScriptMeta {
pub fn list_scripts() { pub fn list_scripts() {
debugging!("Loading URL: {}", FILE_META); debugging!("Loading URL: {}", FILE_META);
let response = reqwest::blocking::get(FILE_META).unwrap_or_else(|e| { let response = reqwest::blocking::get(FILE_META).unwrap_or_else(|e| {
failure_and_exit!("Get file-meta.txt failed: {}", e); failure_and_exit!("Get file-meta.json failed: {}", e);
}); });
debugging!("Load response: {}", response.status().as_u16()); debugging!("Load response: {}", response.status().as_u16());
if response.status().as_u16() != 200 { if response.status().as_u16() != 200 {
failure_and_exit!("Get file-meta.txt failed, status: {}", response.status().as_u16()); failure_and_exit!("Get file-meta.json failed, status: {}", response.status().as_u16());
} }
let text = response.text().unwrap_or_else(|e| { let text = response.text().unwrap_or_else(|e| {
failure_and_exit!("Get file-meta.txt failed: {}", e); failure_and_exit!("Get file-meta.json failed: {}", e);
}); });
debugging!("Response text: {}", &text); debugging!("Response text: {}", &text);
@@ -33,8 +37,8 @@ pub fn list_scripts() {
messages.push(format!("Found {} script(s):", script_meta_map.len())); messages.push(format!("Found {} script(s):", script_meta_map.len()));
for (_, script_meta) in &script_meta_map { for (_, script_meta) in &script_meta_map {
let script_name = &script_meta.script_name; let script_name = &script_meta.script_name;
let real_script_name = if script_name.ends_with("-rs") { let real_script_name = if script_name.ends_with(SCRIPT_HYPHEN_EXT) {
script_name.chars().take(script_name.len() - 3).collect::<String>() + ".rs" script_name.chars().take(script_name.len() - 3).collect::<String>() + SCRIPT_DOT_EXT
} else { } else {
script_name.to_string() script_name.to_string()
}; };

View File

@@ -5,27 +5,48 @@ use std::env;
use rust_util::util_os::get_user_home; use rust_util::util_os::get_user_home;
use crate::help::print_help; #[cfg(not(feature = "switch-go-lang"))]
use crate::help_rs::print_help;
#[cfg(feature = "switch-go-lang")]
use crate::help_go::print_help;
use crate::install::install_script; use crate::install::install_script;
use crate::list::list_scripts; use crate::list::list_scripts;
use crate::util::{build_script_command, get_run_script_bin_name, read_file_and_digest, run_script_command}; use crate::util::{
build_script_command, get_run_script_bin_name, read_file_and_digest, run_script_command,
};
mod util; #[cfg(feature = "switch-go-lang")]
mod help; mod help_go;
mod list; #[cfg(not(feature = "switch-go-lang"))]
mod help_rs;
mod install; mod install;
mod list;
mod util;
const SCRIPT_TEMPLATE: &'static str = include_str!("script.template"); #[cfg(not(feature = "switch-go-lang"))]
const SCRIPT_TEMPLATE: &'static str = include_str!("script.template.rs");
#[cfg(feature = "switch-go-lang")]
const SCRIPT_TEMPLATE: &'static str = include_str!("script.template.go");
#[cfg(not(feature = "switch-go-lang"))]
const CMD_NAME: &str = "runrs";
#[cfg(feature = "switch-go-lang")]
const CMD_NAME: &str = "rungo";
fn main() { fn main() {
let user_home = get_user_home().unwrap_or_else(|| failure_and_exit!("$HOME not found!"));
let rust_script = get_run_script_bin_name(&user_home);
let args = env::args().skip(1).collect::<Vec<_>>(); let args = env::args().skip(1).collect::<Vec<_>>();
if args.is_empty() { if args.is_empty() {
failure_and_exit!("runrs v{}, need arguments, `runrs -h` or `runrs --help` for help", env!("CARGO_PKG_VERSION")); failure_and_exit!(
"{} v{}, need arguments, `{} -h` or `{} --help` for help",
CMD_NAME,
env!("CARGO_PKG_VERSION"),
CMD_NAME,
CMD_NAME,
);
} }
let first_argument = args.get(0).unwrap_or_else(|| failure_and_exit!("Must assign a script file name")); let first_argument = args
.get(0)
.unwrap_or_else(|| failure_and_exit!("Must assign a script file name"));
if first_argument == "--help" || first_argument == "-h" { if first_argument == "--help" || first_argument == "-h" {
print_help(); print_help();
return; return;
@@ -43,20 +64,42 @@ fn main() {
return; return;
} }
let script_file = first_argument; #[cfg(feature = "switch-go-lang")]
if true {
// rungo, and run .go file is not supported
failure_and_exit!("Go script should run by gorun, template for: rungo -t");
}
let script_file = first_argument;
let (_, script_sha256) = read_file_and_digest(script_file); let (_, script_sha256) = read_file_and_digest(script_file);
debugging!("File {} -> sha256: {}", script_file, script_sha256); debugging!("File {} -> sha256: {}", script_file, script_sha256);
#[cfg(target_os = "macos")] let user_home = get_user_home().unwrap_or_else(|| failure_and_exit!("$HOME not found!"));
let cache_script_bin_name = format!("{}/Library/Caches/rust-script/binaries/release/{}", user_home, script_sha256); let rust_script = get_run_script_bin_name(&user_home);
// #[cfg(target_os = "linux")] let cache_script_bin_name = get_cache_script_bin_name(&user_home, &script_sha256);
#[cfg(not(target_os = "macos"))] let mut run_script_cmd = build_script_command(
let cache_script_bin_name = format!("{}/.cache/rust-script/binaries/release/{}", user_home, script_sha256); rust_script,
script_file,
let mut run_script_cmd = build_script_command(rust_script, script_file, &script_sha256, &cache_script_bin_name); &script_sha256,
&cache_script_bin_name,
);
for arg in args.iter().skip(1) { for arg in args.iter().skip(1) {
run_script_cmd.arg(arg); run_script_cmd.arg(arg);
} }
run_script_command(script_file, &cache_script_bin_name, &mut run_script_cmd) run_script_command(script_file, &cache_script_bin_name, &mut run_script_cmd)
} }
fn get_cache_script_bin_name(user_home: &str, script_sha256: &str) -> String {
#[cfg(target_os = "macos")]
let cache_script_bin_name = format!(
"{}/Library/Caches/rust-script/binaries/release/{}",
user_home, script_sha256
);
// #[cfg(target_os = "linux")]
#[cfg(not(target_os = "macos"))]
let cache_script_bin_name = format!(
"{}/.cache/rust-script/binaries/release/{}",
user_home, script_sha256
);
cache_script_bin_name
}

40
src/script.template.go Normal file
View File

@@ -0,0 +1,40 @@
/// 2>/dev/null ; gorun "$0" "$@" ; exit $?
// OR: #!/usr/bin/env gorun
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
const GetIpUrl = "https://hatter.ink/ip/ip.jsonp"
type IpResponse struct {
Status int16 `json:"status"`
Message string `json:"message"`
IP string `json:"ip"`
UserAgent string `json:"userAgent"`
}
func main() {
response, err := http.Get(GetIpUrl)
if err != nil {
fmt.Printf("[ERROR] Get IP failed: %s\n", err)
os.Exit(1)
}
body, err := io.ReadAll(response.Body)
if err != nil {
fmt.Printf("[ERROR] Get IP failed: %s\n", err)
os.Exit(2)
}
var ipReponse IpResponse
if err := json.Unmarshal(body, &ipReponse); err != nil {
fmt.Printf("[ERROR] Get IP failed: %s\n", err)
os.Exit(3)
}
fmt.Printf("[INFO] Your IP address: %s\n", ipReponse.IP)
}

View File

@@ -5,6 +5,16 @@ use std::process::Command;
use std::time::SystemTime; use std::time::SystemTime;
use std::{env, fs, process}; use std::{env, fs, process};
#[cfg(not(feature = "switch-go-lang"))]
pub const SCRIPT_HYPHEN_EXT: &str = "-rs";
#[cfg(feature = "switch-go-lang")]
pub const SCRIPT_HYPHEN_EXT: &str = "-go";
#[cfg(not(feature = "switch-go-lang"))]
pub const SCRIPT_DOT_EXT: &str = ".rs";
#[cfg(feature = "switch-go-lang")]
pub const SCRIPT_DOT_EXT: &str = ".go";
pub fn build_script_command(rust_script: PathBuf, script_file: &str, script_sha256: &str, cache_script_bin_name: &str) -> Command { pub fn build_script_command(rust_script: PathBuf, script_file: &str, script_sha256: &str, cache_script_bin_name: &str) -> Command {
let skip_cache = is_env_on("RUNRS_SKIP_CACHE"); let skip_cache = is_env_on("RUNRS_SKIP_CACHE");