ddollar-octopi 0.0.13
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/.gitignore +3 -0
- data/LICENSE +20 -0
- data/README.rdoc +169 -0
- data/Rakefile +83 -0
- data/VERSION.yml +4 -0
- data/contrib/backup.rb +100 -0
- data/examples/authenticated.rb +20 -0
- data/examples/github.yml.example +14 -0
- data/examples/issues.rb +18 -0
- data/examples/overall.rb +50 -0
- data/lib/octopi.rb +236 -0
- data/lib/octopi/base.rb +111 -0
- data/lib/octopi/blob.rb +21 -0
- data/lib/octopi/branch.rb +18 -0
- data/lib/octopi/commit.rb +65 -0
- data/lib/octopi/error.rb +23 -0
- data/lib/octopi/file_object.rb +15 -0
- data/lib/octopi/issue.rb +102 -0
- data/lib/octopi/key.rb +18 -0
- data/lib/octopi/repository.rb +111 -0
- data/lib/octopi/resource.rb +75 -0
- data/lib/octopi/tag.rb +17 -0
- data/lib/octopi/user.rb +99 -0
- data/octopi.gemspec +66 -0
- data/test/octopi_test.rb +46 -0
- data/test/test_helper.rb +10 -0
- metadata +83 -0
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Felipe Coury
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
= octopi
|
2
|
+
|
3
|
+
Octopi is a Ruby interface to GitHub API v2 (http://develop.github.com).
|
4
|
+
|
5
|
+
To install it as a Gem, just run:
|
6
|
+
|
7
|
+
$ sudo gem install octopi
|
8
|
+
|
9
|
+
Get notifications via Twitter, following @octopi_gem:
|
10
|
+
http://twitter.com/octopi_gem
|
11
|
+
|
12
|
+
== Authenticated Usage
|
13
|
+
|
14
|
+
=== Seamless authentication using .gitconfig defaults
|
15
|
+
|
16
|
+
If you have your <tt>~/.gitconfig</tt> file in place, and you have a [github] section (if you don't, take a look at this GitHub Guides entry: http://github.com/guides/tell-git-your-user-name-and-email-address), you can use seamless authentication using this method:
|
17
|
+
|
18
|
+
authenticated do |g|
|
19
|
+
repo = g.repository("api-labrat")
|
20
|
+
(...)
|
21
|
+
end
|
22
|
+
|
23
|
+
=== Explicit authentication
|
24
|
+
|
25
|
+
Sometimes, you may not want to get authentication data from <tt>~/.gitconfig</tt>. You want to use GitHub API authenticated as a third party. For this use case, you have a couple of options too.
|
26
|
+
|
27
|
+
<b>1. Providing login and token inline:</b>
|
28
|
+
|
29
|
+
authenticated_with "mylogin", "mytoken" do |g|
|
30
|
+
repo = g.repository("api-labrat")
|
31
|
+
issue = repo.open_issue :title => "Sample issue",
|
32
|
+
:body => "This issue was opened using GitHub API and Octopi"
|
33
|
+
puts issue.number
|
34
|
+
end
|
35
|
+
|
36
|
+
<b>2. Providing a YAML file with authentication information:</b>
|
37
|
+
|
38
|
+
Use the following format:
|
39
|
+
|
40
|
+
#
|
41
|
+
# Octopi GitHub API configuration file
|
42
|
+
#
|
43
|
+
|
44
|
+
# GitHub user login and token
|
45
|
+
login: github-username
|
46
|
+
token: github-token
|
47
|
+
|
48
|
+
# Trace level
|
49
|
+
# Possible values:
|
50
|
+
# false - no tracing, same as if the param is ommited
|
51
|
+
# true - will output each POST or GET operation to the stdout
|
52
|
+
# curl - same as true, but in addition will output the curl equivalent of each command (for debugging)
|
53
|
+
trace: curl
|
54
|
+
|
55
|
+
And change the way you connect to:
|
56
|
+
|
57
|
+
authenticated_with :config => "github.yml" do |g|
|
58
|
+
(...)
|
59
|
+
end
|
60
|
+
|
61
|
+
== Anonymous Usage
|
62
|
+
|
63
|
+
This reflects the usage of the API to retrieve information on a read-only fashion, where the user doesn't have to be authenticated.
|
64
|
+
|
65
|
+
=== Users API
|
66
|
+
|
67
|
+
Getting user information
|
68
|
+
|
69
|
+
user = User.find("fcoury")
|
70
|
+
puts "#{user.name} is being followed by #{user.followers.join(", ")} and following #{user.following.join(", ")}"
|
71
|
+
|
72
|
+
The bang methods `followers!` and `following!` retrieves a full User object for each user login returned, so it has to be used carefully.
|
73
|
+
|
74
|
+
user.followers!.each do |u|
|
75
|
+
puts " - #{u.name} (#{u.login}) has #{u.public_repo_count} repo(s)"
|
76
|
+
end
|
77
|
+
|
78
|
+
Searching for user
|
79
|
+
|
80
|
+
users = User.find_all("silva")
|
81
|
+
puts "#{users.size} users found for 'silva':"
|
82
|
+
users.each do |u|
|
83
|
+
puts " - #{u.name}"
|
84
|
+
end
|
85
|
+
|
86
|
+
=== Repositories API
|
87
|
+
|
88
|
+
repo = user.repository("octopi") # same as: Repository.find("fcoury", "octopi")
|
89
|
+
puts "Repository: #{repo.name} - #{repo.description} (by #{repo.owner}) - #{repo.url}"
|
90
|
+
puts " Tags: #{repo.tags and repo.tags.map {|t| t.name}.join(", ")}"
|
91
|
+
|
92
|
+
Search:
|
93
|
+
|
94
|
+
repos = Repository.find_all("ruby", "git")
|
95
|
+
puts "#{repos.size} repository(ies) with 'ruby' and 'git':"
|
96
|
+
repos.each do |r|
|
97
|
+
puts " - #{r.name}"
|
98
|
+
end
|
99
|
+
|
100
|
+
Issues API integrated into the Repository object:
|
101
|
+
|
102
|
+
issue = repo.issues.first
|
103
|
+
puts "First open issue: #{issue.number} - #{issue.title} - Created at: #{issue.created_at}"
|
104
|
+
|
105
|
+
Single issue information:
|
106
|
+
|
107
|
+
issue = repo.issue(11)
|
108
|
+
|
109
|
+
Commits API information from a Repository object:
|
110
|
+
|
111
|
+
first_commit = repo.commits.first
|
112
|
+
puts "First commit: #{first_commit.id} - #{first_commit.message} - by #{first_commit.author['name']}"
|
113
|
+
|
114
|
+
Single commit information:
|
115
|
+
|
116
|
+
puts "Diff:"
|
117
|
+
first_commit.details.modified.each {|m| puts "#{m['filename']} DIFF: #{m['diff']}" }
|
118
|
+
|
119
|
+
== Tracing
|
120
|
+
|
121
|
+
=== Levels
|
122
|
+
|
123
|
+
You can can use tracing to enable better debugging output when something goes wrong. There are 3 tracing levels:
|
124
|
+
|
125
|
+
* false (default) - no tracing
|
126
|
+
* true - will output each GET and POST calls, along with URL and params
|
127
|
+
* curl - same as true, but additionally outputs the curl command to replicate the issue
|
128
|
+
|
129
|
+
If you choose curl tracing, the curl command equivalent to each command sent to GitHub will be output to the stdout, like this example:
|
130
|
+
|
131
|
+
=> Trace on: curl
|
132
|
+
POST: /issues/open/webbynode/api-labrat params: body=This issue was opened using GitHub API and Octopi, title=Sample issue
|
133
|
+
===== curl version
|
134
|
+
curl -F 'body=This issue was opened using GitHub API and Octopi' -F 'login=mylogin' -F 'token=mytoken' -F 'title=Sample issue' http://github.com/api/v2/issues/open/webbynode/api-labrat
|
135
|
+
==================
|
136
|
+
|
137
|
+
=== Enabling
|
138
|
+
|
139
|
+
Tracing can be enabled in different ways, depending on the API feature you're using:
|
140
|
+
|
141
|
+
<b>Anonymous (this will be improved later):</b>
|
142
|
+
|
143
|
+
ANONYMOUS_API.trace_level = "trace-level"
|
144
|
+
|
145
|
+
<b>Seamless authenticated</b>
|
146
|
+
|
147
|
+
authenticated :trace => "trace-level" do |g|; ...; end
|
148
|
+
|
149
|
+
<b>Explicitly authenticated</b>
|
150
|
+
|
151
|
+
Current version of explicit authentication requires a :config param to a YAML file to allow tracing. For enabling tracing on a YAML file refer to the config.yml example presented on the Explicit authentication section.
|
152
|
+
|
153
|
+
== Author
|
154
|
+
|
155
|
+
* Felipe Coury - http://felipecoury.com
|
156
|
+
* HasMany.info blog - http://hasmany.info
|
157
|
+
|
158
|
+
== Contributors
|
159
|
+
|
160
|
+
In alphabetical order:
|
161
|
+
|
162
|
+
* Brandon Calloway - http://github.com/bcalloway
|
163
|
+
* runpaint - http://github.com/runpaint
|
164
|
+
|
165
|
+
Thanks guys!
|
166
|
+
|
167
|
+
== Copyright
|
168
|
+
|
169
|
+
Copyright (c) 2009 Felipe Coury. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "octopi"
|
8
|
+
gem.summary = %Q{A Ruby interface to GitHub API v2}
|
9
|
+
gem.email = "felipe.coury@gmail.com"
|
10
|
+
gem.homepage = "http://github.com/fcoury/octopi"
|
11
|
+
gem.authors = ["Felipe Coury"]
|
12
|
+
gem.rubyforge_project = "octopi"
|
13
|
+
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
18
|
+
end
|
19
|
+
|
20
|
+
begin
|
21
|
+
require 'rake/contrib/sshpublisher'
|
22
|
+
namespace :rubyforge do
|
23
|
+
|
24
|
+
desc "Release gem and RDoc documentation to RubyForge"
|
25
|
+
task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
|
26
|
+
|
27
|
+
namespace :release do
|
28
|
+
desc "Publish RDoc to RubyForge."
|
29
|
+
task :docs => [:rdoc] do
|
30
|
+
config = YAML.load(
|
31
|
+
File.read(File.expand_path('~/.rubyforge/user-config.yml'))
|
32
|
+
)
|
33
|
+
|
34
|
+
host = "#{config['username']}@rubyforge.org"
|
35
|
+
remote_dir = "/var/www/gforge-projects/octopi/"
|
36
|
+
local_dir = 'rdoc'
|
37
|
+
|
38
|
+
Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
rescue LoadError
|
43
|
+
puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
|
44
|
+
end
|
45
|
+
|
46
|
+
require 'rake/testtask'
|
47
|
+
Rake::TestTask.new(:test) do |test|
|
48
|
+
test.libs << 'lib' << 'test'
|
49
|
+
test.pattern = 'test/**/*_test.rb'
|
50
|
+
test.verbose = false
|
51
|
+
end
|
52
|
+
|
53
|
+
begin
|
54
|
+
require 'rcov/rcovtask'
|
55
|
+
Rcov::RcovTask.new do |test|
|
56
|
+
test.libs << 'test'
|
57
|
+
test.pattern = 'test/**/*_test.rb'
|
58
|
+
test.verbose = true
|
59
|
+
end
|
60
|
+
rescue LoadError
|
61
|
+
task :rcov do
|
62
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
task :default => :test
|
68
|
+
|
69
|
+
require 'rake/rdoctask'
|
70
|
+
Rake::RDocTask.new do |rdoc|
|
71
|
+
if File.exist?('VERSION.yml')
|
72
|
+
config = YAML.load(File.read('VERSION.yml'))
|
73
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
74
|
+
else
|
75
|
+
version = ""
|
76
|
+
end
|
77
|
+
|
78
|
+
rdoc.rdoc_dir = 'rdoc'
|
79
|
+
rdoc.title = "octopi #{version}"
|
80
|
+
rdoc.rdoc_files.include('README*')
|
81
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
82
|
+
end
|
83
|
+
|
data/VERSION.yml
ADDED
data/contrib/backup.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'octopi')
|
2
|
+
|
3
|
+
USAGE_MSG = <<EOF
|
4
|
+
Usage: #{$0} <user> [<directory>]
|
5
|
+
|
6
|
+
Performs a backup of the named user's GitHub.com data.
|
7
|
+
|
8
|
+
This script will fetch the repositories, along with their metadata and
|
9
|
+
associated issues, for the named user. It will also retrieve the user's
|
10
|
+
profile, and those of his followers. This data will be stored in
|
11
|
+
<directory>/<user>. If a directory is not supplied, ~/.github-backup will be
|
12
|
+
used instead.
|
13
|
+
EOF
|
14
|
+
# TODO: Accept list of targets as argument. The main use case is somebody
|
15
|
+
# wanting all of their repositories checked out, without the performane hit
|
16
|
+
# and clutter of the extraneous metadata,
|
17
|
+
include Octopi
|
18
|
+
|
19
|
+
class Object
|
20
|
+
def to_yaml_file(file)
|
21
|
+
File.open("#{file}.yaml", 'w') do |f|
|
22
|
+
YAML.dump(self, f)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
TARGETS = [:user, :followers, :repositories, :issues]
|
28
|
+
|
29
|
+
@user, @basedir = ARGV
|
30
|
+
raise ArgumentError, USAGE_MSG unless @user
|
31
|
+
@basedir ||= File.expand_path("~/.github-backup")
|
32
|
+
@basedir = File.join(@basedir,@user)
|
33
|
+
TARGETS.map{|k| k.to_s}.each do |dir|
|
34
|
+
dir = File.join(@basedir,dir)
|
35
|
+
FileUtils.mkdir_p(dir) unless File.exists? dir
|
36
|
+
end
|
37
|
+
|
38
|
+
@user = User.find(@user)
|
39
|
+
|
40
|
+
def user
|
41
|
+
puts "* Saving profile"
|
42
|
+
@user.to_yaml_file(@user.login)
|
43
|
+
end
|
44
|
+
|
45
|
+
def followers
|
46
|
+
@user.followers!.each do |follower|
|
47
|
+
puts "* #{follower.login} (#{follower.name})"
|
48
|
+
follower.to_yaml_file(follower.login)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def repositories
|
53
|
+
@user.repositories.each do |repo|
|
54
|
+
puts "* #{repo.name} (#{repo.description})\n---"
|
55
|
+
|
56
|
+
git_dir = File.join(repo.name,'.git')
|
57
|
+
# FIXME: Instead of just checking for a Git directory, we could try `git
|
58
|
+
# pull`, and if that indicates that the repository doesn't exist, `git
|
59
|
+
# clone`
|
60
|
+
if File.exists? git_dir
|
61
|
+
Dir.chdir repo.name do
|
62
|
+
# FIXME: If this fails, try deleting the clone and re-cloning?
|
63
|
+
# FIXME: Confirm this is the best solution as opposed to re-cloning
|
64
|
+
# every time, using `git fetch` or `git clone --mirror`.
|
65
|
+
system("git pull")
|
66
|
+
end
|
67
|
+
else
|
68
|
+
system("git clone #{repo.clone_url}")
|
69
|
+
end
|
70
|
+
repo.to_yaml_file(repo.name)
|
71
|
+
puts
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# TODO: For forked repositories whose parents have issue trackers, get their
|
76
|
+
# issues instead.
|
77
|
+
def issues
|
78
|
+
FileUtils.mkdir_p @user.repositories.map{|r| r.name}
|
79
|
+
@user.repositories.each do |repo|
|
80
|
+
puts "#{repo.name}"
|
81
|
+
Dir.chdir(repo.name) do
|
82
|
+
repo.all_issues.each do |issue|
|
83
|
+
puts "* #{issue.title} [#{issue.state}]"
|
84
|
+
issue.to_yaml_file(issue.number)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
TARGETS.each do |target|
|
91
|
+
target.to_s.each do |title|
|
92
|
+
puts title.capitalize
|
93
|
+
title.length.times {print '#'}
|
94
|
+
end
|
95
|
+
puts
|
96
|
+
Dir.chdir(File.join(@basedir, target.to_s)) do
|
97
|
+
send(target)
|
98
|
+
end
|
99
|
+
puts
|
100
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'octopi')
|
2
|
+
|
3
|
+
include Octopi
|
4
|
+
|
5
|
+
authenticated :trace => "curl" do |g|
|
6
|
+
repo = g.repository("api-labrat")
|
7
|
+
|
8
|
+
issue = repo.open_issue :title => "Sample issue",
|
9
|
+
:body => "This issue was opened using GitHub API and Octopi"
|
10
|
+
puts "Successfully opened issue \##{issue.number}"
|
11
|
+
|
12
|
+
# # labels = issue.add_label "Working", "Todo"
|
13
|
+
# # puts "Labels: #{labels.inspect}"
|
14
|
+
|
15
|
+
issue.close
|
16
|
+
puts "Successfully closed issue \##{issue.number}"
|
17
|
+
|
18
|
+
# labels = issue.remove_label "Todo"
|
19
|
+
# puts "Successfully removed label Todo. Current labels: #{labels.inspect}"
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#
|
2
|
+
# Octopi GitHub API configuration file
|
3
|
+
#
|
4
|
+
|
5
|
+
# GitHub user login and token
|
6
|
+
login: github-username
|
7
|
+
token: github-token
|
8
|
+
|
9
|
+
# Trace level
|
10
|
+
# Possible values:
|
11
|
+
# false - no tracing, same as if the param is ommited
|
12
|
+
# true - will output each POST or GET operation to the stdout
|
13
|
+
# curl - same as true, but in addition will output the curl equivalent of each command (for debugging)
|
14
|
+
trace: curl
|
data/examples/issues.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'octopi')
|
2
|
+
|
3
|
+
include Octopi
|
4
|
+
|
5
|
+
user = User.find("fcoury")
|
6
|
+
puts user.name
|
7
|
+
|
8
|
+
repo = user.repository("octopi")
|
9
|
+
puts repo.description
|
10
|
+
|
11
|
+
issue = Issue.find_all(user.login, repo.name).first
|
12
|
+
puts "First open issue: #{issue.number} - #{issue.title} - Created at: #{issue.created_at}"
|
13
|
+
|
14
|
+
issue2 = repo.issues.first
|
15
|
+
puts "First open issue: #{issue.number} - #{issue.title} - Created at: #{issue.created_at}"
|
16
|
+
|
17
|
+
issue3 = repo.issue(issue2.number)
|
18
|
+
puts "First open issue: #{issue.number} - #{issue.title} - Created at: #{issue.created_at}"
|
data/examples/overall.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'octopi')
|
2
|
+
|
3
|
+
include Octopi
|
4
|
+
|
5
|
+
# user information
|
6
|
+
user = User.find("fcoury")
|
7
|
+
puts "#{user.name} is being followed by #{user.followers.join(", ")} and following #{user.following.join(", ")}"
|
8
|
+
|
9
|
+
# the bang version of followers and following
|
10
|
+
# fetches user object for each user, but is
|
11
|
+
# a lot more expensive
|
12
|
+
user.followers!.each do |u|
|
13
|
+
puts " - #{u.name} (#{u.login}) has #{u.public_repo_count} repo(s)"
|
14
|
+
end
|
15
|
+
|
16
|
+
# search user
|
17
|
+
users = User.find_all("silva")
|
18
|
+
puts "#{users.size} users found for 'silva':"
|
19
|
+
users.each do |u|
|
20
|
+
puts " - #{u.name}"
|
21
|
+
end
|
22
|
+
|
23
|
+
# repository information
|
24
|
+
# to get all repos for user: user.repositories
|
25
|
+
repo = user.repository("octopi") # same as: Repository.find("fcoury", "octopi")
|
26
|
+
puts "Repository: #{repo.name} - #{repo.description} (by #{repo.owner}) - #{repo.url}"
|
27
|
+
puts " Tags: #{repo.tags and repo.tags.map {|t| t.name}.join(", ")}"
|
28
|
+
|
29
|
+
issue = repo.issues.first
|
30
|
+
puts "Sample open issue: #{issue.number} - #{issue.title} - Created at: #{issue.created_at}"
|
31
|
+
|
32
|
+
# commits of a the repository
|
33
|
+
commit = repo.commits.first
|
34
|
+
puts "Commit: #{commit.id} - #{commit.message} - by #{commit.author['name']}"
|
35
|
+
|
36
|
+
# single commit information
|
37
|
+
# details is the same as: Commit.find(commit)
|
38
|
+
puts "Diff:"
|
39
|
+
commit.details.modified.each {|m| puts "#{m['filename']} DIFF: #{m['diff']}" }
|
40
|
+
|
41
|
+
# repository search
|
42
|
+
repos = Repository.find_all("ruby", "git")
|
43
|
+
puts "#{repos.size} repository(ies) with 'ruby' and 'git':"
|
44
|
+
repos.each do |r|
|
45
|
+
puts " - #{r.name}"
|
46
|
+
end
|
47
|
+
|
48
|
+
# connect "user", "<< token >>" do |github|
|
49
|
+
# puts github.user.name
|
50
|
+
# end
|