From a4e766bb01114f0055eb04c39d8f0923b9cb4d6e Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Tue, 29 Aug 2023 17:41:10 +0200 Subject: 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. --- pkg/vcs/git.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'pkg') 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 } -- cgit mrf-deployment