#!/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 _mirrorURL unless @cache.has_key?(:mirror) req = Net::HTTP::Get.new(URI(_info["web_url"]+"/mirror")) req.add_field("PRIVATE-TOKEN", @api_key) con = _connection(req.uri) res = con.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) _mirrorURL req = Net::HTTP::Patch.new(URI(_info["web_url"]+"/mirror")) req.add_field("PRIVATE-TOKEN", @api_key) # 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, } con = _connection(req.uri) res = con.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 cmd_get_meta map = super map["mirror"] = _mirrorURL.to_s return map end def cmd_set_meta(map) if map.has_key?("mirror") mirror = map["mirror"] map.delete("mirror") super(map) self._mirrorURL=url else super(map) end end def cmd_repo_mode return "active" end end if __FILE__ == $0 if ARGV.length != 1 throw "Usage: $0 ACCOUNT_NAME" end GitLabEE.new().repl(ARGV[1]) end