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
@@ -22,6 +22,7 @@ class Admin::GroupsController < AdminController | @@ -22,6 +22,7 @@ class Admin::GroupsController < AdminController | ||
22 | 22 | ||
23 | def create | 23 | def create |
24 | @group = Group.new(params[:group]) | 24 | @group = Group.new(params[:group]) |
25 | + @group.path = @group.name.dup.parameterize if @group.name | ||
25 | @group.owner = current_user | 26 | @group.owner = current_user |
26 | 27 | ||
27 | if @group.save | 28 | if @group.save |
app/controllers/projects_controller.rb
@@ -34,11 +34,16 @@ class ProjectsController < ProjectResourceController | @@ -34,11 +34,16 @@ class ProjectsController < ProjectResourceController | ||
34 | end | 34 | end |
35 | 35 | ||
36 | def update | 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 | end | 47 | end |
43 | 48 | ||
44 | respond_to do |format| | 49 | respond_to do |format| |
app/helpers/application_helper.rb
@@ -84,6 +84,7 @@ module ApplicationHelper | @@ -84,6 +84,7 @@ module ApplicationHelper | ||
84 | end | 84 | end |
85 | 85 | ||
86 | options = [ | 86 | options = [ |
87 | + ["Global", [['/', Namespace.global_id]] ], | ||
87 | ["Groups", groups.map {|g| [g.human_name, g.id]} ], | 88 | ["Groups", groups.map {|g| [g.human_name, g.id]} ], |
88 | [ "Users", users.map {|u| [u.human_name, u.id]} ] | 89 | [ "Users", users.map {|u| [u.human_name, u.id]} ] |
89 | ] | 90 | ] |
app/models/namespace.rb
@@ -35,6 +35,10 @@ class Namespace < ActiveRecord::Base | @@ -35,6 +35,10 @@ class Namespace < ActiveRecord::Base | ||
35 | where("name LIKE :query OR path LIKE :query", query: "%#{query}%") | 35 | where("name LIKE :query OR path LIKE :query", query: "%#{query}%") |
36 | end | 36 | end |
37 | 37 | ||
38 | + def self.global_id | ||
39 | + 'GLN' | ||
40 | + end | ||
41 | + | ||
38 | def to_param | 42 | def to_param |
39 | path | 43 | path |
40 | end | 44 | end |
@@ -51,6 +55,9 @@ class Namespace < ActiveRecord::Base | @@ -51,6 +55,9 @@ class Namespace < ActiveRecord::Base | ||
51 | def move_dir | 55 | def move_dir |
52 | old_path = File.join(Gitlab.config.git_base_path, path_was) | 56 | old_path = File.join(Gitlab.config.git_base_path, path_was) |
53 | new_path = File.join(Gitlab.config.git_base_path, path) | 57 | new_path = File.join(Gitlab.config.git_base_path, path) |
58 | + if File.exists?(new_path) | ||
59 | + raise "Already exists" | ||
60 | + end | ||
54 | system("mv #{old_path} #{new_path}") | 61 | system("mv #{old_path} #{new_path}") |
55 | end | 62 | end |
56 | 63 |
app/models/project.rb
@@ -111,12 +111,14 @@ class Project < ActiveRecord::Base | @@ -111,12 +111,14 @@ class Project < ActiveRecord::Base | ||
111 | 111 | ||
112 | # Apply namespace if user has access to it | 112 | # Apply namespace if user has access to it |
113 | # else fallback to user namespace | 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 | end | 122 | end |
121 | end | 123 | end |
122 | 124 | ||
@@ -254,12 +256,16 @@ class Project < ActiveRecord::Base | @@ -254,12 +256,16 @@ class Project < ActiveRecord::Base | ||
254 | old_dir = old_namespace.try(:path) || '' | 256 | old_dir = old_namespace.try(:path) || '' |
255 | new_dir = new_namespace.try(:path) || '' | 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 | Gitlab::ProjectMover.new(self, old_dir, new_dir).execute | 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 | save! | 269 | save! |
264 | end | 270 | end |
265 | end | 271 | end |
app/roles/repository.rb
@@ -83,7 +83,7 @@ module Repository | @@ -83,7 +83,7 @@ module Repository | ||
83 | end | 83 | end |
84 | 84 | ||
85 | def path_to_repo | 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 | end | 87 | end |
88 | 88 | ||
89 | def namespace_dir | 89 | def namespace_dir |
@@ -165,7 +165,7 @@ module Repository | @@ -165,7 +165,7 @@ module Repository | ||
165 | 165 | ||
166 | # Build file path | 166 | # Build file path |
167 | file_name = self.path + "-" + commit.id.to_s + ".tar.gz" | 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 | file_path = File.join(storage_path, file_name) | 169 | file_path = File.join(storage_path, file_name) |
170 | 170 | ||
171 | # Put files into a directory before archiving | 171 | # Put files into a directory before archiving |
app/views/admin/dashboard/index.html.haml
@@ -28,6 +28,8 @@ | @@ -28,6 +28,8 @@ | ||
28 | %h1= Project.count | 28 | %h1= Project.count |
29 | %hr | 29 | %hr |
30 | = link_to 'New Project', new_project_path, class: "btn small" | 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 | .span4 | 33 | .span4 |
32 | .ui-box | 34 | .ui-box |
33 | %h5 Users | 35 | %h5 Users |
@@ -44,7 +46,7 @@ | @@ -44,7 +46,7 @@ | ||
44 | %hr | 46 | %hr |
45 | - @projects.each do |project| | 47 | - @projects.each do |project| |
46 | %p | 48 | %p |
47 | - = link_to project.name, [:admin, project] | 49 | + = link_to project.name_with_namespace, [:admin, project] |
48 | .span6 | 50 | .span6 |
49 | %h3 Latest users | 51 | %h3 Latest users |
50 | %hr | 52 | %hr |
app/views/admin/groups/new.html.haml
1 | %h3.page_title New Group | 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,7 +22,7 @@ | ||
22 | %b | 22 | %b |
23 | Path: | 23 | Path: |
24 | %td | 24 | %td |
25 | - = @group.path | 25 | + %span.monospace= File.join(Gitlab.config.git_base_path, @group.path) |
26 | %tr | 26 | %tr |
27 | %td | 27 | %td |
28 | %b | 28 | %b |
@@ -43,10 +43,14 @@ | @@ -43,10 +43,14 @@ | ||
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" | 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 | .clearfix | 44 | .clearfix |
45 | 45 | ||
46 | -%br | ||
47 | -%h3 Add new project | ||
48 | -%br | 46 | + |
49 | = form_tag project_update_admin_group_path(@group), class: "bulk_import", method: :put do | 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,52 +6,42 @@ | ||
6 | - @admin_user.errors.full_messages.each do |msg| | 6 | - @admin_user.errors.full_messages.each do |msg| |
7 | %li= msg | 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 | .clearfix | 45 | .clearfix |
56 | = f.label :projects_limit | 46 | = f.label :projects_limit |
57 | .input= f.number_field :projects_limit | 47 | .input= f.number_field :projects_limit |
@@ -60,23 +50,27 @@ | @@ -60,23 +50,27 @@ | ||
60 | = f.label :admin do | 50 | = f.label :admin do |
61 | %strong.cred Administrator | 51 | %strong.cred Administrator |
62 | .input= f.check_box :admin | 52 | .input= f.check_box :admin |
53 | + .span4 | ||
63 | - unless @admin_user.new_record? | 54 | - unless @admin_user.new_record? |
64 | - %hr | ||
65 | - .padded.cred | 55 | + .alert.alert-error |
66 | - if @admin_user.blocked | 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 | - else | 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 | .actions | 74 | .actions |
81 | = f.submit 'Save', class: "btn save-btn" | 75 | = f.submit 'Save', class: "btn save-btn" |
82 | - if @admin_user.new_record? | 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 | xml.instruct! | 1 | xml.instruct! |
2 | xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do | 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 | xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any? | 7 | xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any? |
8 | 8 | ||
9 | @issues.each do |issue| | 9 | @issues.each do |issue| |
app/views/events/_event.html.haml
1 | - if event.allowed? | 1 | - if event.allowed? |
2 | %div.event-item | 2 | %div.event-item |
3 | = event_image(event) | 3 | = event_image(event) |
4 | - = image_tag gravatar_icon(event.author_email), class: "avatar" | 4 | + = image_tag gravatar_icon(event.author_email), class: "avatar s24" |
5 | 5 | ||
6 | - if event.push? | 6 | - if event.push? |
7 | = render "events/event/push", event: event | 7 | = render "events/event/push", event: event |
app/views/layouts/notify.html.haml
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | %td{style: "font-size: 0px;", width: "20"} | 20 | %td{style: "font-size: 0px;", width: "20"} |
21 | \ | 21 | \ |
22 | %td{align: "left", style: "padding: 18px 0 10px;", width: "580"} | 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 | GITLAB | 24 | GITLAB |
25 | - if @project | 25 | - if @project |
26 | | #{@project.name} | 26 | | #{@project.name} |
app/views/search/show.html.haml
@@ -23,7 +23,7 @@ | @@ -23,7 +23,7 @@ | ||
23 | %tr | 23 | %tr |
24 | %td | 24 | %td |
25 | = link_to project do | 25 | = link_to project do |
26 | - %strong.term= project.name | 26 | + %strong.term= project.name_with_namespace |
27 | %small.cgray | 27 | %small.cgray |
28 | last activity at | 28 | last activity at |
29 | = project.last_activity_date.stamp("Aug 25, 2011") | 29 | = project.last_activity_date.stamp("Aug 25, 2011") |
app/views/shared/_no_ssh.html.haml
1 | - if current_user.require_ssh_key? | 1 | - if current_user.require_ssh_key? |
2 | %p.error_message | 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
@@ -23,7 +23,7 @@ module Gitlab | @@ -23,7 +23,7 @@ module Gitlab | ||
23 | end | 23 | end |
24 | 24 | ||
25 | def update_repository project | 25 | def update_repository project |
26 | - config.update_project!(project.path, project) | 26 | + config.update_project!(project) |
27 | end | 27 | end |
28 | 28 | ||
29 | def move_repository(old_repo, new_repo, project) | 29 | def move_repository(old_repo, new_repo, project) |
lib/gitlab/backend/gitolite_config.rb
@@ -109,18 +109,18 @@ module Gitlab | @@ -109,18 +109,18 @@ module Gitlab | ||
109 | end | 109 | end |
110 | 110 | ||
111 | # update or create | 111 | # update or create |
112 | - def update_project(repo_name, project) | 112 | + def update_project(project) |
113 | repo = update_project_config(project, conf) | 113 | repo = update_project_config(project, conf) |
114 | conf.add_repo(repo, true) | 114 | conf.add_repo(repo, true) |
115 | end | 115 | end |
116 | 116 | ||
117 | - def update_project!(repo_name, project) | 117 | + def update_project!( project) |
118 | apply do |config| | 118 | apply do |config| |
119 | - config.update_project(repo_name, project) | 119 | + config.update_project(project) |
120 | end | 120 | end |
121 | end | 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 | # An order of magnitude faster than update_project | 124 | # An order of magnitude faster than update_project |
125 | def update_projects(projects) | 125 | def update_projects(projects) |
126 | projects.each do |project| | 126 | projects.each do |project| |
lib/gitlab/project_mover.rb
@@ -21,6 +21,10 @@ module Gitlab | @@ -21,6 +21,10 @@ module Gitlab | ||
21 | old_path = File.join(Gitlab.config.git_base_path, old_dir, "#{project.path}.git") | 21 | old_path = File.join(Gitlab.config.git_base_path, old_dir, "#{project.path}.git") |
22 | new_path = File.join(new_dir_path, "#{project.path}.git") | 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 | if system("mv #{old_path} #{new_path}") | 28 | if system("mv #{old_path} #{new_path}") |
25 | log_info "Project #{project.name} was moved from #{old_path} to #{new_path}" | 29 | log_info "Project #{project.name} was moved from #{old_path} to #{new_path}" |
26 | true | 30 | true |