Fix linter issues and test failures

- Fix spelling: cancelled → canceled, cancelling → canceling
- Remove unused error return from performFlush() function
- Check cmd.Help() error return in search.go
- Fix file permissions in gitignore.go (0644 → 0600)
- Update tests to match performFlush signature change
- Remove unused os import from flush_manager.go
This commit is contained in:
Steve Yegge
2025-11-22 00:11:45 -08:00
parent 7009acb169
commit b409870ce5
6 changed files with 67 additions and 83 deletions

File diff suppressed because one or more lines are too long

View File

@@ -165,7 +165,7 @@ func applyFixes(result doctorResult) {
response = strings.TrimSpace(strings.ToLower(response)) response = strings.TrimSpace(strings.ToLower(response))
if response != "" && response != "y" && response != "yes" { if response != "" && response != "y" && response != "yes" {
fmt.Println("Fix cancelled.") fmt.Println("Fix canceled.")
return return
} }

View File

@@ -94,8 +94,8 @@ func CheckGitignore() DoctorCheck {
func FixGitignore() error { func FixGitignore() error {
gitignorePath := filepath.Join(".beads", ".gitignore") gitignorePath := filepath.Join(".beads", ".gitignore")
// Write canonical template with standard git file permissions (world-readable) // Write canonical template with secure file permissions
if err := os.WriteFile(gitignorePath, []byte(GitignoreTemplate), 0644); err != nil { if err := os.WriteFile(gitignorePath, []byte(GitignoreTemplate), 0600); err != nil {
return err return err
} }

View File

@@ -3,7 +3,6 @@ package main
import ( import (
"context" "context"
"fmt" "fmt"
"os"
"sync" "sync"
"time" "time"
) )
@@ -136,7 +135,7 @@ func (fm *FlushManager) Shutdown() error {
var shutdownErr error var shutdownErr error
fm.shutdownOnce.Do(func() { fm.shutdownOnce.Do(func() {
// Send shutdown request FIRST (before cancelling context) // Send shutdown request FIRST (before canceling context)
// This ensures the run() loop processes the shutdown request // This ensures the run() loop processes the shutdown request
responseCh := make(chan error, 1) responseCh := make(chan error, 1)
select { select {
@@ -209,16 +208,11 @@ func (fm *FlushManager) run() {
case <-fm.timerFiredCh: case <-fm.timerFiredCh:
// Debounce timer fired - flush if dirty // Debounce timer fired - flush if dirty
if isDirty { if isDirty {
err := fm.performFlush(needsFullExport) fm.performFlush(needsFullExport)
if err != nil { // Clear dirty flags after flush
// Log error from timer-triggered flush
fmt.Fprintf(os.Stderr, "Warning: auto-flush timer failed: %v\n", err)
} else {
// Clear dirty flags after successful flush
isDirty = false isDirty = false
needsFullExport = false needsFullExport = false
} }
}
case responseCh := <-fm.flushNowCh: case responseCh := <-fm.flushNowCh:
// Immediate flush requested // Immediate flush requested
@@ -234,13 +228,11 @@ func (fm *FlushManager) run() {
} }
// Perform the flush // Perform the flush
err := fm.performFlush(needsFullExport) fm.performFlush(needsFullExport)
if err == nil { // Clear dirty flags
// Success - clear dirty flags
isDirty = false isDirty = false
needsFullExport = false needsFullExport = false
} responseCh <- nil
responseCh <- err
case req := <-fm.shutdownCh: case req := <-fm.shutdownCh:
// Shutdown requested // Shutdown requested
@@ -249,16 +241,15 @@ func (fm *FlushManager) run() {
} }
// Perform final flush if dirty // Perform final flush if dirty
var err error
if isDirty { if isDirty {
err = fm.performFlush(needsFullExport) fm.performFlush(needsFullExport)
} }
req.responseCh <- err req.responseCh <- nil
return // Exit goroutine return // Exit goroutine
case <-fm.ctx.Done(): case <-fm.ctx.Done():
// Context cancelled (shouldn't normally happen) // Context canceled (shouldn't normally happen)
return return
} }
} }
@@ -266,12 +257,12 @@ func (fm *FlushManager) run() {
// performFlush executes the actual flush operation. // performFlush executes the actual flush operation.
// Called only from the run() goroutine, so no concurrency issues. // Called only from the run() goroutine, so no concurrency issues.
func (fm *FlushManager) performFlush(fullExport bool) error { func (fm *FlushManager) performFlush(fullExport bool) {
// Check if store is still active // Check if store is still active
storeMutex.Lock() storeMutex.Lock()
if !storeActive { if !storeActive {
storeMutex.Unlock() storeMutex.Unlock()
return nil // Store closed, nothing to do return // Store closed, nothing to do
} }
storeMutex.Unlock() storeMutex.Unlock()
@@ -281,6 +272,4 @@ func (fm *FlushManager) performFlush(fullExport bool) error {
forceDirty: true, // We know we're dirty (we wouldn't be here otherwise) forceDirty: true, // We know we're dirty (we wouldn't be here otherwise)
forceFullExport: fullExport, forceFullExport: fullExport,
}) })
return nil
} }

View File

@@ -437,15 +437,12 @@ func TestPerformFlushErrorHandling(t *testing.T) {
} }
}() }()
// performFlush with inactive store should return nil (graceful degradation) // performFlush with inactive store should handle gracefully (no return value)
storeMutex.Lock() storeMutex.Lock()
storeActive = false storeActive = false
storeMutex.Unlock() storeMutex.Unlock()
err := fm.performFlush(false) fm.performFlush(false) // Should not panic
if err != nil {
t.Errorf("performFlush should return nil when store inactive, got: %v", err)
}
// Restore store for cleanup // Restore store for cleanup
storeMutex.Lock() storeMutex.Lock()
@@ -470,16 +467,10 @@ func TestPerformFlushStoreInactive(t *testing.T) {
storeActive = false storeActive = false
storeMutex.Unlock() storeMutex.Unlock()
// performFlush should handle this gracefully // performFlush should handle this gracefully (no return value)
err := fm.performFlush(false) fm.performFlush(false) // Should not panic
if err != nil {
t.Errorf("Expected performFlush to handle inactive store gracefully, got error: %v", err)
}
err = fm.performFlush(true) // Try full export too fm.performFlush(true) // Try full export too - should not panic
if err != nil {
t.Errorf("Expected performFlush (full) to handle inactive store gracefully, got error: %v", err)
}
// Restore store for cleanup // Restore store for cleanup
storeMutex.Lock() storeMutex.Lock()

View File

@@ -41,10 +41,9 @@ Examples:
// If no query provided, show help // If no query provided, show help
if query == "" { if query == "" {
fmt.Fprintf(os.Stderr, "Error: search query is required\n") fmt.Fprintf(os.Stderr, "Error: search query is required\n")
// #nosec G104 -- cmd.Help() error intentionally ignored. We're already in an if err := cmd.Help(); err != nil {
// error path (missing query) and will exit(1) regardless. Help() errors are fmt.Fprintf(os.Stderr, "Error displaying help: %v\n", err)
// rare (I/O failures) and don't affect the outcome. See TestSearchCommand_HelpErrorHandling }
cmd.Help()
os.Exit(1) os.Exit(1)
} }