refactor: remove unused bd pin/unpin/hook commands (bd-x0zl)

Analysis found these commands are dead code:
- gt never calls `bd pin` - uses `bd update --status=pinned` instead
- Beads.Pin() wrapper exists but is never called
- bd hook functionality duplicated by gt mol status
- Code comment says "pinned field is cosmetic for bd hook visibility"

Removed:
- cmd/bd/pin.go
- cmd/bd/unpin.go
- cmd/bd/hook.go

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-27 16:02:15 -08:00
parent c8b912cbe6
commit 1611f16751
178 changed files with 10291 additions and 1682 deletions

View File

@@ -48,10 +48,10 @@ func TestMain(m *testing.M) {
fmt.Fprintf(os.Stderr, "Failed to build bd binary: %v\n%s\n", err, out)
os.Exit(1)
}
// Optimize git for tests
os.Setenv("GIT_CONFIG_NOSYSTEM", "1")
os.Exit(m.Run())
}
@@ -85,35 +85,35 @@ func TestHashIDs_MultiCloneConverge(t *testing.T) {
}
t.Parallel()
tmpDir := testutil.TempDirInMemory(t)
bdPath := getBDPath()
if _, err := os.Stat(bdPath); err != nil {
t.Fatalf("bd binary not found at %s", bdPath)
}
// Setup remote and 3 clones
remoteDir := setupBareRepo(t, tmpDir)
cloneA := setupClone(t, tmpDir, remoteDir, "A", bdPath)
cloneB := setupClone(t, tmpDir, remoteDir, "B", bdPath)
cloneC := setupClone(t, tmpDir, remoteDir, "C", bdPath)
// Each clone creates unique issue (different content = different hash ID)
createIssueInClone(t, cloneA, "Issue from clone A")
createIssueInClone(t, cloneB, "Issue from clone B")
createIssueInClone(t, cloneC, "Issue from clone C")
// Sync all clones once (hash IDs prevent collisions, don't need multiple rounds)
for _, clone := range []string{cloneA, cloneB, cloneC} {
runCmdOutputWithEnvAllowError(t, clone, map[string]string{"BEADS_NO_DAEMON": "1"}, true, bdPath, "sync")
}
// Verify all clones have all 3 issues
expectedTitles := map[string]bool{
"Issue from clone A": true,
"Issue from clone B": true,
"Issue from clone C": true,
}
allConverged := true
for name, dir := range map[string]string{"A": cloneA, "B": cloneB, "C": cloneC} {
titles := getTitlesFromClone(t, dir)
@@ -122,7 +122,7 @@ func TestHashIDs_MultiCloneConverge(t *testing.T) {
allConverged = false
}
}
if allConverged {
t.Log("✓ All 3 clones converged with hash-based IDs")
} else {
@@ -138,26 +138,26 @@ func TestHashIDs_IdenticalContentDedup(t *testing.T) {
}
t.Parallel()
tmpDir := testutil.TempDirInMemory(t)
bdPath := getBDPath()
if _, err := os.Stat(bdPath); err != nil {
t.Fatalf("bd binary not found at %s", bdPath)
}
// Setup remote and 2 clones
remoteDir := setupBareRepo(t, tmpDir)
cloneA := setupClone(t, tmpDir, remoteDir, "A", bdPath)
cloneB := setupClone(t, tmpDir, remoteDir, "B", bdPath)
// Both clones create identical issue (same content = same hash ID)
createIssueInClone(t, cloneA, "Identical issue")
createIssueInClone(t, cloneB, "Identical issue")
// Sync both clones once (hash IDs handle dedup automatically)
for _, clone := range []string{cloneA, cloneB} {
runCmdOutputWithEnvAllowError(t, clone, map[string]string{"BEADS_NO_DAEMON": "1"}, true, bdPath, "sync")
}
// Verify both clones have exactly 1 issue (deduplication worked)
for name, dir := range map[string]string{"A": cloneA, "B": cloneB} {
titles := getTitlesFromClone(t, dir)
@@ -168,7 +168,7 @@ func TestHashIDs_IdenticalContentDedup(t *testing.T) {
t.Errorf("Clone %s missing expected issue: %v", name, sortedKeys(titles))
}
}
t.Log("✓ Identical content deduplicated correctly with hash-based IDs")
}
@@ -177,36 +177,36 @@ func TestHashIDs_IdenticalContentDedup(t *testing.T) {
func setupBareRepo(t *testing.T, tmpDir string) string {
t.Helper()
remoteDir := filepath.Join(tmpDir, "remote.git")
runCmd(t, tmpDir, "git", "init", "--bare", remoteDir)
runCmd(t, tmpDir, "git", "init", "--bare", "-b", "master", remoteDir)
tempClone := filepath.Join(tmpDir, "temp-init")
runCmd(t, tmpDir, "git", "clone", remoteDir, tempClone)
runCmd(t, tempClone, "git", "commit", "--allow-empty", "-m", "Initial commit")
runCmd(t, tempClone, "git", "push", "origin", "master")
return remoteDir
}
func setupClone(t *testing.T, tmpDir, remoteDir, name, bdPath string) string {
t.Helper()
cloneDir := filepath.Join(tmpDir, "clone-"+strings.ToLower(name))
// Use shallow, shared clones for speed
runCmd(t, tmpDir, "git", "clone", "--shared", "--depth=1", "--no-tags", remoteDir, cloneDir)
// Disable hooks to avoid overhead
emptyHooks := filepath.Join(cloneDir, ".empty-hooks")
os.MkdirAll(emptyHooks, 0755)
runCmd(t, cloneDir, "git", "config", "core.hooksPath", emptyHooks)
// Speed configs
runCmd(t, cloneDir, "git", "config", "gc.auto", "0")
runCmd(t, cloneDir, "git", "config", "core.fsync", "false")
runCmd(t, cloneDir, "git", "config", "commit.gpgSign", "false")
bdCmd := getBDCommand()
copyFile(t, bdPath, filepath.Join(cloneDir, filepath.Base(bdCmd)))
if name == "A" {
runCmd(t, cloneDir, bdCmd, "init", "--quiet", "--prefix", "test")
runCmd(t, cloneDir, "git", "add", ".beads")
@@ -216,7 +216,7 @@ func setupClone(t *testing.T, tmpDir, remoteDir, name, bdPath string) string {
runCmd(t, cloneDir, "git", "pull", "origin", "master")
runCmd(t, cloneDir, bdCmd, "init", "--quiet", "--prefix", "test")
}
return cloneDir
}
@@ -231,13 +231,13 @@ func getTitlesFromClone(t *testing.T, cloneDir string) map[string]bool {
"BEADS_NO_DAEMON": "1",
"BD_NO_AUTO_IMPORT": "1",
}, getBDCommand(), "list", "--json")
jsonStart := strings.Index(listJSON, "[")
if jsonStart == -1 {
return make(map[string]bool)
}
listJSON = listJSON[jsonStart:]
var issues []struct {
Title string `json:"title"`
}
@@ -245,7 +245,7 @@ func getTitlesFromClone(t *testing.T, cloneDir string) map[string]bool {
t.Logf("Failed to parse JSON: %v", err)
return make(map[string]bool)
}
titles := make(map[string]bool)
for _, issue := range issues {
titles[issue.Title] = true
@@ -280,7 +280,7 @@ func installGitHooks(t *testing.T, repoDir string) {
hooksDir := filepath.Join(repoDir, ".git", "hooks")
// Ensure POSIX-style path for sh scripts (even on Windows)
bdCmd := strings.ReplaceAll(getBDCommand(), "\\", "/")
preCommit := fmt.Sprintf(`#!/bin/sh
%s --no-daemon export -o .beads/issues.jsonl >/dev/null 2>&1 || true
git add .beads/issues.jsonl >/dev/null 2>&1 || true

View File

@@ -5,6 +5,8 @@ import (
"os/exec"
"path/filepath"
"testing"
"github.com/steveyegge/beads/internal/git"
)
func TestFindDatabasePathEnvVar(t *testing.T) {
@@ -821,6 +823,7 @@ func TestFindGitRoot_RegularRepo(t *testing.T) {
}
t.Chdir(subDir)
git.ResetCaches() // Reset after chdir for caching tests
// findGitRoot should return the repo root
result := findGitRoot()
@@ -897,6 +900,7 @@ func TestFindGitRoot_Worktree(t *testing.T) {
// Change to the worktree directory
t.Chdir(worktreeDir)
git.ResetCaches() // Reset after chdir for caching tests
// findGitRoot should return the WORKTREE root, not the main repo root
result := findGitRoot()
@@ -927,6 +931,7 @@ func TestFindGitRoot_NotGitRepo(t *testing.T) {
defer os.RemoveAll(tmpDir)
t.Chdir(tmpDir)
git.ResetCaches() // Reset after chdir for caching tests
// findGitRoot should return empty string
result := findGitRoot()
@@ -1024,6 +1029,7 @@ func TestFindBeadsDir_Worktree(t *testing.T) {
// Change to worktree
t.Chdir(worktreeDir)
git.ResetCaches() // Reset after chdir for caching tests
// FindBeadsDir should prioritize the main repo's .beads for worktrees (bd-de6)
result := FindBeadsDir()
@@ -1134,6 +1140,7 @@ func TestFindDatabasePath_Worktree(t *testing.T) {
t.Fatal(err)
}
t.Chdir(worktreeSubDir)
git.ResetCaches() // Reset after chdir for caching tests
// FindDatabasePath should find the main repo's shared database
result := FindDatabasePath()
@@ -1241,6 +1248,7 @@ func TestFindDatabasePath_WorktreeNoLocalDB(t *testing.T) {
// Change to worktree
t.Chdir(worktreeDir)
git.ResetCaches() // Reset after chdir for caching tests
// FindDatabasePath should find the main repo's shared database
result := FindDatabasePath()