fix(hooks): improve uninstall safety with jq and better fallback handling
This commit is contained in:
+54
-10
@@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
"github.com/alecthomas/kong"
|
||||||
"github.com/carlosarraes/shush/internal/config"
|
"github.com/carlosarraes/shush/internal/config"
|
||||||
@@ -111,7 +112,7 @@ func showLLMGuide() {
|
|||||||
fmt.Print(`# Shush CLI - LLM Guide
|
fmt.Print(`# Shush CLI - LLM Guide
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
Shush is a fast comment removal tool for source code files using sed under the hood.
|
Shush is a fast comment removal tool for source code files using in-memory processing.
|
||||||
- **Purpose**: Remove comments from source code while preserving file structure
|
- **Purpose**: Remove comments from source code while preserving file structure
|
||||||
- **Key Strength**: Processes individual files or entire directories with recursive support
|
- **Key Strength**: Processes individual files or entire directories with recursive support
|
||||||
- **LLM-Friendly**: Supports dry-run mode with colored preview for safe operation
|
- **LLM-Friendly**: Supports dry-run mode with colored preview for safe operation
|
||||||
@@ -210,7 +211,7 @@ shush src/ -r --inline --backup # Apply line comment removal
|
|||||||
### Verbose Mode (--verbose)
|
### Verbose Mode (--verbose)
|
||||||
- **File discovery**: Shows which files found and processed
|
- **File discovery**: Shows which files found and processed
|
||||||
- **Language detection**: Displays detected language per file
|
- **Language detection**: Displays detected language per file
|
||||||
- **Command execution**: Shows sed commands being run
|
- **Processing details**: Shows in-memory processing operations
|
||||||
- **Progress tracking**: File-by-file processing status
|
- **Progress tracking**: File-by-file processing status
|
||||||
|
|
||||||
### Backup Mode (--backup)
|
### Backup Mode (--backup)
|
||||||
@@ -393,14 +394,30 @@ func uninstallHooks(scope string) error {
|
|||||||
return fmt.Errorf("failed to load settings: %w", err)
|
return fmt.Errorf("failed to load settings: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scopeName := "user-wide"
|
||||||
|
if hookScope == hooks.ScopeProject {
|
||||||
|
scopeName = "project"
|
||||||
|
}
|
||||||
|
|
||||||
if !hooks.HasShushHook(settings) {
|
if !hooks.HasShushHook(settings) {
|
||||||
scopeName := "user-wide"
|
|
||||||
if hookScope == hooks.ScopeProject {
|
|
||||||
scopeName = "project"
|
|
||||||
}
|
|
||||||
return fmt.Errorf("shush hook not found for %s scope at %s", scopeName, path)
|
return fmt.Errorf("shush hook not found for %s scope at %s", scopeName, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if _, err := exec.LookPath("jq"); err == nil {
|
||||||
|
|
||||||
|
if err := uninstallWithJQ(path, scopeName); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("⚠️ jq removal failed, using Go implementation\n")
|
||||||
|
} else {
|
||||||
|
|
||||||
|
fmt.Printf("⚠️ jq not available. For surgical removal, install jq and run again.\n")
|
||||||
|
fmt.Printf(" Manual removal: edit %s and remove shush hook entries\n", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if err := hooks.RemoveShushHook(settings); err != nil {
|
if err := hooks.RemoveShushHook(settings); err != nil {
|
||||||
return fmt.Errorf("failed to remove shush hook: %w", err)
|
return fmt.Errorf("failed to remove shush hook: %w", err)
|
||||||
}
|
}
|
||||||
@@ -409,14 +426,41 @@ func uninstallHooks(scope string) error {
|
|||||||
return fmt.Errorf("failed to save settings: %w", err)
|
return fmt.Errorf("failed to save settings: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
scopeName := "user-wide"
|
|
||||||
if hookScope == hooks.ScopeProject {
|
|
||||||
scopeName = "project"
|
|
||||||
}
|
|
||||||
fmt.Printf("✓ Hooks uninstalled for %s scope at %s\n", scopeName, path)
|
fmt.Printf("✓ Hooks uninstalled for %s scope at %s\n", scopeName, path)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func uninstallWithJQ(path, scopeName string) error {
|
||||||
|
|
||||||
|
jqFilter := `
|
||||||
|
.hooks.PostToolUse |= (
|
||||||
|
map(
|
||||||
|
.hooks |= map(select(.command != "shush --changes-only"))
|
||||||
|
) |
|
||||||
|
map(select(.hooks | length > 0))
|
||||||
|
) |
|
||||||
|
if .hooks.PostToolUse | length == 0 then
|
||||||
|
.hooks |= del(.PostToolUse)
|
||||||
|
else
|
||||||
|
.
|
||||||
|
end
|
||||||
|
`
|
||||||
|
|
||||||
|
cmd := exec.Command("jq", jqFilter, path)
|
||||||
|
output, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("jq command failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if err := os.WriteFile(path, output, 0644); err != nil {
|
||||||
|
return fmt.Errorf("failed to write updated settings: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("✓ Hooks uninstalled for %s scope at %s (using jq)\n", scopeName, path)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func showHooksStatus() error {
|
func showHooksStatus() error {
|
||||||
userPath, _ := hooks.GetSettingsPath(hooks.ScopeUser)
|
userPath, _ := hooks.GetSettingsPath(hooks.ScopeUser)
|
||||||
projectPath, _ := hooks.GetSettingsPath(hooks.ScopeProject)
|
projectPath, _ := hooks.GetSettingsPath(hooks.ScopeProject)
|
||||||
|
|||||||
Reference in New Issue
Block a user