[#325] add abibity to create fork with different name

This commit is contained in:
Alexander Machehin 2013-11-19 17:02:05 +06:00
parent 2899728a33
commit 188c3be355
11 changed files with 98 additions and 25 deletions

View File

@ -0,0 +1,19 @@
$(document).ready(function() {
var fork_name = $('#fork_name');
var forks_path = $('#possible_forks_path');
fork_name.keyup(function(){
$.ajax({
type: 'GET',
url: forks_path.val(),
data: 'name=' + fork_name.val(),
success: function(data){
$('#forks_list').html(data);
},
error: function(data){
alert('error'); // TODO remove
}
});
});
});

View File

@ -279,3 +279,10 @@ table.blame td.message .message {
background: #ECECEC; background: #ECECEC;
color: #000; color: #000;
} }
.fork_name {
height: 20px;
margin-left: 10px;
width: 450px;
padding: 0 5px;
}

View File

@ -66,7 +66,7 @@ class Api::V1::ProjectsController < Api::V1::BaseController
def fork def fork
owner = (Group.find params[:group_id] if params[:group_id].present?) || current_user owner = (Group.find params[:group_id] if params[:group_id].present?) || current_user
authorize! :write, owner if owner.class == Group authorize! :write, owner if owner.class == Group
if forked = @project.fork(owner) and forked.valid? if forked = @project.fork(owner, params[:fork_name]) and forked.valid?
render_json_response forked, 'Project has been forked successfully' render_json_response forked, 'Project has been forked successfully'
else else
render_validation_error forked, 'Project has not been forked' render_validation_error forked, 'Project has not been forked'

View File

@ -2,7 +2,7 @@
class Projects::ProjectsController < Projects::BaseController class Projects::ProjectsController < Projects::BaseController
include ProjectsHelper include ProjectsHelper
before_filter :authenticate_user! before_filter :authenticate_user!
load_and_authorize_resource :id_param => :project_name # to force member actions load load_and_authorize_resource :id_param => :project_name, :collection => :possible_forks # to force member actions load
def index def index
@projects = Project.accessible_by(current_ability, :membered) @projects = Project.accessible_by(current_ability, :membered)
@ -68,7 +68,7 @@ class Projects::ProjectsController < Projects::BaseController
def fork def fork
owner = (Group.find params[:group] if params[:group].present?) || current_user owner = (Group.find params[:group] if params[:group].present?) || current_user
authorize! :write, owner if owner.class == Group authorize! :write, owner if owner.class == Group
if forked = @project.fork(owner) and forked.valid? if forked = @project.fork(owner, params[:fork_name]) and forked.valid?
redirect_to forked, :notice => t("flash.project.forked") redirect_to forked, :notice => t("flash.project.forked")
else else
flash[:warning] = t("flash.project.fork_error") flash[:warning] = t("flash.project.fork_error")
@ -77,6 +77,11 @@ class Projects::ProjectsController < Projects::BaseController
end end
end end
def possible_forks
render :partial => 'projects/git/base/forks', :layout => false,
:locals => { :owner => current_user, :name => (params[:name].presence || @project.name) }
end
def sections def sections
if request.post? if request.post?
if @project.update_attributes(params[:project]) if @project.update_attributes(params[:project])

View File

@ -189,8 +189,10 @@ class Project < ActiveRecord::Base
build_list.save build_list.save
end end
def fork(new_owner) def fork(new_owner, new_name)
new_name = new_name.presence || name
dup.tap do |c| dup.tap do |c|
c.name = new_name
c.parent_id = id c.parent_id = id
c.owner = new_owner c.owner = new_owner
c.updated_at = nil; c.created_at = nil # :id = nil c.updated_at = nil; c.created_at = nil # :id = nil

View File

