diff options
| author | Paul Buetow <paul@buetow.org> | 2025-06-23 23:38:55 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-06-23 23:38:55 +0300 |
| commit | 42d3df9fe18663f5c6f7067b964f0b09071910e6 (patch) | |
| tree | fff4b4708115caa29c4daadc1444e02ab14c41b7 /internal/sync/sync.go | |
| parent | 006724744a943aad877a92406a5e2b4d5d12acd3 (diff) | |
Add debugging features and improve error handling
- Add --test-github-token flag to validate GitHub authentication
- Improve error messages for 401 authentication failures
- Add merge conflict detection before sync attempts
- Stop sync on first error for easier debugging
- Add GitHub repo creation support for --sync and --sync-all commands
- Add detailed token loading debug output
- Create test script for GitHub token validation
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'internal/sync/sync.go')
| -rw-r--r-- | internal/sync/sync.go | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/internal/sync/sync.go b/internal/sync/sync.go index 7f9b81e..a22089d 100644 --- a/internal/sync/sync.go +++ b/internal/sync/sync.go @@ -250,6 +250,35 @@ func (s *Syncer) getAllBranches() ([]string, error) { // syncBranch synchronizes a specific branch across all remotes func (s *Syncer) syncBranch(branch string, remotes map[string]*config.Organization) error { + // First check if we have unresolved merge conflicts + cmd := exec.Command("git", "status", "--porcelain") + output, err := cmd.Output() + if err == nil && len(output) > 0 { + // Check for merge conflicts + statusStr := string(output) + if strings.Contains(statusStr, "UU ") || strings.Contains(statusStr, "AA ") || strings.Contains(statusStr, "DD ") { + // Get the repo name from the work directory + repoName := filepath.Base(s.workDir) + if repoName == ".gitsyncer-work" || repoName == "" { + // If we're in the work directory itself, extract from current directory + cmd := exec.Command("git", "rev-parse", "--show-toplevel") + if output, err := cmd.Output(); err == nil { + repoName = filepath.Base(strings.TrimSpace(string(output))) + } + } + return fmt.Errorf("repository has unresolved merge conflicts - please resolve manually or delete %s", s.workDir) + } + // If we have uncommitted changes but no conflicts, try to stash them + fmt.Println(" Stashing uncommitted changes...") + if err := exec.Command("git", "stash", "push", "-m", "gitsyncer-auto-stash").Run(); err != nil { + return fmt.Errorf("failed to stash changes: %w", err) + } + defer func() { + // Try to pop the stash at the end + exec.Command("git", "stash", "pop").Run() + }() + } + // Create or checkout the branch if err := s.checkoutBranch(branch); err != nil { return fmt.Errorf("failed to checkout branch %s: %w", branch, err) @@ -333,9 +362,14 @@ func (s *Syncer) syncBranch(branch string, remotes map[string]*config.Organizati func (s *Syncer) checkoutBranch(branch string) error { // First try to checkout existing branch cmd := exec.Command("git", "checkout", branch) - if err := cmd.Run(); err == nil { + output, err := cmd.CombinedOutput() + if err == nil { return nil } + + // If checkout failed, check the error + outputStr := string(output) + fmt.Printf(" Initial checkout failed: %s\n", strings.TrimSpace(outputStr)) // If that fails, create a new branch tracking the first remote that has it for i := range s.config.Organizations { @@ -344,7 +378,11 @@ func (s *Syncer) checkoutBranch(branch string) error { if s.remoteBranchExists(remoteName, branch) { cmd = exec.Command("git", "checkout", "-b", branch, fmt.Sprintf("%s/%s", remoteName, branch)) - return cmd.Run() + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("failed to create tracking branch: %s", string(output)) + } + return nil } } |
