1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
#!/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 get_meta
map = super
map["mirror"] = _mirrorURL.to_s
return map
end
def set_meta(map)
if map.has_key?("mirror")
self._mirrorURL=map["mirror"]
map.delete("mirror")
end
return super(map)
end
def create(id, map)
super(id, map)
self._mirrorURL=map["mirror"]
end
def capabilities
return super.map{|c|
if c[0] == "get-meta" or c[0] == "set-meta"
c << "mirror"
end
c
}
end
end
|