Skip to content

Commit e558316

Browse files
committed
fix(git): limit git hooks to staged files only
Fix to limit git hooks to staged files only, preventing post-commit unstaged changes - Update stage_changes() in common.sh to accept specific file lists for targeted staging - Modify 10-format-code to only format files that were originally staged for commit - Update 20-lint-markdown to only auto-fix staged markdown files, not entire codebase - Prevent hooks from processing whole project and leaving unexpected unstaged changes - Maintain project-wide consistency checks while limiting automated modifications scope InfoSec: Reduces automated file modification scope during git operations, improving workflow security and predictability
1 parent aeb56b0 commit e558316

File tree

3 files changed

+127
-47
lines changed

3 files changed

+127
-47
lines changed

adhoc/git/hooks/10-format-code

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,50 +7,70 @@
77
echo " 🎨 Formatting code..."
88
files_changed=false
99

10-
# Format TypeScript/JavaScript with Deno
10+
# Get list of staged files to limit formatting scope
11+
staged_files=$(git diff --cached --name-only)
12+
if [ -z "$staged_files" ]; then
13+
log_info "No staged files to format"
14+
exit 0
15+
fi
16+
17+
log_info "Staged files: $(echo $staged_files | tr '\n' ' ')"
18+
19+
# Format with Deno (includes TypeScript, JavaScript, Markdown, JSON)
1120
if command -v deno >/dev/null 2>&1; then
1221
log_info "Formatting with deno fmt..."
13-
# Use deno fmt without --ext to respect deno.json configuration
14-
if deno fmt; then
15-
# Check if any supported files were modified (deno handles exclusions)
16-
if files_modified '*.ts *.js *.tsx *.jsx *.md *.json *.jsonc'; then
17-
files_changed=true
18-
log_success "Files formatted with Deno"
22+
23+
# Filter staged files for Deno-supported extensions
24+
deno_files=$(echo "$staged_files" | grep -E '\.(ts|js|tsx|jsx|md|json|jsonc)$' || true)
25+
26+
if [ -n "$deno_files" ]; then
27+
# Format only the staged files
28+
if echo "$deno_files" | xargs deno fmt; then
29+
# Check if any of the staged files were modified by formatting
30+
for file in $deno_files; do
31+
if [ -f "$file" ] && ! git diff --quiet HEAD -- "$file" 2>/dev/null; then
32+
files_changed=true
33+
break
34+
fi
35+
done
36+
37+
if [ "$files_changed" = true ]; then
38+
log_success "Staged files formatted with Deno"
39+
else
40+
log_info "Staged files already formatted"
41+
fi
1942
else
20-
log_info "Files already formatted"
43+
log_error "deno fmt failed"
44+
exit 1
2145
fi
2246
else
23-
log_error "deno fmt failed"
24-
exit 1
47+
log_info "No Deno-supported files in staging area"
2548
fi
2649
elif [ -f "package.json" ] && command -v prettier >/dev/null 2>&1; then
27-
# Node.js project - use prettier for JS/TS
50+
# Fallback: Node.js project without Deno - use prettier
2851
log_info "Formatting with prettier..."
29-
if prettier --write '**/*.{js,ts,tsx,jsx}' --print-width=100 --semi --single-quote=false; then
30-
if files_modified '*.js *.ts *.tsx *.jsx'; then
31-
files_changed=true
32-
log_success "JavaScript/TypeScript formatted"
33-
fi
34-
fi
35-
fi
36-
37-
# For Deno projects, skip separate markdown formatting since deno fmt handles it
38-
# Only do separate markdown formatting for non-Deno projects
39-
if ! command -v deno >/dev/null 2>&1; then
40-
# Format Markdown with Prettier (only if not a Deno project)
41-
if command -v prettier >/dev/null 2>&1; then
42-
log_info "Formatting Markdown..."
43-
if prettier --write '**/*.md' --print-width=100 --prose-wrap=preserve; then
44-
if files_modified '*.md'; then
45-
files_changed=true
46-
log_success "Markdown formatted"
47-
else
48-
log_info "Markdown already formatted"
52+
53+
# Filter staged files for Prettier-supported extensions
54+
prettier_files=$(echo "$staged_files" | grep -E '\.(js|ts|tsx|jsx|md)$' || true)
55+
56+
if [ -n "$prettier_files" ]; then
57+
if echo "$prettier_files" | xargs prettier --write --print-width=120 --prose-wrap=preserve; then
58+
for file in $prettier_files; do
59+
if [ -f "$file" ] && ! git diff --quiet HEAD -- "$file" 2>/dev/null; then
60+
files_changed=true
61+
break
62+
fi
63+
done
64+
65+
if [ "$files_changed" = true ]; then
66+
log_success "Staged files formatted with Prettier"
4967
fi
5068
fi
5169
else
52-
log_warn "prettier not found - install with: brew install prettier"
70+
log_info "No Prettier-supported files in staging area"
5371
fi
72+
else
73+
log_warn "Neither deno nor prettier found - install deno for best experience"
5474
fi
5575

