Skip to content

Commit 5fac372

Browse files
committed
fix: backup in attributes init, validate hook names, --force overwrites gitignore, cargo check before install-delta
1 parent 89f473f commit 5fac372

4 files changed

Lines changed: 52 additions & 5 deletions

File tree

src/attributes/mod.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,16 @@ pub fn run(cmd: AttributesCommand) -> Result<()> {
2929
let root = find_repo_root()?;
3030
let path = root.join(".gitattributes");
3131

32-
if path.exists() && !force && !confirm(".gitattributes already exists. Overwrite?", yes) {
33-
println!("Aborted.");
34-
return Ok(());
32+
if path.exists() && !force {
33+
if !confirm(".gitattributes already exists. Overwrite?", yes) {
34+
println!("Aborted.");
35+
return Ok(());
36+
}
37+
if !dry_run {
38+
let backup = root.join(".gitattributes.bak");
39+
std::fs::copy(&path, &backup).context("Failed to backup .gitattributes")?;
40+
println!("Backed up to {}", backup.display());
41+
}
3542
}
3643

3744
if dry_run {

src/config/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ fn delta_installed() -> bool {
122122
}
123123

124124
fn install_delta() -> Result<()> {
125+
anyhow::ensure!(
126+
Command::new("cargo")
127+
.arg("--version")
128+
.output()
129+
.map(|o| o.status.success())
130+
.unwrap_or(false),
131+
"cargo not found in PATH — install Rust from https://rustup.rs to install git-delta"
132+
);
125133
println!("Installing git-delta...");
126134
let status = Command::new("cargo")
127135
.args(["install", "git-delta"])

src/hooks/mod.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,29 @@ fn hook_script(target: &str) -> String {
6161
format!("#!/bin/sh\nset -e\n{target}\n")
6262
}
6363

64+
const VALID_HOOKS: &[&str] = &[
65+
"applypatch-msg",
66+
"commit-msg",
67+
"fsmonitor-watchman",
68+
"post-update",
69+
"pre-applypatch",
70+
"pre-commit",
71+
"pre-merge-commit",
72+
"pre-push",
73+
"pre-rebase",
74+
"pre-receive",
75+
"prepare-commit-msg",
76+
"push-to-checkout",
77+
"update",
78+
];
79+
6480
fn init(hook: &str, target: &str, yes: bool, force: bool, dry_run: bool) -> Result<()> {
81+
if !VALID_HOOKS.contains(&hook) {
82+
anyhow::bail!(
83+
"'{hook}' is not a valid git hook. Valid hooks: {}",
84+
VALID_HOOKS.join(", ")
85+
);
86+
}
6587
let dir = hooks_dir()?;
6688
let path = dir.join(hook);
6789

src/ignore/mod.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,16 @@ pub fn run(cmd: IgnoreCommand) -> Result<()> {
3535
}
3636
}
3737

38-
fn add(templates: &str, _yes: bool, _force: bool, dry_run: bool) -> Result<()> {
38+
fn add(templates: &str, _yes: bool, force: bool, dry_run: bool) -> Result<()> {
3939
let root = find_repo_root()?;
4040
let path = root.join(".gitignore");
4141

4242
let new_content = resolve_templates(templates)?;
43-
let merged = merge_gitignore(&path, &new_content);
43+
let merged = if force {
44+
new_content.clone()
45+
} else {
46+
merge_gitignore(&path, &new_content)
47+
};
4448

4549
if dry_run {
4650
println!("[dry-run] Would write .gitignore:\n{merged}");
@@ -80,6 +84,12 @@ fn resolve_templates(templates: &str) -> Result<String> {
8084
.context("Failed to fetch gitignore templates")?
8185
.into_string()
8286
.context("Failed to read response")?;
87+
if fetched.trim().is_empty() {
88+
anyhow::bail!(
89+
"No templates found for: {}. Run 'gitkit ignore list' to see available templates.",
90+
joined
91+
);
92+
}
8393
output.push_str(&fetched);
8494
}
8595

0 commit comments

Comments
 (0)