diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 8c90f5aee26cb84f8c7053009eddc1fe8623e33b..d34e5a99c796ac8024baca26bbe92bb723b15706 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -27,10 +27,13 @@ class Namespace < ActiveRecord::Base after_create :ensure_dir_exist after_update :move_dir + after_commit :update_gitolite, on: :update, if: :require_update_gitolite after_destroy :rm_dir scope :root, where('type IS NULL') + attr_accessor :require_update_gitolite + def self.search query where("name LIKE :query OR path LIKE :query", query: "%#{query}%") end @@ -48,8 +51,17 @@ class Namespace < ActiveRecord::Base end def ensure_dir_exist - namespace_dir_path = File.join(Gitlab.config.gitolite.repos_path, path) - system("mkdir -m 770 #{namespace_dir_path}") unless File.exists?(namespace_dir_path) + unless dir_exists? + system("mkdir -m 770 #{namespace_full_path}") + end + end + + def dir_exists? + File.exists?(namespace_full_path) + end + + def namespace_full_path + @namespace_full_path ||= File.join(Gitlab.config.gitolite.repos_path, path) end def move_dir @@ -62,10 +74,18 @@ class Namespace < ActiveRecord::Base if system("mv #{old_path} #{new_path}") send_update_instructions + @require_update_gitolite = true + else + raise "Namespace move error #{old_path} #{new_path}" end end end + def update_gitolite + @require_update_gitolite = false + projects.each(&:update_repository) + end + def rm_dir dir_path = File.join(Gitlab.config.gitolite.repos_path, path) system("rm -rf #{dir_path}") diff --git a/app/observers/user_observer.rb b/app/observers/user_observer.rb index 09b3c1d622fe9033991bb244b00f292677daf795..73a1d00ca3bf6f647b3c8ddaa9e26477c1cd6936 100644 --- a/app/observers/user_observer.rb +++ b/app/observers/user_observer.rb @@ -14,7 +14,7 @@ class UserObserver < ActiveRecord::Observer if user.namespace user.namespace.update_attributes(path: user.username) else - user.create_namespace!(path: user.username, name: user.name) + user.create_namespace!(path: user.username, name: user.username) end end end diff --git a/app/roles/namespaced_project.rb b/app/roles/namespaced_project.rb index 8656890a45690557413b9b6e440ef2bc2bc3e357..dbd533f84947c308d0dcc546eeb46156bb8c637a 100644 --- a/app/roles/namespaced_project.rb +++ b/app/roles/namespaced_project.rb @@ -24,7 +24,7 @@ module NamespacedProject save! end rescue Gitlab::ProjectMover::ProjectMoveError => ex - raise TransferError.new(ex.message) + raise Project::TransferError.new(ex.message) end def name_with_namespace diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml index d40d9525bb89d42edac9cb70cff303e6822382c0..f47e8b3e9ff882c0fb32392608a1f1c9dad12034 100644 --- a/app/views/layouts/group.html.haml +++ b/app/views/layouts/group.html.haml @@ -15,7 +15,7 @@ = nav_link(path: 'groups#merge_requests') do = link_to merge_requests_group_path(@group) do Merge Requests - %span.count= current_user.cared_merge_requests.of_group(@group).count + %span.count= current_user.cared_merge_requests.opened.of_group(@group).count = nav_link(path: 'groups#search') do = link_to "Search", search_group_path(@group) = nav_link(path: 'groups#people') do diff --git a/config/initializers/4_resque.rb b/config/initializers/4_resque.rb index 419dbe0606107554236ba85e1abd556bb03c1dfa..03c2b785fae43020336982a7645ee31f15021fcd 100644 --- a/config/initializers/4_resque.rb +++ b/config/initializers/4_resque.rb @@ -27,3 +27,5 @@ Resque::Server.use Authentication # Mailer Resque::Mailer.excluded_environments = [] + +Resque.before_fork = Proc.new { ActiveRecord::Base.establish_connection } diff --git a/db/migrate/20121218164840_move_noteable_commit_to_own_field.rb b/db/migrate/20121218164840_move_noteable_commit_to_own_field.rb index 6f2da4136a3cad9623e68ce7c6021abbe3358ad2..f6b97390b938cee842fd26d6b95b57dbfe031df3 100644 --- a/db/migrate/20121218164840_move_noteable_commit_to_own_field.rb +++ b/db/migrate/20121218164840_move_noteable_commit_to_own_field.rb @@ -5,7 +5,7 @@ class MoveNoteableCommitToOwnField < ActiveRecord::Migration Note.where(noteable_type: 'Commit').update_all('commit_id = noteable_id') if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL' - Note.where("noteable_type != 'Commit'").update_all('new_noteable_id = CAST (noteable_id AS INTEGER)') + Note.where("noteable_type != 'Commit'").update_all('new_noteable_id = CAST (CASE noteable_id WHEN \'\' THEN NULL ELSE noteable_id END AS INTEGER)') else Note.where("noteable_type != 'Commit'").update_all('new_noteable_id = noteable_id') end diff --git a/doc/install/installation.md b/doc/install/installation.md index 718e4cf6419ad367b1d96b8fcdbc1b12115865ea..c85cfd3149eeeabb0fa52ccbf4a4db5f4d379d1a 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -146,8 +146,9 @@ Fix the directory permissions for the configuration directory: Fix the directory permissions for the repositories: # Make sure the repositories dir is owned by git and it stays that way - sudo chmod -R ug+rwXs,o-rwx /home/git/repositories/ + sudo chmod -R ug+rwX,o-rwx /home/git/repositories/ sudo chown -R git:git /home/git/repositories/ + find -type d /home/git/repositories -print0 | sudo xargs -0 chmod g+s ## Disable StrictHostKeyChecking for localhost and your domain diff --git a/lib/tasks/gitlab/cleanup.rake b/lib/tasks/gitlab/cleanup.rake new file mode 100644 index 0000000000000000000000000000000000000000..2a0ffe0f4bdf918e9d8bbeb06acf39b729c0a359 --- /dev/null +++ b/lib/tasks/gitlab/cleanup.rake @@ -0,0 +1,128 @@ +namespace :gitlab do + namespace :cleanup do + desc "GITLAB | Cleanup | Clean gitolite config" + task :config => :environment do + warn_user_is_not_gitlab + + real_repos = Project.all.map(&:path_with_namespace) + real_repos << "gitolite-admin" + real_repos << "@all" + + remove_flag = ENV['REMOVE'] + + puts "Looking for repositories to remove... " + Gitlab::GitoliteConfig.new.apply do |config| + all_repos = [] + garbage_repos = [] + + all_repos = config.conf.repos.keys + garbage_repos = all_repos - real_repos + + garbage_repos.each do |repo_name| + if remove_flag + config.conf.rm_repo(repo_name) + print "to remove...".red + end + + puts repo_name.red + end + end + + unless remove_flag + puts "To cleanup repositories run this command with REMOVE=true".yellow + end + end + + desc "GITLAB | Cleanup | Clean namespaces" + task :dirs => :environment do + warn_user_is_not_gitlab + remove_flag = ENV['REMOVE'] + + + namespaces = Namespace.pluck(:path) + git_base_path = Gitlab.config.gitolite.repos_path + all_dirs = Dir.glob(git_base_path + '/*') + + puts git_base_path.yellow + puts "Looking for directories to remove... " + + all_dirs.reject! do |dir| + # skip if git repo + dir =~ /.git$/ + end + + all_dirs.reject! do |dir| + dir_name = File.basename dir + + # skip if namespace present + namespaces.include?(dir_name) + end + + all_dirs.each do |dir_path| + + if remove_flag + if FileUtils.rm_rf dir_path + puts "Removed...#{dir_path}".red + else + puts "Cannot remove #{dir_path}".red + end + else + puts "Can be removed: #{dir_path}".red + end + end + + unless remove_flag + puts "To cleanup this directories run this command with REMOVE=true".yellow + end + end + + desc "GITLAB | Cleanup | Clean respositories" + task :repos => :environment do + warn_user_is_not_gitlab + remove_flag = ENV['REMOVE'] + + git_base_path = Gitlab.config.gitolite.repos_path + all_dirs = Dir.glob(git_base_path + '/*') + + global_projects = Project.where(namespace_id: nil).pluck(:path) + + puts git_base_path.yellow + puts "Looking for global repos to remove... " + + # skip non git repo + all_dirs.select! do |dir| + dir =~ /.git$/ + end + + # skip existing repos + all_dirs.reject! do |dir| + repo_name = File.basename dir + path = repo_name.gsub(/\.git$/, "") + global_projects.include?(path) + end + + # skip gitolite admin + all_dirs.reject! do |dir| + repo_name = File.basename dir + repo_name == 'gitolite-admin.git' + end + + + all_dirs.each do |dir_path| + if remove_flag + if FileUtils.rm_rf dir_path + puts "Removed...#{dir_path}".red + else + puts "Cannot remove #{dir_path}".red + end + else + puts "Can be removed: #{dir_path}".red + end + end + + unless remove_flag + puts "To cleanup this directories run this command with REMOVE=true".yellow + end + end + end +end diff --git a/lib/tasks/gitlab/enable_namespaces.rake b/lib/tasks/gitlab/enable_namespaces.rake index 1be9ba6469d29860c9a3f62df7002d25136fa0e1..ee80c0905cb4f41a88a677b94636032e0c16c141 100644 --- a/lib/tasks/gitlab/enable_namespaces.rake +++ b/lib/tasks/gitlab/enable_namespaces.rake @@ -1,34 +1,87 @@ namespace :gitlab do desc "GITLAB | Enable usernames and namespaces for user projects" task enable_namespaces: :environment do - print "\nUsernames for users:".yellow + warn_user_is_not_gitlab + migrate_user_namespaces + migrate_groups + migrate_projects + + puts "Rebuild Gitolite ... " + gitolite = Gitlab::Gitolite.new + gitolite.update_repositories(Project.where('namespace_id IS NOT NULL')) + puts "... #{"done".green}" + end + + def migrate_user_namespaces + puts "\nGenerate usernames for users without one: ".blue User.find_each(batch_size: 500) do |user| - next if user.namespace + if user.namespace + print '-'.cyan + next + end - User.transaction do - username = user.email.match(/^[^@]*/)[0] - if user.update_attributes!(username: username) + username = if user.username.present? + # if user already has username filled + user.username + else + build_username(user) + end + + begin + User.transaction do + user.update_attributes!(username: username) print '.'.green - else - print 'F'.red end + rescue + print 'F'.red end end + puts "\nDone" + end + + def build_username(user) + username = nil + + # generate username + username = user.email.match(/^[^@]*/)[0] + username.gsub!("+", ".") + + # return username if no mathes + return username unless User.find_by_username(username) + + # look for same username + (1..10).each do |i| + suffixed_username = "#{username}#{i}" + + return suffixed_username unless User.find_by_username(suffixed_username) + end + end - print "\n\nDirs for groups:".yellow + def migrate_groups + puts "\nCreate directories for groups: ".blue Group.find_each(batch_size: 500) do |group| - if group.ensure_dir_exist - print '.'.green - else + begin + if group.dir_exists? + print '-'.cyan + else + if group.ensure_dir_exist + print '.'.green + else + print 'F'.red + end + end + rescue print 'F'.red end end + puts "\nDone" + end - print "\n\nMove projects from groups under groups dirs:".yellow + def migrate_projects git_path = Gitlab.config.gitolite.repos_path - + puts "\nMove projects in groups into respective directories ... ".blue Project.where('namespace_id IS NOT NULL').find_each(batch_size: 500) do |project| next unless project.group @@ -59,9 +112,6 @@ namespace :gitlab do end end - print "\n\nRebuild gitolite:".yellow - gitolite = Gitlab::Gitolite.new - gitolite.update_repositories(Project.where('namespace_id IS NOT NULL')) - puts "\n" + puts "\nDone" end end diff --git a/lib/tasks/resque.rake b/lib/tasks/resque.rake index 0825324a424812fcc902cbf9a4326856ed85332c..bf031403db8ef9209e9911eedfb4ae8a7cf9c4e3 100644 --- a/lib/tasks/resque.rake +++ b/lib/tasks/resque.rake @@ -4,6 +4,7 @@ task "resque:setup" => :environment do Resque.after_fork do Resque.redis.client.reconnect end + Resque.before_fork = Proc.new { ActiveRecord::Base.establish_connection } end desc "Alias for resque:work (To run workers on Heroku)"