diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-12-15 04:36:19 -0500 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-12-15 04:36:19 -0500 |
commit | 381a9b85d4ea82c5792fcc75383b2d0d98b72100 (patch) | |
tree | 182f7421375f771c210405e8586674b2a9f31c06 /git-mirror-gitlab-ee | |
parent | 445d6d320e75917eb6678648b1571be97cf3dcd9 (diff) |
more
Diffstat (limited to 'git-mirror-gitlab-ee')
-rwxr-xr-x | git-mirror-gitlab-ee | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/git-mirror-gitlab-ee b/git-mirror-gitlab-ee new file mode 100755 index 0000000..5467e16 --- /dev/null +++ b/git-mirror-gitlab-ee @@ -0,0 +1,105 @@ +#!/usr/bin/env ruby +# coding: utf-8 + +# GitLab EE supports configuring a "project" (GitLab's term for a +# repository+metadata) to display as a mirror of another repository. +# +# http://docs.gitlab.com/ee/workflow/repository_mirroring.html +# +# Unfortunately, the JSON API doesn't support this +# +# https://gitlab.com/gitlab-org/gitlab-ee/issues/767 +# +# So, we must use the (undocumented!) HTTP API, which is actually +# pretty clean, except that screen-scraping the reads (via nokogiri) +# is gross, and that the error messages are unhelpful. + +load 'gitlab-ce' +require 'net/http' +require 'uri' +require 'nokogiri' + +class GitLabEE < GitLabCE + 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 < GitLabCE::Project + def mirrorURL + unless @cache.has_key?(:mirror) + req = Net::HTTP::Get.new(URI(_info["web_url"]+"/mirror")) + req.add_field("PRIVATE-TOKEN", @api_key) + res = @gl.connection(req.uri).request(req) + if res.code != "200" + throw res + end + @cache[:mirror_res]=res + doc = Nokogiri::HTML(res.body) + + @cache[:mirror_cookie] = res["set-cookie"] + @cache[:mirror_token] = doc.css('input[name="authenticity_token"]').first["value"] + is_mirror = doc.css("#project_mirror").first["checked"] + if !is_mirror + @cache[:mirror] = nil + else + @cache[:mirror] = URI(doc.css("#project_import_url").first["value"]) + end + end + return @cache[:mirror] + end + + def mirrorURL=(url) + self.mirrorURL() + + req = Net::HTTP::Patch.new(URI(self.info["web_url"]+"/mirror")) + req.add_field("PRIVATE-TOKEN", @gl.config['apikey']) # authenticate + req.add_field("Cookie", @cache[:mirror_cookie]) # session id + req.form_data = { + "utf8" => "✓", + "authenticity_token" => @cache[:mirror_token], # session state + "project[mirror]" => (url.nil? ? "0" : "1"), + "project[import_url]" => url.to_s, + } + + res = @gl.connection(req.uri).request(req) + if res.code != "302" + throw res + end + + @cache.delete(:mirror) + @cache.delete(:mirror_token) + @cache.delete(:mirror_cookie) + return URI(url) + end + + def get_meta + map = super + map["mirror"] = self.mirrorURL.to_s + return map + end + + def set_meta(map) + if map.has_key?("mirror") + url = map["mirror"] + map.delete("mirror") + super(map) + self.mirrorURL = url + else + super(map) + end + end + + def repo_mode + return (self.mirrorURL.nil? ? "active" : "passive") + end + end +end + +if __FILE__ == $0 + if ARGV.length != 1 + throw "Usage: $0 ACCOUNT_NAME" + end + GitLabEE.new().repl(ARGV[1]) +end |