summaryrefslogtreecommitdiff
path: root/backends/gitlab-ee
blob: d0db8b9ca94d26bb23cafebaa21b9291442c497d (plain)
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