Commit c2e53438 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'improve-mr-reloading' into 'master'

Improve MR reloading

## Theory

Every time you pushed to master it updates merge requests that has master
as target branch. So if you have 50 open merge requests point to master
it will reload all of them every time you push a single commit to
master. The funny thing is that after reloading diff of most merge
requests looks the same.

After this patch we update diff only if we push commit to master that
includes in MR commits list.

For example we have next repository:

    feature: A - B - C
    master: A

We create merge request with code from feature to master.

    MR: B - C

If we push to master commit D - MR will not be reloaded. So picture will
look next:

    feature: A - B - C
    master: A - D
    MR: B - C

And if we push to master commit B - MR will be reloaded. So picture will
look next:

    feature: A - B - C
    master: A - B
    MR: C

## Benchmark

For project with 45 open merge requests to master

Before

```
Benchmark post-receive | Cache and size:   0.060000   0.040000   0.100000 (  0.379720)
Benchmark post-receive | Push commits selection:   0.130000   0.020000   0.150000 (  0.149299)
Benchmark post-receive | Update merge requests:   9.180000   2.030000  11.210000 ( 11.971747)
Benchmark post-receive | Process commit messages:   0.140000   0.010000   0.150000 (  0.168810)
Benchmark post-receive | Push data:   0.020000   0.000000   0.020000 (  0.016363)
Benchmark post-receive | Push event and services:   0.030000   0.000000   0.030000 (  0.088062)
```

After

```
Benchmark post-receive | Cache and size:   0.070000   0.030000   0.100000 (  0.106676)
Benchmark post-receive | Push commits selection:   0.130000   0.020000   0.150000 (  0.143081)
Benchmark post-receive | Update merge requests:   0.660000   0.210000   0.870000 (  0.892663)
Benchmark post-receive | Process commit messages:   0.030000   0.000000   0.030000 (  0.029263)
Benchmark post-receive | Push data:   0.020000   0.000000   0.020000 (  0.018479)
Benchmark post-receive | Push event and services:   0.030000   0.000000   0.030000 (  0.038230)
```
- - -

## References

Discussion in gitlab/gitlabhq#1796

See merge request !1288
parents 1587c36b 835cbc06
...@@ -3,6 +3,7 @@ module MergeRequests ...@@ -3,6 +3,7 @@ module MergeRequests
def execute(oldrev, newrev, ref) def execute(oldrev, newrev, ref)
return true unless ref =~ /heads/ return true unless ref =~ /heads/
@oldrev, @newrev = oldrev, newrev
@branch_name = ref.gsub("refs/heads/", "") @branch_name = ref.gsub("refs/heads/", "")
@fork_merge_requests = @project.fork_merge_requests.opened @fork_merge_requests = @project.fork_merge_requests.opened
@commits = @project.repository.commits_between(oldrev, newrev) @commits = @project.repository.commits_between(oldrev, newrev)
...@@ -35,6 +36,10 @@ module MergeRequests ...@@ -35,6 +36,10 @@ module MergeRequests
end end
end end
def force_push?
Gitlab::ForcePushCheck.force_push?(@project, @oldrev, @newrev)
end
# Refresh merge request diff if we push to source or target branch of merge request # Refresh merge request diff if we push to source or target branch of merge request
# Note: we should update merge requests from forks too # Note: we should update merge requests from forks too
def reload_merge_requests def reload_merge_requests
...@@ -43,8 +48,22 @@ module MergeRequests ...@@ -43,8 +48,22 @@ module MergeRequests
merge_requests = filter_merge_requests(merge_requests) merge_requests = filter_merge_requests(merge_requests)
merge_requests.each do |merge_request| merge_requests.each do |merge_request|
if merge_request.source_branch == @branch_name || force_push?
merge_request.reload_code merge_request.reload_code
merge_request.mark_as_unchecked merge_request.mark_as_unchecked
else
mr_commit_ids = merge_request.commits.map(&:id)
push_commit_ids = @commits.map(&:id)
matches = mr_commit_ids & push_commit_ids
if matches.any?
merge_request.reload_code
merge_request.mark_as_unchecked
else
merge_request.mark_as_unchecked
end
end
end end
end end
......
module Gitlab
class ForcePushCheck
def self.force_push?(project, oldrev, newrev)
return false if project.empty_repo?
if oldrev != Gitlab::Git::BLANK_SHA && newrev != Gitlab::Git::BLANK_SHA
missed_refs = IO.popen(%W(git --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev})).read
missed_refs.split("\n").size > 0
else
false
end
end
end
end
...@@ -94,14 +94,7 @@ module Gitlab ...@@ -94,14 +94,7 @@ module Gitlab
end end
def forced_push?(project, oldrev, newrev) def forced_push?(project, oldrev, newrev)
return false if project.empty_repo? Gitlab::ForcePushCheck.force_push?(project, oldrev, newrev)
if oldrev != Gitlab::Git::BLANK_SHA && newrev != Gitlab::Git::BLANK_SHA
missed_refs = IO.popen(%W(git --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev})).read
missed_refs.split("\n").size > 0
else
false
end
end end
private private
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment