Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ just doc # Documentation generation

If `gt` (Graphite CLI) is available in PATH, use it instead of `gh` to create pull requests.

PR titles must use [Conventional Commits](https://www.conventionalcommits.org) format: `type(scope): summary` (scope is optional), e.g. `feat(cache): add LRU eviction`, `fix: handle symlink loops`, `test(e2e): add ctrl-c propagation test`.

## Tests

```bash
Expand Down
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/vite_task_bin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ pty_terminal = { workspace = true }
pty_terminal_test = { workspace = true }
regex = { workspace = true }
serde = { workspace = true, features = ["derive", "rc"] }
shell-escape = { workspace = true }
tempfile = { workspace = true }
toml = { workspace = true }
vec1 = { workspace = true, features = ["serde"] }
vite_path = { workspace = true, features = ["absolute-redaction"] }
vite_workspace = { workspace = true }

Expand Down
7 changes: 7 additions & 0 deletions crates/vite_task_bin/src/vtt/cp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub fn run(args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
if args.len() != 2 {
return Err("Usage: vtt cp <src> <dst>".into());
}
std::fs::copy(&args[0], &args[1])?;
Ok(())
}
4 changes: 4 additions & 0 deletions crates/vite_task_bin/src/vtt/exit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub fn run(args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
let code: i32 = args.first().map(|s| s.parse()).transpose()?.unwrap_or(0);
std::process::exit(code);
}
14 changes: 13 additions & 1 deletion crates/vite_task_bin/src/vtt/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,26 @@

mod barrier;
mod check_tty;
mod cp;
mod exit;
mod mkdir;
mod pipe_stdin;
mod print;
mod print_cwd;
mod print_env;
mod print_file;
mod read_stdin;
mod replace_file_content;
mod rm;
mod touch_file;
mod write_file;

fn main() {
let args: Vec<String> = std::env::args().collect();
if args.len() < 2 {
eprintln!("Usage: vtt <subcommand> [args...]");
eprintln!(
"Subcommands: barrier, check-tty, print, print-cwd, print-env, print-file, read-stdin, replace-file-content, touch-file"
"Subcommands: barrier, check-tty, cp, exit, mkdir, pipe-stdin, print, print-cwd, print-env, print-file, read-stdin, replace-file-content, rm, touch-file, write-file"
);
std::process::exit(1);
}
Expand All @@ -32,6 +38,9 @@ fn main() {
check_tty::run();
Ok(())
}
"cp" => cp::run(&args[2..]),
"exit" => exit::run(&args[2..]),
"mkdir" => mkdir::run(&args[2..]),
"print" => {
print::run(&args[2..]);
Ok(())
Expand All @@ -41,7 +50,10 @@ fn main() {
"print-file" => print_file::run(&args[2..]),
"read-stdin" => read_stdin::run(),
"replace-file-content" => replace_file_content::run(&args[2..]),
"pipe-stdin" => pipe_stdin::run(&args[2..]),
"rm" => rm::run(&args[2..]),
"touch-file" => touch_file::run(&args[2..]),
"write-file" => write_file::run(&args[2..]),
other => {
eprintln!("Unknown subcommand: {other}");
std::process::exit(1);
Expand Down
21 changes: 21 additions & 0 deletions crates/vite_task_bin/src/vtt/mkdir.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
pub fn run(args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
let mut parents = false;
let mut paths = Vec::new();
for arg in args {
match arg.as_str() {
"-p" => parents = true,
_ => paths.push(arg.as_str()),
}
}
if paths.is_empty() {
return Err("Usage: vtt mkdir [-p] <path>...".into());
}
for path in paths {
if parents {
std::fs::create_dir_all(path)?;
} else {
std::fs::create_dir(path)?;
}
}
Ok(())
}
33 changes: 33 additions & 0 deletions crates/vite_task_bin/src/vtt/pipe_stdin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/// pipe-stdin `<data>` -- `<command>` \[`<args>`...\]
///
/// Spawns `<command>` with `<data>` piped to its stdin, then exits with
/// the child's exit code. If `<data>` is empty, an empty stdin is provided.
pub fn run(args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
let sep = args
.iter()
.position(|a| a == "--")
.ok_or("Usage: vtt pipe-stdin <data> -- <command> [args...]")?;
let data = &args[..sep].join(" ");
let cmd_args = &args[sep + 1..];
if cmd_args.is_empty() {
return Err("Usage: vtt pipe-stdin <data> -- <command> [args...]".into());
}

let mut child = std::process::Command::new(&cmd_args[0])
.args(&cmd_args[1..])
.stdin(std::process::Stdio::piped())
.spawn()?;

{
use std::io::Write;
let mut stdin = child.stdin.take().unwrap();
if !data.is_empty() {
stdin.write_all(data.as_bytes())?;
}
stdin.write_all(b"\n")?;
// stdin is closed when dropped, signaling EOF
}

let status = child.wait()?;
std::process::exit(status.code().unwrap_or(1));
}
22 changes: 22 additions & 0 deletions crates/vite_task_bin/src/vtt/rm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
pub fn run(args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
let mut recursive = false;
let mut paths = Vec::new();
for arg in args {
match arg.as_str() {
"-r" | "-rf" | "-f" => recursive = true,
_ => paths.push(arg.as_str()),
}
}
if paths.is_empty() {
return Err("Usage: vtt rm [-rf] <path>...".into());
}
for path in paths {
let p = std::path::Path::new(path);
if p.is_dir() && recursive {
std::fs::remove_dir_all(p)?;
} else {
std::fs::remove_file(p)?;
}
}
Ok(())
}
7 changes: 7 additions & 0 deletions crates/vite_task_bin/src/vtt/write_file.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub fn run(args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
if args.len() < 2 {
return Err("Usage: vtt write-file <filename> <content>".into());
}
std::fs::write(&args[0], &args[1])?;
Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,26 @@
[[e2e]]
name = "associate existing cache"
steps = [
"vt run script1 # cache miss",
"vt run script2 # cache hit, same command as script1",
"vtt replace-file-content package.json '\"script2\": \"vtt print hello\"' '\"script2\": \"vtt print world\"' # change script2",
"vt run script2 # cache miss",
{ argv = [
"vt",
"run",
"script1",
], comment = "cache miss" },
{ argv = [
"vt",
"run",
"script2",
], comment = "cache hit, same command as script1" },
{ argv = [
"vtt",
"replace-file-content",
"package.json",
"\"script2\": \"vtt print hello\"",
"\"script2\": \"vtt print world\"",
], comment = "change script2" },
{ argv = [
"vt",
"run",
"script2",
], comment = "cache miss" },
]
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,24 @@
[[e2e]]
name = "builtin different cwd"
steps = [
"vt run cwd1 # cache miss in folder1",
"vt run cwd2 # cache miss in folder2 (different cwd)",
"vt run cwd1 # cache hit in folder1",
"vt run cwd2 # cache hit in folder2",
{ argv = [
"vt",
"run",
"cwd1",
], comment = "cache miss in folder1" },
{ argv = [
"vt",
"run",
"cwd2",
], comment = "cache miss in folder2 (different cwd)" },
{ argv = [
"vt",
"run",
"cwd1",
], comment = "cache hit in folder1" },
{ argv = [
"vt",
"run",
"cwd2",
], comment = "cache hit in folder2" },
]
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,30 @@

[[e2e]]
name = "task with cache disabled"
steps = ["vt run no-cache-task # cache miss", "vt run no-cache-task # cache disabled, runs again"]
steps = [
{ argv = [
"vt",
"run",
"no-cache-task",
], comment = "cache miss" },
{ argv = [
"vt",
"run",
"no-cache-task",
], comment = "cache disabled, runs again" },
]

[[e2e]]
name = "task with cache enabled"
steps = ["vt run cached-task # cache miss", "vt run cached-task # cache hit"]
steps = [
{ argv = [
"vt",
"run",
"cached-task",
], comment = "cache miss" },
{ argv = [
"vt",
"run",
"cached-task",
], comment = "cache hit" },
]
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,33 @@
[[e2e]]
name = "cache miss command change"
steps = [
"vt run task # cache miss",
"vtt replace-file-content vite-task.json 'vtt print foo && vtt print bar' 'vtt print baz && vtt print bar' # change first subtask",
"vt run task # first: cache miss, second: cache hit",
"vtt replace-file-content vite-task.json 'vtt print baz && vtt print bar' 'vtt print bar' # remove first subtask",
"vt run task # cache hit",
{ argv = [
"vt",
"run",
"task",
], comment = "cache miss" },
{ argv = [
"vtt",
"replace-file-content",
"vite-task.json",
"vtt print foo && vtt print bar",
"vtt print baz && vtt print bar",
], comment = "change first subtask" },
{ argv = [
"vt",
"run",
"task",
], comment = "first: cache miss, second: cache hit" },
{ argv = [
"vtt",
"replace-file-content",
"vite-task.json",
"vtt print baz && vtt print bar",
"vtt print bar",
], comment = "remove first subtask" },
{ argv = [
"vt",
"run",
"task",
], comment = "cache hit" },
]
Loading
Loading