repository.rb 3.1 KB
Newer Older
D
Dmitriy Zaporozhets 已提交
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
D
Dmitriy Zaporozhets 已提交
18
        else
J
Jacob Vosmaer 已提交
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
D
Dmitriy Zaporozhets 已提交
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
J
Jacob Vosmaer 已提交
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
D
Dmitriy Zaporozhets 已提交
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)
D
Dmitriy Zaporozhets 已提交
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)
D
Dmitriy Zaporozhets 已提交
63 64 65
          puts "[DONE]".green
        else
          puts "[FAILED]".red
J
Jacob Vosmaer 已提交
66
          abort 'Restore failed'
D
Dmitriy Zaporozhets 已提交
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
J
Jacob Vosmaer 已提交
77
            abort 'Restore failed'
78 79
          end
        end
D
Dmitriy Zaporozhets 已提交
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

D
Dmitriy Zaporozhets 已提交
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
D
Dmitriy Zaporozhets 已提交
117 118
  end
end