diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index c57fe4fd..8a0a9e9b 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -22,6 +22,7 @@ class Admin::GroupsController < AdminController def create @group = Group.new(params[:group]) + @group.path = @group.name.dup.parameterize if @group.name @group.owner = current_user if @group.save diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 37b47ade..ed340691 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -34,11 +34,16 @@ class ProjectsController < ProjectResourceController end def update - namespace_id = params[:project].delete(:namespace_id) - - if namespace_id.present? and namespace_id.to_i != project.namespace_id - namespace = Namespace.find(namespace_id) - project.transfer(namespace) + if params[:project].has_key?(:namespace_id) + namespace_id = params[:project].delete(:namespace_id) + if namespace_id == Namespace.global_id and project.namespace.present? + # Transfer to global namespace from anyone + project.transfer(nil) + elsif namespace_id.present? and namespace_id.to_i != project.namespace_id + # Transfer to someone namespace + namespace = Namespace.find(namespace_id) + project.transfer(namespace) + end end respond_to do |format| diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 45d41d92..a284d8ff 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -84,6 +84,7 @@ module ApplicationHelper end options = [ + ["Global", [['/', Namespace.global_id]] ], ["Groups", groups.map {|g| [g.human_name, g.id]} ], [ "Users", users.map {|u| [u.human_name, u.id]} ] ] diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 8eae36db..4e6125e3 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -35,6 +35,10 @@ class Namespace < ActiveRecord::Base where("name LIKE :query OR path LIKE :query", query: "%#{query}%") end + def self.global_id + 'GLN' + end + def to_param path end @@ -51,6 +55,9 @@ class Namespace < ActiveRecord::Base def move_dir old_path = File.join(Gitlab.config.git_base_path, path_was) new_path = File.join(Gitlab.config.git_base_path, path) + if File.exists?(new_path) + raise "Already exists" + end system("mv #{old_path} #{new_path}") end diff --git a/app/models/project.rb b/app/models/project.rb index 707f8286..330f533a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -111,12 +111,14 @@ class Project < ActiveRecord::Base # Apply namespace if user has access to it # else fallback to user namespace - project.namespace_id = user.namespace_id + if namespace_id != Namespace.global_id + project.namespace_id = user.namespace_id - if namespace_id - group = Group.find_by_id(namespace_id) - if user.can? :manage_group, group - project.namespace_id = namespace_id + if namespace_id + group = Group.find_by_id(namespace_id) + if user.can? :manage_group, group + project.namespace_id = namespace_id + end end end @@ -254,12 +256,16 @@ class Project < ActiveRecord::Base old_dir = old_namespace.try(:path) || '' new_dir = new_namespace.try(:path) || '' - old_repo = File.join(old_dir, self.path) - - git_host.move_repository(old_repo, self.path_with_namespace, self) + old_repo = if old_dir.present? + File.join(old_dir, self.path) + else + self.path + end Gitlab::ProjectMover.new(self, old_dir, new_dir).execute + git_host.move_repository(old_repo, self.path_with_namespace, self) + save! end end diff --git a/app/roles/repository.rb b/app/roles/repository.rb index c655ec95..74cae5c8 100644 --- a/app/roles/repository.rb +++ b/app/roles/repository.rb @@ -83,7 +83,7 @@ module Repository end def path_to_repo - File.join(Gitlab.config.git_base_path, namespace_dir, "#{path}.git") + File.join(Gitlab.config.git_base_path, "#{path_with_namespace}.git") end def namespace_dir @@ -165,7 +165,7 @@ module Repository # Build file path file_name = self.path + "-" + commit.id.to_s + ".tar.gz" - storage_path = Rails.root.join("tmp", "repositories", self.path) + storage_path = Rails.root.join("tmp", "repositories", self.path_with_namespace) file_path = File.join(storage_path, file_name) # Put files into a directory before archiving diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index ad8d9f00..b68d7f0d 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -28,6 +28,8 @@ %h1= Project.count %hr = link_to 'New Project', new_project_path, class: "btn small" +   + = link_to 'New Group', new_admin_group_path, class: "btn small" .span4 .ui-box %h5 Users @@ -44,7 +46,7 @@ %hr - @projects.each do |project| %p - = link_to project.name, [:admin, project] + = link_to project.name_with_namespace, [:admin, project] .span6 %h3 Latest users %hr diff --git a/app/views/admin/groups/new.html.haml b/app/views/admin/groups/new.html.haml index d6b6ea15..6ff0e781 100644 --- a/app/views/admin/groups/new.html.haml +++ b/app/views/admin/groups/new.html.haml @@ -1,3 +1,21 @@ %h3.page_title New Group -%br -= render 'form' +%hr += form_for [:admin, @group] do |f| + - if @group.errors.any? + .alert-message.block-message.error + %span= @group.errors.full_messages.first + .clearfix + = f.label :name do + Group name is + .input + = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" +   + = f.submit 'Create group', class: "btn primary" + %hr + .padded + %ul + %li Group is kind of directory for several projects + %li All created groups are private + %li People within a group see only projects they have access to + %li All projects of group will be stored in group directory + %li You will be able to move existing projects into group diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 0254d98a..f447ac10 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -22,7 +22,7 @@ %b Path: %td - = @group.path + %span.monospace= File.join(Gitlab.config.git_base_path, @group.path) %tr %td %b @@ -43,10 +43,14 @@ = 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" .clearfix -%br -%h3 Add new project -%br + = form_tag project_update_admin_group_path(@group), class: "bulk_import", method: :put do - = select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5' - .form-actions - = submit_tag 'Add', class: "btn primary" + %fieldset + %legend Move projects to group + .clearfix + = label_tag :project_ids do + Projects + .input + = select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5' + .form-actions + = submit_tag 'Add', class: "btn primary" diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index 31239856..45195152 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -6,52 +6,42 @@ - @admin_user.errors.full_messages.each do |msg| %li= msg - .row - .span7 - .ui-box - %br - .clearfix - = f.label :name - .input - = f.text_field :name - %span.help-inline * required - .clearfix - = f.label :username - .input - = f.text_field :username - %span.help-inline * required - .clearfix - = f.label :email - .input - = f.text_field :email - %span.help-inline * required - %hr - -if f.object.new_record? - .clearfix - = f.label :force_random_password do - %span Generate random password - .input= f.check_box :force_random_password, {}, true, nil + %fieldset + %legend Account + .clearfix + = f.label :name + .input + = f.text_field :name, required: true + %span.help-inline * required + .clearfix + = f.label :username + .input + = f.text_field :username, required: true + %span.help-inline * required + .clearfix + = f.label :email + .input + = f.text_field :email, required: true + %span.help-inline * required - %div.password-fields - .clearfix - = f.label :password - .input= f.password_field :password, disabled: f.object.force_random_password - .clearfix - = f.label :password_confirmation - .input= f.password_field :password_confirmation, disabled: f.object.force_random_password - %hr - .clearfix - = f.label :skype - .input= f.text_field :skype - .clearfix - = f.label :linkedin - .input= f.text_field :linkedin - .clearfix - = f.label :twitter - .input= f.text_field :twitter - .span5 - .ui-box - %br + %fieldset + %legend Password + .clearfix + = f.label :password + .input= f.password_field :password, disabled: f.object.force_random_password + .clearfix + = f.label :password_confirmation + .input= f.password_field :password_confirmation, disabled: f.object.force_random_password + -if f.object.new_record? + .clearfix + = f.label :force_random_password do + %span Generate random password + .input= f.check_box :force_random_password, {}, true, nil + + %fieldset + %legend Access + .row + .span8 .clearfix = f.label :projects_limit .input= f.number_field :projects_limit @@ -60,23 +50,27 @@ = f.label :admin do %strong.cred Administrator .input= f.check_box :admin + .span4 - unless @admin_user.new_record? - %hr - .padded.cred + .alert.alert-error - if @admin_user.blocked - %span - This user is blocked and is not able to login to GitLab - .clearfix - = link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn small right" + %p This user is blocked and is not able to login to GitLab + = link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn small" - else - %span - Blocked users will be removed from all projects & will not be able to login to GitLab. - .clearfix - = 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" + %p Blocked users will be removed from all projects & will not be able to login to GitLab. + = link_to 'Block User', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small danger" + %fieldset + %legend Profile + .clearfix + = f.label :skype + .input= f.text_field :skype + .clearfix + = f.label :linkedin + .input= f.text_field :linkedin + .clearfix + = f.label :twitter + .input= f.text_field :twitter - .row - .span6 - .span6 .actions = f.submit 'Save', class: "btn save-btn" - if @admin_user.new_record? diff --git a/app/views/admin/users/edit.html.haml b/app/views/admin/users/edit.html.haml index 032e3cfa..f8ff77b8 100644 --- a/app/views/admin/users/edit.html.haml +++ b/app/views/admin/users/edit.html.haml @@ -1,3 +1,6 @@ -%h3.page_title #{@admin_user.name} → Edit user +%h3.page_title + #{@admin_user.name} → + %i.icon-edit + Edit user %hr = render 'form' diff --git a/app/views/admin/users/new.html.haml b/app/views/admin/users/new.html.haml index 70ead0d3..1e82b249 100644 --- a/app/views/admin/users/new.html.haml +++ b/app/views/admin/users/new.html.haml @@ -1,3 +1,5 @@ -%h3.page_title New user -%br +%h3.page_title + %i.icon-plus + New user +%hr = render 'form' diff --git a/app/views/dashboard/issues.atom.builder b/app/views/dashboard/issues.atom.builder index 5bd07bcd..28bdc5ed 100644 --- a/app/views/dashboard/issues.atom.builder +++ b/app/views/dashboard/issues.atom.builder @@ -1,9 +1,9 @@ xml.instruct! xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do - xml.title "#{@user.name} issues" - xml.link :href => dashboard_issues_url(:atom, :private_token => @user.private_token), :rel => "self", :type => "application/atom+xml" - xml.link :href => dashboard_issues_url(:private_token => @user.private_token), :rel => "alternate", :type => "text/html" - xml.id dashboard_issues_url(:private_token => @user.private_token) + xml.title "#{current_user.name} issues" + xml.link :href => dashboard_issues_url(:atom, :private_token => current_user.private_token), :rel => "self", :type => "application/atom+xml" + xml.link :href => dashboard_issues_url(:private_token => current_user.private_token), :rel => "alternate", :type => "text/html" + xml.id dashboard_issues_url(:private_token => current_user.private_token) xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any? @issues.each do |issue| diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml index 0d91a67a..2446b764 100644 --- a/app/views/events/_event.html.haml +++ b/app/views/events/_event.html.haml @@ -1,7 +1,7 @@ - if event.allowed? %div.event-item = event_image(event) - = image_tag gravatar_icon(event.author_email), class: "avatar" + = image_tag gravatar_icon(event.author_email), class: "avatar s24" - if event.push? = render "events/event/push", event: event diff --git a/app/views/layouts/notify.html.haml b/app/views/layouts/notify.html.haml index 8cfe1982..35bf5577 100644 --- a/app/views/layouts/notify.html.haml +++ b/app/views/layouts/notify.html.haml @@ -20,7 +20,7 @@ %td{style: "font-size: 0px;", width: "20"} \  %td{align: "left", style: "padding: 18px 0 10px;", width: "580"} - %h1{style: "color: #BBBBBB; font: normal 32px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 40px;"} + %h1{style: "color: #BBBBBB; font: normal 22px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 32px;"} GITLAB - if @project | #{@project.name} diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml index 0d5f5458..8448193d 100644 --- a/app/views/search/show.html.haml +++ b/app/views/search/show.html.haml @@ -23,7 +23,7 @@ %tr %td = link_to project do - %strong.term= project.name + %strong.term= project.name_with_namespace %small.cgray last activity at = project.last_activity_date.stamp("Aug 25, 2011") diff --git a/app/views/shared/_no_ssh.html.haml b/app/views/shared/_no_ssh.html.haml index c75a1d93..4e643090 100644 --- a/app/views/shared/_no_ssh.html.haml +++ b/app/views/shared/_no_ssh.html.haml @@ -1,3 +1,3 @@ - if current_user.require_ssh_key? %p.error_message - 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 + 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 diff --git a/lib/gitlab/backend/gitolite.rb b/lib/gitlab/backend/gitolite.rb index 79fe150c..05a54ac6 100644 --- a/lib/gitlab/backend/gitolite.rb +++ b/lib/gitlab/backend/gitolite.rb @@ -23,7 +23,7 @@ module Gitlab end def update_repository project - config.update_project!(project.path, project) + config.update_project!(project) end def move_repository(old_repo, new_repo, project) diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb index c000aab0..70ccc478 100644 --- a/lib/gitlab/backend/gitolite_config.rb +++ b/lib/gitlab/backend/gitolite_config.rb @@ -109,18 +109,18 @@ module Gitlab end # update or create - def update_project(repo_name, project) + def update_project(project) repo = update_project_config(project, conf) conf.add_repo(repo, true) end - def update_project!(repo_name, project) + def update_project!( project) apply do |config| - config.update_project(repo_name, project) + config.update_project(project) end end - # Updates many projects and uses project.path as the repo path + # Updates many projects and uses project.path_with_namespace as the repo path # An order of magnitude faster than update_project def update_projects(projects) projects.each do |project| diff --git a/lib/gitlab/project_mover.rb b/lib/gitlab/project_mover.rb index 4b23a546..31ede063 100644 --- a/lib/gitlab/project_mover.rb +++ b/lib/gitlab/project_mover.rb @@ -21,6 +21,10 @@ module Gitlab old_path = File.join(Gitlab.config.git_base_path, old_dir, "#{project.path}.git") new_path = File.join(new_dir_path, "#{project.path}.git") + if File.exists? new_path + raise ProjectMoveError.new("Destination #{new_path} already exists") + end + if system("mv #{old_path} #{new_path}") log_info "Project #{project.name} was moved from #{old_path} to #{new_path}" true