From d03964d6ec4351be76ec978fc0481f24c3b623ec Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 28 Dec 2012 06:14:05 +0300
Subject: [PATCH] Fixed and improved enable_naamespace migration task

---
 app/models/namespace.rb                 |  6 +-
 app/observers/user_observer.rb          |  2 +-
 lib/tasks/gitlab/enable_namespaces.rake | 85 +++++++++++++++++++------
 3 files changed, 71 insertions(+), 22 deletions(-)

diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 96f8f291451..d9c45cb13e2 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -51,8 +51,12 @@ class Namespace < ActiveRecord::Base
   end
 
   def ensure_dir_exist
+    dir_exists? || system("mkdir -m 770 #{namespace_dir_path}")
+  end
+
+  def dir_exists?
     namespace_dir_path = File.join(Gitlab.config.gitolite.repos_path, path)
-    system("mkdir -m 770 #{namespace_dir_path}") unless File.exists?(namespace_dir_path)
+    File.exists?(namespace_dir_path)
   end
 
   def move_dir
diff --git a/app/observers/user_observer.rb b/app/observers/user_observer.rb
index 09b3c1d622f..73a1d00ca3b 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/lib/tasks/gitlab/enable_namespaces.rake b/lib/tasks/gitlab/enable_namespaces.rake
index 81b86d56eb3..aa76a2f7d83 100644
--- a/lib/tasks/gitlab/enable_namespaces.rake
+++ b/lib/tasks/gitlab/enable_namespaces.rake
@@ -3,36 +3,85 @@ namespace :gitlab do
   task enable_namespaces: :environment do
     warn_user_is_not_gitlab
 
-    print "Generate usernames for users without one: "
+    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
 
-    puts ""
-    print "Create directories for groups: "
+  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 ""
+    puts "\nDone"
+  end
 
+  def migrate_projects
     git_path = Gitlab.config.gitolite.repos_path
-    puts ""
-    puts "Move projects in groups into respective directories ... "
+    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
 
@@ -62,10 +111,6 @@ namespace :gitlab do
       end
     end
 
-    puts ""
-    puts "Rebuild Gitolite ... "
-    gitolite = Gitlab::Gitolite.new
-    gitolite.update_repositories(Project.where('namespace_id IS NOT NULL'))
-    puts "... #{"done".green}"
+    puts "\nDone"
   end
 end
-- 
GitLab