Skip to content

Commit 9422f50

Browse files
committed
feat: add run command
1 parent c74b7e6 commit 9422f50

File tree

6 files changed

+120
-18
lines changed

6 files changed

+120
-18
lines changed

Cargo.lock

+49
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ clap = { version = "4.5.4", features = ["derive"] }
1111
colored = "2.1.0"
1212
serde = { version = "1.0.201", features = ["derive"] }
1313
serde_json = "1.0.117"
14+
atty = "0.2.14"

src/cli.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ enum Commands {
6161
name: String,
6262

6363
/// Arguments to pass to the package
64-
#[arg(required = true, last = true)]
64+
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
6565
subcommand: Vec<String>,
6666
},
6767
}

src/commands.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::env;
55
use std::error::Error;
66
use crate::files::versions::{remove, upsert};
77
use crate::packages::Package;
8+
use crate::runner::run;
89

910
pub fn show_info() -> Result<(), Box<dyn Error>> {
1011
println!("\n{}:", "System Information".bold().underline());
@@ -58,7 +59,7 @@ pub fn add_package(name: String, version: String, set_default: bool) -> Result<(
5859
}
5960
run_pull_and_add_shim(&name, &version, package)?;
6061
} else {
61-
let package = Package::new(&name, crate::files::index::Package::new(&name), crate::files::versions::Package::new(&version));
62+
let package = Package::new(&name, crate::files::versions::Package::new(&version))?;
6263
run_pull_and_add_shim(&name, &version, package)?;
6364
}
6465
Ok(())
@@ -110,13 +111,20 @@ pub fn set_package_version(name: String, version: String) -> Result<(), Box<dyn
110111
}
111112
}
112113

113-
pub fn run_package(_name: String, _subcommand: Vec<String>) -> Result<(), Box<dyn Error>> {
114-
Ok(())
114+
pub fn run_package(name: String, subcommand: Vec<String>) -> Result<(), Box<dyn Error>> {
115+
if let Some(package) = Package::load(&name)? {
116+
run(&package, &subcommand);
117+
Ok(())
118+
} else {
119+
Err(format!("Package '{}' does not exists.", name).into())
120+
}
115121
}
116122

117123
fn run_pull_and_add_shim(name: &String, version: &String, package: Package) -> Result<(), Box<dyn Error>> {
118-
if crate::runner::pull(&package) {
119-
crate::files::versions::upsert(&name, package)?;
124+
let mut new_package = package.clone();
125+
new_package.versions.current = version.clone();
126+
if crate::runner::pull(&new_package) {
127+
upsert(&name, package)?;
120128
add_shim(&name)?;
121129
Ok(())
122130
} else {

src/packages.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::files::index::Package as IndexPackage;
22
use crate::files::versions::Package as VersionsPackage;
33
use std::error::Error;
44

5-
#[derive(Debug)]
5+
#[derive(Debug, Clone)]
66
pub struct Package {
77
pub name: String,
88
pub index: IndexPackage,
@@ -11,12 +11,16 @@ pub struct Package {
1111

1212
// Public API
1313
impl Package {
14-
pub fn new(name: &str, index_package: IndexPackage, versions_package: VersionsPackage) -> Self {
15-
Self {
14+
pub fn new(name: &str, versions_package: VersionsPackage) -> Result<Self, Box<dyn Error>> {
15+
let index_packages = crate::files::index::parse()?;
16+
let index_package = index_packages.packages.get(name)
17+
.map(|pkg| pkg.to_owned())
18+
.unwrap_or_else(|| IndexPackage::new(name));
19+
Ok(Self {
1620
name: String::from(name),
1721
index: index_package,
1822
versions: versions_package,
19-
}
23+
})
2024
}
2125

2226
pub fn load(name: &str) -> Result<Option<Self>, Box<dyn Error>> {

src/runner.rs

+48-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,56 @@
1+
use std::io::{self, Read, Write};
2+
use std::process::{Command, Stdio};
3+
use atty::Stream;
14
use crate::packages::Package;
25

3-
pub fn pull(package: &Package) -> bool {
4-
let command = format!("docker pull {}", package.container_image_url());
5-
run_command(&command)
6+
fn run_command(command: &str, stdin_buffer: Option<Vec<u8>>) -> bool {
7+
println!("Running command: {}", command);
8+
9+
let mut parts = command.split_whitespace();
10+
let cmd = parts.next().unwrap(); // Extract command
11+
let args = parts.collect::<Vec<_>>(); // Extract arguments
12+
13+
let mut child = Command::new(cmd)
14+
.args(args)
15+
.stdout(Stdio::inherit()) // Inherit stdout
16+
.stderr(Stdio::inherit()) // Inherit stderr
17+
.stdin(Stdio::piped()) // Set stdin to piped to write the buffer later
18+
.spawn() // Spawn the command
19+
.expect("Failed to spawn command");
20+
21+
// If stdin_buffer is Some, write it to the child's stdin
22+
if let Some(buffer) = stdin_buffer {
23+
let child_stdin = child.stdin.as_mut().expect("Failed to open stdin");
24+
child_stdin.write_all(&buffer).expect("Failed to write to stdin");
25+
}
26+
27+
// Wait for the command to complete and check the status
28+
match child.wait() {
29+
Ok(status) => status.success(),
30+
Err(e) => {
31+
println!("Command failed to complete: {}", e);
32+
false
33+
}
34+
}
635
}
736

837
pub fn run(package: &Package, params: &Vec<String>) -> bool {
9-
let command = format!("docker run {} {}", package.name, params.join(" "));
10-
run_command(&command)
38+
let interactive = !atty::is(Stream::Stdin);
39+
40+
let mut buffer = Vec::new();
41+
if interactive {
42+
io::stdin().read_to_end(&mut buffer).expect("Failed to read stdin");
43+
buffer.len();
44+
}
45+
46+
let interactive_flag = if interactive { "-i " } else { "" };
47+
let command = format!("docker run {}{} {}", interactive_flag, package.container_image_url(), params.join(" "));
48+
49+
run_command(&command, Some(buffer))
1150
}
1251

13-
fn run_command(command: &str) -> bool {
14-
println!("Pretending I'm running {}", command);
15-
true
52+
pub fn pull(package: &Package) -> bool {
53+
let command = format!("docker pull {}", package.container_image_url());
54+
// Normally, pull does not need stdin interaction
55+
run_command(&command, None)
1656
}

0 commit comments

Comments
 (0)