5676
# Format other languages based on project type
@@ -87,9 +107,9 @@ case "$(detect_project_type)" in
87107
;;
88108
esac
89109

90-
# Stage any changes
110+
# Stage any changes (only for the originally staged files)
91111
if [ "$files_changed" = true ]; then
92-
stage_changes
112+
stage_changes "$staged_files"
93113
fi
94114

95-
exit 0
115+
exit 0

adhoc/git/hooks/20-lint-markdown

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,54 @@
55

66
echo " 🔍 Linting Markdown..."
77

8+
# Get list of staged files to limit linting scope
9+
staged_files=$(git diff --cached --name-only)
10+
if [ -z "$staged_files" ]; then
11+
log_info "No staged files to lint"
12+
exit 0
13+
fi
14+
15+
# Filter for markdown files only
16+
md_files=$(echo "$staged_files" | grep '\.md$' || true)
17+
if [ -z "$md_files" ]; then
18+
log_info "No markdown files in staging area"
19+
exit 0
20+
fi
21+
22+
log_info "Staged markdown files: $(echo $md_files | tr '\n' ' ')"
23+
824
if command -v markdownlint-cli2 >/dev/null 2>&1; then
9-
if markdownlint-cli2 '**/*.md' --config='{"MD013":{"line_length":100,"code_blocks":false},"MD033":false,"MD041":false}'; then
10-
log_success "Markdown linting passed"
25+
# Auto-fix simple markdown issues for staged files only
26+
log_info "Auto-fixing markdown issues..."
27+
if echo "$md_files" | xargs markdownlint-cli2 --fix; then
28+
# Check if any staged files were modified by the fixes
29+
files_changed=false
30+
for file in $md_files; do
31+
if [ -f "$file" ] && ! git diff --quiet -- "$file" 2>/dev/null; then
32+
files_changed=true
33+
break
34+
fi
35+
done
36+
37+
if [ "$files_changed" = true ]; then
38+
log_success "Markdown issues auto-fixed"
39+
stage_changes "$md_files"
40+
fi
41+
42+
# Now run final linting check on all markdown files (for project consistency)
43+
if markdownlint-cli2 "**/*.md"; then
44+
log_success "Markdown linting passed"
45+
else
46+
log_error "Markdown linting failed - manual fixes needed"
47+
exit 1
48+
fi
1149
else
12-
log_error "Markdown linting failed"
50+
log_error "Markdown auto-fix failed"
1351
exit 1
1452
fi
1553
else
16-
log_warn "markdownlint-cli2 not found - install with: brew install markdownlint-cli2"
54+
log_warn "markdownlint-cli2 not found - install with: npm install -g markdownlint-cli2"
1755
log_info "Skipping markdown linting"
1856
fi
1957

20-
exit 0
58+
exit 0

adhoc/git/hooks/lib/common.sh

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,37 @@ files_modified() {
3535
fi
3636
}
3737

38-
# Stage modified files
38+
# Stage modified files (optionally for specific files only)
3939
stage_changes() {
40-
if files_modified; then
41-
git add -u
42-
log_success "Changes staged"
43-
return 0
40+
local files="$1" # Optional: specific files to stage
41+
42+
if [ -n "$files" ]; then
43+
# Stage only specific files if they were modified by formatting
44+
local files_to_stage=""
45+
for file in $files; do
46+
if [ -f "$file" ] && ! git diff --quiet -- "$file" 2>/dev/null; then
47+
files_to_stage="$files_to_stage $file"
48+
fi
49+
done
50+
51+
if [ -n "$files_to_stage" ]; then
52+
git add $files_to_stage
53+
log_success "Staged formatting changes: $files_to_stage"
54+
return 0
55+
else
56+
log_info "No formatting changes to stage"
57+
return 1
58+
fi
4459
else
45-
log_info "No files were modified"
46-
return 1
60+
# Original behavior: stage all modified tracked files
61+
if files_modified; then
62+
git add -u
63+
log_success "Changes staged"
64+
return 0
65+
else
66+
log_info "No files were modified"
67+
return 1
68+
fi
4769
fi
4870
}
4971

0 commit comments

Comments
 (0)