git-pulls 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/LICENSE +20 -0
  2. data/bin/git-pulls +6 -0
  3. data/lib/git-pulls.rb +202 -0
  4. metadata +96 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Scott Chacon
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,6 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
3
+
4
+ require 'git-pulls'
5
+
6
+ GitPulls.start(ARGV)
@@ -0,0 +1,202 @@
1
+ require 'rubygems'
2
+ require 'json'
3
+ require 'httparty'
4
+ require 'pp'
5
+
6
+ class GitPulls
7
+
8
+ PULLS_CACHE_FILE = '.git/pulls_cache.json'
9
+
10
+ def initialize(args)
11
+ @command = args.shift
12
+ @user, @repo = repo_info
13
+ @args = args
14
+ end
15
+
16
+ def self.start(args)
17
+ GitPulls.new(args).run
18
+ end
19
+
20
+ def run
21
+ if @command && self.respond_to?(@command)
22
+ self.send @command
23
+ else
24
+ help
25
+ end
26
+ end
27
+
28
+ ## COMMANDS ##
29
+
30
+ def help
31
+ puts "No command: #{@command}"
32
+ puts "Try: update, list, show, merge, browse"
33
+ end
34
+
35
+ def merge
36
+ num = @args.shift
37
+ if p = pull_num(num)
38
+ o = p['head']['repository']['owner']
39
+ r = p['head']['repository']['name']
40
+ s = p['head']['sha']
41
+ msg = "Merge pull request ##{num} from #{o}/#{r}"
42
+ puts cmd = "git merge --no-ff -m '#{msg}' #{s}"
43
+ exec(cmd)
44
+ else
45
+ puts "No such number"
46
+ end
47
+ end
48
+
49
+ def show
50
+ num = @args.shift
51
+ option = @args.shift
52
+ if p = pull_num(num)
53
+ puts "Number : #{p['number']}"
54
+ puts "Label : #{p['head']['label']}"
55
+ puts "Created : #{p['created_at']}"
56
+ puts "Votes : #{p['votes']}"
57
+ puts "Comments : #{p['comments']}"
58
+ puts
59
+ puts "Title : #{p['title']}"
60
+ puts "Body :"
61
+ puts
62
+ puts p['body']
63
+ puts
64
+ puts '------------'
65
+ puts
66
+ if option == '--full'
67
+ exec "git diff --color=always HEAD...#{p['head']['sha']}"
68
+ else
69
+ puts "cmd: git diff HEAD...#{p['head']['sha']}"
70
+ puts git("diff --stat --color=always HEAD...#{p['head']['sha']}")
71
+ end
72
+ else
73
+ puts "No such number"
74
+ end
75
+ end
76
+
77
+ def browse
78
+ num = @args.shift
79
+ if p = pull_num(num)
80
+ `open #{p['html_url']}`
81
+ else
82
+ puts "No such number"
83
+ end
84
+ end
85
+
86
+ def list
87
+ option = @args.shift
88
+ puts "Open Pull Requests for #{@user}/#{@repo}"
89
+ pulls = get_pull_info
90
+ pulls.reverse! if option == '--reverse'
91
+ pulls.each do |pull|
92
+ line = []
93
+ line << l(pull['number'], 4)
94
+ line << l(Date.parse(pull['created_at']).strftime("%m/%d"), 5)
95
+ line << l(pull['comments'], 2)
96
+ line << l(pull['title'], 35)
97
+ line << l(pull['head']['label'], 20)
98
+ sha = pull['head']['sha']
99
+ if not_merged?(sha)
100
+ puts line.join ' '
101
+ end
102
+ end
103
+ end
104
+
105
+ def update
106
+ puts "Updating #{@user}/#{@repo}"
107
+ cache_pull_info
108
+ fetch_stale_forks
109
+ list
110
+ end
111
+
112
+ def fetch_stale_forks
113
+ puts "Checking for forks in need of fetching"
114
+ pulls = get_pull_info
115
+ repos = {}
116
+ pulls.each do |pull|
117
+ o = pull['head']['repository']['owner']
118
+ r = pull['head']['repository']['name']
119
+ s = pull['head']['sha']
120
+ if !has_sha(s)
121
+ repo = "#{o}/#{r}"
122
+ repos[repo] = true
123
+ end
124
+ end
125
+ repos.each do |repo, bool|
126
+ puts " fetching #{repo}"
127
+ git("fetch git://github.com/#{repo}.git refs/heads/*:refs/pr/#{repo}/*")
128
+ end
129
+ end
130
+
131
+ def has_sha(sha)
132
+ git("show #{sha} 2>&1")
133
+ $?.exitstatus == 0
134
+ end
135
+
136
+ def not_merged?(sha)
137
+ commits = git("rev-list #{sha} ^HEAD 2>&1")
138
+ commits.split("\n").size > 0
139
+ end
140
+
141
+
142
+ # DISPLAY HELPER FUNCTIONS #
143
+
144
+ def l(info, size)
145
+ clean(info)[0, size].ljust(size)
146
+ end
147
+
148
+ def r(info, size)
149
+ clean(info)[0, size].rjust(size)
150
+ end
151
+
152
+ def clean(info)
153
+ info.to_s.gsub("\n", ' ')
154
+ end
155
+
156
+ # API/DATA HELPER FUNCTIONS #
157
+
158
+ def get_pull_info
159
+ get_data(PULLS_CACHE_FILE)['pulls']
160
+ end
161
+
162
+ def cache_pull_info
163
+ path = "/pulls/#{@user}/#{@repo}/open"
164
+ response = HTTParty.get('https://github.com/api/v2/json' << path)
165
+ save_data(response, PULLS_CACHE_FILE)
166
+ end
167
+
168
+ def get_data(file)
169
+ data = JSON.parse(File.read(file))
170
+ end
171
+
172
+ def save_data(data, file)
173
+ File.open(file, "w+") do |f|
174
+ f.puts data.to_json
175
+ end
176
+ end
177
+
178
+ def pull_num(num)
179
+ data = get_pull_info
180
+ data.select { |p| p['number'].to_s == num.to_s }.first
181
+ end
182
+
183
+
184
+ def repo_info
185
+ c = {}
186
+ config = git('config --list')
187
+ config.split("\n").each do |line|
188
+ k, v = line.split('=')
189
+ c[k] = v
190
+ end
191
+ u = c['remote.origin.url']
192
+ if m = /github\.com.(.*?)\/(.*?)\.git/.match(u)
193
+ user = m[1]
194
+ proj = m[2]
195
+ end
196
+ [user, proj]
197
+ end
198
+
199
+ def git(command)
200
+ `git #{command}`.chomp
201
+ end
202
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: git-pulls
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Scott Chacon
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-31 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: json
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: httparty
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ description: " git-pulls facilitates github pull requests.\n"
50
+ email: schacon@gmail.com
51
+ executables:
52
+ - git-pulls
53
+ extensions: []
54
+
55
+ extra_rdoc_files: []
56
+
57
+ files:
58
+ - LICENSE
59
+ - lib/git-pulls.rb
60
+ - bin/git-pulls
61
+ has_rdoc: true
62
+ homepage: http://github.com/schacon/git-pulls
63
+ licenses: []
64
+
65
+ post_install_message:
66
+ rdoc_options: []
67
+
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ hash: 3
85
+ segments:
86
+ - 0
87
+ version: "0"
88
+ requirements: []
89
+
90
+ rubyforge_project:
91
+ rubygems_version: 1.3.7
92
+ signing_key:
93
+ specification_version: 3
94
+ summary: facilitates github pull requests
95
+ test_files: []
96
+