summaryrefslogtreecommitdiff
path: root/git-mirror-gitlab-ce
diff options
context:
space:
mode:
Diffstat (limited to 'git-mirror-gitlab-ce')
-rwxr-xr-xgit-mirror-gitlab-ce202
1 files changed, 202 insertions, 0 deletions
diff --git a/git-mirror-gitlab-ce b/git-mirror-gitlab-ce
new file mode 100755
index 0000000..a8d885e
--- /dev/null
+++ b/git-mirror-gitlab-ce
@@ -0,0 +1,202 @@
+#!/usr/bin/env ruby
+# coding: utf-8
+
+load 'git-mirror-backend.rb'
+require 'net/http'
+require 'uri'
+require 'cgi'
+require 'json'
+
+class GitLabCE < GitMirrorBackend
+ class Error < RuntimeError
+ def initialize(obj)
+ @obj = obj
+ end
+ def obj
+ return @obj
+ end
+ end
+
+ def initialize()
+ @connections = {}
+ @projects = {}
+ @config = {}
+ end
+
+ def connection(uri)
+ key=URI(uri.scheme+":")
+ key.host = uri.host
+ key.port = uri.port
+
+ @connections[key] ||= Net::HTTP::start(uri.host, uri.port, :use_ssl => uri.scheme == 'https')
+ return @connections[key]
+ end
+
+ def finish
+ @connections.each do |k,v|
+ v.finish()
+ end
+ @connections = {}
+ super
+ end
+
+ def config
+ return @config
+ end
+
+ # Project
+ def project(project_id)
+ unless @projects.has_key?(project_id)
+ @projects[project_id] = Project.new(self, project_id)
+ end
+ return @projects[project_id]
+ end
+ class Project
+ def initialize(gl, project_id)
+ @gl = gl
+ @project_id = project_id
+ @cache = {}
+ end
+
+ def info
+ unless @cache.has_key?(:info)
+ req = Net::HTTP::Get.new(@gl.config['apiurl'] + "projects/" + CGI::escape(@project_id))
+ req.add_field("PRIVATE-TOKEN", @gl.config['apikey'])
+ res = @gl.connection(req.uri).request(req)
+ case res.code
+ when "200"
+ @cache[:info] = JSON::parse(res.body)
+ when "404"
+ @cache[:info] = nil
+ else
+ raise Error.new(res)
+ end
+ end
+ return @cache[:info]
+ end
+
+ def info=(i)
+ @cache[:info] = i
+ end
+
+ def get_meta
+ return self.info.select{|k,v| @vars.include?(k.to_sym)}
+ end
+
+ def set_meta(map)
+ mirror = map["mirror"]
+ map.delete("mirror")
+
+ illegal = map.select{|k,v| not @vars.include?(k.to_sym)}
+ if illegal.count > 0
+ raise Error.new(illegal)
+ end
+
+ if info == nil
+ # create
+ req = Net::HTTP::Put.new(@gl.config['apiurl'] + "projects")
+ req.add_field("PRIVATE-TOKEN", @gl.config['apikey'])
+ req.add_field("Content-Type", "application/json")
+ map["path"] = @project_id
+ if not mirror.nil?
+ map["import_url"] = mirror
+ end
+ req.body = JSON::dump(map)
+ res = @gl.connection(req.uri).request(req)
+ if res.code != "201"
+ raise Error.new(res)
+ end
+ info = JSON::parse(res.body)
+ else
+ # update
+ req = Net::HTTP::Put.new(@gl.config['apiurl'] + "projects/" + CGI::escape(info["id"].to_s))
+ req.add_field("PRIVATE-TOKEN", @gl.config['apikey'])
+ req.add_field("Content-Type", "application/json")
+ req.body = JSON::dump(map)
+ res = @gl.connection(req.uri).request(req)
+ if res.code != "200"
+ raise Error.new(res)
+ end
+ info = JSON::parse(res.body)
+ end
+ return self.get_meta
+ end
+
+ def repo_mode
+ return "passive"
+ end
+ end
+
+ # commands
+ def cmd_config(*args)
+ args.each do |arg|
+ key, val = arg.split('=', 2)
+ case key
+ when "apiurl"
+ val = URI(val)
+ unless val.path.end_with?("/")
+ val.path += "/"
+ end
+ end
+ @config[key] = val
+ end
+ end
+
+ def cmd_get_meta(project_id)
+ return self.project(project_id).get_meta()
+ end
+
+ def cmd_set_meta(project_id, *pairs)
+ map = {}
+ pairs.each do |pair|
+ key, val = arg.split('=', 2)
+ map[key] = val
+ end
+ return self.project(project_id).set_meta(map)
+ end
+
+ def cmd_push_url(project_id)
+ return self.project(project_id).info["ssh_url_to_repo"]
+ end
+
+ def cmd_pull_url(project_id)
+ return self.project(project_id).info["http_url_to_repo"]
+ end
+
+ def cmd_repo_mode(project_id)
+ return self.project(projecT_id).repo_mode()
+ end
+
+ def vars
+ # API docs suck, look at `lib/api/projects.rb` instead.
+ return [
+ :builds_enabled, # create | create-user | edit
+ :container_registry_enabled, # XXX # create | | edit
+ :default_branch, # | create-user | edit
+ :description, # create | create-user | edit
+ #:import_url, # XXX # create | create-user |
+ :issues_enabled, # create | create-user | edit
+ :lfs_enabled, # create | create-user | edit
+ :merge_requests_enabled, # create | create-user | edit
+ :name, # create | create-user | edit
+ #:namespace_id, # create | |
+ :only_allow_merge_if_build_succeeds, # create | create-user | edit
+ #:path, # create | | edit
+ :public, # create | create-user | edit
+ :public_builds, # create | create-user | edit
+ :request_access_enabled, # create | create-user | edit
+ :shared_runners_enabled, # create | create-user | edit
+ :snippets_enabled, # create | create-user | edit
+ :visibility_level, # create | create-user | edit
+ :wiki_enabled, # create | create-user | edit
+ :only_allow_merge_if_all_discussions_are_resolved # create | create-user | edit
+ ]
+ end
+end
+
+if __FILE__ == $0
+ if ARGV.length != 1
+ raise "Usage: $0 ACCOUNT_NAME"
+ end
+ GitLabCE.new().repl(ARGV[1])
+end