aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/vcs
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2023-08-29 17:41:10 +0200
committerAleksandr Nogikh <nogikh@google.com>2023-08-30 09:27:19 +0000
commita4e766bb01114f0055eb04c39d8f0923b9cb4d6e (patch)
tree90e5e9b8d8213e51350519eb3bfec44cd4bd8ddf /pkg/vcs
parentb42ca3a7c82c932ad7ee2ae2a89ae7dfe1e583a5 (diff)
pkg/vcs: circumvent ref conflicts during fetch
If the remote repo's tags conflict with the local ones, `git fetch` may fail with `error: cannot lock ref %: % exists`. It seems that the only way to restore the repository in this case is to do `git fetch` with `--prune --prune-tags`. Since this also forces the repository to forget all tags not present in the remote, let's do it only when we got the error message.
Diffstat (limited to 'pkg/vcs')
-rw-r--r--pkg/vcs/git.go13
1 files changed, 13 insertions, 0 deletions
diff --git a/pkg/vcs/git.go b/pkg/vcs/git.go
index e1682afb0..b3e9a7ace 100644
--- a/pkg/vcs/git.go
+++ b/pkg/vcs/git.go
@@ -6,6 +6,7 @@ package vcs
import (
"bufio"
"bytes"
+ "errors"
"fmt"
"net/mail"
"os"
@@ -144,6 +145,18 @@ func (git *git) fetchRemote(repo string) error {
// Ignore error as we can double add the same remote and that will fail.
git.git("remote", "add", repoHash, repo)
_, err := git.git("fetch", "--force", "--tags", repoHash)
+ if err != nil {
+ var verbose *osutil.VerboseError
+ if errors.As(err, &verbose) &&
+ bytes.Contains(verbose.Output, []byte("error: cannot lock ref")) {
+ // It can happen that the fetched repo has tags names that conflict
+ // with the ones already present in the repository.
+ // Try to fetch more, but this time prune tags, it should help.
+ // The --prune-tags option will remove all tags that are not present
+ // in this remote repo, so don't do it always. Only when necessary.
+ _, err = git.git("fetch", "--force", "--tags", "--prune", "--prune-tags", repoHash)
+ }
+ }
return err
}