ghi 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,180 @@
1
+ === 0.2.0 / 2009-11-03
2
+
3
+ * Major-minor release!
4
+
5
+ * Cleanup! (Better help, warnings and errors.)
6
+
7
+
8
+ === 0.1.7 / 2009-08-26
9
+
10
+ * 2 bugfixes
11
+
12
+ * Allow dots in repo names.
13
+ * Fix bug preventing invocation from non-GitHub repo directories.
14
+
15
+
16
+ === 0.1.6 / 2009-08-05
17
+
18
+ * 1 minor enhancement
19
+
20
+ * Support for non-"origin" remotes.
21
+
22
+
23
+ * 1 bugfix
24
+
25
+ * Graceful offline error.
26
+
27
+
28
+ === 0.1.5 / 2009-07-08
29
+
30
+ * 2 bugfixes
31
+
32
+ * Long titles should wrap in show/verbose issue view.
33
+ * If a non-OptionParser argument fails early, re-parse when valid.
34
+
35
+
36
+ === 0.1.4 / 2009-05-15
37
+
38
+ * 1 minor enhancement
39
+
40
+ * Minor Windows support.
41
+
42
+
43
+ === 0.1.3 / 2009-05-08
44
+
45
+ * 1 minor enhancement
46
+
47
+ * Fix bug where `more' was being passed `less' options.
48
+ * Fix scoping of commands so `ghi user/repo` can run outside of a repo
49
+ directory.
50
+
51
+
52
+ === 0.1.2 / 2009-05-07
53
+
54
+ * 1 major enhancement
55
+
56
+ * Better fallbacks. Enter `ghi open`, `ghi list closed`, `ghi search term`,
57
+ `ghi show 2`, `ghi user/repo`, etc., it will try to work. Fallbacks do not
58
+ accept options, though.
59
+
60
+
61
+ === 0.1.1 / 2009-05-01
62
+
63
+ * 3 major enhancements
64
+
65
+ * Use `more' (or $GHI_PAGER) to accommodate lengthy output.
66
+ * Default to "-l" if Dir.pwd is a git repo.
67
+ * Accept numbered args/flags to shortcut "show" (e.g., "ghi -2", "ghi 2")
68
+
69
+
70
+ * 1 minor enhancement
71
+
72
+ * Update --url flag to GitHub's new convention.
73
+
74
+
75
+ === 0.1.0 / 2009-04-27
76
+
77
+ * 2 major enhancements
78
+
79
+ * Use tempfiles when we should, the gitdir otherwise.
80
+ * Now a minor!
81
+
82
+
83
+ * 2 minor enhancement
84
+
85
+ * Small ANSI tweaks.
86
+ * Truncation fix.
87
+
88
+
89
+ === 0.0.9 / 2009-04-27
90
+
91
+ * 1 major enhancement
92
+
93
+ * ANSI colors (honors your .gitconfig).
94
+
95
+
96
+ * 1 minor enhancement
97
+
98
+ * Bugfixes.
99
+
100
+
101
+ === 0.0.8 / 2009-04-26
102
+
103
+ * 1 major enhancement
104
+
105
+ * Flag to return issues URLs.
106
+
107
+
108
+ * 1 minor enhancement
109
+
110
+ * Preliminary specs for top-level module and API class.
111
+
112
+
113
+ === 0.0.7 / 2009-04-25
114
+
115
+ * 1 major enhancement
116
+
117
+ * Labels! Label and un-label at your whim.
118
+
119
+
120
+ * 1 minor enhancement
121
+
122
+ * Tail arguments are sometimes parsed. E.g., ghi -om "Issue message parsed".
123
+
124
+
125
+ === 0.0.6 / 2009-04-25
126
+
127
+ * 2 minor enhancements
128
+
129
+ * Accept comments as arguments in more places.
130
+ * Update error message to accommodate both issues and comments.
131
+
132
+
133
+ === 0.0.5 / 2009-04-25
134
+
135
+ * 3 major enhancements
136
+
137
+ * Flag to claim/label issues with your GitHub username (thanks, Jamie).
138
+ * Flag for commenting on issues.
139
+ * Prompt for GitHub login and token if absent from gitconfig.
140
+
141
+
142
+ * 1 minor enhancement
143
+
144
+ * Opening issues with a title bypasses your $EDITOR.
145
+
146
+
147
+ === 0.0.4 / 2009-04-24
148
+
149
+ * 1 major enhancement
150
+
151
+ * Cache messages created in $EDITOR.
152
+
153
+
154
+ * 2 minor enhancements
155
+
156
+ * Refactoring and cleanup.
157
+ * Change editing messages.
158
+
159
+
160
+ === 0.0.3 / 2009-04-23
161
+
162
+ * 2 minor enhancements
163
+
164
+ * Typo corrected.
165
+ * README updated.
166
+
167
+
168
+ === 0.0.2 / 2009-04-22
169
+
170
+ * 1 major enhancement
171
+
172
+ * Add --search flag.
173
+ * Add --repo flag.
174
+
175
+
176
+ === 0.0.1 / 2009-04-21
177
+
178
+ * 1 major enhancement
179
+
180
+ * Birthday!
@@ -0,0 +1,14 @@
1
+ History.rdoc
2
+ Manifest.txt
3
+ MIT-LICENSE
4
+ Rakefile
5
+ README.rdoc
6
+ bin/ghi
7
+ lib/ghi/api.rb
8
+ lib/ghi/cli.rb
9
+ lib/ghi/issue.rb
10
+ lib/ghi.rb
11
+ spec/ghi/api_spec.rb
12
+ spec/ghi/cli_spec.rb
13
+ spec/ghi/issue_spec.rb
14
+ spec/ghi_spec.rb
@@ -0,0 +1,92 @@
1
+ = ghi
2
+
3
+ http://github.com/stephencelis/ghi
4
+
5
+
6
+ GitHub Issues on the command line. Use your <tt>$EDITOR</tt>, not your
7
+ browser.
8
+
9
+ == HOW?
10
+
11
+ Get:
12
+
13
+ % gem install stephencelis-ghi --source=http://gems.github.com
14
+
15
+
16
+ Go:
17
+
18
+ Usage: ghi [options]
19
+ -l, --list [state|term|number]
20
+ --search, --show
21
+ -v, --verbose
22
+ -o, --open [title|number]
23
+ --reopen
24
+ -c, --closed, --close [number]
25
+ -e, --edit [number]
26
+ -r, --repo, --repository [name]
27
+ -m, --comment [number|comment]
28
+ -t, --label [number] [label]
29
+ --claim [number]
30
+ -d, --unlabel [number] [label]
31
+ -u, --url [state|number]
32
+ --[no-]color
33
+ --[no-]pager
34
+ -V, --version
35
+ -h, --help
36
+
37
+
38
+ == EXAMPLE?
39
+
40
+ ghi works simply from within a repository. Some short examples:
41
+
42
+ ghi -l # Lists all open issues
43
+ ghi # Shorter shorthand for "ghi -l"
44
+ ghi -v # Lists all open issues, verbosely (includes body)
45
+ ghi -lc # Lists all closed issues
46
+ ghi -l "doesn't work" # Searches for open issues matching "doesn't work"
47
+ ghi -l invalid -c # Searches for closed issues matching "invalid"
48
+ ghi -l1 # Shows issue 1
49
+ ghi -1 # Shorter shorthand for "ghi -l1"
50
+ ghi 1 # Shorter shorthand still
51
+ ghi -o # Opens a new issue (in your $EDITOR)
52
+ ghi -o "New issue" # Opens a new issue with the title "New issue"
53
+ ghi -o "Title" -m "Body" # Opens a new issue with specified title and body
54
+ ghi -e1 # Edits issue number 1 (in your $EDITOR)
55
+ ghi -e1 -m "New body" # Edits issue number 1 with the specified body
56
+ ghi -c1 # Closes issue 1
57
+ ghi -c1 -m # Closes issue with comment (from your $EDITOR)
58
+ ghi -c1 -m "Comment" # Closes issue with specified comment
59
+ ghi -o1 # Reopens 1 (accepts comments, too)
60
+ ghi -m1 # Comments on issue 1 (in your $EDITOR)
61
+ ghi -t1 "tag" # Labels issue 1 with "tag"
62
+ ghi -d1 "tag" # Removes the label, "tag"
63
+ ghi --claim 1 # Tags issue 1 with your GitHub username
64
+ ghi -u # Loads issues in your browser.
65
+ ghi -u1 # Loads an issue in your browser.
66
+
67
+
68
+ ghi also works anywhere:
69
+
70
+ ghi -rghi # Your fork of "ghi"
71
+ ghi -rstephencelis/ghi # Mine: "stephencelis/ghi"
72
+ ghi stephencelis/ghi # Shorthand to merely list open.
73
+
74
+
75
+ ghi uses ANSI colors if you use them in git.
76
+
77
+ ghi looks for a <tt>$GHI_PAGER</tt> variable for paging.
78
+
79
+
80
+ == CONTRIBUTORS
81
+
82
+ * Jamie Macey (http://blog.tracefunc.com)
83
+ * Hiroshi Nakamura (http://github.com/nahi)
84
+
85
+
86
+ === CONTRIBUTE?
87
+
88
+ ghi is not under currently under the control of any gem packaging system. To
89
+ build, use RubyGems:
90
+
91
+ % gem build ghi.gemspec
92
+ % sudo gem install ghi*.gem
data/bin/ghi ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
4
+ require "ghi/cli"
5
+ $stdout.sync = true
6
+ GHI::CLI::Executable.new.parse!(ARGV)
@@ -0,0 +1,55 @@
1
+ require "net/http"
2
+ require "yaml"
3
+
4
+ module GHI
5
+ VERSION = "0.2"
6
+
7
+ class << self
8
+ def login
9
+ return @login if defined? @login
10
+ @login = `git config --get github.user`.chomp
11
+ if @login.empty?
12
+ begin
13
+ print "Please enter your GitHub username: "
14
+ @login = gets.chomp
15
+ valid = user? @login
16
+ warn "invalid username" unless valid
17
+ end until valid
18
+ `git config --global github.user #@login`
19
+ end
20
+ @login
21
+ end
22
+
23
+ def token
24
+ return @token if defined? @token
25
+ @token = `git config --get github.token`.chomp
26
+ if @token.empty?
27
+ begin
28
+ print "GitHub token (https://github.com/account): "
29
+ @token = gets.chomp
30
+ valid = token? @token
31
+ warn "invalid token for #{login}" unless valid
32
+ end until valid
33
+ `git config --global github.token #@token`
34
+ end
35
+ @token
36
+ end
37
+
38
+ private
39
+
40
+ def user?(username)
41
+ url = "http://github.com/api/v2/yaml/user/show/#{username}"
42
+ !YAML.load(Net::HTTP.get(URI.parse(url)))["user"].nil?
43
+ rescue ArgumentError, URI::InvalidURIError
44
+ false
45
+ end
46
+
47
+ def token?(token)
48
+ url = "http://github.com/api/v2/yaml/user/show/#{login}"
49
+ url += "?login=#{login}&token=#{token}"
50
+ !YAML.load(Net::HTTP.get(URI.parse(url)))["user"]["plan"].nil?
51
+ rescue ArgumentError, NoMethodError, URI::InvalidURIError
52
+ false
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,106 @@
1
+ require "net/http"
2
+ require "yaml"
3
+
4
+ class GHI::API
5
+ class InvalidRequest < StandardError
6
+ end
7
+
8
+ class InvalidConnection < StandardError
9
+ end
10
+
11
+ class ResponseError < StandardError
12
+ end
13
+
14
+ API_URL = "http://github.com/api/v2/yaml/issues/:action/:user/:repo"
15
+
16
+ attr_reader :user, :repo
17
+
18
+ def initialize(user, repo)
19
+ raise InvalidConnection if user.nil? || repo.nil?
20
+ @user, @repo = user, repo
21
+ end
22
+
23
+ def search(term, state = :open)
24
+ get(:search, state, term)["issues"].map { |attrs| GHI::Issue.new(attrs) }
25
+ end
26
+
27
+ def list(state = :open)
28
+ get(:list, state)["issues"].map { |attrs| GHI::Issue.new(attrs) }
29
+ end
30
+
31
+ def show(number)
32
+ GHI::Issue.new get(:show, number)["issue"]
33
+ end
34
+
35
+ def open(title, body)
36
+ GHI::Issue.new post(:open, :title => title, :body => body)["issue"]
37
+ end
38
+
39
+ def edit(number, title, body)
40
+ res = post :edit, number, :title => title, :body => body
41
+ GHI::Issue.new res["issue"]
42
+ end
43
+
44
+ def close(number)
45
+ GHI::Issue.new post(:close, number)["issue"]
46
+ end
47
+
48
+ def reopen(number)
49
+ GHI::Issue.new post(:reopen, number)["issue"]
50
+ end
51
+
52
+ def add_label(label, number)
53
+ post("label/add", label, number)["labels"]
54
+ end
55
+
56
+ def remove_label(label, number)
57
+ post("label/remove", label, number)["labels"]
58
+ end
59
+
60
+ def comment(number, comment)
61
+ post(:comment, number, :comment => comment)["comment"]
62
+ end
63
+
64
+ private
65
+
66
+ def get(*args)
67
+ res = YAML.load Net::HTTP.get(URI.parse(url(*args) + auth(true)))
68
+ raise ResponseError, errors(res) if res["error"]
69
+ res
70
+ rescue ArgumentError, URI::InvalidURIError
71
+ raise ResponseError, "GitHub hiccuped on your request"
72
+ rescue SocketError
73
+ raise ResponseError, "couldn't find the internet"
74
+ end
75
+
76
+ def post(*args)
77
+ params = args.last.is_a?(Hash) ? args.pop : {}
78
+ params.update auth
79
+ res = YAML.load Net::HTTP.post_form(URI.parse(url(*args)), params).body
80
+ raise ResponseError, errors(res) if res["error"]
81
+ res
82
+ rescue ArgumentError, URI::InvalidURIError
83
+ raise ResponseError, "GitHub hiccuped on your request"
84
+ rescue SocketError
85
+ raise ResponseError, "couldn't find the internet"
86
+ end
87
+
88
+ def errors(response)
89
+ [*response["error"]].map { |e| e["error"] } * ", "
90
+ end
91
+
92
+ def auth(query = false)
93
+ if query
94
+ "?login=#{GHI.login}&token=#{GHI.token}"
95
+ else
96
+ { :login => GHI.login, :token => GHI.token }
97
+ end
98
+ end
99
+
100
+ def url(action, *args)
101
+ @url ||= API_URL.sub(":user", user).sub(":repo", repo)
102
+ uri = @url.sub ":action", action.to_s
103
+ uri += "/#{args.join("/")}" unless args.empty?
104
+ uri
105
+ end
106
+ end