Sutto-gitauth-gh 0.0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/gitauth-gh ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'pathname'
5
+ require Pathname.new(__FILE__).dirname.dirname.join("lib", "gitauth", "gh_mirror")
6
+
7
+ GitAuth::Application.processing(ARGV) do |a|
8
+
9
+ a.option :user, "The user to mirror, defaults to the result of `git config --global github.user`"
10
+ a.option :token, "The token for said user, defaults to the result of `git config --global github.token`"
11
+ a.controller! :mirror, "Automatically mirrors the specific users repositories", :skip_path => true
12
+
13
+ end
@@ -0,0 +1,204 @@
1
+ require 'httparty'
2
+ require 'yaml'
3
+ require 'ostruct'
4
+ require 'hpricot'
5
+
6
+ class GitHubApi
7
+ include HTTParty
8
+
9
+ class Error < StandardError; end
10
+
11
+ base_uri 'https://github.com'
12
+
13
+ attr_accessor :user, :api_key
14
+
15
+ def initialize(user, api_key)
16
+ @user = user
17
+ @api_key = api_key
18
+ end
19
+
20
+ # Repository Manipulation
21
+
22
+ def create_repository(details = {})
23
+ name = details[:name]
24
+ description = details[:description]
25
+ homepage = details[:homepage]
26
+ is_public = (!!details.fetch(:public, false) ? 1 : 0)
27
+ if [name, description, homepage].any? { |v| v.blank? }
28
+ raise ArgumentError, "You must provide atleast a name, description and a homepage"
29
+ end
30
+ results = post('repos/create', {
31
+ :name => name,
32
+ :description => description,
33
+ :homepage => homepage,
34
+ :public => is_public
35
+ })
36
+ hash_get(results, "repository")
37
+ end
38
+
39
+ def repository(name, user = @user)
40
+ results = get("repos/show/#{user}/#{name}")
41
+ repo = hash_get(results, "repository")
42
+ repo ? Repository.new(repo, self) : nil
43
+ end
44
+
45
+ def repositories(user = @user)
46
+ res = hash_get(get("repos/show/#{user}"), "repositories")
47
+ res.respond_to?(:map) ? res.map { |h| Repository.new(h, self) } : []
48
+ end
49
+
50
+ class Repository
51
+
52
+ class SSHPublicKey < Struct.new(:name, :id); end
53
+
54
+ attr_accessor :name, :api, :attributes, :owner
55
+
56
+ def initialize(attributes, api)
57
+ @name = attributes[:name]
58
+ @owner = attributes[:owner]
59
+ @api = api
60
+ @attributes = OpenStruct.new(attributes)
61
+ end
62
+
63
+ def destroy
64
+ token = api.post("repos/delete/#{@name}")["delete_token"]
65
+ result = api.post("repos/delete/#{@name}", :delete_token => token)
66
+ result.is_a?(Hash) && result["status"] == "deleted"
67
+ end
68
+
69
+ def private?
70
+ !!@attributes.private
71
+ end
72
+
73
+ def public?
74
+ !private?
75
+ end
76
+
77
+ # User Manipulation
78
+
79
+ def collaborators
80
+ res = api.get("repos/show/#{@owner}/#{@name}/collaborators")
81
+ api.hash_get(res, "collaborators")
82
+ end
83
+
84
+ def add_collaborator(name)
85
+ return if name.blank?
86
+ res = api.post("repos/collaborators/#{@name}/add/#{name}")
87
+ api.hash_get(res, "collaborators")
88
+ end
89
+
90
+ def remove_collaborator(name)
91
+ res = api.post("repos/collaborators/#{@name}/remove/#{name}")
92
+ api.hash_get(res, "collaborators")
93
+ end
94
+
95
+ # Hooks
96
+
97
+ def hooks
98
+ response = Hpricot(api.get("https://github.com/#{@owner}/#{@name}/edit/hooks").to_s)
99
+ response.search("//input[@name=urls[]]").map { |e| e[:value] }.compact
100
+ end
101
+
102
+ def hooks=(list)
103
+ list = [*list].compact.uniq
104
+ query_string = list.map { |u| "urls[]=#{URI.escape(u)}" }.join("&")
105
+ post_url = "https://github.com/#{@owner}/#{@name}/edit/postreceive_urls"
106
+ api.post(post_url, query_string)
107
+ end
108
+
109
+ def add_hook(url)
110
+ self.hooks = (hooks + [url])
111
+ hooks.include?(url)
112
+ end
113
+
114
+ def remove_hook(url)
115
+ self.hooks = (hooks - [url])
116
+ !hooks.include?(url)
117
+ end
118
+
119
+ # Keys
120
+
121
+ def keys
122
+ keys = api.hash_get(api.get("repos/keys/#{@name}"), "public_keys")
123
+ return false if keys.nil?
124
+ keys.map { |k| SSHPublicKey.new(k["title"], k["id"]) }
125
+ end
126
+
127
+ def add_key(title, key)
128
+ result = api.get("repos/key/#{@name}/add", {
129
+ :title => title,
130
+ :key => key
131
+ })
132
+ keys = api.hash_get(result, "public_keys")
133
+ return false if keys.nil?
134
+ keys.map { |k| SSHPublicKey.new(k["title"], k["id"]) }
135
+ end
136
+
137
+ def remove_key(key_id)
138
+ end
139
+
140
+ # Misc. Information
141
+
142
+ def tags
143
+ api.hash_get(api.get("repos/show/#{@owner}/#{@name}/tags"), "tags")
144
+ end
145
+
146
+ end
147
+
148
+ # Methods
149
+
150
+ def get(path, opts = {})
151
+ self.class.get(full_path_for(path), :query => with_auth(opts))
152
+ end
153
+
154
+ def post(path, opts = {})
155
+ self.class.post(full_path_for(path), :body => with_auth(opts))
156
+ end
157
+
158
+ def put(path, opts = {})
159
+ self.class.put(full_path_for(path), :body => with_auth(opts))
160
+ end
161
+
162
+ def delete(path, opts = {})
163
+ self.class.delete(full_path_for(path), :body => with_auth(opts))
164
+ end
165
+
166
+ def full_path_for(path, version = 2, format = 'yaml')
167
+ return path if path =~ /^https?\:\/\//i
168
+ File.join("/api/v#{version}/#{format}", path)
169
+ end
170
+
171
+ def with_auth(opts)
172
+ auth = {
173
+ :login => @user,
174
+ :token => @api_key
175
+ }
176
+ if opts.is_a?(Hash)
177
+ opts.merge(auth)
178
+ else
179
+ params = opts.to_s.strip
180
+ params << "&" if params != ""
181
+ params << auth.to_params
182
+ end
183
+ end
184
+
185
+ def check_results!(res)
186
+ if res.is_a?(Hash) && res["error"].present?
187
+ error_msg = res["error"].to_a.map { |h| h["error"] }.join(", ")
188
+ raise Error, error_msg
189
+ end
190
+ end
191
+
192
+ def hash_get(h, k)
193
+ check_results!(h)
194
+ h.is_a?(Hash) && h[k]
195
+ end
196
+
197
+ def self.default
198
+ return @@default if defined?(@@default) && @@default.present?
199
+ user = `git config --global github.user`.strip
200
+ token = `git config --global github.token`.strip
201
+ @@default = self.new(user, token)
202
+ end
203
+
204
+ end
@@ -0,0 +1,93 @@
1
+ require 'gitauth'
2
+
3
+ dir = Pathname.new(__FILE__).dirname.dirname
4
+ $:.unshift(dir) unless $:.include?(dir)
5
+
6
+ require 'git_hub_api'
7
+
8
+ module GitAuth
9
+ class GitHubMirror
10
+ include GitAuth::Loggable
11
+
12
+ Project = Struct.new(:name, :github_clone_url, :repository)
13
+
14
+ VERSION = [0, 0, 1, 0]
15
+
16
+ def initialize(username, token)
17
+ @api = GitHubApi.new(username, token)
18
+ end
19
+
20
+ def projects
21
+ @projects ||= @api.repositories.map do |repository|
22
+ local_repo = GitAuth::Repo.get(repository.name)
23
+ Project.new(repository.name, github_url_for_repo(repository), local_repo)
24
+ end
25
+ end
26
+
27
+ def mirror!(p)
28
+ mirrored?(p) ? update!(p) : clone!(p)
29
+ end
30
+
31
+ def update!(p)
32
+ return unless p.repository
33
+ Dir.chdir(p.repository.real_path) do
34
+ GitAuth.run "git pull origin master --force"
35
+ end
36
+ end
37
+
38
+ def clone!(p)
39
+ if repository = GitAuth::Repo.create(p.name, "#{p.name}.git")
40
+ FileUtils.rm_rf(repository.real_path)
41
+ path = repository.real_path
42
+ Dir.chdir(File.dirname(path)) do
43
+ GitAuth.run "git clone --mirror #{p.github_clone_url} #{File.basename(path)}"
44
+ end
45
+ p.repository = repository
46
+ else
47
+ raise "Error creating local mirror of repository '#{p.name}'"
48
+ end
49
+ end
50
+
51
+ def mirror_all
52
+ logger.info "Mirroring all projects"
53
+ projects.each do |project|
54
+ logger.info "Mirroring for #{project.name} (#{project.github_clone_url})"
55
+ mirror!(project)
56
+ end
57
+ end
58
+
59
+ class << self
60
+
61
+ def run(options = {})
62
+ options = GitAuth::Nash.new(options)
63
+ options.user = `git config --global github.user`.strip unless options.user?
64
+ options.token = `git config --global github.token`.strip unless options.token?
65
+ logger.info "Preparing to run GitHub mirror for #{options.user}"
66
+ mirror = self.new(options.user, options.token)
67
+ mirror.mirror_all
68
+ rescue Exception => e
69
+ logger.fatal "Got Exception: #{e.class.name} - #{e.message}"
70
+ e.backtrace.each { |l| logger.fatal "--> #{l}" }
71
+ end
72
+
73
+ def version(include_path = false)
74
+ VERSION[0, (include_path ? 4 : 3)].join(".")
75
+ end
76
+
77
+ end
78
+
79
+ protected
80
+
81
+ def github_url_for_repo(repo)
82
+ p = repo.private?
83
+ "git#{p ? "@" : "://"}github.com#{p ? ":" : "/"}#{repo.owner}/#{repo.name}.git"
84
+ end
85
+
86
+ def mirrored?(repo)
87
+ repo.repository.present?
88
+ end
89
+
90
+ end
91
+ end
92
+
93
+ GitAuth::Loader.register_controller :mirror, GitAuth::GitHubMirror
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: Sutto-gitauth-gh
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Darcy Laycock
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-17 00:00:00 -07:00
13
+ default_executable: gitauth-gh
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: brownbeagle-gitauth
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.4.5
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: httparty
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description:
36
+ email: sutto@sutto.net
37
+ executables:
38
+ - gitauth-gh
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - bin/gitauth-gh
45
+ - lib/git_hub_api.rb
46
+ - lib/gitauth
47
+ - lib/gitauth/gh_mirror.rb
48
+ has_rdoc: false
49
+ homepage: http://sutto.net/
50
+ licenses:
51
+ post_install_message:
52
+ rdoc_options: []
53
+
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project:
71
+ rubygems_version: 1.3.5
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Automatic mirror for github -> gitauth
75
+ test_files: []
76
+