octonaut 0.0.1
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/LICENSE.md +20 -0
- data/README.md +184 -0
- data/Rakefile +8 -0
- data/bin/octonaut +4 -0
- data/lib/octonaut.rb +66 -0
- data/lib/octonaut/commands/common.rb +19 -0
- data/lib/octonaut/commands/repositories.rb +42 -0
- data/lib/octonaut/commands/users.rb +88 -0
- data/lib/octonaut/helpers.rb +20 -0
- data/lib/octonaut/printer.rb +31 -0
- data/lib/octonaut/printers/organizations.rb +37 -0
- data/lib/octonaut/printers/repositories.rb +49 -0
- data/lib/octonaut/printers/users.rb +41 -0
- data/lib/octonaut/version.rb +3 -0
- data/octonaut.gemspec +32 -0
- data/spec/fixtures/.netrc +2 -0
- data/spec/fixtures/languages.json +10 -0
- data/spec/fixtures/languages.table +8 -0
- data/spec/fixtures/repositories.json +2522 -0
- data/spec/fixtures/repositories.ls +30 -0
- data/spec/fixtures/repository.json +85 -0
- data/spec/fixtures/user.json +42 -0
- data/spec/fixtures/users.json +542 -0
- data/spec/fixtures/users.ls +30 -0
- data/spec/octonaut_spec.rb +69 -0
- data/spec/repositories_spec.rb +56 -0
- data/spec/spec_helper.rb +90 -0
- data/spec/users_spec.rb +138 -0
- metadata +265 -0
data/LICENSE.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Wynn Netherland
|
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.md
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
# Octonaut
|
2
|
+
|
3
|
+
A little CLI sugar for the GitHub API, built with [gli][] and [Octokit][].
|
4
|
+
|
5
|
+
**Still early. Rapidly evolving.** Why not [help out][contributing]?
|
6
|
+
|
7
|
+
### Why not `hub`?
|
8
|
+
|
9
|
+
[hub][] is great, you should use it. But hub focuses mostly on smoothing the
|
10
|
+
git workflow for GitHub and most commands are in the context of a GitHub
|
11
|
+
repository.
|
12
|
+
|
13
|
+
Octonaut is more general purpose CLI for the GitHub API. Oh and [plugins][].
|
14
|
+
|
15
|
+
### Installation
|
16
|
+
|
17
|
+
Install via Rubygems:
|
18
|
+
|
19
|
+
```
|
20
|
+
gem install octonaut
|
21
|
+
```
|
22
|
+
|
23
|
+
### Example usage
|
24
|
+
```
|
25
|
+
$ octonaut
|
26
|
+
NAME
|
27
|
+
octonaut - Octokit-powered CLI for GitHub
|
28
|
+
|
29
|
+
SYNOPSIS
|
30
|
+
octonaut [global options] command [command options] [arguments...]
|
31
|
+
|
32
|
+
GLOBAL OPTIONS
|
33
|
+
-a, --[no-]auto_traversal - Automatically fetch all pages of paginated results
|
34
|
+
--help - Show this message
|
35
|
+
-n, --[no-]netrc - Use .netrc file for authentication
|
36
|
+
-p, --password=arg - GitHub password (default: ********)
|
37
|
+
-t, --oauth_token, --token=arg - GitHub API token (default: ********)
|
38
|
+
-u, --login=arg - GitHub login (default: none)
|
39
|
+
|
40
|
+
COMMANDS
|
41
|
+
browse - Browse resource on github.com
|
42
|
+
follow - Follow a user
|
43
|
+
followers - View followers for a user
|
44
|
+
following - View who a user is following
|
45
|
+
follows - Check to see if a user follows another
|
46
|
+
help - Shows a list of commands or help for one command
|
47
|
+
langs, languages - Display languages for a repo
|
48
|
+
me - View your profile
|
49
|
+
repo, repository - Display details for a repository
|
50
|
+
repos, repositories - List repositories for a user or organization
|
51
|
+
say - An plugin method
|
52
|
+
unfollow - Unfollow a user
|
53
|
+
user, whois - View profile for a user
|
54
|
+
```
|
55
|
+
|
56
|
+
View a user's profile:
|
57
|
+
|
58
|
+
```
|
59
|
+
$ octonaut whois cloudhead
|
60
|
+
ID 40774
|
61
|
+
JOINED 2008-12-16T15:09:49Z
|
62
|
+
LOGIN cloudhead
|
63
|
+
NAME Alexis Sellier
|
64
|
+
COMPANY SoundCloud, Ltd.
|
65
|
+
LOCATION Berlin
|
66
|
+
FOLLOWERS 2347
|
67
|
+
FOLLOWING 48
|
68
|
+
HIREABLE true
|
69
|
+
URL http://twitter.com/cloudhead
|
70
|
+
```
|
71
|
+
|
72
|
+
Browse a user on github.com in your default browser:
|
73
|
+
|
74
|
+
```
|
75
|
+
$ octonaut browse cloudhead
|
76
|
+
```
|
77
|
+
|
78
|
+
List followers:
|
79
|
+
```
|
80
|
+
$ octonaut followers pengwynn
|
81
|
+
krisbulman
|
82
|
+
camdub
|
83
|
+
cglee
|
84
|
+
nextmat
|
85
|
+
zachinglis
|
86
|
+
seaofclouds
|
87
|
+
njonsson
|
88
|
+
davidnorth
|
89
|
+
polomasta
|
90
|
+
webiest
|
91
|
+
mchelen
|
92
|
+
brogers
|
93
|
+
marclove
|
94
|
+
adamstac
|
95
|
+
marshall
|
96
|
+
asenchi
|
97
|
+
piyush
|
98
|
+
rmetzler
|
99
|
+
nileshtrivedi
|
100
|
+
sferik
|
101
|
+
jimmybaker
|
102
|
+
jnunemaker
|
103
|
+
peterberkenbosch
|
104
|
+
leah
|
105
|
+
jakestutzman
|
106
|
+
nkabbara
|
107
|
+
etagwerker
|
108
|
+
vagostino
|
109
|
+
johan--
|
110
|
+
bry4n
|
111
|
+
...
|
112
|
+
```
|
113
|
+
|
114
|
+
Follow a user:
|
115
|
+
```
|
116
|
+
$ octonaut follow linus
|
117
|
+
Followed linus.
|
118
|
+
```
|
119
|
+
|
120
|
+
Unfollow a user:
|
121
|
+
```
|
122
|
+
$ octonaut unfollow pengwynn
|
123
|
+
Unfollowed pengwynn.
|
124
|
+
```
|
125
|
+
|
126
|
+
## Extend with plugins
|
127
|
+
|
128
|
+
Octonaut makes it simple to extend the CLI with new commands just by adding
|
129
|
+
some Ruby files to `~/.octonaut/plugins`:
|
130
|
+
|
131
|
+
```
|
132
|
+
$ cat ~/.octonaut/plugins/test.rb
|
133
|
+
module Octonaut
|
134
|
+
|
135
|
+
desc 'An plugin method'
|
136
|
+
arg_name 'text'
|
137
|
+
command :say do |c|
|
138
|
+
c.action do |global,options,args|
|
139
|
+
puts @client.say args.shift
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
$ octonaut say "hello from plugins"
|
145
|
+
|
146
|
+
MMM. .MMM
|
147
|
+
MMMMMMMMMMMMMMMMMMM
|
148
|
+
MMMMMMMMMMMMMMMMMMM ____________________
|
149
|
+
MMMMMMMMMMMMMMMMMMMMM | |
|
150
|
+
MMMMMMMMMMMMMMMMMMMMMMM | hello from plugins |
|
151
|
+
MMMMMMMMMMMMMMMMMMMMMMMM |_ ________________|
|
152
|
+
MMMM::- -:::::::- -::MMMM |/
|
153
|
+
MM~:~ ~:::::~ ~:~MM
|
154
|
+
.. MMMMM::. .:::+:::. .::MMMMM ..
|
155
|
+
.MM::::: ._. :::::MM.
|
156
|
+
MMMM;:::::;MMMM
|
157
|
+
-MM MMMMMMM
|
158
|
+
^ M+ MMMMMMMMM
|
159
|
+
MMMMMMM MM MM MM
|
160
|
+
MM MM MM MM
|
161
|
+
MM MM MM MM
|
162
|
+
.~~MM~MM~MM~MM~~.
|
163
|
+
~~~~MM:~MM~~~MM~:MM~~~~
|
164
|
+
~~~~~~==~==~~~==~==~~~~~~
|
165
|
+
~~~~~~==~==~==~==~~~~~~
|
166
|
+
:~==~==~==~==~~
|
167
|
+
```
|
168
|
+
|
169
|
+
## Inspiration
|
170
|
+
|
171
|
+
Octonaut is inspired by [`t`, the awesome Twitter CLI][t] from [Erik Michaels-Ober][sferik].
|
172
|
+
|
173
|
+
## Copyright
|
174
|
+
|
175
|
+
Copyright (c) 2013 Wynn Netherland. See [LICENSE][] for details.
|
176
|
+
|
177
|
+
[hub]: https://github.com/defunkt/hub
|
178
|
+
[gli]: https://github.com/davetron5000/gli
|
179
|
+
[octokit]: https://github.com/pengwynn/octokit
|
180
|
+
[plugins]: #extend-with-plugins
|
181
|
+
[contributing]: https://github.com/pengwynn/octonaut/blob/master/CONTRIBUTING.md
|
182
|
+
[t]: https://github.com/sferik/t
|
183
|
+
[sferik]: https://github.com/sferik
|
184
|
+
[LICENSE]: https://github.com/pengwynn/octonaut/blob/master/LICENSE.md
|
data/Rakefile
ADDED
data/bin/octonaut
ADDED
data/lib/octonaut.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'csv'
|
2
|
+
require 'gli'
|
3
|
+
require 'launchy'
|
4
|
+
require 'octokit'
|
5
|
+
require 'octonaut/printer'
|
6
|
+
require 'octonaut/helpers'
|
7
|
+
require 'octonaut/version'
|
8
|
+
|
9
|
+
module Octonaut
|
10
|
+
extend GLI::App
|
11
|
+
extend Octonaut::Printer
|
12
|
+
extend Octonaut::Helpers
|
13
|
+
|
14
|
+
program_desc 'Octokit-powered CLI for GitHub'
|
15
|
+
commands_from 'octonaut/commands'
|
16
|
+
commands_from File.join(ENV['HOME'], '.octonaut', 'plugins')
|
17
|
+
|
18
|
+
|
19
|
+
desc 'Use .netrc file for authentication'
|
20
|
+
default_value false
|
21
|
+
switch [:n, :netrc]
|
22
|
+
|
23
|
+
desc 'GitHub login'
|
24
|
+
flag [:u, :login]
|
25
|
+
desc 'GitHub password'
|
26
|
+
flag [:p, :password], :mask => true
|
27
|
+
desc 'GitHub API token'
|
28
|
+
flag [:t, :oauth_token, :token], :mask => true
|
29
|
+
desc 'Automatically fetch all pages of paginated results'
|
30
|
+
switch [:a, :auto_traversal]
|
31
|
+
|
32
|
+
|
33
|
+
pre do |global,command,options,args|
|
34
|
+
# Pre logic here
|
35
|
+
# Return true to proceed; false to abourt and not call the
|
36
|
+
# chosen command
|
37
|
+
# Use skips_pre before a command to skip this block
|
38
|
+
# on that command only
|
39
|
+
|
40
|
+
@client = client(global, options)
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
post do |global,command,options,args|
|
45
|
+
# Post logic here
|
46
|
+
# Use skips_post before a command to skip this
|
47
|
+
# block on that command only
|
48
|
+
end
|
49
|
+
|
50
|
+
on_error do |exception|
|
51
|
+
case exception
|
52
|
+
when Octokit::Unauthorized
|
53
|
+
puts "Authentication required. Please check your login, password, or token."
|
54
|
+
else
|
55
|
+
# Need to handle other return codes within the calling method
|
56
|
+
true
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.client(global, options)
|
61
|
+
opts = global.merge(options).
|
62
|
+
select {|k, v| Octokit::Configuration::VALID_OPTIONS_KEYS.include?(k) }
|
63
|
+
Octokit::Client.new(opts)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Octonaut
|
2
|
+
desc 'Browse resource on github.com'
|
3
|
+
arg_name 'name'
|
4
|
+
command :browse do |c|
|
5
|
+
c.action do |global,options,args|
|
6
|
+
name = args.shift
|
7
|
+
raise ArgumentError.new("Name required") if name.nil?
|
8
|
+
|
9
|
+
owner, repo = name.split("/")
|
10
|
+
if repo.nil?
|
11
|
+
item = @client.user owner
|
12
|
+
else
|
13
|
+
item = @client.repo(name)
|
14
|
+
end
|
15
|
+
|
16
|
+
Octonaut.open item
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Octonaut
|
2
|
+
|
3
|
+
desc "Display details for a repository"
|
4
|
+
arg_name 'name'
|
5
|
+
command [:repo, :repository] do |c|
|
6
|
+
c.action do |global,options,args|
|
7
|
+
name = args.shift
|
8
|
+
|
9
|
+
print_repo_table @client.repo(name)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "List repositories for a user or organization"
|
14
|
+
arg_name 'login', :optional
|
15
|
+
command [:repos, :repositories] do |c|
|
16
|
+
c.desc "Filter repos by type: all, owner, member, public, private"
|
17
|
+
c.flag :type
|
18
|
+
|
19
|
+
c.desc "Sort repos by: created, updated, pushed, full_name"
|
20
|
+
c.flag :sort
|
21
|
+
|
22
|
+
c.desc "Sort direction: asc or desc"
|
23
|
+
c.flag :direction
|
24
|
+
|
25
|
+
c.action do |global,options,args|
|
26
|
+
login = args.shift
|
27
|
+
opts = options.select {|k,v| !v.nil? }
|
28
|
+
|
29
|
+
ls_repos @client.repositories(login, opts)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Display languages for a repo"
|
34
|
+
arg_name "owner/repo"
|
35
|
+
command [:langs, :languages] do |c|
|
36
|
+
c.action do |global,options,args|
|
37
|
+
name = args.shift
|
38
|
+
|
39
|
+
print_table @client.languages(name)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Octonaut
|
2
|
+
desc "View your profile"
|
3
|
+
command :me do |c|
|
4
|
+
c.action do |global,options,args|
|
5
|
+
user = @client.user
|
6
|
+
print_user_table user
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "View profile for a user"
|
11
|
+
arg_name 'login'
|
12
|
+
command [:user, :whois] do |c|
|
13
|
+
c.action do |global,options,args|
|
14
|
+
login = args.shift
|
15
|
+
begin
|
16
|
+
user = @client.user login
|
17
|
+
case user['type']
|
18
|
+
when 'Organization'
|
19
|
+
print_org_table user
|
20
|
+
else
|
21
|
+
print_user_table user
|
22
|
+
end
|
23
|
+
rescue Octokit::NotFound
|
24
|
+
puts "User or organization #{login} not found"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "View followers for a user"
|
30
|
+
arg_name 'login', :optional
|
31
|
+
command :followers do |c|
|
32
|
+
c.action do |global,options,args|
|
33
|
+
login = args.shift || @client.login
|
34
|
+
print_users @client.followers(login), options
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "View who a user is following"
|
39
|
+
arg_name 'login', :optional
|
40
|
+
command :following do |c|
|
41
|
+
c.action do |global,options,args|
|
42
|
+
login = args.shift || @client.login
|
43
|
+
print_users @client.following(login), options
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "Check to see if a user follows another"
|
48
|
+
arg_name 'target'
|
49
|
+
command :follows do |c|
|
50
|
+
c.action do |global,options,args|
|
51
|
+
target = args.shift
|
52
|
+
message = if @client.follows?(target)
|
53
|
+
"Yes, #{@client.login} follows #{target}."
|
54
|
+
else
|
55
|
+
"No, #{@client.login} does not follow #{target}."
|
56
|
+
end
|
57
|
+
|
58
|
+
puts message
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
desc "Follow a user"
|
63
|
+
arg_name 'target', :multiple
|
64
|
+
command :follow do |c|
|
65
|
+
c.action do |global,options,args|
|
66
|
+
targets = args
|
67
|
+
targets.each {|t| follow_user(t) }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
desc "Unfollow a user"
|
72
|
+
arg_name 'target', :multiple
|
73
|
+
command :unfollow do |c|
|
74
|
+
c.action do |global,options,args|
|
75
|
+
targets = args
|
76
|
+
targets.each {|t| unfollow_user(t) }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.follow_user(target)
|
81
|
+
puts "Followed #{target}." if @client.follow(target)
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.unfollow_user(target)
|
85
|
+
puts "Unfollowed #{target}." if @client.unfollow(target)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Octonaut
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
def open(resource, relation = 'html')
|
5
|
+
link_field = case relation
|
6
|
+
when 'self'
|
7
|
+
'url'
|
8
|
+
when /_url$/
|
9
|
+
relation
|
10
|
+
else
|
11
|
+
"#{relation}_url"
|
12
|
+
end
|
13
|
+
|
14
|
+
url = resource.send(link_field.to_sym)
|
15
|
+
|
16
|
+
Launchy.open url
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|