@ -1,11 +1,12 @@
- if owner.own_projects.exists? :name => @project.name - if owner.own_projects.exists? :name => name
- is_group = owner.class == Group ? "(#{t 'activerecord.models.group'})" : '' - is_group = owner.class == Group ? "(#{t 'activerecord.models.group'})" : ''
%p.center %p.center
=t 'layout.projects.already_exists' =t 'layout.projects.already_exists'
=link_to "#{owner.uname}/#{@project.name} #{is_group}", project_path(owner, @project.name) =link_to "#{owner.uname}/#{name} #{is_group}", project_path(owner, name)
- else - else
= form_for @project, :url => fork_project_path(@project), :html => { :class => :form, :multipart => true, :method => :post } do |f| = form_for @project, :url => fork_project_path(@project), :html => { :class => :form, :multipart => true, :method => :post } do |f|
= hidden_field_tag :group, owner.id if owner.class == Group = hidden_field_tag :group, owner.id if owner.class == Group
= hidden_field_tag :fork_name, name, :name => 'fork_name'
=f.submit t('layout.projects.fork_to', :to => "#{owner.uname} #{is_group}"), :class => 'btn btn-primary disabled', 'data-loading-text' => t('layout.processing'), :id => 'create_fork' =f.submit t('layout.projects.fork_to', :to => "#{owner.uname} #{is_group}"), :class => 'btn btn-primary disabled', 'data-loading-text' => t('layout.processing'), :id => 'create_fork'
:javascript :javascript

View File

@ -1,3 +1,5 @@
= hidden_field_tag :possible_forks_path, possible_forks_project_path(@project)
- if can? :write, @project - if can? :write, @project
.r{:style => "display: block"} .r{:style => "display: block"}
=link_to t("projects.pull_requests.show.pull"), new_project_pull_request_path(@project, :treeish => @treeish), :id => 'send_pull_request', :class => 'button' =link_to t("projects.pull_requests.show.pull"), new_project_pull_request_path(@project, :treeish => @treeish), :id => 'send_pull_request', :class => 'button'
@ -8,11 +10,12 @@
.modal-header .modal-header
%a.close{"data-dismiss" => "modal"} × %a.close{"data-dismiss" => "modal"} ×
%h3=t 'layout.projects.fork_modal_header' %h3=t 'layout.projects.fork_modal_header'
.modal-body.modal-body-fork = hidden_field_tag :possible_forks, possible_forks_project_path(@project)
=render 'choose_fork', :owner => current_user %div
%hr.bootstrap = Project.human_attribute_name :name
- Group.can_own_project(current_user).each do |group| = text_field_tag 'fork_name', @project.name, :id => 'fork_name', :class => 'fork_name'
=render 'choose_fork', :owner => group #forks_list.modal-body.modal-body-fork
%hr.bootstrap = render 'forks', :owner => current_user, :name => @project.name
- if @project.is_package && can?(:create, @project.build_lists.new) - if @project.is_package && can?(:create, @project.build_lists.new)
.r{:style => "display: block"}= link_to t('layout.projects.new_build_list'), new_project_build_list_path(@project), :class => 'button' .r{:style => "display: block"}= link_to t('layout.projects.new_build_list'), new_project_build_list_path(@project), :class => 'button'

View File

@ -0,0 +1,5 @@
=render 'projects/git/base/choose_fork', :owner => current_user, :name => name
%hr.bootstrap
- Group.can_own_project(current_user).each do |group|
=render 'projects/git/base/choose_fork', :owner => group, :name => name
%hr.bootstrap

View File

@ -344,6 +344,7 @@ Rosa::Application.routes.draw do
delete '/' => 'projects#destroy' delete '/' => 'projects#destroy'
# Member # Member
post '/fork' => 'projects#fork', :as => :fork_project post '/fork' => 'projects#fork', :as => :fork_project
get '/possible_forks' => 'projects#possible_forks', :as => :possible_forks_project
get '/sections' => 'projects#sections', :as => :sections_project get '/sections' => 'projects#sections', :as => :sections_project
post '/sections' => 'projects#sections' post '/sections' => 'projects#sections'
delete '/remove_user' => 'projects#remove_user', :as => :remove_user_project delete '/remove_user' => 'projects#remove_user', :as => :remove_user_project

