Commit f5551efdfd71c6aedb609093374a6c4dbed6a78b
1 parent
70bf7f6e
Exists in
master
and in
4 other branches
Rewrite and improve git backend logic. Fix project movind. Raise exception to pr…
…event unexpected issues
Showing
20 changed files
with
147 additions
and
100 deletions
Show diff stats
app/controllers/admin/groups_controller.rb
app/controllers/projects_controller.rb
... | ... | @@ -34,11 +34,16 @@ class ProjectsController < ProjectResourceController |
34 | 34 | end |
35 | 35 | |
36 | 36 | def update |
37 | - namespace_id = params[:project].delete(:namespace_id) | |
38 | - | |
39 | - if namespace_id.present? and namespace_id.to_i != project.namespace_id | |
40 | - namespace = Namespace.find(namespace_id) | |
41 | - project.transfer(namespace) | |
37 | + if params[:project].has_key?(:namespace_id) | |
38 | + namespace_id = params[:project].delete(:namespace_id) | |
39 | + if namespace_id == Namespace.global_id and project.namespace.present? | |
40 | + # Transfer to global namespace from anyone | |
41 | + project.transfer(nil) | |
42 | + elsif namespace_id.present? and namespace_id.to_i != project.namespace_id | |
43 | + # Transfer to someone namespace | |
44 | + namespace = Namespace.find(namespace_id) | |
45 | + project.transfer(namespace) | |
46 | + end | |
42 | 47 | end |
43 | 48 | |
44 | 49 | respond_to do |format| | ... | ... |
app/helpers/application_helper.rb
app/models/namespace.rb
... | ... | @@ -35,6 +35,10 @@ class Namespace < ActiveRecord::Base |
35 | 35 | where("name LIKE :query OR path LIKE :query", query: "%#{query}%") |
36 | 36 | end |
37 | 37 | |
38 | + def self.global_id | |
39 | + 'GLN' | |
40 | + end | |
41 | + | |
38 | 42 | def to_param |
39 | 43 | path |
40 | 44 | end |
... | ... | @@ -51,6 +55,9 @@ class Namespace < ActiveRecord::Base |
51 | 55 | def move_dir |
52 | 56 | old_path = File.join(Gitlab.config.git_base_path, path_was) |
53 | 57 | new_path = File.join(Gitlab.config.git_base_path, path) |
58 | + if File.exists?(new_path) | |
59 | + raise "Already exists" | |
60 | + end | |
54 | 61 | system("mv #{old_path} #{new_path}") |
55 | 62 | end |
56 | 63 | ... | ... |
app/models/project.rb
... | ... | @@ -111,12 +111,14 @@ class Project < ActiveRecord::Base |
111 | 111 | |
112 | 112 | # Apply namespace if user has access to it |
113 | 113 | # else fallback to user namespace |
114 | - project.namespace_id = user.namespace_id | |
115 | - | |
116 | - if namespace_id | |
117 | - group = Group.find_by_id(namespace_id) | |
118 | - if user.can? :manage_group, group | |
119 | - project.namespace_id = namespace_id | |
114 | + if namespace_id != Namespace.global_id | |
115 | + project.namespace_id = user.namespace_id | |
116 | + | |
117 | + if namespace_id | |
118 | + group = Group.find_by_id(namespace_id) | |
119 | + if user.can? :manage_group, group | |
120 | + project.namespace_id = namespace_id | |
121 | + end | |
120 | 122 | end |
121 | 123 | end |
122 | 124 | |
... | ... | @@ -254,12 +256,16 @@ class Project < ActiveRecord::Base |
254 | 256 | old_dir = old_namespace.try(:path) || '' |
255 | 257 | new_dir = new_namespace.try(:path) || '' |
256 | 258 | |
257 | - old_repo = File.join(old_dir, self.path) | |
258 | - | |
259 | - git_host.move_repository(old_repo, self.path_with_namespace, self) | |
259 | + old_repo = if old_dir.present? | |
260 | + File.join(old_dir, self.path) | |
261 | + else | |
262 | + self.path | |
263 | + end | |
260 | 264 | |
261 | 265 | Gitlab::ProjectMover.new(self, old_dir, new_dir).execute |
262 | 266 | |
267 | + git_host.move_repository(old_repo, self.path_with_namespace, self) | |
268 | + | |
263 | 269 | save! |
264 | 270 | end |
265 | 271 | end | ... | ... |
app/roles/repository.rb
... | ... | @@ -83,7 +83,7 @@ module Repository |
83 | 83 | end |
84 | 84 | |
85 | 85 | def path_to_repo |
86 | - File.join(Gitlab.config.git_base_path, namespace_dir, "#{path}.git") | |
86 | + File.join(Gitlab.config.git_base_path, "#{path_with_namespace}.git") | |
87 | 87 | end |
88 | 88 | |
89 | 89 | def namespace_dir |
... | ... | @@ -165,7 +165,7 @@ module Repository |
165 | 165 | |
166 | 166 | # Build file path |
167 | 167 | file_name = self.path + "-" + commit.id.to_s + ".tar.gz" |
168 | - storage_path = Rails.root.join("tmp", "repositories", self.path) | |
168 | + storage_path = Rails.root.join("tmp", "repositories", self.path_with_namespace) | |
169 | 169 | file_path = File.join(storage_path, file_name) |
170 | 170 | |
171 | 171 | # Put files into a directory before archiving | ... | ... |
app/views/admin/dashboard/index.html.haml
... | ... | @@ -28,6 +28,8 @@ |
28 | 28 | %h1= Project.count |
29 | 29 | %hr |
30 | 30 | = link_to 'New Project', new_project_path, class: "btn small" |
31 | + | |
32 | + = link_to 'New Group', new_admin_group_path, class: "btn small" | |
31 | 33 | .span4 |
32 | 34 | .ui-box |
33 | 35 | %h5 Users |
... | ... | @@ -44,7 +46,7 @@ |
44 | 46 | %hr |
45 | 47 | - @projects.each do |project| |
46 | 48 | %p |
47 | - = link_to project.name, [:admin, project] | |
49 | + = link_to project.name_with_namespace, [:admin, project] | |
48 | 50 | .span6 |
49 | 51 | %h3 Latest users |
50 | 52 | %hr | ... | ... |
app/views/admin/groups/new.html.haml
1 | 1 | %h3.page_title New Group |
2 | -%br | |
3 | -= render 'form' | |
2 | +%hr | |
3 | += form_for [:admin, @group] do |f| | |
4 | + - if @group.errors.any? | |
5 | + .alert-message.block-message.error | |
6 | + %span= @group.errors.full_messages.first | |
7 | + .clearfix | |
8 | + = f.label :name do | |
9 | + Group name is | |
10 | + .input | |
11 | + = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" | |
12 | + | |
13 | + = f.submit 'Create group', class: "btn primary" | |
14 | + %hr | |
15 | + .padded | |
16 | + %ul | |
17 | + %li Group is kind of directory for several projects | |
18 | + %li All created groups are private | |
19 | + %li People within a group see only projects they have access to | |
20 | + %li All projects of group will be stored in group directory | |
21 | + %li You will be able to move existing projects into group | ... | ... |
app/views/admin/groups/show.html.haml
... | ... | @@ -22,7 +22,7 @@ |
22 | 22 | %b |
23 | 23 | Path: |
24 | 24 | %td |
25 | - = @group.path | |
25 | + %span.monospace= File.join(Gitlab.config.git_base_path, @group.path) | |
26 | 26 | %tr |
27 | 27 | %td |
28 | 28 | %b |
... | ... | @@ -43,10 +43,14 @@ |
43 | 43 | = link_to 'Remove from group', remove_project_admin_group_path(@group, project_id: project.id), confirm: 'Are you sure?', method: :delete, class: "btn danger small" |
44 | 44 | .clearfix |
45 | 45 | |
46 | -%br | |
47 | -%h3 Add new project | |
48 | -%br | |
46 | + | |
49 | 47 | = form_tag project_update_admin_group_path(@group), class: "bulk_import", method: :put do |
50 | - = select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5' | |
51 | - .form-actions | |
52 | - = submit_tag 'Add', class: "btn primary" | |
48 | + %fieldset | |
49 | + %legend Move projects to group | |
50 | + .clearfix | |
51 | + = label_tag :project_ids do | |
52 | + Projects | |
53 | + .input | |
54 | + = select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5' | |
55 | + .form-actions | |
56 | + = submit_tag 'Add', class: "btn primary" | ... | ... |
app/views/admin/users/_form.html.haml
... | ... | @@ -6,52 +6,42 @@ |
6 | 6 | - @admin_user.errors.full_messages.each do |msg| |
7 | 7 | %li= msg |
8 | 8 | |
9 | - .row | |
10 | - .span7 | |
11 | - .ui-box | |
12 | - %br | |
13 | - .clearfix | |
14 | - = f.label :name | |
15 | - .input | |
16 | - = f.text_field :name | |
17 | - %span.help-inline * required | |
18 | - .clearfix | |
19 | - = f.label :username | |
20 | - .input | |
21 | - = f.text_field :username | |
22 | - %span.help-inline * required | |
23 | - .clearfix | |
24 | - = f.label :email | |
25 | - .input | |
26 | - = f.text_field :email | |
27 | - %span.help-inline * required | |
28 | - %hr | |
29 | - -if f.object.new_record? | |
30 | - .clearfix | |
31 | - = f.label :force_random_password do | |
32 | - %span Generate random password | |
33 | - .input= f.check_box :force_random_password, {}, true, nil | |
9 | + %fieldset | |
10 | + %legend Account | |
11 | + .clearfix | |
12 | + = f.label :name | |
13 | + .input | |
14 | + = f.text_field :name, required: true | |
15 | + %span.help-inline * required | |
16 | + .clearfix | |
17 | + = f.label :username | |
18 | + .input | |
19 | + = f.text_field :username, required: true | |
20 | + %span.help-inline * required | |
21 | + .clearfix | |
22 | + = f.label :email | |
23 | + .input | |
24 | + = f.text_field :email, required: true | |
25 | + %span.help-inline * required | |
34 | 26 | |
35 | - %div.password-fields | |
36 | - .clearfix | |
37 | - = f.label :password | |
38 | - .input= f.password_field :password, disabled: f.object.force_random_password | |
39 | - .clearfix | |
40 | - = f.label :password_confirmation | |
41 | - .input= f.password_field :password_confirmation, disabled: f.object.force_random_password | |
42 | - %hr | |
43 | - .clearfix | |
44 | - = f.label :skype | |
45 | - .input= f.text_field :skype | |
46 | - .clearfix | |
47 | - = f.label :linkedin | |
48 | - .input= f.text_field :linkedin | |
49 | - .clearfix | |
50 | - = f.label :twitter | |
51 | - .input= f.text_field :twitter | |
52 | - .span5 | |
53 | - .ui-box | |
54 | - %br | |
27 | + %fieldset | |
28 | + %legend Password | |
29 | + .clearfix | |
30 | + = f.label :password | |
31 | + .input= f.password_field :password, disabled: f.object.force_random_password | |
32 | + .clearfix | |
33 | + = f.label :password_confirmation | |
34 | + .input= f.password_field :password_confirmation, disabled: f.object.force_random_password | |
35 | + -if f.object.new_record? | |
36 | + .clearfix | |
37 | + = f.label :force_random_password do | |
38 | + %span Generate random password | |
39 | + .input= f.check_box :force_random_password, {}, true, nil | |
40 | + | |
41 | + %fieldset | |
42 | + %legend Access | |
43 | + .row | |
44 | + .span8 | |
55 | 45 | .clearfix |
56 | 46 | = f.label :projects_limit |
57 | 47 | .input= f.number_field :projects_limit |
... | ... | @@ -60,23 +50,27 @@ |
60 | 50 | = f.label :admin do |
61 | 51 | %strong.cred Administrator |
62 | 52 | .input= f.check_box :admin |
53 | + .span4 | |
63 | 54 | - unless @admin_user.new_record? |
64 | - %hr | |
65 | - .padded.cred | |
55 | + .alert.alert-error | |
66 | 56 | - if @admin_user.blocked |
67 | - %span | |
68 | - This user is blocked and is not able to login to GitLab | |
69 | - .clearfix | |
70 | - = link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn small right" | |
57 | + %p This user is blocked and is not able to login to GitLab | |
58 | + = link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn small" | |
71 | 59 | - else |
72 | - %span | |
73 | - Blocked users will be removed from all projects & will not be able to login to GitLab. | |
74 | - .clearfix | |
75 | - = link_to 'Block User', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small right danger" | |
60 | + %p Blocked users will be removed from all projects & will not be able to login to GitLab. | |
61 | + = link_to 'Block User', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small danger" | |
62 | + %fieldset | |
63 | + %legend Profile | |
64 | + .clearfix | |
65 | + = f.label :skype | |
66 | + .input= f.text_field :skype | |
67 | + .clearfix | |
68 | + = f.label :linkedin | |
69 | + .input= f.text_field :linkedin | |
70 | + .clearfix | |
71 | + = f.label :twitter | |
72 | + .input= f.text_field :twitter | |
76 | 73 | |
77 | - .row | |
78 | - .span6 | |
79 | - .span6 | |
80 | 74 | .actions |
81 | 75 | = f.submit 'Save', class: "btn save-btn" |
82 | 76 | - if @admin_user.new_record? | ... | ... |
app/views/admin/users/edit.html.haml
app/views/admin/users/new.html.haml
app/views/dashboard/issues.atom.builder
1 | 1 | xml.instruct! |
2 | 2 | xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do |
3 | - xml.title "#{@user.name} issues" | |
4 | - xml.link :href => dashboard_issues_url(:atom, :private_token => @user.private_token), :rel => "self", :type => "application/atom+xml" | |
5 | - xml.link :href => dashboard_issues_url(:private_token => @user.private_token), :rel => "alternate", :type => "text/html" | |
6 | - xml.id dashboard_issues_url(:private_token => @user.private_token) | |
3 | + xml.title "#{current_user.name} issues" | |
4 | + xml.link :href => dashboard_issues_url(:atom, :private_token => current_user.private_token), :rel => "self", :type => "application/atom+xml" | |
5 | + xml.link :href => dashboard_issues_url(:private_token => current_user.private_token), :rel => "alternate", :type => "text/html" | |
6 | + xml.id dashboard_issues_url(:private_token => current_user.private_token) | |
7 | 7 | xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any? |
8 | 8 | |
9 | 9 | @issues.each do |issue| | ... | ... |
app/views/events/_event.html.haml
app/views/layouts/notify.html.haml
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | %td{style: "font-size: 0px;", width: "20"} |
21 | 21 | \ |
22 | 22 | %td{align: "left", style: "padding: 18px 0 10px;", width: "580"} |
23 | - %h1{style: "color: #BBBBBB; font: normal 32px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 40px;"} | |
23 | + %h1{style: "color: #BBBBBB; font: normal 22px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 32px;"} | |
24 | 24 | GITLAB |
25 | 25 | - if @project |
26 | 26 | | #{@project.name} | ... | ... |
app/views/search/show.html.haml
app/views/shared/_no_ssh.html.haml
1 | 1 | - if current_user.require_ssh_key? |
2 | 2 | %p.error_message |
3 | - You won't be able to pull or push project code until you #{link_to 'add an SSH key', new_key_path} to your profile | |
3 | + You won't be able to pull or push project code via SSH until you #{link_to 'add an SSH key', new_key_path} to your profile | ... | ... |
lib/gitlab/backend/gitolite.rb
lib/gitlab/backend/gitolite_config.rb
... | ... | @@ -109,18 +109,18 @@ module Gitlab |
109 | 109 | end |
110 | 110 | |
111 | 111 | # update or create |
112 | - def update_project(repo_name, project) | |
112 | + def update_project(project) | |
113 | 113 | repo = update_project_config(project, conf) |
114 | 114 | conf.add_repo(repo, true) |
115 | 115 | end |
116 | 116 | |
117 | - def update_project!(repo_name, project) | |
117 | + def update_project!( project) | |
118 | 118 | apply do |config| |
119 | - config.update_project(repo_name, project) | |
119 | + config.update_project(project) | |
120 | 120 | end |
121 | 121 | end |
122 | 122 | |
123 | - # Updates many projects and uses project.path as the repo path | |
123 | + # Updates many projects and uses project.path_with_namespace as the repo path | |
124 | 124 | # An order of magnitude faster than update_project |
125 | 125 | def update_projects(projects) |
126 | 126 | projects.each do |project| | ... | ... |
lib/gitlab/project_mover.rb
... | ... | @@ -21,6 +21,10 @@ module Gitlab |
21 | 21 | old_path = File.join(Gitlab.config.git_base_path, old_dir, "#{project.path}.git") |
22 | 22 | new_path = File.join(new_dir_path, "#{project.path}.git") |
23 | 23 | |
24 | + if File.exists? new_path | |
25 | + raise ProjectMoveError.new("Destination #{new_path} already exists") | |
26 | + end | |
27 | + | |
24 | 28 | if system("mv #{old_path} #{new_path}") |
25 | 29 | log_info "Project #{project.name} was moved from #{old_path} to #{new_path}" |
26 | 30 | true | ... | ... |