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.
@@ -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.
@@ -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
@@ -0,0 +1,8 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :test => :spec
8
+ task :default => :spec
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'octonaut'
3
+
4
+ exit Octonaut.run(ARGV)
@@ -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