Sutto-gitauth-gh 0.0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+