Skip to content

Commit e72ffcd

Browse files
jdettergefjon
andauthored
Delete Files Flag for Generate Command (#693)
* Generate now has a clear flag which will clear the output directory before generating files * Some change - will explain in PR description. * Only delete files which were generated by SpacetimeDB * Slightly better pattern matching to reduce false negatives or positives * Added force command for CI * Fix for help section * Update crates/cli/src/subcommands/generate/mod.rs Co-authored-by: Phoebe Goldman <[email protected]> Signed-off-by: John Detter <[email protected]> * Update crates/cli/src/subcommands/generate/mod.rs Co-authored-by: Phoebe Goldman <[email protected]> Signed-off-by: John Detter <[email protected]> --------- Signed-off-by: John Detter <[email protected]> Co-authored-by: John Detter <[email protected]> Co-authored-by: Phoebe Goldman <[email protected]>
1 parent 63cbdb0 commit e72ffcd

File tree

1 file changed

+69
-2
lines changed
  • crates/cli/src/subcommands/generate

1 file changed

+69
-2
lines changed

crates/cli/src/subcommands/generate/mod.rs

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::fs;
2+
use std::io::Write;
23
use std::path::{Path, PathBuf};
34

45
use clap::Arg;
@@ -66,11 +67,25 @@ pub fn cli() -> clap::Command {
6667
Arg::new("skip_clippy")
6768
.long("skip_clippy")
6869
.short('s')
70+
.short('S')
6971
.action(SetTrue)
7072
.env("SPACETIME_SKIP_CLIPPY")
7173
.value_parser(clap::builder::FalseyValueParser::new())
7274
.help("Skips running clippy on the module before generating (intended to speed up local iteration, not recommended for CI)"),
7375
)
76+
.arg(
77+
Arg::new("delete_files")
78+
.long("delete-files")
79+
.action(SetTrue)
80+
.help("Delete outdated generated files whose definitions have been removed from the module. Prompts before deleting unless --force is supplied."),
81+
)
82+
.arg(
83+
Arg::new("force")
84+
.long("force")
85+
.action(SetTrue)
86+
.requires("delete_files")
87+
.help("delete-files without prompting first. Useful for scripts."),
88+
)
7489
.arg(
7590
Arg::new("debug")
7691
.long("debug")
@@ -89,6 +104,8 @@ pub fn exec(args: &clap::ArgMatches) -> anyhow::Result<()> {
89104
let namespace = args.get_one::<String>("namespace").unwrap();
90105
let skip_clippy = args.get_flag("skip_clippy");
91106
let build_debug = args.get_flag("debug");
107+
let delete_files = args.get_flag("delete_files");
108+
let force = args.get_flag("force");
92109

93110
let wasm_file = match wasm_file {
94111
Some(x) => x,
@@ -101,7 +118,7 @@ pub fn exec(args: &clap::ArgMatches) -> anyhow::Result<()> {
101118
Failed to compile module {:?}. See cargo errors above for more details.",
102119
e,
103120
project_path,
104-
))
121+
));
105122
}
106123
},
107124
};
@@ -120,7 +137,54 @@ Failed to compile module {:?}. See cargo errors above for more details.",
120137
fs::write(path, code)?;
121138
}
122139

123-
format_files(paths, lang)?;
140+
format_files(paths.clone(), lang)?;
141+
142+
if delete_files {
143+
let mut files_to_delete = vec![];
144+
for entry in fs::read_dir(out_dir)? {
145+
let entry = entry?;
146+
let path = entry.path();
147+
if path.is_file() {
148+
if let Ok(contents) = fs::read_to_string(&path) {
149+
if !contents.starts_with("// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB.") {
150+
continue;
151+
}
152+
}
153+
154+
if paths
155+
.iter()
156+
.any(|x| x.file_name().unwrap() == path.file_name().unwrap())
157+
{
158+
continue;
159+
}
160+
files_to_delete.push(path);
161+
}
162+
}
163+
if !files_to_delete.is_empty() {
164+
let mut input = "y".to_string();
165+
println!("The following files were not generated by this command and will be deleted:");
166+
for path in &files_to_delete {
167+
println!(" {}", path.to_str().unwrap());
168+
}
169+
170+
if !force {
171+
print!("Are you sure you want to delete these files? [y/N] ");
172+
std::io::stdout().flush()?;
173+
std::io::stdin().read_line(&mut input)?;
174+
} else {
175+
println!("Force flag present, deleting files without prompting.");
176+
}
177+
178+
if input.trim().to_lowercase() == "y" || input.trim().to_lowercase() == "yes" {
179+
for path in files_to_delete {
180+
fs::remove_file(path)?;
181+
}
182+
println!("Files deleted successfully.");
183+
} else {
184+
println!("Files not deleted.");
185+
}
186+
}
187+
}
124188

125189
println!("Generate finished successfully.");
126190
Ok(())
@@ -133,6 +197,7 @@ pub enum Language {
133197
Python,
134198
Rust,
135199
}
200+
136201
impl clap::ValueEnum for Language {
137202
fn value_variants<'a>() -> &'a [Self] {
138203
&[Self::Csharp, Self::TypeScript, Self::Python, Self::Rust]
@@ -407,6 +472,7 @@ struct WasmCtx {
407472
mem: Option<Memory>,
408473
buffers: slab::Slab<Vec<u8>>,
409474
}
475+
410476
impl WasmCtx {
411477
fn mem(&self) -> Memory {
412478
self.mem.unwrap()
@@ -426,6 +492,7 @@ impl WasmCtx {
426492
struct Memory {
427493
mem: wasmtime::Memory,
428494
}
495+
429496
impl Memory {
430497
fn deref_slice<'a>(&self, store: &'a impl AsContext, offset: u32, len: u32) -> Option<&'a [u8]> {
431498
self.mem

0 commit comments

Comments
 (0)