summaryrefslogtreecommitdiff
path: root/internal/sync
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-06-27 23:05:10 +0300
committerPaul Buetow <paul@buetow.org>2025-06-27 23:05:10 +0300
commit59d7b258cff47b0640f44f1068460403459a4bde (patch)
treee6f4021682f5379628ac964bcf701cf51be2c49a /internal/sync
parentab401decdae831009b1edef6e2d7338d5720929d (diff)
feat: add detailed error message for tag conflicts
Diffstat (limited to 'internal/sync')
-rw-r--r--internal/sync/git_operations.go51
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