BigW Consortium Gitlab

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

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
    # Update HEAD for repository
    #
    # path - project path with namespace
    # branch - repository branch name
    #
    # Ex.
    #  update_repository_head("gitlab/gitlab-ci", "3-1-stable")
    #
    def update_repository_head(path, branch)
66 67
      Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'update-head',
                                   "#{path}.git", branch])
68 69
    end

70 71 72 73 74 75 76 77 78
    # 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)
79 80
      Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'fork-project',
                                   "#{path}.git", fork_namespace])
81 82
    end

83
    # Remove repository from file system
84
    #
85
    # name - project path with namespace
86 87 88 89
    #
    # Ex.
    #   remove_repository("gitlab/gitlab-ci")
    #
90
    def remove_repository(name)
91 92
      Gitlab::Utils.system_silent([gitlab_shell_projects_path,
                                   'rm-project', "#{name}.git"])
93 94
    end

95 96 97 98 99 100 101 102 103 104
    # Add repository branch from passed ref
    #
    # path - project path with namespace
    # branch_name - new branch name
    # ref - HEAD for new branch
    #
    # Ex.
    #   add_branch("gitlab/gitlab-ci", "4-0-stable", "master")
    #
    def add_branch(path, branch_name, ref)
105 106
      Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'create-branch',
                                   "#{path}.git", branch_name, ref])
107 108 109 110 111 112 113 114 115 116 117
    end

    # Remove repository branch
    #
    # path - project path with namespace
    # branch_name - branch name to remove
    #
    # Ex.
    #   rm_branch("gitlab/gitlab-ci", "4-0-stable")
    #
    def rm_branch(path, branch_name)
118 119
      Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'rm-branch',
                                   "#{path}.git", branch_name])
120 121
    end

122 123 124 125 126
    # Add repository tag from passed ref
    #
    # path - project path with namespace
    # tag_name - new tag name
    # ref - HEAD for new tag
127
    # message - optional message for tag (annotated tag)
128 129 130
    #
    # Ex.
    #   add_tag("gitlab/gitlab-ci", "v4.0", "master")
131
    #   add_tag("gitlab/gitlab-ci", "v4.0", "master", "message")
132
    #
133 134 135 136
    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?
137
      Gitlab::Utils.system_silent(cmd)
138 139 140 141 142 143 144 145 146 147 148
    end

    # Remove repository tag
    #
    # path - project path with namespace
    # tag_name - tag name to remove
    #
    # Ex.
    #   rm_tag("gitlab/gitlab-ci", "v4.0")
    #
    def rm_tag(path, tag_name)
149 150
      Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'rm-tag',
                                   "#{path}.git", tag_name])
151 152
    end

153 154 155 156 157 158 159 160 161 162 163 164
    # 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

165
    # Add new key to gitlab-shell
166
    #
167
    # Ex.
168
    #   add_key("key-42", "sha-rsa ...")
169
    #
170
    def add_key(key_id, key_content)
171 172
      Gitlab::Utils.system_silent([gitlab_shell_keys_path,
                                   'add-key', key_id, key_content])
173 174
    end

175 176 177 178 179 180 181 182 183 184
    # 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

185
    # Remove ssh key from gitlab shell
186 187
    #
    # Ex.
188
    #   remove_key("key-342", "sha-rsa ...")
189
    #
190
    def remove_key(key_id, key_content)
191 192
      Gitlab::Utils.system_silent([gitlab_shell_keys_path,
                                   'rm-key', key_id, key_content])
193 194
    end

195 196 197
    # Remove all ssh keys from gitlab shell
    #
    # Ex.
Johannes Schleifenbaum committed
198
    #   remove_all_keys
199 200
    #
    def remove_all_keys
201
      Gitlab::Utils.system_silent([gitlab_shell_keys_path, 'clear'])
202 203
    end

204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
    # 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

234
    def url_to_repo(path)
235
      Gitlab.config.gitlab_shell.ssh_path_prefix + "#{path}.git"
236
    end
237

238 239
    # Return GitLab shell version
    def version
240
      gitlab_shell_version_file = "#{gitlab_shell_path}/VERSION"
241 242

      if File.readable?(gitlab_shell_version_file)
243
        File.read(gitlab_shell_version_file).chomp
244 245 246
      end
    end

247 248 249 250 251 252 253 254 255 256
    # 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

257 258
    protected

259 260 261 262
    def gitlab_shell_path
      Gitlab.config.gitlab_shell.path
    end

263 264 265 266
    def gitlab_shell_user_home
      File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}")
    end

267 268 269 270 271 272 273 274 275 276
    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

277 278 279 280 281 282 283
    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
284 285
  end
end