Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
gitlab-ce
Commits
fdb5f285
Commit
fdb5f285
authored
Jul 30, 2018
by
Felipe Artur
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Retrieve merge request closing issues from database cache
parent
cb2e0730
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
112 additions
and
12 deletions
+112
-12
app/models/merge_request.rb
app/models/merge_request.rb
+18
-3
app/presenters/merge_request_presenter.rb
app/presenters/merge_request_presenter.rb
+1
-1
app/services/merge_requests/post_merge_service.rb
app/services/merge_requests/post_merge_service.rb
+1
-1
app/services/merge_requests/reopen_service.rb
app/services/merge_requests/reopen_service.rb
+1
-0
changelogs/unreleased/issue_44821.yml
changelogs/unreleased/issue_44821.yml
+5
-0
lib/api/merge_requests.rb
lib/api/merge_requests.rb
+1
-1
spec/factories/merge_requests.rb
spec/factories/merge_requests.rb
+4
-0
spec/lib/gitlab/import_export/all_models.yml
spec/lib/gitlab/import_export/all_models.yml
+1
-0
spec/models/merge_request_spec.rb
spec/models/merge_request_spec.rb
+69
-3
spec/presenters/merge_request_presenter_spec.rb
spec/presenters/merge_request_presenter_spec.rb
+1
-1
spec/requests/api/merge_requests_spec.rb
spec/requests/api/merge_requests_spec.rb
+1
-0
spec/services/issues/reopen_service_spec.rb
spec/services/issues/reopen_service_spec.rb
+1
-1
spec/services/merge_requests/merge_service_spec.rb
spec/services/merge_requests/merge_service_spec.rb
+1
-0
spec/services/merge_requests/post_merge_service_spec.rb
spec/services/merge_requests/post_merge_service_spec.rb
+1
-1
spec/services/merge_requests/reopen_service_spec.rb
spec/services/merge_requests/reopen_service_spec.rb
+6
-0
No files found.
app/models/merge_request.rb
View file @
fdb5f285
...
...
@@ -52,6 +52,8 @@ class MergeRequest < ActiveRecord::Base
class_name:
'MergeRequestsClosingIssues'
,
dependent: :delete_all
# rubocop:disable Cop/ActiveRecordDependent
has_many
:cached_closes_issues
,
through: :merge_requests_closing_issues
,
source: :issue
belongs_to
:assignee
,
class_name:
"User"
serialize
:merge_params
,
Hash
# rubocop:disable Cop/ActiveRecordSerialize
...
...
@@ -755,8 +757,9 @@ class MergeRequest < ActiveRecord::Base
# Calculating this information for a number of merge requests requires
# running `ReferenceExtractor` on each of them separately.
# This optimization does not apply to issues from external sources.
def
cache_merge_request_closes_issues!
(
current_user
)
def
cache_merge_request_closes_issues!
(
current_user
=
self
.
author
)
return
unless
project
.
issues_enabled?
return
if
closed?
||
merged?
transaction
do
self
.
merge_requests_closing_issues
.
delete_all
...
...
@@ -769,6 +772,18 @@ class MergeRequest < ActiveRecord::Base
end
end
def
visible_closing_issues_for
(
current_user
=
self
.
author
)
strong_memoize
(
:visible_closing_issues_for
)
do
if
self
.
target_project
.
has_external_issue_tracker?
closes_issues
(
current_user
)
else
cached_closes_issues
.
select
do
|
issue
|
Ability
.
allowed?
(
current_user
,
:read_issue
,
issue
)
end
end
end
end
# Return the set of issues that will be closed if this merge request is accepted.
def
closes_issues
(
current_user
=
self
.
author
)
if
target_branch
==
project
.
default_branch
...
...
@@ -788,7 +803,7 @@ class MergeRequest < ActiveRecord::Base
ext
=
Gitlab
::
ReferenceExtractor
.
new
(
project
,
current_user
)
ext
.
analyze
(
"
#{
title
}
\n
#{
description
}
"
)
ext
.
issues
-
closes_issues
(
current_user
)
ext
.
issues
-
visible_closing_issues_for
(
current_user
)
end
def
target_project_path
...
...
@@ -836,7 +851,7 @@ class MergeRequest < ActiveRecord::Base
end
def
merge_commit_message
(
include_description:
false
)
closes_issues_references
=
closes_issues
.
map
do
|
issue
|
closes_issues_references
=
visible_closing_issues_for
.
map
do
|
issue
|
issue
.
to_reference
(
target_project
)
end
...
...
app/presenters/merge_request_presenter.rb
View file @
fdb5f285
...
...
@@ -206,7 +206,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
end
def
closing_issues
@closing_issues
||=
closes_issues
(
current_user
)
@closing_issues
||=
visible_closing_issues_for
(
current_user
)
end
def
pipeline
...
...
app/services/merge_requests/post_merge_service.rb
View file @
fdb5f285
...
...
@@ -25,7 +25,7 @@ module MergeRequests
def
close_issues
(
merge_request
)
return
unless
merge_request
.
target_branch
==
project
.
default_branch
closed_issues
=
merge_request
.
closes_issues
(
current_user
)
closed_issues
=
merge_request
.
visible_closing_issues_for
(
current_user
)
closed_issues
.
each
do
|
issue
|
if
can?
(
current_user
,
:update_issue
,
issue
)
...
...
app/services/merge_requests/reopen_service.rb
View file @
fdb5f285
...
...
@@ -14,6 +14,7 @@ module MergeRequests
merge_request
.
mark_as_unchecked
invalidate_cache_counts
(
merge_request
,
users:
merge_request
.
assignees
)
merge_request
.
update_project_counter_caches
merge_request
.
cache_merge_request_closes_issues!
(
current_user
)
end
merge_request
...
...
changelogs/unreleased/issue_44821.yml
0 → 100644
View file @
fdb5f285
---
title
:
Retrieve merge request closing issues from database cache
merge_request
:
20911
author
:
type
:
fixed
lib/api/merge_requests.rb
View file @
fdb5f285
...
...
@@ -380,7 +380,7 @@ module API
end
get
':id/merge_requests/:merge_request_iid/closes_issues'
do
merge_request
=
find_merge_request_with_access
(
params
[
:merge_request_iid
])
issues
=
::
Kaminari
.
paginate_array
(
merge_request
.
closes_issues
(
current_user
))
issues
=
::
Kaminari
.
paginate_array
(
merge_request
.
visible_closing_issues_for
(
current_user
))
issues
=
paginate
(
issues
)
external_issues
,
internal_issues
=
issues
.
partition
{
|
issue
|
issue
.
is_a?
(
ExternalIssue
)
}
...
...
spec/factories/merge_requests.rb
View file @
fdb5f285
...
...
@@ -100,6 +100,10 @@ FactoryBot.define do
end
end
after
(
:create
)
do
|
merge_request
,
evaluator
|
merge_request
.
cache_merge_request_closes_issues!
end
factory
:merged_merge_request
,
traits:
[
:merged
]
factory
:closed_merge_request
,
traits:
[
:closed
]
factory
:reopened_merge_request
,
traits:
[
:opened
]
...
...
spec/lib/gitlab/import_export/all_models.yml
View file @
fdb5f285
...
...
@@ -87,6 +87,7 @@ merge_requests:
-
merge_request_diff
-
events
-
merge_requests_closing_issues
-
cached_closes_issues
-
metrics
-
timelogs
-
head_pipeline
...
...
spec/models/merge_request_spec.rb
View file @
fdb5f285
...
...
@@ -310,6 +310,51 @@ describe MergeRequest do
end
end
describe
'#visible_closing_issues_for'
do
let
(
:guest
)
{
create
(
:user
)
}
let
(
:developer
)
{
create
(
:user
)
}
let
(
:issue_1
)
{
create
(
:issue
,
project:
subject
.
source_project
)
}
let
(
:issue_2
)
{
create
(
:issue
,
project:
subject
.
source_project
)
}
let
(
:confidential_issue
)
{
create
(
:issue
,
:confidential
,
project:
subject
.
source_project
)
}
before
do
subject
.
project
.
add_developer
(
subject
.
author
)
subject
.
target_branch
=
subject
.
project
.
default_branch
commit
=
double
(
'commit1'
,
safe_message:
"Fixes
#{
issue_1
.
to_reference
}
#{
issue_2
.
to_reference
}
#{
confidential_issue
.
to_reference
}
"
)
allow
(
subject
).
to
receive
(
:commits
).
and_return
([
commit
])
end
it
'shows only allowed issues to guest'
do
subject
.
project
.
add_guest
(
guest
)
subject
.
cache_merge_request_closes_issues!
expect
(
subject
.
visible_closing_issues_for
(
guest
)).
to
match_array
([
issue_1
,
issue_2
])
end
it
'shows only allowed issues to developer'
do
subject
.
project
.
add_developer
(
developer
)
subject
.
cache_merge_request_closes_issues!
expect
(
subject
.
visible_closing_issues_for
(
developer
)).
to
match_array
([
issue_1
,
confidential_issue
,
issue_2
])
end
context
'when external issue tracker is enabled'
do
before
do
subject
.
project
.
has_external_issue_tracker
=
true
subject
.
project
.
save!
end
it
'calls non #closes_issues to retrieve data'
do
expect
(
subject
).
to
receive
(
:closes_issues
)
expect
(
subject
).
not_to
receive
(
:cached_closes_issues
)
subject
.
visible_closing_issues_for
end
end
end
describe
'#cache_merge_request_closes_issues!'
do
before
do
subject
.
project
.
add_developer
(
subject
.
author
)
...
...
@@ -324,6 +369,25 @@ describe MergeRequest do
expect
{
subject
.
cache_merge_request_closes_issues!
(
subject
.
author
)
}.
to
change
(
subject
.
merge_requests_closing_issues
,
:count
).
by
(
1
)
end
it
'does not cache closed issues when merge request is closed'
do
issue
=
create
:issue
,
project:
subject
.
project
commit
=
double
(
'commit1'
,
safe_message:
"Fixes
#{
issue
.
to_reference
}
"
)
allow
(
subject
).
to
receive
(
:commits
).
and_return
([
commit
])
allow
(
subject
).
to
receive
(
:state
).
and_return
(
"closed"
)
expect
{
subject
.
cache_merge_request_closes_issues!
(
subject
.
author
)
}.
not_to
change
(
subject
.
merge_requests_closing_issues
,
:count
)
end
it
'does not cache closed issues when merge request is merged'
do
issue
=
create
:issue
,
project:
subject
.
project
commit
=
double
(
'commit1'
,
safe_message:
"Fixes
#{
issue
.
to_reference
}
"
)
allow
(
subject
).
to
receive
(
:commits
).
and_return
([
commit
])
allow
(
subject
).
to
receive
(
:state
).
and_return
(
"merged"
)
expect
{
subject
.
cache_merge_request_closes_issues!
(
subject
.
author
)
}.
not_to
change
(
subject
.
merge_requests_closing_issues
,
:count
)
end
context
'when both internal and external issue trackers are enabled'
do
before
do
subject
.
project
.
has_external_issue_tracker
=
true
...
...
@@ -632,6 +696,7 @@ describe MergeRequest do
allow
(
subject
).
to
receive
(
:commits
).
and_return
([
commit
])
allow
(
subject
.
project
).
to
receive
(
:default_branch
)
.
and_return
(
subject
.
target_branch
)
subject
.
cache_merge_request_closes_issues!
expect
(
subject
.
issues_mentioned_but_not_closing
(
subject
.
author
)).
to
match_array
([
mentioned_issue
])
end
...
...
@@ -649,6 +714,8 @@ describe MergeRequest do
end
it
'detects issues mentioned in description but not closed'
do
subject
.
cache_merge_request_closes_issues!
expect
(
subject
.
issues_mentioned_but_not_closing
(
subject
.
author
).
map
(
&
:to_s
)).
to
match_array
([
'TEST-2'
])
end
end
...
...
@@ -779,9 +846,8 @@ describe MergeRequest do
subject
.
project
.
add_developer
(
subject
.
author
)
subject
.
description
=
"This issue Closes
#{
issue
.
to_reference
}
"
allow
(
subject
.
project
).
to
receive
(
:default_branch
)
.
and_return
(
subject
.
target_branch
)
allow
(
subject
.
project
).
to
receive
(
:default_branch
).
and_return
(
subject
.
target_branch
)
subject
.
cache_merge_request_closes_issues!
expect
(
subject
.
merge_commit_message
)
.
to
match
(
"Closes
#{
issue
.
to_reference
}
"
)
...
...
spec/presenters/merge_request_presenter_spec.rb
View file @
fdb5f285
...
...
@@ -117,9 +117,9 @@ describe MergeRequestPresenter do
before
do
project
.
add_developer
(
user
)
allow
(
resource
.
project
).
to
receive
(
:default_branch
)
.
and_return
(
resource
.
target_branch
)
resource
.
cache_merge_request_closes_issues!
end
describe
'#closing_issues_links'
do
...
...
spec/requests/api/merge_requests_spec.rb
View file @
fdb5f285
...
...
@@ -954,6 +954,7 @@ describe API::MergeRequests do
issue
=
create
(
:issue
,
project:
project
)
mr
=
merge_request
.
tap
do
|
mr
|
mr
.
update_attribute
(
:description
,
"Closes
#{
issue
.
to_reference
(
mr
.
project
)
}
"
)
mr
.
cache_merge_request_closes_issues!
end
get
api
(
"/projects/
#{
project
.
id
}
/merge_requests/
#{
mr
.
iid
}
/closes_issues"
,
user
)
...
...
spec/services/issues/reopen_service_spec.rb
View file @
fdb5f285
...
...
@@ -20,7 +20,7 @@ describe Issues::ReopenService do
end
end
context
'when user is authrized to reopen issue'
do
context
'when user is auth
o
rized to reopen issue'
do
let
(
:user
)
{
create
(
:user
)
}
before
do
...
...
spec/services/merge_requests/merge_service_spec.rb
View file @
fdb5f285
...
...
@@ -49,6 +49,7 @@ describe MergeRequests::MergeService do
issue
=
create
:issue
,
project:
project
commit
=
double
(
'commit'
,
safe_message:
"Fixes
#{
issue
.
to_reference
}
"
)
allow
(
merge_request
).
to
receive
(
:commits
).
and_return
([
commit
])
merge_request
.
cache_merge_request_closes_issues!
service
.
execute
(
merge_request
)
...
...
spec/services/merge_requests/post_merge_service_spec.rb
View file @
fdb5f285
...
...
@@ -53,7 +53,7 @@ describe MergeRequests::PostMergeService do
allow
(
project
).
to
receive
(
:default_branch
).
and_return
(
'foo'
)
issue
=
create
(
:issue
,
project:
project
)
allow
(
merge_request
).
to
receive
(
:
closes_issues
).
and_return
([
issue
])
allow
(
merge_request
).
to
receive
(
:
visible_closing_issues_for
).
and_return
([
issue
])
allow_any_instance_of
(
Issues
::
CloseService
).
to
receive
(
:execute
).
with
(
issue
,
commit:
merge_request
).
and_raise
expect
{
described_class
.
new
(
project
,
user
,
{}).
execute
(
merge_request
)
}.
to
raise_error
...
...
spec/services/merge_requests/reopen_service_spec.rb
View file @
fdb5f285
...
...
@@ -47,6 +47,12 @@ describe MergeRequests::ReopenService do
end
end
it
'caches merge request closing issues'
do
expect
(
merge_request
).
to
receive
(
:cache_merge_request_closes_issues!
)
described_class
.
new
(
project
,
user
,
{}).
execute
(
merge_request
)
end
it
'updates metrics'
do
metrics
=
merge_request
.
metrics
service
=
double
(
MergeRequestMetricsService
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment