fix(init): bootstrap from sync-branch when configured (bd-0is)
When sync-branch is configured in config.yaml, bd init now reads from that branch (origin/<branch> first, then local <branch>) instead of HEAD. This ensures fresh clones correctly import issues from the sync branch. Key changes: - checkGitForIssues() now returns gitRef (third return value) - New getLocalSyncBranch() reads sync-branch directly from config.yaml (not cached global config) to handle test environments where CWD changes - importFromGit() accepts gitRef parameter to read from correct branch - Added readFirstIssueFromGit() for prefix auto-detection from git - Fixed macOS symlink issue: filepath.EvalSymlinks() ensures /var and /private/var paths are normalized before filepath.Rel() Part of GitHub issue #464 (beads deletes issues in multi-clone environments) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -89,9 +90,9 @@ With --stealth: configures global git settings for invisible beads usage:
|
||||
|
||||
// auto-detect prefix from first issue in JSONL file
|
||||
if prefix == "" {
|
||||
issueCount, jsonlPath := checkGitForIssues()
|
||||
issueCount, jsonlPath, gitRef := checkGitForIssues()
|
||||
if issueCount > 0 {
|
||||
firstIssue, err := readFirstIssueFromJSONL(jsonlPath)
|
||||
firstIssue, err := readFirstIssueFromGit(jsonlPath, gitRef)
|
||||
if firstIssue != nil && err == nil {
|
||||
prefix = utils.ExtractIssuePrefix(firstIssue.ID)
|
||||
}
|
||||
@@ -347,16 +348,16 @@ With --stealth: configures global git settings for invisible beads usage:
|
||||
}
|
||||
|
||||
// Check if git has existing issues to import (fresh clone scenario)
|
||||
issueCount, jsonlPath := checkGitForIssues()
|
||||
issueCount, jsonlPath, gitRef := checkGitForIssues()
|
||||
if issueCount > 0 {
|
||||
if !quiet {
|
||||
fmt.Fprintf(os.Stderr, "\n✓ Database initialized. Found %d issues in git, importing...\n", issueCount)
|
||||
}
|
||||
|
||||
if err := importFromGit(ctx, initDBPath, store, jsonlPath); err != nil {
|
||||
if err := importFromGit(ctx, initDBPath, store, jsonlPath, gitRef); err != nil {
|
||||
if !quiet {
|
||||
fmt.Fprintf(os.Stderr, "Warning: auto-import failed: %v\n", err)
|
||||
fmt.Fprintf(os.Stderr, "Try manually: git show HEAD:%s | bd import -i /dev/stdin\n", jsonlPath)
|
||||
fmt.Fprintf(os.Stderr, "Try manually: git show %s:%s | bd import -i /dev/stdin\n", gitRef, jsonlPath)
|
||||
}
|
||||
// Non-fatal - continue with empty database
|
||||
} else if !quiet {
|
||||
@@ -1208,6 +1209,41 @@ func readFirstIssueFromJSONL(path string) (*types.Issue, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// readFirstIssueFromGit reads the first issue from a git ref (bd-0is: supports sync-branch)
|
||||
func readFirstIssueFromGit(jsonlPath, gitRef string) (*types.Issue, error) {
|
||||
// Get content from git (use ToSlash for Windows compatibility)
|
||||
gitPath := filepath.ToSlash(jsonlPath)
|
||||
cmd := exec.Command("git", "show", fmt.Sprintf("%s:%s", gitRef, gitPath)) // #nosec G204
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read from git: %w", err)
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(bytes.NewReader(output))
|
||||
lineNum := 0
|
||||
for scanner.Scan() {
|
||||
lineNum++
|
||||
line := scanner.Text()
|
||||
|
||||
// skip empty lines
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
var issue types.Issue
|
||||
if err := json.Unmarshal([]byte(line), &issue); err == nil {
|
||||
return &issue, nil
|
||||
}
|
||||
// Skip malformed lines silently (called during auto-detection)
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, fmt.Errorf("error scanning git content: %w", err)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// setupStealthMode configures global git settings for stealth operation
|
||||
func setupStealthMode(verbose bool) error {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
|
||||
Reference in New Issue
Block a user