OSDN Git Service

refactor backup/restore
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Fri, 5 Apr 2013 16:01:19 +0000 (19:01 +0300)
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Fri, 5 Apr 2013 16:01:19 +0000 (19:01 +0300)
doc/install/databases.md
lib/backup.rb [deleted file]
lib/backup/database.rb [new file with mode: 0644]
lib/backup/repository.rb [new file with mode: 0644]
lib/tasks/gitlab/backup.rake

index fade5d4..a198e72 100644 (file)
@@ -21,7 +21,7 @@ GitLab supports the following databases:
     mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
 
     # Grant the GitLab user necessary permissopns on the table.
-    mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `gitlabhq_production`.* TO 'gitlab'@'localhost';
+    mysql> GRANT SELECT, LOCK TABLES, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `gitlabhq_production`.* TO 'gitlab'@'localhost';
 
     # Quit the database session
     mysql> \q
diff --git a/lib/backup.rb b/lib/backup.rb
deleted file mode 100644 (file)
index ad80ab1..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-require 'yaml'
-
-class Backup
-  attr_reader :config, :db_dir
-
-  def initialize
-    @config = YAML.load_file(File.join(Rails.root,'config','database.yml'))[Rails.env]
-    @db_dir = File.join(Gitlab.config.backup.path, 'db')
-    FileUtils.mkdir_p(@db_dir) unless Dir.exists?(@db_dir)
-  end
-
-  def backup_db
-    case config["adapter"]
-    when /^mysql/ then
-      system("mysqldump #{mysql_args} #{config['database']} > #{db_file_name}")
-    when "postgresql" then
-      pg_env
-      system("pg_dump #{config['database']} > #{db_file_name}")
-    end
-  end
-
-  def restore_db
-    case config["adapter"]
-    when /^mysql/ then
-      system("mysql #{mysql_args} #{config['database']} < #{db_file_name}")
-    when "postgresql" then
-      pg_env
-      system("pg_restore #{config['database']} #{db_file_name}")
-    end
-  end
-
-  protected
-
-  def db_file_name
-    File.join(db_dir, 'database.sql')
-  end
-
-  def mysql_args
-    args = {
-      'host'      => '--host',
-      'port'      => '--port',
-      'socket'    => '--socket',
-      'username'  => '--user',
-      'encoding'  => '--default-character-set',
-      'password'  => '--password'
-    }
-    args.map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }.compact.join(' ')
-  end
-
-  def pg_env
-    ENV['PGUSER']     = config["username"] if config["username"]
-    ENV['PGHOST']     = config["host"] if config["host"]
-    ENV['PGPORT']     = config["port"].to_s if config["port"]
-    ENV['PGPASSWORD'] = config["password"].to_s if config["password"]
-  end
-end
diff --git a/lib/backup/database.rb b/lib/backup/database.rb
new file mode 100644 (file)
index 0000000..cfa9971
--- /dev/null
@@ -0,0 +1,58 @@
+require 'yaml'
+
+module Backup
+  class Database
+    attr_reader :config, :db_dir
+
+    def initialize
+      @config = YAML.load_file(File.join(Rails.root,'config','database.yml'))[Rails.env]
+      @db_dir = File.join(Gitlab.config.backup.path, 'db')
+      FileUtils.mkdir_p(@db_dir) unless Dir.exists?(@db_dir)
+    end
+
+    def dump
+      case config["adapter"]
+      when /^mysql/ then
+        system("mysqldump #{mysql_args} #{config['database']} > #{db_file_name}")
+      when "postgresql" then
+        pg_env
+        system("pg_dump #{config['database']} > #{db_file_name}")
+      end
+    end
+
+    def restore
+      case config["adapter"]
+      when /^mysql/ then
+        system("mysql #{mysql_args} #{config['database']} < #{db_file_name}")
+      when "postgresql" then
+        pg_env
+        system("pg_restore #{config['database']} #{db_file_name}")
+      end
+    end
+
+    protected
+
+    def db_file_name
+      File.join(db_dir, 'database.sql')
+    end
+
+    def mysql_args
+      args = {
+        'host'      => '--host',
+        'port'      => '--port',
+        'socket'    => '--socket',
+        'username'  => '--user',
+        'encoding'  => '--default-character-set',
+        'password'  => '--password'
+      }
+      args.map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }.compact.join(' ')
+    end
+
+    def pg_env
+      ENV['PGUSER']     = config["username"] if config["username"]
+      ENV['PGHOST']     = config["host"] if config["host"]
+      ENV['PGPORT']     = config["port"].to_s if config["port"]
+      ENV['PGPASSWORD'] = config["password"].to_s if config["password"]
+    end
+  end
+end
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
new file mode 100644 (file)
index 0000000..c1d0896
--- /dev/null
@@ -0,0 +1,74 @@
+require 'yaml'
+
+module Backup
+  class Repository
+    attr_reader :repos_path
+
+    def dump
+      prepare
+
+      Project.find_each(batch_size: 1000) do |project|
+        print " * #{project.path_with_namespace} ... "
+
+        if project.empty_repo?
+          puts "[SKIPPED]".cyan
+          next
+        end
+
+        # Create namespace dir if missing
+        FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.path)) if project.namespace
+
+        if system("cd #{path_to_repo(project)} > /dev/null 2>&1 && git bundle create #{path_to_bundle(project)} --all > /dev/null 2>&1")
+          puts "[DONE]".green
+        else
+          puts "[FAILED]".red
+        end
+      end
+    end
+
+    def restore
+      if File.exists?(repos_path)
+        # Move repos dir to 'repositories.old' dir
+        bk_repos_path = File.join(repos_path, '..', 'repositories.old')
+        FileUtils.mv(repos_path, bk_repos_path)
+      end
+
+      FileUtils.mkdir_p(repos_path)
+
+      Project.find_each(batch_size: 1000) do |project|
+        print "#{project.path_with_namespace} ... "
+
+        project.namespace.ensure_dir_exist if project.namespace
+
+        if system("git clone --bare #{path_to_bundle(project)} #{path_to_repo(project)} > /dev/null 2>&1")
+          puts "[DONE]".green
+        else
+          puts "[FAILED]".red
+        end
+      end
+    end
+
+    protected
+
+    def path_to_repo(project)
+      File.join(repos_path, project.path_with_namespace + '.git')
+    end
+
+    def path_to_bundle(project)
+      File.join(backup_repos_path, project.path_with_namespace + ".bundle")
+    end
+
+    def repos_path
+      Gitlab.config.gitlab_shell.repos_path
+    end
+
+    def backup_repos_path
+      File.join(Gitlab.config.backup.path, "repositories")
+    end
+
+    def prepare
+      FileUtils.rm_rf(backup_repos_path)
+      FileUtils.mkdir_p(backup_repos_path)
+    end
+  end
+end
index 393f816..1f86342 100644 (file)
@@ -111,67 +111,28 @@ namespace :gitlab do
 
     namespace :repo do
       task :create => :environment do
-        backup_path_repo = File.join(Gitlab.config.backup.path, "repositories")
-        FileUtils.mkdir_p(backup_path_repo) until Dir.exists?(backup_path_repo)
         puts "Dumping repositories ...".blue
-
-        Project.find_each(:batch_size => 1000) do |project|
-          print " * #{project.path_with_namespace} ... "
-
-          if project.empty_repo?
-            puts "[SKIPPED]".cyan
-            next
-          end
-
-          # Create namespace dir if missing
-          FileUtils.mkdir_p(File.join(backup_path_repo, project.namespace.path)) if project.namespace
-
-          # Build a destination path for backup
-          path_to_bundle  = File.join(backup_path_repo, project.path_with_namespace + ".bundle")
-
-          if Kernel.system("cd #{project.repository.path_to_repo} > /dev/null 2>&1 && git bundle create #{path_to_bundle} --all > /dev/null 2>&1")
-            puts "[DONE]".green
-          else
-            puts "[FAILED]".red
-          end
-        end
+        Backup::Repository.new.dump
+        puts "done".green
       end
 
       task :restore => :environment do
-        backup_path_repo = File.join(Gitlab.config.backup.path, "repositories")
-        repos_path = Gitlab.config.gitlab_shell.repos_path
-
-        puts "Restoring repositories ... "
-
-        Project.find_each(:batch_size => 1000) do |project|
-          print "#{project.path_with_namespace} ... "
-
-          if project.namespace
-            project.namespace.ensure_dir_exist
-          end
-
-          # Build a backup path
-          path_to_bundle  = File.join(backup_path_repo, project.path_with_namespace + ".bundle")
-
-          if Kernel.system("git clone --bare #{path_to_bundle} #{project.repository.path_to_repo} > /dev/null 2>&1")
-            puts "[DONE]".green
-          else
-            puts "[FAILED]".red
-          end
-        end
+        puts "Restoring repositories ...".blue
+        Backup::Repository.new.restore
+        puts "done".green
       end
     end
 
     namespace :db do
       task :create => :environment do
         puts "Dumping database ... ".blue
-        Backup.new.backup_db
+        Backup::Database.new.dump
         puts "done".green
       end
 
       task :restore => :environment do
         puts "Restoring database ... ".blue
-        Backup.new.restore_db
+        Backup::Database.new.restore
         puts "done".green
       end
     end