Skip to content
This repository has been archived by the owner on Dec 21, 2024. It is now read-only.

Commit

Permalink
chore: add show_term task
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanFlurry committed Jul 23, 2024
1 parent d37b436 commit 4440872
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 10 deletions.
2 changes: 2 additions & 0 deletions rivet-toolchain/src/tasks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub mod get_bootstrap_data;
pub mod get_hub_link;
pub mod get_settings_paths;
pub mod open;
pub mod show_term;
pub mod start_device_link;
pub mod unlink;
pub mod wait_for_login;
Expand Down Expand Up @@ -84,6 +85,7 @@ gen_run_task!(
get_bootstrap_data::Task,
get_hub_link::Task,
open::Task,
show_term::Task,
start_device_link::Task,
unlink::Task,
wait_for_login::Task,
Expand Down
33 changes: 33 additions & 0 deletions rivet-toolchain/src/tasks/show_term.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use global_error::prelude::*;
use serde::{Deserialize, Serialize};

use crate::{util, util::task::TaskCtx};

#[derive(Deserialize)]
pub struct Input {
pub command: String,
pub args: Vec<String>,
}

#[derive(Serialize)]
pub struct Output {}

pub struct Task;

impl super::Task for Task {
type Input = Input;
type Output = Output;

fn name() -> &'static str {
"show_term"
}

async fn run(_task: TaskCtx, input: Self::Input) -> GlobalResult<Self::Output> {
let mut command = Vec::new();
command.push(input.command);
command.extend(input.args);
util::show_term::show_term(&command).await?;

Ok(Output {})
}
}
8 changes: 2 additions & 6 deletions rivet-toolchain/src/tasks/wait_for_login.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ pub struct Input {
}

#[derive(Serialize)]
pub struct Output {
pub output: String,
}
pub struct Output {}

pub struct Task;

Expand Down Expand Up @@ -64,8 +62,6 @@ impl super::Task for Task {

config::meta::insert_project(input.api_endpoint, token).await?;

Ok(Output {
output: "Token saved".to_string(),
})
Ok(Output {})
}
}
31 changes: 27 additions & 4 deletions rivet-toolchain/src/util/show_term.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,12 @@ pub async fn show_term(args: &[String]) -> GlobalResult<Child> {
// Write the script content to the script file
let command_to_run = format!(
"cd \"{}\" && {} && rm \"{}\"",
current_dir,
args.join(" "),
script_path.display()
shell_escape(&current_dir),
args.iter()
.map(|x| shell_escape(x))
.collect::<Vec<_>>()
.join(" "),
shell_escape(&script_path.display().to_string()),
);
std::fs::write(&script_path, format!("#!/bin/bash\n{}", command_to_run))?;
std::fs::set_permissions(
Expand Down Expand Up @@ -156,7 +159,7 @@ pub async fn show_term(args: &[String]) -> GlobalResult<Child> {
.args(terminal.prompt_str)
// We pass everything to a shell manually so that we can
// pass an entire string of the rest of the commands.
// This is more consistant across terminals on linux.
// This is more consistent across terminals on linux.
.arg(shell)
.arg("-c")
.args(&args)
Expand All @@ -172,6 +175,26 @@ pub async fn show_term(args: &[String]) -> GlobalResult<Child> {
Ok(child)
}

fn shell_escape(s: &str) -> String {
if s.is_empty() {
return String::from("''");
}
if !s.contains(|c: char| c.is_whitespace() || "[]{}()*;'\"\\|<>~&^$?!`".contains(c)) {
return s.to_string();
}
let mut result = String::with_capacity(s.len() + 2);
result.push('\'');
for c in s.chars() {
if c == '\'' {
result.push_str("'\\''");
} else {
result.push(c);
}
}
result.push('\'');
result
}

#[cfg(target_os = "linux")]
#[cfg(test)]
mod tests {
Expand Down

0 comments on commit 4440872

Please sign in to comment.