Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Speicher <rspeicher@gmail.com>2020-03-12 21:47:59 +0300
committerRobert Speicher <rspeicher@gmail.com>2020-03-16 17:42:52 +0300
commitb012da20fe72d15afebfd4d5d9b10cef1548d3f4 (patch)
treea5192fa284921152c259a6ff52219793e3c87c18
parent4bd9b1536b4776ae369b8e43388a25941e18a19e (diff)
Don't push divergent remote branches with keep_divergent_refs
Previously, if a remote branch had completely diverged from the source (i.e., it is no longer an ancestor of the source), we'd still attempt to push to it and would only realize it failed when the server came back with an error. Now when selecting local branches to push to the remote, the `keep_divergent_refs` option allows us to limit the list to only branches that have no divergence.
-rw-r--r--changelogs/unreleased/rs-keep-divergent-refs-for-push.yml5
-rw-r--r--internal/service/remote/update_remote_mirror_test.go26
-rw-r--r--ruby/lib/gitlab/git/remote_mirror.rb18
3 files changed, 48 insertions, 1 deletions
diff --git a/changelogs/unreleased/rs-keep-divergent-refs-for-push.yml b/changelogs/unreleased/rs-keep-divergent-refs-for-push.yml
new file mode 100644
index 000000000..d736230ac
--- /dev/null
+++ b/changelogs/unreleased/rs-keep-divergent-refs-for-push.yml
@@ -0,0 +1,5 @@
+---
+title: Don't push divergent remote branches with keep_divergent_refs
+merge_request: 1915
+author:
+type: added
diff --git a/internal/service/remote/update_remote_mirror_test.go b/internal/service/remote/update_remote_mirror_test.go
index 87e51eb8c..0cb8524a9 100644
--- a/internal/service/remote/update_remote_mirror_test.go
+++ b/internal/service/remote/update_remote_mirror_test.go
@@ -195,6 +195,10 @@ func TestSuccessfulUpdateRemoteMirrorRequestWithKeepDivergentRefs(t *testing.T)
{"remote", "add", remoteName, mirrorPath},
{"fetch", remoteName},
+ // Create a divergence by moving `master` to the HEAD of another branch
+ // ba3faa7d only exists on `after-create-delete-modify-move`
+ {"update-ref", "refs/heads/master", "ba3faa7dbecdb555c748b36e8bc0f427e69de5e7"},
+
// Delete a branch and a tag to ensure they're kept around in the mirror
{"branch", "-D", "not-merged-branch"},
{"tag", "-d", "v2.0.0"},
@@ -224,8 +228,30 @@ func TestSuccessfulUpdateRemoteMirrorRequestWithKeepDivergentRefs(t *testing.T)
mirrorRefs := string(testhelper.MustRunCommand(t, nil, "git", "-C", mirrorPath, "for-each-ref"))
+ // Verify `master` didn't get updated, since its HEAD is no longer an ancestor of remote's version
+ require.Contains(t, mirrorRefs, "1e292f8fedd741b75372e19097c76d327140c312 commit\trefs/heads/master")
+
+ // Verify refs deleted on the source stick around on the mirror
require.Contains(t, mirrorRefs, "refs/heads/not-merged-branch")
require.Contains(t, mirrorRefs, "refs/tags/v2.0.0")
+
+ // Re-run mirroring without KeepDivergentRefs
+ firstRequest.KeepDivergentRefs = false
+
+ stream, err = client.UpdateRemoteMirror(ctx)
+ require.NoError(t, err)
+ require.NoError(t, stream.Send(firstRequest))
+
+ _, err = stream.CloseAndRecv()
+ require.NoError(t, err)
+
+ mirrorRefs = string(testhelper.MustRunCommand(t, nil, "git", "-C", mirrorPath, "for-each-ref"))
+
+ // Verify `master` gets overwritten with the value from the source
+ require.Contains(t, mirrorRefs, "ba3faa7dbecdb555c748b36e8bc0f427e69de5e7 commit\trefs/heads/master")
+
+ // Verify a branch only on the mirror is now deleted
+ require.NotContains(t, mirrorRefs, "refs/heads/not-merged-branch")
}
func TestFailedUpdateRemoteMirrorRequestDueToValidation(t *testing.T) {
diff --git a/ruby/lib/gitlab/git/remote_mirror.rb b/ruby/lib/gitlab/git/remote_mirror.rb
index 9311a8b25..2ad02bb26 100644
--- a/ruby/lib/gitlab/git/remote_mirror.rb
+++ b/ruby/lib/gitlab/git/remote_mirror.rb
@@ -60,7 +60,23 @@ module Gitlab
local_refs.select do |ref_name, ref|
remote_ref = remote_refs[ref_name]
- remote_ref.nil? || ref.dereferenced_target != remote_ref.dereferenced_target
+ # Ref doesn't exist on the remote, it should be created
+ next true if remote_ref.nil?
+
+ local_target = ref.dereferenced_target
+ remote_target = remote_ref.dereferenced_target
+
+ if local_target == remote_target
+ # Ref is identical on the remote, no point mirroring
+ false
+ elsif @keep_divergent_refs
+ # Mirror the ref if its remote counterpart hasn't diverged
+ repository.ancestor?(remote_target&.id, local_target&.id)
+ else
+ # Attempt to overwrite whatever's on the remote; push rules and
+ # protected branches may still prevent this
+ true
+ end
end
end