mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-07 08:27:12 +00:00
Add fabro repo deinit command to reverse project initialization
Removes fabro.toml and the fabro/ directory from the git repo root. Fails with a clear error when the project is not initialized. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a41bc899e4
commit
7c16f3b3c9
3 changed files with 118 additions and 0 deletions
|
|
@ -110,6 +110,59 @@ draft = true
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_deinit() -> Result<()> {
|
||||
let output = std::process::Command::new("git")
|
||||
.args(["rev-parse", "--show-toplevel"])
|
||||
.output()
|
||||
.context("failed to run git")?;
|
||||
|
||||
if !output.status.success() {
|
||||
bail!("not a git repository");
|
||||
}
|
||||
|
||||
let repo_root = PathBuf::from(
|
||||
String::from_utf8(output.stdout)
|
||||
.context("git output was not valid UTF-8")?
|
||||
.trim(),
|
||||
);
|
||||
|
||||
let fabro_toml = repo_root.join("fabro.toml");
|
||||
if !fabro_toml.exists() {
|
||||
bail!("not initialized — fabro.toml not found");
|
||||
}
|
||||
|
||||
let green = console::Style::new().green();
|
||||
let dim = console::Style::new().dim();
|
||||
|
||||
std::fs::remove_file(&fabro_toml)
|
||||
.with_context(|| format!("failed to remove {}", fabro_toml.display()))?;
|
||||
eprintln!(
|
||||
" {} {}",
|
||||
green.apply_to("✔"),
|
||||
dim.apply_to("removed fabro.toml")
|
||||
);
|
||||
|
||||
let fabro_dir = repo_root.join("fabro");
|
||||
if fabro_dir.exists() {
|
||||
std::fs::remove_dir_all(&fabro_dir)
|
||||
.with_context(|| format!("failed to remove {}", fabro_dir.display()))?;
|
||||
eprintln!(
|
||||
" {} {}",
|
||||
green.apply_to("✔"),
|
||||
dim.apply_to("removed fabro/")
|
||||
);
|
||||
}
|
||||
|
||||
eprintln!(
|
||||
"\n{}",
|
||||
console::Style::new()
|
||||
.bold()
|
||||
.apply_to("Project deinitialized.")
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn check_github_app_installation() {
|
||||
// Get the git remote origin URL
|
||||
let output = match std::process::Command::new("git")
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ enum Command {
|
|||
command: PrCommand,
|
||||
},
|
||||
/// Skill management
|
||||
#[command(hide = true)]
|
||||
Skill {
|
||||
#[command(subcommand)]
|
||||
command: SkillCommand,
|
||||
|
|
@ -199,6 +200,8 @@ enum SystemCommand {
|
|||
enum RepoCommand {
|
||||
/// Initialize a new project
|
||||
Init,
|
||||
/// Remove fabro.toml and fabro/ directory
|
||||
Deinit,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
|
|
@ -450,6 +453,7 @@ async fn main_inner() -> (String, Result<()>) {
|
|||
Command::Doctor { .. } => "doctor",
|
||||
Command::Repo { command } => match command {
|
||||
RepoCommand::Init => "repo init",
|
||||
RepoCommand::Deinit => "repo deinit",
|
||||
},
|
||||
Command::Init => "init",
|
||||
Command::Install => "install",
|
||||
|
|
@ -783,6 +787,9 @@ async fn main_inner() -> (String, Result<()>) {
|
|||
RepoCommand::Init => {
|
||||
init::run_init().await?;
|
||||
}
|
||||
RepoCommand::Deinit => {
|
||||
init::run_deinit()?;
|
||||
}
|
||||
},
|
||||
Command::Init => {
|
||||
eprintln!(
|
||||
|
|
|
|||
|
|
@ -410,6 +410,64 @@ fn scenario_full_stack(sandbox: &str) {
|
|||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// repo deinit
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
fn init_git_repo(path: &Path) {
|
||||
std::process::Command::new("git")
|
||||
.args(["init"])
|
||||
.current_dir(path)
|
||||
.output()
|
||||
.expect("git init should succeed");
|
||||
}
|
||||
|
||||
fn init_fabro_project(path: &Path) {
|
||||
std::fs::write(path.join("fabro.toml"), "version = 1\n").unwrap();
|
||||
let workflow_dir = path.join("fabro/workflows/hello");
|
||||
std::fs::create_dir_all(&workflow_dir).unwrap();
|
||||
std::fs::write(workflow_dir.join("workflow.fabro"), "digraph {}").unwrap();
|
||||
std::fs::write(workflow_dir.join("workflow.toml"), "version = 1\n").unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_repo_deinit_removes_fabro_toml_and_dir() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
init_git_repo(tmp.path());
|
||||
init_fabro_project(tmp.path());
|
||||
|
||||
assert!(tmp.path().join("fabro.toml").exists());
|
||||
assert!(tmp.path().join("fabro").exists());
|
||||
|
||||
fabro()
|
||||
.args(["repo", "deinit"])
|
||||
.current_dir(tmp.path())
|
||||
.assert()
|
||||
.success();
|
||||
|
||||
assert!(
|
||||
!tmp.path().join("fabro.toml").exists(),
|
||||
"fabro.toml should be removed"
|
||||
);
|
||||
assert!(
|
||||
!tmp.path().join("fabro").exists(),
|
||||
"fabro/ directory should be removed"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_repo_deinit_fails_when_not_initialized() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
init_git_repo(tmp.path());
|
||||
|
||||
fabro()
|
||||
.args(["repo", "deinit"])
|
||||
.current_dir(tmp.path())
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicates::str::contains("not initialized"));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Standalone tests (no sandbox parametrization)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue