repository.rb 3.14 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
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} ... "

        # Create namespace dir if missing
        FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.path)) if project.namespace

16 17
        if project.empty_repo?
          puts "[SKIPPED]".cyan
18
        else
19 20 21 22 23 24 25 26
          output, status = Gitlab::Popen.popen(%W(git --git-dir=#{path_to_repo(project)} bundle create #{path_to_bundle(project)} --all))
          if status.zero?
            puts "[DONE]".green
          else
            puts "[FAILED]".red
            puts output
            abort 'Backup failed'
          end
27
        end
28

29
        wiki = ProjectWiki.new(project)
30 31 32

        if File.exists?(path_to_repo(wiki))
          print " * #{wiki.path_with_namespace} ... "
33
          if wiki.repository.empty?
34
            puts " [SKIPPED]".cyan
35
          else
36 37 38 39 40 41 42
            output, status = Gitlab::Popen.popen(%W(git --git-dir=#{path_to_repo(wiki)} bundle create #{path_to_bundle(wiki)} --all))
            if status.zero?
              puts " [DONE]".green
            else
              puts " [FAILED]".red
              abort 'Backup failed'
            end
43 44
          end
        end
45 46 47 48 49 50
      end
    end

    def restore
      if File.exists?(repos_path)
        # Move repos dir to 'repositories.old' dir
51
        bk_repos_path = File.join(repos_path, '..', 'repositories.old.' + Time.now.to_i.to_s)
52 53 54 55 56 57 58 59 60 61
        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

62
        if system(*%W(git clone --bare #{path_to_bundle(project)} #{path_to_repo(project)}), silent)
63 64 65
          puts "[DONE]".green
        else
          puts "[FAILED]".red
66
          abort 'Restore failed'
67
        end
68

69
        wiki = ProjectWiki.new(project)
70 71 72

        if File.exists?(path_to_bundle(wiki))
          print " * #{wiki.path_with_namespace} ... "
73
          if system(*%W(git clone --bare #{path_to_bundle(wiki)} #{path_to_repo(wiki)}), silent)
74 75 76
            puts " [DONE]".green
          else
            puts " [FAILED]".red
77
            abort 'Restore failed'
78 79
          end
        end
80
      end
81 82

      print 'Put GitLab hooks in repositories dirs'.yellow
83
      if system("#{Gitlab.config.gitlab_shell.path}/bin/create-hooks")
84 85 86 87 88
        puts " [DONE]".green
      else
        puts " [FAILED]".red
      end

89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
    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
113 114 115 116

    def silent
      {err: '/dev/null', out: '/dev/null'}
    end
117 118
  end
end