diff options
-rwxr-xr-x | backends/gitlab-ce | 188 | ||||
-rwxr-xr-x | backends/gitlab-ee | 28 | ||||
-rw-r--r-- | backends/gitmirrorbackend.rb | 30 | ||||
-rw-r--r-- | docs.org | 2 | ||||
-rwxr-xr-x | git-mirror | 2 |
5 files changed, 150 insertions, 100 deletions
diff --git a/backends/gitlab-ce b/backends/gitlab-ce index 3b6cc90..c91effc 100755 --- a/backends/gitlab-ce +++ b/backends/gitlab-ce @@ -4,37 +4,39 @@ # http://docs.gitlab.com/ee/workflow/repository_mirroring.html # https://gitlab.com/gitlab-org/gitlab-ee/issues/767 +load 'gitmirrorbackend.rb' require 'net/http' require 'uri' require 'cgi' require 'json' -class GitLabCE - def initialize(api_uri, api_key, project_id) - @api_uri = URI(api_uri) - unless @api_uri.path.end_with?("/") - @api_uri.path += "/" +class GitLabCE < GitMirrorBackend + class Error < RuntimeError + def initialize(obj) + @obj = obj end - @api_key = api_key.to_s - @project_id = project_id.to_s - + def obj + return @obj + end + end + def initialize() @connections = {} @cache = {} - # API docs suck, just look at `lib/api/projects.rb` + # API docs suck, look at `lib/api/projects.rb` instead. @vars = [ :builds_enabled, # create | create-user | edit - :container_registry_enabled, # create | | edit - :default_branch # | create-user | edit + :container_registry_enabled, # XXX # create | | edit + :default_branch, # | create-user | edit :description, # create | create-user | edit - :import_url, # create | create-user | + #: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 | | + #:namespace_id, # create | | :only_allow_merge_if_build_succeeds, # create | create-user | edit - :path, # create | | edit + #:path, # create | | edit :public, # create | create-user | edit :public_builds, # create | create-user | edit :request_access_enabled, # create | create-user | edit @@ -44,27 +46,14 @@ class GitLabCE :wiki_enabled, # create | create-user | edit :only_allow_merge_if_all_discussions_are_resolved # create | create-user | edit ] + end - @vars = [ - "builds_enabled", - "container_registry_enabled", - "default_branch", - "description", - "issues_enabled", - "lfs_enabled", - "merge_requests_enabled", - "name", - "only_allow_merge_if_all_discussions_are_resolved", - "only_allow_merge_if_build_succeeds", - "path", - "public", - "public_builds", - "request_access_enabled", - "shared_runners_enabled", - "snippets_enabled", - "visibility_level", - "wiki_enabled", - ] + def finish + @connections.each do |k,v| + v.finish() + end + @connections = {} + super end def _connection(uri) @@ -76,77 +65,108 @@ class GitLabCE return @connections[key] end - def _info - unless @cache.has_key?(:info) - req = Net::HTTP::Get.new(@api_uri + "projects/" + CGI::escape(@project_id)) + def _info(project_id) + @cache[project_id] ||= {} + unless @cache[project_id].has_key?(:info) + req = Net::HTTP::Get.new(@api_uri + "projects/" + CGI::escape(project_id)) req.add_field("PRIVATE-TOKEN", @api_key) con = _connection(req.uri) res = con.request(req) - if res.code != "200" - throw res + case res.code + when "200" + @cache[project_id][:info] = JSON::parse(res.body) + when "404" + @cache[project_id][:info] = nil + else + raise Error.new(res) + end + end + return @cache[project_id][:info] + end + + def cmd_config(*args) + args.each do |arg| + key, val = arg.split('=', 2) + case key + when "apiurl" + @api_uri = URI(val) + unless @api_uri.path.end_with?("/") + @api_uri.path += "/" + end + when "apikey" + @api_key = val end - @cache[:info] = JSON::parse(res.body) end - return @cache[:info] end - def get_meta - return _info.select{|k,v| @vars.include?(k)} + def cmd_get_meta(project_id) + return _info(project_id).select{|k,v| @vars.include?(k.to_sym)} end - def set_meta(map) - illegal = map.select{|k,v| not @vars.include?(k)} + def cmd_set_meta(project_id, *pairs) + map = {} + pairs.each do |pair| + key, val = arg.split('=', 2) + map[key] = val + end + + mirror = map["mirror"] + map.delete("mirror") + + illegal = map.select{|k,v| not @vars.include?(k.to_sym)} if illegal.count > 0 - throw illegal + raise Error.new(illegal) end - req = Net::HTTP::Put.new(@api_uri + "projects/" + CGI::escape(_info["id"].to_s)) - req.add_field("PRIVATE-TOKEN", @api_key) - req.add_field("Content-Type", "application/json") - req.body = JSON::dump(map) - con = _connection(req.uri) - res = con.request(req) - if res.code != "200" - throw res + info = self._info(project_id) + if info == nil + # create + req = Net::HTTP::Put.new(@api_uri + "projects")) + req.add_field("PRIVATE-TOKEN", @api_key) + 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) + con = _connection(req.uri) + res = con.request(req) + if res.code != "201" + raise Error.new(res) + end + @cache[project_id][:info] = JSON::parse(res.body) + else + # update + req = Net::HTTP::Put.new(@api_uri + "projects/" + CGI::escape(info["id"].to_s)) + req.add_field("PRIVATE-TOKEN", @api_key) + req.add_field("Content-Type", "application/json") + req.body = JSON::dump(map) + con = _connection(req.uri) + res = con.request(req) + if res.code != "200" + raise Error.new(res) + end + @cache[project_id][:info] = JSON::parse(res.body) end - @cache[:info] = JSON::parse(res.body) return get_meta end - def pushURL - return _info["ssh_url_to_repo"] + def cmd_push_url(project_id) + return _info(project_id)["ssh_url_to_repo"] end - def pullURL - return _info["http_url_to_repo"] + def cmd_pull_url(project_id) + return _info(project_id)["http_url_to_repo"] end - def create(id, map) - if map.has_key?("mirror") - map["import_url"] = map["mirror"] - map.delete("mirror") - end - req = Net::HTTP::Post.new(@api_uri + "projects") - req.add_field("PRIVATE-TOKEN", @api_key) - req.add_field("Content-Type", "application/json") - req.body = JSON::dump(map) - con = _connection(req.uri) - res = con.request(req) - end - - def capabilities - return [ - [ "get-meta", @vars ].flatten, - [ "set-meta", @vars ].flatten, - [ "push-url" ], - [ "pull-url" ], - ] + def cmd_repo_mode + return "passive" end +end - def finish - @connections.each do |k,v| - v.finish() - end - @connections = {} +if __FILE__ == $0 + if ARGV.length != 1 + raise "Usage: $0 ACCOUNT_NAME" end + GitLabCE.new().repl(ARGV[1]) end diff --git a/backends/gitlab-ee b/backends/gitlab-ee index d0db8b9..b69b1fc 100755 --- a/backends/gitlab-ee +++ b/backends/gitlab-ee @@ -69,31 +69,31 @@ class GitLabEE < GitLabCE return URI(url) end - def get_meta + def cmd_get_meta map = super map["mirror"] = _mirrorURL.to_s return map end - def set_meta(map) + def cmd_set_meta(map) if map.has_key?("mirror") - self._mirrorURL=map["mirror"] + mirror = map["mirror"] map.delete("mirror") + super(map) + self._mirrorURL=url + else + super(map) end - return super(map) end - def create(id, map) - super(id, map) - self._mirrorURL=map["mirror"] + def cmd_repo_mode + return "active" end +end - def capabilities - return super.map{|c| - if c[0] == "get-meta" or c[0] == "set-meta" - c << "mirror" - end - c - } +if __FILE__ == $0 + if ARGV.length != 1 + throw "Usage: $0 ACCOUNT_NAME" end + GitLabEE.new().repl(ARGV[1]) end diff --git a/backends/gitmirrorbackend.rb b/backends/gitmirrorbackend.rb new file mode 100644 index 0000000..25f7c3e --- /dev/null +++ b/backends/gitmirrorbackend.rb @@ -0,0 +1,30 @@ +# coding: utf-8 + +require 'shellwords' + +class GitMirrorBackend + def repl(accountName) + @accountName = account_name + $stdin.each do |line| + args = line.shellsplit + out = self.send('cmd_'+args[0].gsub('-', '_'), *args[1..0]) + if out.is_a? String + puts out + elsif out.is_a? Array + out.each do |outline| + puts outline + end + elsif out.is_a? Hash + out.each do |k,v| + puts "#{k}=#{v}" + end + else + raise "I don't know what to do with output value: #{out}" + end + end + self.finish + end + def finish + # noop + end +end @@ -4,7 +4,7 @@ ** push-url PATH => URL ** get-meta PATH => KEY=VAL\n... ** set-meta PATH KEY=VAL... -** repo-mode => push|pull +** repo-mode => active|passive * ruby interface ** capabilities: .capabilities() => array Returns an array of arrays. Each item in the array is an array of @@ -97,7 +97,7 @@ upload() { # push repository local repo_mode repo_mode=$(remote "$remote" repo-mode) - if [[ $repo_mode == push ]]; then + if [[ $repo_mode == passive ]]; then local push_url push_url="$(remote "$remote" push-url)" cd "$local" && git push --mirror "$push_url" |