summaryrefslogtreecommitdiff
path: root/internal/sync/git_operations.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/sync/git_operations.go')
-rw-r--r--internal/sync/git_operations.go74
1 files changed, 41 insertions, 33 deletions
diff --git a/internal/sync/git_operations.go b/internal/sync/git_operations.go
index 0bd698e..62a530b 100644
--- a/internal/sync/git_operations.go
+++ b/internal/sync/git_operations.go
@@ -11,9 +11,17 @@ import (
"codeberg.org/snonux/gitsyncer/internal/config"
)
+func gitCommand(repoPath string, args ...string) *exec.Cmd {
+ cmd := exec.Command("git", args...)
+ if repoPath != "" {
+ cmd.Dir = repoPath
+ }
+ return cmd
+}
+
// checkForMergeConflicts checks if the repository has merge conflicts
-func checkForMergeConflicts() (bool, string, error) {
- cmd := exec.Command("git", "status", "--porcelain")
+func checkForMergeConflicts(repoPath string) (bool, string, error) {
+ cmd := gitCommand(repoPath, "status", "--porcelain")
output, err := cmd.Output()
if err != nil {
return false, "", err
@@ -28,21 +36,21 @@ func checkForMergeConflicts() (bool, string, error) {
}
// stashChanges stashes uncommitted changes
-func stashChanges() error {
+func stashChanges(repoPath string) error {
fmt.Println(" Stashing uncommitted changes...")
- return exec.Command("git", "stash", "push", "-m", "gitsyncer-auto-stash").Run()
+ return gitCommand(repoPath, "stash", "push", "-m", "gitsyncer-auto-stash").Run()
}
// popStash attempts to pop the stash (used in defer)
-func popStash() {
- exec.Command("git", "stash", "pop").Run()
+func popStash(repoPath string) {
+ gitCommand(repoPath, "stash", "pop").Run()
}
// mergeBranch merges a branch from a remote
-func mergeBranch(remoteName, branch string) error {
+func mergeBranch(repoPath, remoteName, branch string) error {
fmt.Printf(" Merging from %s/%s...\n", remoteName, branch)
- cmd := exec.Command("git", "merge", fmt.Sprintf("%s/%s", remoteName, branch), "--no-edit")
+ cmd := gitCommand(repoPath, "merge", fmt.Sprintf("%s/%s", remoteName, branch), "--no-edit")
output, err := cmd.CombinedOutput()
if err != nil {
@@ -57,8 +65,8 @@ func mergeBranch(remoteName, branch string) error {
}
// pushBranch pushes a branch to a remote
-func pushBranch(remoteName, branch string, remoteHasBranch bool) error {
- cmd := exec.Command("git", "push", remoteName, branch, "--tags")
+func pushBranch(repoPath, remoteName, branch string, remoteHasBranch bool) error {
+ cmd := gitCommand(repoPath, "push", remoteName, branch, "--tags")
output, err := cmd.CombinedOutput()
if err != nil {
@@ -74,7 +82,7 @@ func pushBranch(remoteName, branch string, remoteHasBranch bool) error {
if isBranchMissing(outputStr) {
fmt.Printf(" Creating new branch on %s\n", remoteName)
// Try again with -u flag to set upstream
- cmd = exec.Command("git", "push", "-u", remoteName, branch, "--tags")
+ cmd = gitCommand(repoPath, "push", "-u", remoteName, branch, "--tags")
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to push to %s: %w", remoteName, err)
}
@@ -103,8 +111,8 @@ func isBranchMissing(output string) bool {
}
// getRemotesList extracts unique remote names from git remote -v output
-func getRemotesList() (map[string]bool, error) {
- cmd := exec.Command("git", "remote", "-v")
+func getRemotesList(repoPath string) (map[string]bool, error) {
+ cmd := gitCommand(repoPath, "remote", "-v")
output, err := cmd.Output()
if err != nil {
return nil, fmt.Errorf("failed to list remotes: %w", err)
@@ -126,14 +134,14 @@ func getRemotesList() (map[string]bool, error) {
}
// fetchRemote fetches from a single remote with error handling
-func fetchRemote(remote string) error {
- cmd := exec.Command("git", "fetch", remote, "--prune", "--tags")
+func fetchRemote(repoPath, remote string) error {
+ cmd := gitCommand(repoPath, "fetch", remote, "--prune", "--tags")
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)
+ return handleTagConflict(repoPath, remote, output)
}
// Check if it's because the repository doesn't exist
@@ -147,7 +155,7 @@ func fetchRemote(remote string) error {
}
// handleTagConflict provides a detailed error message for tag conflicts.
-func handleTagConflict(remote string, output []byte) error {
+func handleTagConflict(repoPath, remote string, output []byte) error {
var conflictDetails strings.Builder
conflictDetails.WriteString("tag conflict detected while fetching from remote: ")
conflictDetails.WriteString(remote)
@@ -159,8 +167,8 @@ func handleTagConflict(remote string, output []byte) error {
for _, match := range matches {
if len(match) > 1 {
tag := string(match[1])
- localHash, _ := getTagCommitHash(tag, "local")
- remoteHash, _ := getTagCommitHash(tag, remote)
+ localHash, _ := getTagCommitHash(repoPath, tag, "local")
+ remoteHash, _ := getTagCommitHash(repoPath, tag, remote)
conflictDetails.WriteString(fmt.Sprintf("\n - Tag: %s\n Local: %s\n Remote: %s", tag, localHash, remoteHash))
}
}
@@ -169,12 +177,12 @@ func handleTagConflict(remote string, output []byte) error {
}
// getTagCommitHash retrieves the commit hash for a given tag, either locally or from a remote.
-func getTagCommitHash(tag, source string) (string, error) {
+func getTagCommitHash(repoPath, tag, source string) (string, error) {
var cmd *exec.Cmd
if source == "local" {
- cmd = exec.Command("git", "rev-parse", tag+"^{\\}")
+ cmd = gitCommand(repoPath, "rev-parse", tag+"^{\\}")
} else {
- cmd = exec.Command("git", "ls-remote", "--tags", source, tag)
+ cmd = gitCommand(repoPath, "ls-remote", "--tags", source, tag)
}
output, err := cmd.Output()
@@ -187,8 +195,8 @@ func getTagCommitHash(tag, source string) (string, error) {
}
// checkoutExistingBranch tries to checkout an existing branch
-func checkoutExistingBranch(branch string) error {
- cmd := exec.Command("git", "checkout", branch)
+func checkoutExistingBranch(repoPath, branch string) error {
+ cmd := gitCommand(repoPath, "checkout", branch)
output, err := cmd.CombinedOutput()
if err != nil {
fmt.Printf(" Initial checkout failed: %s\n", strings.TrimSpace(string(output)))
@@ -198,8 +206,8 @@ func checkoutExistingBranch(branch string) error {
}
// createTrackingBranch creates a new branch tracking a remote branch
-func createTrackingBranch(branch, remoteName string) error {
- cmd := exec.Command("git", "checkout", "-b", branch, fmt.Sprintf("%s/%s", remoteName, branch))
+func createTrackingBranch(repoPath, branch, remoteName string) error {
+ cmd := gitCommand(repoPath, "checkout", "-b", branch, fmt.Sprintf("%s/%s", remoteName, branch))
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("failed to create tracking branch: %s", string(output))
@@ -265,8 +273,8 @@ func createSSHBareRepository(sshHost, repoPath string) error {
}
// pushBranchWithBackupSupport pushes a branch to a remote, creating SSH repos if needed
-func pushBranchWithBackupSupport(remoteName, branch string, remoteHasBranch bool, org *config.Organization) error {
- cmd := exec.Command("git", "push", remoteName, branch, "--tags")
+func pushBranchWithBackupSupport(repoPath, remoteName, branch string, remoteHasBranch bool, org *config.Organization) error {
+ cmd := gitCommand(repoPath, "push", remoteName, branch, "--tags")
output, err := cmd.CombinedOutput()
if err != nil {
@@ -276,7 +284,7 @@ func pushBranchWithBackupSupport(remoteName, branch string, remoteHasBranch bool
// If it's an SSH backup location, try to create the repository
if org.BackupLocation && org.IsSSH() {
// Get the repository name from the remote URL
- remoteURL, err := getRemoteURL(remoteName)
+ remoteURL, err := getRemoteURL(repoPath, remoteName)
if err != nil {
return fmt.Errorf("failed to get remote URL: %w", err)
}
@@ -293,7 +301,7 @@ func pushBranchWithBackupSupport(remoteName, branch string, remoteHasBranch bool
}
// Try pushing again
- cmd = exec.Command("git", "push", remoteName, branch, "--tags")
+ cmd = gitCommand(repoPath, "push", remoteName, branch, "--tags")
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to push after creating repository: %w", err)
}
@@ -310,7 +318,7 @@ func pushBranchWithBackupSupport(remoteName, branch string, remoteHasBranch bool
if isBranchMissing(outputStr) {
fmt.Printf(" Creating new branch on %s\n", remoteName)
// Try again with -u flag to set upstream
- cmd = exec.Command("git", "push", "-u", remoteName, branch, "--tags")
+ cmd = gitCommand(repoPath, "push", "-u", remoteName, branch, "--tags")
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to push to %s: %w", remoteName, err)
}
@@ -328,8 +336,8 @@ func pushBranchWithBackupSupport(remoteName, branch string, remoteHasBranch bool
}
// getRemoteURL gets the URL for a given remote
-func getRemoteURL(remoteName string) (string, error) {
- cmd := exec.Command("git", "remote", "get-url", remoteName)
+func getRemoteURL(repoPath, remoteName string) (string, error) {
+ cmd := gitCommand(repoPath, "remote", "get-url", remoteName)
output, err := cmd.Output()
if err != nil {
return "", err