View File

@ -62,6 +62,17 @@ shared_examples_for 'api projects user with fork rights' do
it 'ensures that project has been forked' do it 'ensures that project has been forked' do
lambda { post :fork, :id => @project.id, :format => :json }.should change{ Project.count }.by(1) lambda { post :fork, :id => @project.id, :format => :json }.should change{ Project.count }.by(1)
end end
it 'should be able to perform fork action with different name' do
post :fork, :id => @project.id, :fork_name => (@project.name + '_forked'), :format => :json
response.should be_success
end
it 'ensures that project has been forked' do
new_name = @project.name + '_forked'
lambda { post :fork, :id => @project.id, :fork_name => new_name, :format => :json }.should
change{ Project.where(:name => new_name).count }.by(1)
end
end end
shared_examples_for 'api projects user with fork rights for hidden project' do shared_examples_for 'api projects user with fork rights for hidden project' do
@ -334,16 +345,36 @@ describe Api::V1::ProjectsController do
it_should_behave_like 'api projects user without admin rights' it_should_behave_like 'api projects user without admin rights'
it_should_behave_like 'api projects user without owner rights' it_should_behave_like 'api projects user without owner rights'
it 'group writer should be able to fork project to their group' do context 'group writer' do
group = FactoryGirl.create(:group) it 'should be able to fork project to their group' do
group.actors.create(:actor_type => 'User', :actor_id => @user.id, :role => 'writer') group = FactoryGirl.create(:group)
lambda {post :fork, :id => @project.id, :group_id => group.id}.should change{ Project.count }.by(1) group.actors.create(:actor_type => 'User', :actor_id => @user.id, :role => 'writer')
lambda {post :fork, :id => @project.id, :group_id => group.id}.should change{ Project.count }.by(1)
end
it 'should be able to fork project with different name to their group' do
group = FactoryGirl.create(:group)
group.actors.create(:actor_type => 'User', :actor_id => @user.id, :role => 'writer')
new_name = @project.name + '_forked'
lambda { post :fork, :id => @project.id, :group_id => group.id, :fork_name => new_name }.should
change { Project.where(:name => new_name).count }.by(1)
end
end end
it 'group reader should not be able to fork project to their group' do context 'group reader' do
group = FactoryGirl.create(:group) it 'should not be able to fork project to their group' do
group.actors.create(:actor_type => 'User', :actor_id => @user.id, :role => 'reader') group = FactoryGirl.create(:group)
lambda {post :fork, :id => @project.id, :group_id => group.id}.should change{ Project.count }.by(0) group.actors.create(:actor_type => 'User', :actor_id => @user.id, :role => 'reader')
lambda {post :fork, :id => @project.id, :group_id => group.id}.should change{ Project.count }.by(0)
end
it 'should not be able to fork project with different name to their group' do
group = FactoryGirl.create(:group)
new_name = @project.name + '_forked'
group.actors.create(:actor_type => 'User', :actor_id => @user.id, :role => 'reader')
lambda { post :fork, :id => @project.id, :group_id => group.id, :fork_name => new_name }.should
change{ Project.where(:name => new_name.count) }.by(0)
end
end end
end end

View File

@ -21,11 +21,10 @@ shared_examples_for 'projects user with reader rights' do
:group => group.id}.should change{ Project.count }.by(1) :group => group.id}.should change{ Project.count }.by(1)
end end
# it 'should be able to view project' do it 'should be able to fork project with different name' do
# get :show, :owner_name => @project.owner.uname, :project_name => @project.name post :fork, :owner_name => @project.owner.uname, :project_name => @project.name, :fork_name => 'another_name'
# assigns(:project).should eq @project response.should redirect_to(project_path(Project.where(:name => 'another_name').last))
# end end
end end
shared_examples_for 'projects user with project admin rights' do shared_examples_for 'projects user with project admin rights' do