diff options
| author | Paul Buetow <paul@buetow.org> | 2025-06-27 23:05:10 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-06-27 23:05:10 +0300 |
| commit | 59d7b258cff47b0640f44f1068460403459a4bde (patch) | |
| tree | e6f4021682f5379628ac964bcf701cf51be2c49a /internal/sync | |
| parent | ab401decdae831009b1edef6e2d7338d5720929d (diff) | |
feat: add detailed error message for tag conflicts
Diffstat (limited to 'internal/sync')
| -rw-r--r-- | internal/sync/git_operations.go | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/internal/sync/git_operations.go b/internal/sync/git_operations.go index b5f3016..560a59c 100644 --- a/internal/sync/git_operations.go +++ b/internal/sync/git_operations.go @@ -1,8 +1,10 @@ package sync import ( + "bytes" "fmt" "os/exec" + "regexp" "strings" ) @@ -127,14 +129,59 @@ func fetchRemote(remote string) error { output, err := cmd.CombinedOutput() if err != nil { + // Check if it's a tag conflict error + if bytes.Contains(output, []byte("would clobber existing tag")) { + return handleTagConflict(remote, output) + } + // Check if it's because the repository doesn't exist if isRepositoryMissing(string(output)) { fmt.Printf(" Warning: Remote repository %s does not exist yet\n", remote) return nil // Not an error, just skip } return fmt.Errorf("failed to fetch from %s: %w\n%s", remote, err, string(output)) - } - return nil + } + return nil +} + +// handleTagConflict provides a detailed error message for tag conflicts. +func handleTagConflict(remote string, output []byte) error { + var conflictDetails strings.Builder + conflictDetails.WriteString("tag conflict detected while fetching from remote: ") + conflictDetails.WriteString(remote) + + // Regex to find tag names from error output + re := regexp.MustCompile(`! \[rejected\]\s+([^\s]+)`) + matches := re.FindAllSubmatch(output, -1) + + for _, match := range matches { + if len(match) > 1 { + tag := string(match[1]) + localHash, _ := getTagCommitHash(tag, "local") + remoteHash, _ := getTagCommitHash(tag, remote) + conflictDetails.WriteString(fmt.Sprintf("\n - Tag: %s\n Local: %s\n Remote: %s", tag, localHash, remoteHash)) + } + } + + return fmt.Errorf(conflictDetails.String()) +} + +// getTagCommitHash retrieves the commit hash for a given tag, either locally or from a remote. +func getTagCommitHash(tag, source string) (string, error) { + var cmd *exec.Cmd + if source == "local" { + cmd = exec.Command("git", "rev-parse", tag+"^{\\}") + } else { + cmd = exec.Command("git", "ls-remote", "--tags", source, tag) + } + + output, err := cmd.Output() + if err != nil { + return "", err + } + + hash := strings.Fields(string(output))[0] + return hash, nil } // checkoutExistingBranch tries to checkout an existing branch |
