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
70716a12
Commit
70716a12
authored
Sep 20, 2017
by
Bob Van Landuyt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow creating merge requests across forks of a project
parent
d3280072
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
230 additions
and
28 deletions
+230
-28
app/finders/merge_request_target_project_finder.rb
app/finders/merge_request_target_project_finder.rb
+18
-0
app/helpers/merge_requests_helper.rb
app/helpers/merge_requests_helper.rb
+2
-1
app/models/merge_request.rb
app/models/merge_request.rb
+1
-1
app/models/project.rb
app/models/project.rb
+13
-2
changelogs/unreleased/bvl-fork-network-schema.yml
changelogs/unreleased/bvl-fork-network-schema.yml
+5
-0
db/migrate/20170928133643_create_fork_network_members.rb
db/migrate/20170928133643_create_fork_network_members.rb
+1
-1
lib/gitlab/closing_issue_extractor.rb
lib/gitlab/closing_issue_extractor.rb
+2
-1
spec/features/merge_requests/create_new_mr_from_fork_spec.rb
spec/features/merge_requests/create_new_mr_from_fork_spec.rb
+60
-0
spec/finders/merge_request_target_project_finder_spec.rb
spec/finders/merge_request_target_project_finder_spec.rb
+54
-0
spec/models/merge_request_spec.rb
spec/models/merge_request_spec.rb
+15
-2
spec/models/project_spec.rb
spec/models/project_spec.rb
+59
-0
spec/requests/api/merge_requests_spec.rb
spec/requests/api/merge_requests_spec.rb
+0
-10
spec/requests/api/v3/merge_requests_spec.rb
spec/requests/api/v3/merge_requests_spec.rb
+0
-10
No files found.
app/finders/merge_request_target_project_finder.rb
0 → 100644
View file @
70716a12
class
MergeRequestTargetProjectFinder
attr_reader
:current_user
,
:source_project
def
initialize
(
current_user:
nil
,
source_project
:,
params:
{})
@current_user
=
current_user
@source_project
=
source_project
end
def
execute
if
@source_project
.
fork_network
@source_project
.
fork_network
.
projects
.
public_or_visible_to_user
(
current_user
)
.
with_feature_available_for_user
(
:merge_requests
,
current_user
)
else
Project
.
where
(
id:
source_project
)
end
end
end
app/helpers/merge_requests_helper.rb
View file @
70716a12
...
@@ -73,7 +73,8 @@ module MergeRequestsHelper
...
@@ -73,7 +73,8 @@ module MergeRequestsHelper
end
end
def
target_projects
(
project
)
def
target_projects
(
project
)
[
project
,
project
.
default_merge_request_target
].
uniq
MergeRequestTargetProjectFinder
.
new
(
current_user:
current_user
,
source_project:
project
)
.
execute
end
end
def
merge_request_button_visibility
(
merge_request
,
closed
)
def
merge_request_button_visibility
(
merge_request
,
closed
)
...
...
app/models/merge_request.rb
View file @
70716a12
...
@@ -403,7 +403,7 @@ class MergeRequest < ActiveRecord::Base
...
@@ -403,7 +403,7 @@ class MergeRequest < ActiveRecord::Base
return
false
unless
for_fork?
return
false
unless
for_fork?
return
true
unless
source_project
return
true
unless
source_project
!
source_project
.
forked_from
?
(
target_project
)
!
source_project
.
in_fork_network_of
?
(
target_project
)
end
end
def
reopenable?
def
reopenable?
...
...
app/models/project.rb
View file @
70716a12
...
@@ -1128,8 +1128,19 @@ class Project < ActiveRecord::Base
...
@@ -1128,8 +1128,19 @@ class Project < ActiveRecord::Base
end
end
end
end
def
in_fork_network_of?
(
project
)
def
forked_from?
(
other_project
)
forked?
&&
project
.
fork_network
==
fork_network
forked?
&&
forked_from_project
==
other_project
end
def
in_fork_network_of?
(
other_project
)
# TODO: Remove this in a next release when all fork_networks are populated
# This makes sure all MergeRequests remain valid while the projects don't
# have a fork_network yet.
return
true
if
forked_from?
(
other_project
)
return
false
if
fork_network
.
nil?
||
other_project
.
fork_network
.
nil?
fork_network
==
other_project
.
fork_network
end
end
def
origin_merge_requests
def
origin_merge_requests
...
...
changelogs/unreleased/bvl-fork-network-schema.yml
0 → 100644
View file @
70716a12
---
title
:
Allow creating merge requests across a fork network
merge_request
:
14422
author
:
type
:
changed
db/migrate/20170928133643_create_fork_network_members.rb
View file @
70716a12
...
@@ -18,7 +18,7 @@ class CreateForkNetworkMembers < ActiveRecord::Migration
...
@@ -18,7 +18,7 @@ class CreateForkNetworkMembers < ActiveRecord::Migration
end
end
def
down
def
down
if
foreign_key
_exists?
(
:fork_network_members
,
column: :forked_from_project_id
)
if
foreign_key
s_for
(
:fork_network_members
,
:forked_from_project_id
).
any?
remove_foreign_key
:fork_network_members
,
column: :forked_from_project_id
remove_foreign_key
:fork_network_members
,
column: :forked_from_project_id
end
end
drop_table
:fork_network_members
drop_table
:fork_network_members
...
...
lib/gitlab/closing_issue_extractor.rb
View file @
70716a12
...
@@ -23,7 +23,8 @@ module Gitlab
...
@@ -23,7 +23,8 @@ module Gitlab
@extractor
.
analyze
(
closing_statements
.
join
(
" "
))
@extractor
.
analyze
(
closing_statements
.
join
(
" "
))
@extractor
.
issues
.
reject
do
|
issue
|
@extractor
.
issues
.
reject
do
|
issue
|
@extractor
.
project
.
forked_from?
(
issue
.
project
)
# Don't extract issues on original project
# Don't extract issues from the project this project was forked from
@extractor
.
project
.
forked_from?
(
issue
.
project
)
end
end
end
end
end
end
...
...
spec/features/merge_requests/create_new_mr_from_fork_spec.rb
0 → 100644
View file @
70716a12
require
'spec_helper'
feature
'Creating a merge request from a fork'
,
:js
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:public
,
:repository
)
}
let!
(
:source_project
)
{
::
Projects
::
ForkService
.
new
(
project
,
user
).
execute
}
before
do
source_project
.
add_master
(
user
)
sign_in
(
user
)
end
shared_examples
'create merge request to other project'
do
it
'has all possible target projects'
do
visit
project_new_merge_request_path
(
source_project
)
first
(
'.js-target-project'
).
click
within
(
'.dropdown-target-project .dropdown-content'
)
do
expect
(
page
).
to
have_content
(
project
.
full_path
)
expect
(
page
).
to
have_content
(
target_project
.
full_path
)
expect
(
page
).
to
have_content
(
source_project
.
full_path
)
end
end
it
'allows creating the merge request to another target project'
do
visit
project_merge_requests_path
(
source_project
)
page
.
within
'.content'
do
click_link
'New merge request'
end
find
(
'.js-source-branch'
,
match: :first
).
click
find
(
'.dropdown-source-branch .dropdown-content a'
,
match: :first
).
click
first
(
'.js-target-project'
).
click
find
(
'.dropdown-target-project .dropdown-content a'
,
text:
target_project
.
full_path
).
click
click_button
'Compare branches and continue'
wait_for_requests
expect
{
click_button
'Submit merge request'
}
.
to
change
{
target_project
.
merge_requests
.
reload
.
size
}.
by
(
1
)
end
end
context
'creating to the source of a fork'
do
let
(
:target_project
)
{
project
}
it_behaves_like
(
'create merge request to other project'
)
end
context
'creating to a sibling of a fork'
do
let!
(
:target_project
)
{
::
Projects
::
ForkService
.
new
(
project
,
create
(
:user
)).
execute
}
it_behaves_like
(
'create merge request to other project'
)
end
end
spec/finders/merge_request_target_project_finder_spec.rb
0 → 100644
View file @
70716a12
require
'spec_helper'
describe
MergeRequestTargetProjectFinder
do
include
ProjectForksHelper
let
(
:user
)
{
create
(
:user
)
}
subject
(
:finder
)
{
described_class
.
new
(
current_user:
user
,
source_project:
forked_project
)
}
shared_examples
'finding related projects'
do
it
'finds sibling projects and base project'
do
other_fork
expect
(
finder
.
execute
).
to
contain_exactly
(
base_project
,
other_fork
,
forked_project
)
end
it
'does not include projects that have merge requests turned off'
do
other_fork
.
project_feature
.
update!
(
merge_requests_access_level:
ProjectFeature
::
DISABLED
)
base_project
.
project_feature
.
update!
(
merge_requests_access_level:
ProjectFeature
::
DISABLED
)
expect
(
finder
.
execute
).
to
contain_exactly
(
forked_project
)
end
end
context
'public projects'
do
let
(
:base_project
)
{
create
(
:project
,
:public
,
path:
'base'
)
}
let
(
:forked_project
)
{
fork_project
(
base_project
)
}
let
(
:other_fork
)
{
fork_project
(
base_project
)
}
it_behaves_like
'finding related projects'
end
context
'private projects'
do
let
(
:base_project
)
{
create
(
:project
,
:private
,
path:
'base'
)
}
let
(
:forked_project
)
{
fork_project
(
base_project
,
base_project
.
owner
)
}
let
(
:other_fork
)
{
fork_project
(
base_project
,
base_project
.
owner
)
}
context
'when the user is a member of all projects'
do
before
do
base_project
.
add_developer
(
user
)
forked_project
.
add_developer
(
user
)
other_fork
.
add_developer
(
user
)
end
it_behaves_like
'finding related projects'
end
it
'only finds the projects the user is a member of'
do
other_fork
.
add_developer
(
user
)
base_project
.
add_developer
(
user
)
expect
(
finder
.
execute
).
to
contain_exactly
(
other_fork
,
base_project
)
end
end
end
spec/models/merge_request_spec.rb
View file @
70716a12
...
@@ -49,6 +49,19 @@ describe MergeRequest do
...
@@ -49,6 +49,19 @@ describe MergeRequest do
expect
(
subject
).
to
be_valid
expect
(
subject
).
to
be_valid
end
end
end
end
context
'for forks'
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:fork1
)
{
create
(
:forked_project_link
,
forked_from_project:
project
).
forked_to_project
}
let
(
:fork2
)
{
create
(
:forked_project_link
,
forked_from_project:
project
).
forked_to_project
}
it
'allows merge requests for sibling-forks'
do
subject
.
source_project
=
fork1
subject
.
target_project
=
fork2
expect
(
subject
).
to
be_valid
end
end
end
end
describe
'respond to'
do
describe
'respond to'
do
...
@@ -1425,7 +1438,7 @@ describe MergeRequest do
...
@@ -1425,7 +1438,7 @@ describe MergeRequest do
describe
"#source_project_missing?"
do
describe
"#source_project_missing?"
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
)
}
let
(
:fork_project
)
{
create
(
:
project
,
forked_from_project:
project
)
}
let
(
:fork_project
)
{
create
(
:
forked_project_link
,
forked_from_project:
project
).
forked_to_project
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:unlink_project
)
{
Projects
::
UnlinkForkService
.
new
(
fork_project
,
user
)
}
let
(
:unlink_project
)
{
Projects
::
UnlinkForkService
.
new
(
fork_project
,
user
)
}
...
@@ -1446,7 +1459,7 @@ describe MergeRequest do
...
@@ -1446,7 +1459,7 @@ describe MergeRequest do
end
end
context
"when the fork does not exist"
do
context
"when the fork does not exist"
do
let
(
:merge_request
)
do
let
!
(
:merge_request
)
do
create
(
:merge_request
,
create
(
:merge_request
,
source_project:
fork_project
,
source_project:
fork_project
,
target_project:
project
)
target_project:
project
)
...
...
spec/models/project_spec.rb
View file @
70716a12
...
@@ -1818,6 +1818,65 @@ describe Project do
...
@@ -1818,6 +1818,65 @@ describe Project do
end
end
end
end
context
'forks'
do
let
(
:project
)
{
create
(
:project
,
:public
)
}
let!
(
:forked_project
)
{
fork_project
(
project
)
}
def
fork_project
(
project
)
Projects
::
ForkService
.
new
(
project
,
create
(
:user
)).
execute
end
describe
'#fork_network'
do
it
'includes a fork of the project'
do
expect
(
project
.
fork_network
).
to
include
(
forked_project
)
end
it
'includes a fork of a fork'
do
other_fork
=
fork_project
(
forked_project
)
expect
(
project
.
fork_network
).
to
include
(
other_fork
)
end
it
'includes sibling forks'
do
other_fork
=
fork_project
(
project
)
expect
(
forked_project
.
fork_network
).
to
include
(
other_fork
)
end
it
'includes the base project'
do
expect
(
forked_project
.
fork_network
).
to
include
(
project
)
end
end
describe
'#in_fork_network_of?'
do
it
'is false when the project is not a fork'
do
expect
(
project
.
in_fork_network_of?
(
double
)).
to
be_falsy
end
it
'is true for a real fork'
do
expect
(
forked_project
.
in_fork_network_of?
(
project
)).
to
be_truthy
end
it
'is true for a fork of a fork'
,
:postgresql
do
other_fork
=
fork_project
(
forked_project
)
expect
(
other_fork
.
in_fork_network_of?
(
project
)).
to
be_truthy
end
it
'is true for sibling forks'
do
sibling
=
fork_project
(
project
)
expect
(
sibling
.
in_fork_network_of?
(
forked_project
)).
to
be_truthy
end
it
'is false when another project is given'
do
other_project
=
build_stubbed
(
:project
)
expect
(
forked_project
.
in_fork_network_of?
(
other_project
)).
to
be_falsy
end
end
end
describe
'#pushes_since_gc'
do
describe
'#pushes_since_gc'
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
)
}
...
...
spec/requests/api/merge_requests_spec.rb
View file @
70716a12
...
@@ -676,16 +676,6 @@ describe API::MergeRequests do
...
@@ -676,16 +676,6 @@ describe API::MergeRequests do
end
end
context
'when target_branch is specified'
do
context
'when target_branch is specified'
do
it
'returns 422 if not a forked project'
do
post
api
(
"/projects/
#{
project
.
id
}
/merge_requests"
,
user
),
title:
'Test merge_request'
,
target_branch:
'master'
,
source_branch:
'markdown'
,
author:
user
,
target_project_id:
fork_project
.
id
expect
(
response
).
to
have_gitlab_http_status
(
422
)
end
it
'returns 422 if targeting a different fork'
do
it
'returns 422 if targeting a different fork'
do
post
api
(
"/projects/
#{
fork_project
.
id
}
/merge_requests"
,
user2
),
post
api
(
"/projects/
#{
fork_project
.
id
}
/merge_requests"
,
user2
),
title:
'Test merge_request'
,
title:
'Test merge_request'
,
...
...
spec/requests/api/v3/merge_requests_spec.rb
View file @
70716a12
...
@@ -372,16 +372,6 @@ describe API::MergeRequests do
...
@@ -372,16 +372,6 @@ describe API::MergeRequests do
end
end
context
'when target_branch is specified'
do
context
'when target_branch is specified'
do
it
'returns 422 if not a forked project'
do
post
v3_api
(
"/projects/
#{
project
.
id
}
/merge_requests"
,
user
),
title:
'Test merge_request'
,
target_branch:
'master'
,
source_branch:
'markdown'
,
author:
user
,
target_project_id:
fork_project
.
id
expect
(
response
).
to
have_gitlab_http_status
(
422
)
end
it
'returns 422 if targeting a different fork'
do
it
'returns 422 if targeting a different fork'
do
post
v3_api
(
"/projects/
#{
fork_project
.
id
}
/merge_requests"
,
user2
),
post
v3_api
(
"/projects/
#{
fork_project
.
id
}
/merge_requests"
,
user2
),
title:
'Test merge_request'
,
title:
'Test merge_request'
,
...
...
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