shell.rb 5.99 KB
Newer Older
1
module Gitlab
2
  class Shell
3
    class Error < StandardError; end
4

Gabriel Mazetto's avatar
Gabriel Mazetto committed
5
    KeyAdder = Struct.new(:io) do
6
      def add_key(id, key)
7 8
        key.gsub!(/[[:space:]]+/, ' ').strip!
        io.puts("#{id}\t#{key}")
9 10 11
      end
    end

12 13 14 15 16 17 18
    class << self
      def version_required
        @version_required ||= File.read(Rails.root.
                                        join('GITLAB_SHELL_VERSION')).strip
      end
    end

19
    # Init new repository
20
    #
21
    # name - project path with namespace
22 23
    #
    # Ex.
24
    #   add_repository("gitlab/gitlab-ci")
25
    #
26
    def add_repository(name)
27 28
      Gitlab::Utils.system_silent([gitlab_shell_projects_path,
                                   'add-project', "#{name}.git"])
29 30
    end

31 32 33 34 35 36 37 38
    # Import repository
    #
    # name - project path with namespace
    #
    # Ex.
    #   import_repository("gitlab/gitlab-ci", "https://github.com/randx/six.git")
    #
    def import_repository(name, url)
39
      output, status = Popen::popen([gitlab_shell_projects_path, 'import-project', "#{name}.git", url, '900'])
40 41
      raise Error, output unless status.zero?
      true
42 43
    end

44 45 46 47 48 49
    # Move repository
    #
    # path - project path with namespace
    # new_path - new project path with namespace
    #
    # Ex.
50
    #   mv_repository("gitlab/gitlab-ci", "randx/gitlab-ci-new")
51 52
    #
    def mv_repository(path, new_path)
53 54
      Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'mv-project',
                                   "#{path}.git", "#{new_path}.git"])
55 56
    end

57 58 59 60 61 62 63 64 65
    # Fork repository to new namespace
    #
    # path - project path with namespace
    # fork_namespace - namespace for forked project
    #
    # Ex.
    #  fork_repository("gitlab/gitlab-ci", "randx")
    #
    def fork_repository(path, fork_namespace)
66 67
      Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'fork-project',
                                   "#{path}.git", fork_namespace])
68 69
    end

70
    # Remove repository from file system
71
    #
72
    # name - project path with namespace
73 74 75 76
    #
    # Ex.
    #   remove_repository("gitlab/gitlab-ci")
    #
77
    def remove_repository(name)
78 79
      Gitlab::Utils.system_silent([gitlab_shell_projects_path,
                                   'rm-project', "#{name}.git"])
80 81
    end

82 83 84 85 86
    # Add repository tag from passed ref
    #
    # path - project path with namespace
    # tag_name - new tag name
    # ref - HEAD for new tag
87
    # message - optional message for tag (annotated tag)
88 89 90
    #
    # Ex.
    #   add_tag("gitlab/gitlab-ci", "v4.0", "master")
91
    #   add_tag("gitlab/gitlab-ci", "v4.0", "master", "message")
92
    #
93 94 95 96
    def add_tag(path, tag_name, ref, message = nil)
      cmd = %W(#{gitlab_shell_path}/bin/gitlab-projects create-tag #{path}.git
               #{tag_name} #{ref})
      cmd << message unless message.nil? || message.empty?
97
      Gitlab::Utils.system_silent(cmd)
98 99
    end

100 101 102 103 104 105 106 107 108 109 110 111
    # Gc repository
    #
    # path - project path with namespace
    #
    # Ex.
    #   gc("gitlab/gitlab-ci")
    #
    def gc(path)
      Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'gc',
                                   "#{path}.git"])
    end

112
    # Add new key to gitlab-shell
113
    #
114
    # Ex.
115
    #   add_key("key-42", "sha-rsa ...")
116
    #
117
    def add_key(key_id, key_content)
118 119
      Gitlab::Utils.system_silent([gitlab_shell_keys_path,
                                   'add-key', key_id, key_content])
120 121
    end

122 123 124 125 126 127 128 129 130 131
    # Batch-add keys to authorized_keys
    #
    # Ex.
    #   batch_add_keys { |adder| adder.add_key("key-42", "sha-rsa ...") }
    def batch_add_keys(&block)
      IO.popen(%W(#{gitlab_shell_path}/bin/gitlab-keys batch-add-keys), 'w') do |io|
        block.call(KeyAdder.new(io))
      end
    end

132
    # Remove ssh key from gitlab shell
133 134
    #
    # Ex.
135
    #   remove_key("key-342", "sha-rsa ...")
136
    #
137
    def remove_key(key_id, key_content)
138 139
      Gitlab::Utils.system_silent([gitlab_shell_keys_path,
                                   'rm-key', key_id, key_content])
140 141
    end

142 143 144
    # Remove all ssh keys from gitlab shell
    #
    # Ex.
Johannes Schleifenbaum's avatar
Johannes Schleifenbaum committed
145
    #   remove_all_keys
146 147
    #
    def remove_all_keys
148
      Gitlab::Utils.system_silent([gitlab_shell_keys_path, 'clear'])
149 150
    end

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
    # Add empty directory for storing repositories
    #
    # Ex.
    #   add_namespace("gitlab")
    #
    def add_namespace(name)
      FileUtils.mkdir(full_path(name), mode: 0770) unless exists?(name)
    end

    # Remove directory from repositories storage
    # Every repository inside this directory will be removed too
    #
    # Ex.
    #   rm_namespace("gitlab")
    #
    def rm_namespace(name)
      FileUtils.rm_r(full_path(name), force: true)
    end

    # Move namespace directory inside repositories storage
    #
    # Ex.
    #   mv_namespace("gitlab", "gitlabhq")
    #
    def mv_namespace(old_name, new_name)
      return false if exists?(new_name) || !exists?(old_name)

      FileUtils.mv(full_path(old_name), full_path(new_name))
    end

181
    def url_to_repo(path)
182
      Gitlab.config.gitlab_shell.ssh_path_prefix + "#{path}.git"
183
    end
184

185 186
    # Return GitLab shell version
    def version
187
      gitlab_shell_version_file = "#{gitlab_shell_path}/VERSION"
188 189

      if File.readable?(gitlab_shell_version_file)
190
        File.read(gitlab_shell_version_file).chomp
191 192 193
      end
    end

194 195 196 197 198 199 200 201 202 203
    # Check if such directory exists in repositories.
    #
    # Usage:
    #   exists?('gitlab')
    #   exists?('gitlab/cookies.git')
    #
    def exists?(dir_name)
      File.exists?(full_path(dir_name))
    end

204 205
    protected

206 207 208 209
    def gitlab_shell_path
      Gitlab.config.gitlab_shell.path
    end

210 211 212 213
    def gitlab_shell_user_home
      File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}")
    end

214 215 216 217 218 219 220 221 222 223
    def repos_path
      Gitlab.config.gitlab_shell.repos_path
    end

    def full_path(dir_name)
      raise ArgumentError.new("Directory name can't be blank") if dir_name.blank?

      File.join(repos_path, dir_name)
    end

224 225 226 227 228 229 230
    def gitlab_shell_projects_path
      File.join(gitlab_shell_path, 'bin', 'gitlab-projects')
    end

    def gitlab_shell_keys_path
      File.join(gitlab_shell_path, 'bin', 'gitlab-keys')
    end
231 232
  end
end