git-review 0.4.1 → 0.4.2
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/bin/git-review +1 -1
- data/lib/git-review.rb +145 -146
- metadata +4 -4
data/bin/git-review
CHANGED
data/lib/git-review.rb
CHANGED
@@ -6,159 +6,182 @@ class GitReview
|
|
6
6
|
|
7
7
|
REVIEW_CACHE_FILE = '.git/review_cache.json'
|
8
8
|
|
9
|
-
|
10
|
-
@command = args.shift
|
11
|
-
@user, @repo = repo_info
|
12
|
-
@args = args
|
13
|
-
end
|
9
|
+
## COMMANDS ##
|
14
10
|
|
15
|
-
|
16
|
-
|
11
|
+
# Default command to show a quick reference of available commands.
|
12
|
+
def help
|
13
|
+
puts 'Usage: git review <command>'
|
14
|
+
puts 'Manage review workflow for projects hosted on GitHub (using pull requests).'
|
15
|
+
puts ''
|
16
|
+
puts 'Available commands:'
|
17
|
+
puts ' list [--reverse] List all open requests.'
|
18
|
+
puts ' show <number> [--full] Show details of a single request.'
|
19
|
+
puts ' browse <number> Open a browser window and review a specified request.'
|
20
|
+
puts ' create Create a new request.'
|
21
|
+
puts ' merge <number> Sign off a specified request by merging it into master.'
|
22
|
+
end
|
23
|
+
|
24
|
+
# List all open requests.
|
25
|
+
def list
|
26
|
+
puts "Open Pull Requests for #{@user}/#{@repo}"
|
27
|
+
option = @args.shift
|
28
|
+
open_requests = get_pull_info
|
29
|
+
open_requests.reverse! if option == '--reverse'
|
30
|
+
count = 0
|
31
|
+
open_requests.each do |pull|
|
32
|
+
line = []
|
33
|
+
line << format_text(pull['number'], 4)
|
34
|
+
line << format_text(Date.parse(pull['created_at']).strftime("%m/%d"), 5)
|
35
|
+
line << format_text(pull['comments'], 2)
|
36
|
+
line << format_text(pull['title'], 35)
|
37
|
+
line << format_text(pull['head']['label'], 20)
|
38
|
+
sha = pull['head']['sha']
|
39
|
+
if not_merged?(sha)
|
40
|
+
puts line.join ' '
|
41
|
+
count += 1
|
42
|
+
end
|
43
|
+
end
|
44
|
+
if count == 0
|
45
|
+
puts ' -- no open pull requests --'
|
46
|
+
end
|
17
47
|
end
|
18
48
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
49
|
+
# Show details of a single request.
|
50
|
+
def show
|
51
|
+
return unless review_exists?
|
52
|
+
option = @args.shift
|
53
|
+
puts "Number : #{@review['number']}"
|
54
|
+
puts "Label : #{@review['head']['label']}"
|
55
|
+
puts "Created : #{@review['created_at']}"
|
56
|
+
puts "Votes : #{@review['votes']}"
|
57
|
+
puts "Comments : #{@review['comments']}"
|
58
|
+
puts
|
59
|
+
puts "Title : #{@review['title']}"
|
60
|
+
puts "Body :"
|
61
|
+
puts
|
62
|
+
puts @review['body']
|
63
|
+
puts
|
64
|
+
puts '------------'
|
65
|
+
puts
|
66
|
+
if option == '--full'
|
67
|
+
exec "git diff --color=always HEAD...#{@review['head']['sha']}"
|
26
68
|
else
|
27
|
-
|
69
|
+
puts "cmd: git diff HEAD...#{@review['head']['sha']}"
|
70
|
+
puts git("diff --stat --color=always HEAD...#{@review['head']['sha']}")
|
28
71
|
end
|
29
72
|
end
|
30
73
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
puts "No command: #{@command}"
|
35
|
-
puts "Try: update, list, show, merge, browse, create"
|
36
|
-
puts "or call with '-h' for usage information"
|
37
|
-
end
|
38
|
-
|
39
|
-
def usage
|
40
|
-
puts <<-USAGE
|
41
|
-
Usage: git review list [--reverse]
|
42
|
-
or: git review show <number> [--full]
|
43
|
-
or: git review browse <number>
|
44
|
-
or: git review merge <number>
|
45
|
-
or: git review create
|
46
|
-
USAGE
|
74
|
+
# Open a browser window and review a specified request.
|
75
|
+
def browse
|
76
|
+
Launchy.open(@review['html_url']) if review_exists?
|
47
77
|
end
|
48
78
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
s = p['head']['sha']
|
68
|
-
|
69
|
-
message = "Merge pull request ##{num} from #{o}/#{r}\n\n---\n\n"
|
70
|
-
message += p['body'].gsub("'", '')
|
71
|
-
cmd = ''
|
72
|
-
if option == '--log'
|
73
|
-
message += "\n\n---\n\nMerge Log:\n"
|
74
|
-
puts cmd = "git merge --no-ff --log -m '#{message}' #{s}"
|
75
|
-
else
|
76
|
-
puts cmd = "git merge --no-ff -m '#{message}' #{s}"
|
77
|
-
end
|
78
|
-
exec(cmd)
|
79
|
+
# Create a new request.
|
80
|
+
def create
|
81
|
+
# Gather information.
|
82
|
+
last_review_id = get_pull_info.collect{|review| review['number']}.sort.last
|
83
|
+
target_repo = "#{@user}/#{@repo}"
|
84
|
+
target_branch = 'master'
|
85
|
+
source_branch = git('branch', false).match(/\*(.*)/)[0][2..-1]
|
86
|
+
title = "Review request: #{github_login} wants to merge changes from '#{source_branch}' into #{target_repo}'s branch '#{target_branch}'."
|
87
|
+
# TODO: Insert commit messages (that are not yet in master) into body (since this will be displayed inside the mail that is sent out).
|
88
|
+
body = 'my body'
|
89
|
+
# Create the actual pull request.
|
90
|
+
Octokit.create_pull_request(target_repo, target_branch, source_branch, title, body)
|
91
|
+
# Switch back to target_branch and check for success.
|
92
|
+
git "co #{target_branch}"
|
93
|
+
update
|
94
|
+
potential_new_review = get_pull_info.find{ |review| review['title'] == title}
|
95
|
+
if potential_new_review['number'] > last_review_id
|
96
|
+
puts 'Review request successfully created.'
|
79
97
|
else
|
80
|
-
puts
|
98
|
+
puts 'Creating new review request failed.'
|
81
99
|
end
|
82
100
|
end
|
83
101
|
|
84
|
-
|
85
|
-
|
102
|
+
# Sign off a specified request by merging it into master.
|
103
|
+
def merge
|
104
|
+
return unless review_exists?
|
86
105
|
option = @args.shift
|
87
|
-
if
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
106
|
+
if @review['head']['repository']
|
107
|
+
o = @review['head']['repository']['owner']
|
108
|
+
r = @review['head']['repository']['name']
|
109
|
+
else # they deleted the source repo
|
110
|
+
o = @review['head']['user']['login']
|
111
|
+
purl = @review['patch_url']
|
112
|
+
puts "Sorry, #{o} deleted the source repository, git-review doesn't support this."
|
113
|
+
puts "You can manually patch your repo by running:"
|
93
114
|
puts
|
94
|
-
puts "
|
95
|
-
puts "Body :"
|
115
|
+
puts " curl #{purl} | git am"
|
96
116
|
puts
|
97
|
-
puts
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
end
|
117
|
+
puts "Tell the contributor not to do this."
|
118
|
+
return false
|
119
|
+
end
|
120
|
+
s = @review['head']['sha']
|
121
|
+
message = "Merge pull request ##{@review['number']} from #{o}/#{r}\n\n---\n\n"
|
122
|
+
message += @review['body'].gsub("'", '')
|
123
|
+
if option == '--log'
|
124
|
+
message += "\n\n---\n\nMerge Log:\n"
|
125
|
+
puts cmd = "git merge --no-ff --log -m '#{message}' #{s}"
|
107
126
|
else
|
108
|
-
puts "
|
127
|
+
puts cmd = "git merge --no-ff -m '#{message}' #{s}"
|
109
128
|
end
|
129
|
+
exec(cmd)
|
110
130
|
end
|
111
131
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
132
|
+
# Start a console session (used for debugging).
|
133
|
+
def console
|
134
|
+
puts 'Entering debug console.'
|
135
|
+
require 'ruby-debug'
|
136
|
+
Debugger.start
|
137
|
+
debugger
|
138
|
+
puts 'Leaving debug console.'
|
119
139
|
end
|
120
140
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
puts line.join ' '
|
137
|
-
count += 1
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
# Setup variables and call actual commands.
|
145
|
+
def initialize(args)
|
146
|
+
command = args.shift
|
147
|
+
@user, @repo = repo_info
|
148
|
+
@args = args
|
149
|
+
configure
|
150
|
+
if command && self.respond_to?(command)
|
151
|
+
update
|
152
|
+
self.send command
|
153
|
+
else
|
154
|
+
unless command.blank? or %w(-h --help).include?(command)
|
155
|
+
puts "git-review: '#{command}' is not a valid command.\n\n"
|
138
156
|
end
|
139
|
-
|
140
|
-
if count == 0
|
141
|
-
puts ' -- no open pull requests --'
|
157
|
+
help
|
142
158
|
end
|
143
159
|
end
|
144
160
|
|
161
|
+
# Get latest changes from GitHub.
|
145
162
|
def update
|
146
163
|
cache_pull_info
|
147
164
|
fetch_stale_forks
|
148
165
|
end
|
149
166
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
Octokit.create_pull_request(repo, to_branch, from_branch, title, body)
|
167
|
+
# Check existence of specified review and assign @review.
|
168
|
+
def review_exists?
|
169
|
+
review_id = @args.shift.to_i
|
170
|
+
@review = get_pull_info.find{ |review| review['number'] == review_id}
|
171
|
+
puts "Review '#{review_id}' does not exist." unless @review
|
172
|
+
not @review.nil?
|
158
173
|
end
|
159
|
-
|
160
|
-
|
161
|
-
|
174
|
+
|
175
|
+
# System call to 'git'.
|
176
|
+
def git(command, chomp=true)
|
177
|
+
s = `git #{command}`
|
178
|
+
s.chomp! if chomp
|
179
|
+
s
|
180
|
+
end
|
181
|
+
|
182
|
+
# Display helper to make output more beautiful.
|
183
|
+
def format_text(info, size)
|
184
|
+
info.to_s.gsub("\n", ' ')[0, size].ljust(size)
|
162
185
|
end
|
163
186
|
|
164
187
|
def fetch_stale_forks
|
@@ -195,20 +218,6 @@ Usage: git review list [--reverse]
|
|
195
218
|
commits.split("\n").size > 0
|
196
219
|
end
|
197
220
|
|
198
|
-
# DISPLAY HELPER FUNCTIONS #
|
199
|
-
|
200
|
-
def l(info, size)
|
201
|
-
clean(info)[0, size].ljust(size)
|
202
|
-
end
|
203
|
-
|
204
|
-
def r(info, size)
|
205
|
-
clean(info)[0, size].rjust(size)
|
206
|
-
end
|
207
|
-
|
208
|
-
def clean(info)
|
209
|
-
info.to_s.gsub("\n", ' ')
|
210
|
-
end
|
211
|
-
|
212
221
|
# PRIVATE REPOSITORIES ACCESS
|
213
222
|
|
214
223
|
def configure
|
@@ -250,7 +259,7 @@ Usage: git review list [--reverse]
|
|
250
259
|
end
|
251
260
|
|
252
261
|
def get_data(file)
|
253
|
-
|
262
|
+
JSON.parse(File.read(file))
|
254
263
|
end
|
255
264
|
|
256
265
|
def cache_pull_info
|
@@ -264,11 +273,6 @@ Usage: git review list [--reverse]
|
|
264
273
|
end
|
265
274
|
end
|
266
275
|
|
267
|
-
def pull_num(num)
|
268
|
-
data = get_pull_info
|
269
|
-
data.select { |p| p['number'].to_s == num.to_s }.first
|
270
|
-
end
|
271
|
-
|
272
276
|
def github_insteadof_matching(c, u)
|
273
277
|
first = c.collect {|k,v| [v, /url\.(.*github\.com.*)\.insteadof/.match(k)]}.
|
274
278
|
find {|v,m| u.index(v) and m != nil}
|
@@ -307,9 +311,4 @@ Usage: git review list [--reverse]
|
|
307
311
|
[user, proj]
|
308
312
|
end
|
309
313
|
|
310
|
-
def git(command, chomp=true)
|
311
|
-
s = `git #{command}`
|
312
|
-
s.chomp! if chomp
|
313
|
-
s
|
314
|
-
end
|
315
314
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git-review
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 0.4.
|
9
|
+
- 2
|
10
|
+
version: 0.4.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Cristian Messel, Dominik Bamberger
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-07-
|
18
|
+
date: 2011-07-13 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|