提交 e1abe283 authored 作者: Serhij S's avatar Serhij S

exec docs

上级 f8931858
...@@ -26,6 +26,12 @@ dependencies = [ ...@@ -26,6 +26,12 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "autocfg"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.71" version = "0.3.71"
...@@ -65,6 +71,27 @@ version = "2.5.0" ...@@ -65,6 +71,27 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.95" version = "1.0.95"
...@@ -146,6 +173,15 @@ version = "0.8.6" ...@@ -146,6 +173,15 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "cpufeatures"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "crc32fast" name = "crc32fast"
version = "1.4.0" version = "1.4.0"
...@@ -155,6 +191,32 @@ dependencies = [ ...@@ -155,6 +191,32 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "data-encoding"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]] [[package]]
name = "dirs" name = "dirs"
version = "5.0.1" version = "5.0.1"
...@@ -211,6 +273,12 @@ dependencies = [ ...@@ -211,6 +273,12 @@ dependencies = [
"miniz_oxide", "miniz_oxide",
] ]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]] [[package]]
name = "foreign-types" name = "foreign-types"
version = "0.3.2" version = "0.3.2"
...@@ -235,6 +303,60 @@ dependencies = [ ...@@ -235,6 +303,60 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "futures-core"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-macro"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-core",
"futures-macro",
"futures-sink",
"futures-task",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.14" version = "0.2.14"
...@@ -264,6 +386,23 @@ version = "0.3.9" ...@@ -264,6 +386,23 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "http"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "httparse"
version = "1.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9"
[[package]] [[package]]
name = "idna" name = "idna"
version = "0.5.0" version = "0.5.0"
...@@ -356,6 +495,17 @@ dependencies = [ ...@@ -356,6 +495,17 @@ dependencies = [
"adler", "adler",
] ]
[[package]]
name = "mio"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"wasi",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "native-tls" name = "native-tls"
version = "0.2.11" version = "0.2.11"
...@@ -445,6 +595,18 @@ version = "2.3.1" ...@@ -445,6 +595,18 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.30" version = "0.3.30"
...@@ -533,15 +695,20 @@ dependencies = [ ...@@ -533,15 +695,20 @@ dependencies = [
[[package]] [[package]]
name = "roboplc-cli" name = "roboplc-cli"
version = "0.1.25" version = "0.4.0"
dependencies = [ dependencies = [
"ansi_term", "ansi_term",
"clap", "clap",
"colored", "colored",
"dirs", "dirs",
"futures-util",
"serde", "serde",
"serde_json", "serde_json",
"shlex", "shlex",
"term_size",
"termios",
"tokio",
"tokio-tungstenite",
"toml", "toml",
"ureq", "ureq",
"ureq_multipart", "ureq_multipart",
...@@ -581,6 +748,19 @@ dependencies = [ ...@@ -581,6 +748,19 @@ dependencies = [
"zeroize", "zeroize",
] ]
[[package]]
name = "rustls"
version = "0.23.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebbbdb961df0ad3f2652da8f3fdc4b36122f568f968f45ad3316f26c025c677b"
dependencies = [
"once_cell",
"rustls-pki-types",
"rustls-webpki",
"subtle",
"zeroize",
]
[[package]] [[package]]
name = "rustls-native-certs" name = "rustls-native-certs"
version = "0.7.0" version = "0.7.0"
...@@ -690,12 +870,42 @@ dependencies = [ ...@@ -690,12 +870,42 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "sha1"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]] [[package]]
name = "shlex" name = "shlex"
version = "1.3.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "socket2"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "spin" name = "spin"
version = "0.9.8" version = "0.9.8"
...@@ -737,6 +947,16 @@ dependencies = [ ...@@ -737,6 +947,16 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "term_size"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
dependencies = [
"libc",
"winapi",
]
[[package]] [[package]]
name = "termcolor" name = "termcolor"
version = "1.4.1" version = "1.4.1"
...@@ -746,6 +966,15 @@ dependencies = [ ...@@ -746,6 +966,15 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "termios"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.59" version = "1.0.59"
...@@ -781,6 +1010,34 @@ version = "0.1.1" ...@@ -781,6 +1010,34 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"pin-project-lite",
"socket2",
"windows-sys 0.48.0",
]
[[package]]
name = "tokio-tungstenite"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd"
dependencies = [
"futures-util",
"log",
"rustls 0.23.7",
"tokio",
"tungstenite",
]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.11" version = "0.5.11"
...@@ -790,6 +1047,30 @@ dependencies = [ ...@@ -790,6 +1047,30 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "tungstenite"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8"
dependencies = [
"byteorder",
"bytes",
"data-encoding",
"http",
"httparse",
"log",
"rand",
"sha1",
"thiserror",
"utf-8",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]] [[package]]
name = "unicase" name = "unicase"
version = "2.7.0" version = "2.7.0"
...@@ -837,7 +1118,7 @@ dependencies = [ ...@@ -837,7 +1118,7 @@ dependencies = [
"log", "log",
"native-tls", "native-tls",
"once_cell", "once_cell",
"rustls", "rustls 0.22.4",
"rustls-native-certs", "rustls-native-certs",
"rustls-pki-types", "rustls-pki-types",
"rustls-webpki", "rustls-webpki",
...@@ -870,6 +1151,12 @@ dependencies = [ ...@@ -870,6 +1151,12 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "utf-8"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
version = "0.2.15" version = "0.2.15"
......
...@@ -17,6 +17,7 @@ path = "src/main.rs" ...@@ -17,6 +17,7 @@ path = "src/main.rs"
clap = { version = "=4.1", features = ["derive", "env"] } clap = { version = "=4.1", features = ["derive", "env"] }
colored = "1" colored = "1"
dirs = "5.0.1" dirs = "5.0.1"
futures-util = { version = "0.3.30", features = ["sink"] }
serde = { version = "1.0.197", features = ["derive"] } serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.115" serde_json = "1.0.115"
shlex = "1.3.0" shlex = "1.3.0"
...@@ -24,8 +25,15 @@ toml = "0.5" ...@@ -24,8 +25,15 @@ toml = "0.5"
ureq = { version = "2.9.6", features = ["json", "native-certs", "native-tls"] } ureq = { version = "2.9.6", features = ["json", "native-certs", "native-tls"] }
ureq_multipart = "1.1.1" ureq_multipart = "1.1.1"
which = "3" which = "3"
term_size = "0.3.2"
tokio = { version = "=1.36", features = ["rt", "fs"] }
tokio-tungstenite = { version = "0.23.1", features = ["rustls"] }
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
ansi_term = "0.12.1" ansi_term = "0.12.1"
[profile.release] [profile.release]
strip = true strip = true
[target.'cfg(not(target_os = "windows"))'.dependencies]
termios = "0.3.3"
...@@ -44,6 +44,11 @@ pub enum SubCommand { ...@@ -44,6 +44,11 @@ pub enum SubCommand {
Restart, Restart,
#[clap(name = "flash", about = "Flash program")] #[clap(name = "flash", about = "Flash program")]
Flash(FlashCommand), Flash(FlashCommand),
#[clap(
name = "x",
about = "Execute program on the remote host in a virtual terminal"
)]
Exec(ExecCommand),
#[clap(name = "purge", about = "Purge program data directory")] #[clap(name = "purge", about = "Purge program data directory")]
Purge, Purge,
} }
...@@ -99,3 +104,65 @@ pub struct FlashCommand { ...@@ -99,3 +104,65 @@ pub struct FlashCommand {
#[clap(short = 'r', long, help = "Put remote in RUN mode after flashing")] #[clap(short = 'r', long, help = "Put remote in RUN mode after flashing")]
pub run: bool, pub run: bool,
} }
#[derive(Parser)]
pub struct ExecCommand {
#[clap(long, env = "CARGO", help = "cargo/cross binary path")]
pub cargo: Option<PathBuf>,
#[clap(long, help = "Override remote cargo target")]
pub cargo_target: Option<String>,
#[clap(long, help = "Extra cargo arguments")]
pub cargo_args: Option<String>,
#[clap(long, help = "Do not compile a Rust project, use a file instead")]
pub file: Option<PathBuf>,
#[clap(
short = 'f',
long,
help = "Force execute (ignore if other program is being executed)"
)]
pub force: bool,
#[arg(
trailing_var_arg = true,
allow_hyphen_values = true,
help = "Arguments after -- are passed to the program as-is"
)]
pub args: Vec<String>,
}
pub struct FlashExec {
pub cargo: Option<PathBuf>,
pub cargo_target: Option<String>,
pub cargo_args: Option<String>,
pub file: Option<PathBuf>,
pub force: bool,
pub run: bool,
pub program_args: Vec<String>,
}
impl From<FlashCommand> for FlashExec {
fn from(cmd: FlashCommand) -> Self {
Self {
cargo: cmd.cargo,
cargo_target: cmd.cargo_target,
cargo_args: cmd.cargo_args,
file: cmd.file,
force: cmd.force,
run: cmd.run,
program_args: Vec::new(),
}
}
}
impl From<ExecCommand> for FlashExec {
fn from(cmd: ExecCommand) -> Self {
Self {
cargo: cmd.cargo,
cargo_target: cmd.cargo_target,
cargo_args: cmd.cargo_args,
file: cmd.file,
force: cmd.force,
run: false,
program_args: cmd.args,
}
}
}
use std::io::Write as _;
use std::path::Path;
use colored::Colorize;
#[cfg(not(target_os = "windows"))]
use tokio::io::AsyncReadExt as _;
use futures_util::{SinkExt, StreamExt};
use serde::{Deserialize, Serialize};
use serde_json::json;
use tokio_tungstenite::tungstenite::Message;
pub fn exec(
url: &str,
key: &str,
file: &Path,
force: bool,
args: Vec<String>,
) -> Result<(), Box<dyn std::error::Error>> {
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()?
.block_on(exec_remote(url, key, file, force, args))?;
Ok(())
}
#[derive(Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
enum Output {
Error(String),
Terminated(i32),
}
#[allow(clippy::too_many_lines)]
async fn exec_remote(
url: &str,
key: &str,
file: &Path,
force: bool,
args: Vec<String>,
) -> Result<(), Box<dyn std::error::Error>> {
let (ws_uri, url_short) = if let Some(u) = url.strip_prefix("http://") {
(format!("ws://{}/roboplc/api/ws.execute", u), u)
} else if let Some(u) = url.strip_prefix("https://") {
(format!("wss://{}/roboplc/api/ws.execute", u), u)
} else {
return Err("Invalid URL".into());
};
println!("Executing on the remote host {}", url_short.green().bold());
println!();
let (mut socket, _) = tokio_tungstenite::connect_async(&ws_uri).await?;
let (width, height) = term_size::dimensions().ok_or("Failed to get terminal size")?;
let payload = json!({
"k": key,
"force": force,
"args": args,
"term": {
"width": width,
"height": height,
"name": std::env::var("TERM").unwrap_or("xterm-256color".to_string()),
},
});
socket
.send(Message::Text(serde_json::to_string(&payload)?))
.await?;
let Some(Ok(Message::Text(msg))) = socket.next().await else {
return Err("Expected text message".into());
};
if msg != "upload" {
if let Ok(Output::Error(e)) = serde_json::from_str::<Output>(&msg) {
return Err(e.into());
}
return Err(format!("Unexpected message: {}", msg).into());
}
let f = tokio::fs::read(file).await?;
socket.send(Message::Binary(f)).await?;
let mut stdout = std::io::stdout();
let mut stderr = std::io::stderr();
#[allow(unused_mut)]
let (mut sender, mut receiver) = socket.split();
#[cfg(target_os = "windows")]
let _ = sender;
// input on windows is currently not supported
#[cfg(not(target_os = "windows"))]
let input_fut = tokio::spawn(async move {
let stdin = std::os::fd::AsRawFd::as_raw_fd(&std::io::stdin().lock());
let mut termios =
termios::Termios::from_fd(stdin).expect("Failed to get termios for stdin");
termios.c_lflag &= !(termios::ICANON | termios::ECHO);
termios::tcsetattr(stdin, termios::TCSANOW, &termios)
.expect("Failed to set termios for stdin");
let mut f = unsafe { <tokio::fs::File as std::os::fd::FromRawFd>::from_raw_fd(stdin) };
let buf = &mut [0u8; 4096];
while let Ok(b) = f.read(buf).await {
if b == 0 {
break;
}
if let Err(e) = sender.send(Message::Binary(buf[..b].to_vec())).await {
eprintln!("Error sending input: {}", e);
break;
}
}
});
macro_rules! handle_out {
($out: expr) => {
let Some(Ok(Message::Binary(b))) = receiver.next().await else {
return Err("Expected binary message".into());
};
$out.write_all(&b)?;
$out.flush()?;
};
}
while let Some(Ok(msg)) = receiver.next().await {
if let Message::Text(m) = msg {
match m.as_str() {
"o" => {
handle_out!(stdout);
}
"e" => {
handle_out!(stderr);
}
v => {
let output = serde_json::from_str::<Output>(v)?;
match output {
Output::Error(e) => {
eprintln!("Program error: {}", e);
break;
}
Output::Terminated(code) => {
if code == 0 {
std::process::exit(0);
} else {
eprintln!("Program terminated with code {}", code);
std::process::exit(code);
}
}
}
}
}
}
}
// actually unreachable
#[cfg(not(target_os = "windows"))]
input_fut.abort();
Ok(())
}
...@@ -10,13 +10,14 @@ use ureq_multipart::MultipartBuilder; ...@@ -10,13 +10,14 @@ use ureq_multipart::MultipartBuilder;
use which::which; use which::which;
use crate::{ use crate::{
arguments::FlashCommand, arguments::FlashExec,
common::{report_ok, KernelInfo}, common::{report_ok, KernelInfo},
config, config,
ureq_err::PrintErr, ureq_err::PrintErr,
API_PREFIX, API_PREFIX,
}; };
#[allow(clippy::too_many_arguments)]
fn flash_file( fn flash_file(
url: &str, url: &str,
key: &str, key: &str,
...@@ -24,10 +25,15 @@ fn flash_file( ...@@ -24,10 +25,15 @@ fn flash_file(
file: &Path, file: &Path,
force: bool, force: bool,
run: bool, run: bool,
exec_only: bool,
program_args: Vec<String>,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
if !file.exists() { if !file.exists() {
return Err(format!("File not found: {}", file.display()).into()); return Err(format!("File not found: {}", file.display()).into());
} }
if exec_only {
return crate::exec::exec(url, key, file, force, program_args);
}
let (content_type, data) = MultipartBuilder::new() let (content_type, data) = MultipartBuilder::new()
.add_file("file", file)? .add_file("file", file)?
.add_text( .add_text(
...@@ -50,6 +56,7 @@ fn flash_file( ...@@ -50,6 +56,7 @@ fn flash_file(
Ok(()) Ok(())
} }
#[allow(clippy::too_many_arguments)]
fn run_build_custom( fn run_build_custom(
url: &str, url: &str,
key: &str, key: &str,
...@@ -58,6 +65,8 @@ fn run_build_custom( ...@@ -58,6 +65,8 @@ fn run_build_custom(
run: bool, run: bool,
cmd: &str, cmd: &str,
file: &Path, file: &Path,
exec_only: bool,
program_args: Vec<String>,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
println!("Remote: {}", url.yellow()); println!("Remote: {}", url.yellow());
println!("Build command line: {}", cmd.yellow()); println!("Build command line: {}", cmd.yellow());
...@@ -73,20 +82,31 @@ fn run_build_custom( ...@@ -73,20 +82,31 @@ fn run_build_custom(
if !file.exists() { if !file.exists() {
return Err(format!("File not found: {}", file.display()).into()); return Err(format!("File not found: {}", file.display()).into());
} }
flash_file(url, key, agent, file, force, run)?; flash_file(url, key, agent, file, force, run, exec_only, program_args)?;
Ok(()) Ok(())
} }
#[allow(clippy::too_many_arguments, clippy::too_many_lines)]
pub fn flash( pub fn flash(
url: &str, url: &str,
key: &str, key: &str,
agent: Agent, agent: Agent,
opts: FlashCommand, opts: FlashExec,
build_config: config::Build, build_config: config::Build,
build_custom: config::BuildCustom, build_custom: config::BuildCustom,
exec_only: bool,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
if let Some(file) = opts.file { if let Some(file) = opts.file {
flash_file(url, key, agent, &file, opts.force, opts.run)?; flash_file(
url,
key,
agent,
&file,
opts.force,
opts.run,
exec_only,
opts.program_args,
)?;
} else if let Some(custom_cmd) = build_custom.command { } else if let Some(custom_cmd) = build_custom.command {
run_build_custom( run_build_custom(
url, url,
...@@ -98,6 +118,8 @@ pub fn flash( ...@@ -98,6 +118,8 @@ pub fn flash(
&build_custom &build_custom
.file .file
.ok_or("Custom build command requires a file")?, .ok_or("Custom build command requires a file")?,
exec_only,
opts.program_args,
)?; )?;
} else { } else {
let mut cargo_target: Option<String> = None; let mut cargo_target: Option<String> = None;
...@@ -163,7 +185,16 @@ pub fn flash( ...@@ -163,7 +185,16 @@ pub fn flash(
return Err("Compilation failed".into()); return Err("Compilation failed".into());
} }
println!("Flashing..."); println!("Flashing...");
flash_file(url, key, agent, &binary_name, opts.force, opts.run)?; flash_file(
url,
key,
agent,
&binary_name,
opts.force,
opts.run,
exec_only,
opts.program_args,
)?;
} }
report_ok() report_ok()
} }
......
...@@ -14,6 +14,7 @@ const TPL_DEFAULT_RS: &str = include_str!("../tpl/default.rs"); ...@@ -14,6 +14,7 @@ const TPL_DEFAULT_RS: &str = include_str!("../tpl/default.rs");
mod arguments; mod arguments;
mod common; mod common;
mod config; mod config;
mod exec;
mod flashing; mod flashing;
mod project; mod project;
mod remote; mod remote;
...@@ -98,9 +99,21 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { ...@@ -98,9 +99,21 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
&url, &url,
&key, &key,
agent, agent,
opts, opts.into(),
build_config.unwrap_or_default(), build_config.unwrap_or_default(),
build_custom.unwrap_or_default(), build_custom.unwrap_or_default(),
false,
)?;
}
SubCommand::Exec(opts) => {
flashing::flash(
&url,
&key,
agent,
opts.into(),
build_config.unwrap_or_default(),
build_custom.unwrap_or_default(),
true,
)?; )?;
} }
SubCommand::Purge => { SubCommand::Purge => {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论