Commit f5551efdfd71c6aedb609093374a6c4dbed6a78b

Authored by Dmitriy Zaporozhets
1 parent 70bf7f6e

Rewrite and improve git backend logic. Fix project movind. Raise exception to pr…

…event unexpected issues
app/controllers/admin/groups_controller.rb
... ... @@ -22,6 +22,7 @@ class Admin::GroupsController < AdminController
22 22  
23 23 def create
24 24 @group = Group.new(params[:group])
  25 + @group.path = @group.name.dup.parameterize if @group.name
25 26 @group.owner = current_user
26 27  
27 28 if @group.save
... ...
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
... ... @@ -84,6 +84,7 @@ module ApplicationHelper
84 84 end
85 85  
86 86 options = [
  87 + ["Global", [['/', Namespace.global_id]] ],
87 88 ["Groups", groups.map {|g| [g.human_name, g.id]} ],
88 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 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
1   -%h3.page_title #{@admin_user.name} → Edit user
  1 +%h3.page_title
  2 + #{@admin_user.name} →
  3 + %i.icon-edit
  4 + Edit user
2 5 %hr
3 6 = render 'form'
... ...
app/views/admin/users/new.html.haml
1   -%h3.page_title New user
2   -%br
  1 +%h3.page_title
  2 + %i.icon-plus
  3 + New user
  4 +%hr
3 5 = render 'form'
... ...
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
1 1 - if event.allowed?
2 2 %div.event-item
3 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 6 - if event.push?
7 7 = render "events/event/push", event: event
... ...
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
... ... @@ -23,7 +23,7 @@
23 23 %tr
24 24 %td
25 25 = link_to project do
26   - %strong.term= project.name
  26 + %strong.term= project.name_with_namespace
27 27 %small.cgray
28 28 last activity at
29 29 = project.last_activity_date.stamp("Aug 25, 2011")
... ...
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
... ... @@ -23,7 +23,7 @@ module Gitlab
23 23 end
24 24  
25 25 def update_repository project
26   - config.update_project!(project.path, project)
  26 + config.update_project!(project)
27 27 end
28 28  
29 29 def move_repository(old_repo, new_repo, project)
... ...
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
... ...