git-review 2.0.0.alpha → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/git-review +18 -9
- data/lib/git-review.rb +35 -12
- data/lib/git-review/commands.rb +157 -172
- data/lib/git-review/errors.rb +6 -0
- data/lib/git-review/helpers.rb +38 -0
- data/lib/git-review/local.rb +157 -20
- data/lib/git-review/provider/base.rb +85 -0
- data/lib/git-review/provider/bitbucket.rb +25 -0
- data/lib/git-review/provider/github.rb +271 -0
- data/lib/git-review/server.rb +61 -0
- data/lib/git-review/settings.rb +26 -21
- data/lib/mixins/accessible.rb +35 -0
- data/lib/mixins/colorizable.rb +30 -0
- data/lib/mixins/nestable.rb +16 -0
- data/lib/mixins/string.rb +13 -0
- data/lib/mixins/time.rb +11 -0
- data/lib/models/commit.rb +14 -0
- data/lib/models/repository.rb +8 -0
- data/lib/models/request.rb +18 -0
- data/lib/models/user.rb +7 -0
- metadata +72 -47
- data/lib/git-review/github.rb +0 -289
- data/lib/git-review/internals.rb +0 -47
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 49d9d8f5c8209622227ccaecb90dbb9db6549f06
|
4
|
+
data.tar.gz: f8041155345b3f1afd104904a64401295fa4bb6f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5e6eca5b975528044e599608d58f4d90adb9d466fbe22e9d3da6b21ba53bbe16a49f21e85cd361d3bb3a804c4cacdb1af71b4d04f714fd98c99f4b0943f35b05
|
7
|
+
data.tar.gz: 05ac7231034a1b309e434b1257645c5df10f7a9dd8126a9efadcfba6b0808520860c28fc682b161c6fcf119adaf93d77a84eaeddf81ab6407cf69e85b7b5274c
|
data/bin/git-review
CHANGED
@@ -7,23 +7,23 @@ require 'git-review'
|
|
7
7
|
require 'gli'
|
8
8
|
|
9
9
|
include GLI::App
|
10
|
-
|
11
10
|
program_desc 'Manage review workflow for Github projects (using pull requests).'
|
12
11
|
|
13
12
|
# Pre-hook before a command is executed
|
14
13
|
pre do |global, cmd, opts, args|
|
15
|
-
|
16
|
-
if
|
17
|
-
|
14
|
+
server = ::GitReview::Server.instance
|
15
|
+
if server.configure_access && server.source_repo
|
16
|
+
server.update unless cmd == 'clean'
|
18
17
|
end
|
19
|
-
|
18
|
+
|
19
|
+
true # return true to explicitly pass precondition
|
20
20
|
end
|
21
21
|
|
22
22
|
desc 'List all pending requests'
|
23
23
|
command :list do |c|
|
24
24
|
c.switch [:r, :reverse]
|
25
25
|
c.action do |global, opts, args|
|
26
|
-
|
26
|
+
::GitReview::Commands.list(opts[:reverse])
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -46,7 +46,7 @@ end
|
|
46
46
|
|
47
47
|
desc 'Checkout a request\'s changes to local repo'
|
48
48
|
command :checkout do |c|
|
49
|
-
c.switch [:b, :branch]
|
49
|
+
c.switch [:b, :branch], default_value: true
|
50
50
|
c.action do |global, opts, args|
|
51
51
|
help_now!('Request number is required.') if args.empty?
|
52
52
|
::GitReview::Commands.checkout(args.shift, opts[:branch])
|
@@ -81,7 +81,7 @@ desc 'Create a new local branch for a request'
|
|
81
81
|
command :prepare do |c|
|
82
82
|
c.switch [:n, :new]
|
83
83
|
c.action do |global, opts, args|
|
84
|
-
::GitReview::Commands.prepare(opts[:new], args.
|
84
|
+
::GitReview::Commands.prepare(opts[:new], args.empty? ? nil : args.join(' '))
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
@@ -100,7 +100,16 @@ command :clean do |c|
|
|
100
100
|
c.action do |global, opts, args|
|
101
101
|
help_now!('Request number is required.') if args.empty? && !opts[:all]
|
102
102
|
number = args.empty? ? nil : args.shift
|
103
|
-
::GitReview::Commands.clean(
|
103
|
+
::GitReview::Commands.clean(args.shift, opts[:force], opts[:all])
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
if ::GitReview::Settings.instance.review_mode == 'debug' || ENV['DEBUG']
|
108
|
+
desc 'Console session for debugging'
|
109
|
+
command :console do |c|
|
110
|
+
c.action do |global, opts, args|
|
111
|
+
::GitReview::Commands.console(args.shift)
|
112
|
+
end
|
104
113
|
end
|
105
114
|
end
|
106
115
|
|
data/lib/git-review.rb
CHANGED
@@ -1,28 +1,51 @@
|
|
1
|
+
### Dependencies
|
2
|
+
|
3
|
+
## External Dependencies
|
4
|
+
|
1
5
|
# Provide access to GitHub's API.
|
2
6
|
require 'octokit'
|
3
7
|
# Open a browser in 'browse' command.
|
4
8
|
require 'launchy'
|
5
9
|
# Parse time strings from git back into Time objects.
|
6
10
|
require 'time'
|
7
|
-
# Use temporary files to allow editing a request's
|
11
|
+
# Use temporary files to allow editing a request's.
|
8
12
|
require 'tempfile'
|
9
13
|
|
10
|
-
##
|
14
|
+
## Internal dependencies
|
11
15
|
|
12
|
-
# Include
|
13
|
-
require_relative 'git-review/
|
14
|
-
# Deal with current git repository.
|
15
|
-
require_relative 'git-review/local'
|
16
|
-
# Communicate with Github via API.
|
17
|
-
require_relative 'git-review/github'
|
18
|
-
# Read and write settings from/to the filesystem.
|
19
|
-
require_relative 'git-review/settings'
|
16
|
+
# Include helper functions to make it work as expected.
|
17
|
+
require_relative 'git-review/helpers'
|
20
18
|
# Provide available commands.
|
21
19
|
require_relative 'git-review/commands'
|
20
|
+
# Read and write settings from/to the filesystem.
|
21
|
+
require_relative 'git-review/settings'
|
22
|
+
# Deal with local git repository.
|
23
|
+
require_relative 'git-review/local'
|
22
24
|
# Include all kinds of custom-defined errors.
|
23
25
|
require_relative 'git-review/errors'
|
26
|
+
# Factory to get git API client..
|
27
|
+
require_relative 'git-review/server'
|
28
|
+
# Generic base class for shared provider methods.
|
29
|
+
require_relative 'git-review/provider/base'
|
30
|
+
# Communicate with Github via API.
|
31
|
+
require_relative 'git-review/provider/github'
|
32
|
+
# Communicate with Bitbucket via API.
|
33
|
+
require_relative 'git-review/provider/bitbucket'
|
24
34
|
|
35
|
+
# Allow easy string colorization in the console.
|
36
|
+
require_relative 'mixins/colorizable'
|
37
|
+
# Allow to access a model's attributes in various ways (feels railsy).
|
38
|
+
require_relative 'mixins/accessible'
|
39
|
+
# Allow to nest models in other model's attributes.
|
40
|
+
require_relative 'mixins/nestable'
|
25
41
|
|
26
|
-
|
42
|
+
# Include custom string helpers.
|
43
|
+
require_relative 'mixins/string'
|
44
|
+
# Include custom time helpers.
|
45
|
+
require_relative 'mixins/time'
|
27
46
|
|
28
|
-
|
47
|
+
# Add some POROs to get some structure into the entities git-review deals with.
|
48
|
+
require_relative 'models/repository'
|
49
|
+
require_relative 'models/user'
|
50
|
+
require_relative 'models/commit'
|
51
|
+
require_relative 'models/request'
|
data/lib/git-review/commands.rb
CHANGED
@@ -2,66 +2,81 @@ module GitReview
|
|
2
2
|
|
3
3
|
module Commands
|
4
4
|
|
5
|
-
include ::GitReview::
|
5
|
+
include ::GitReview::Helpers
|
6
6
|
extend self
|
7
7
|
|
8
8
|
# List all pending requests.
|
9
|
-
def list(reverse=false)
|
10
|
-
requests =
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
def list(reverse = false)
|
10
|
+
requests = server.current_requests_full.reject do |request|
|
11
|
+
# Find only pending (= unmerged) requests and output summary.
|
12
|
+
# Explicitly look for local changes git does not yet know about.
|
13
|
+
# TODO: Isn't this a bit confusing? Maybe display pending pushes?
|
14
|
+
local.merged? request.head.sha
|
15
|
+
end
|
16
16
|
source = local.source
|
17
17
|
if requests.empty?
|
18
18
|
puts "No pending requests for '#{source}'."
|
19
19
|
else
|
20
20
|
puts "Pending requests for '#{source}':"
|
21
|
-
puts "ID Updated Comments Title"
|
22
|
-
requests
|
21
|
+
puts "ID Updated Comments Title".pink
|
22
|
+
print_requests(requests, reverse)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
# Show details for a single request.
|
27
|
-
def show(number, full=false)
|
28
|
-
request = get_request_by_number(number)
|
29
|
-
#
|
27
|
+
def show(number, full = false)
|
28
|
+
request = server.get_request_by_number(number)
|
29
|
+
# Determine whether to show full diff or stats only.
|
30
30
|
option = full ? '' : '--stat '
|
31
31
|
diff = "diff --color=always #{option}HEAD...#{request.head.sha}"
|
32
|
-
|
32
|
+
# TODO: Refactor into using Request model.
|
33
|
+
print_request_details request
|
33
34
|
puts git_call(diff)
|
34
|
-
print_request_discussions
|
35
|
+
print_request_discussions request
|
35
36
|
end
|
36
37
|
|
37
38
|
# Open a browser window and review a specified request.
|
38
39
|
def browse(number)
|
39
|
-
request = get_request_by_number(number)
|
40
|
-
|
40
|
+
request = server.get_request_by_number(number)
|
41
|
+
# FIXME: Use request.html_url as soon as we are using our Request model.
|
42
|
+
Launchy.open request._links.html.href
|
41
43
|
end
|
42
44
|
|
43
45
|
# Checkout a specified request's changes to your local repository.
|
44
|
-
def checkout(number, branch=
|
45
|
-
request = get_request_by_number(number)
|
46
|
+
def checkout(number, branch = true)
|
47
|
+
request = server.get_request_by_number(number)
|
46
48
|
puts 'Checking out changes to your local repository.'
|
47
49
|
puts 'To get back to your original state, just run:'
|
48
50
|
puts
|
49
|
-
puts ' git checkout master'
|
51
|
+
puts ' git checkout master'.pink
|
50
52
|
puts
|
53
|
+
# Ensure we are looking at the right remote.
|
54
|
+
remote = local.remote_for_request(request)
|
55
|
+
git_call "fetch #{remote}"
|
56
|
+
# Checkout the right branch.
|
57
|
+
branch_name = request.head.ref
|
51
58
|
if branch
|
52
|
-
|
59
|
+
if local.branch_exists?(:local, branch_name)
|
60
|
+
if local.source_branch == branch_name
|
61
|
+
puts "On branch #{branch_name}."
|
62
|
+
else
|
63
|
+
git_call "checkout #{branch_name}"
|
64
|
+
end
|
65
|
+
else
|
66
|
+
git_call "checkout --track -b #{branch_name} #{remote}/#{branch_name}"
|
67
|
+
end
|
53
68
|
else
|
54
|
-
git_call
|
69
|
+
git_call "checkout #{remote}/#{branch_name}"
|
55
70
|
end
|
56
71
|
end
|
57
72
|
|
58
73
|
# Add an approving comment to the request.
|
59
74
|
def approve(number)
|
60
|
-
request = get_request_by_number(number)
|
61
|
-
repo =
|
75
|
+
request = server.get_request_by_number(number)
|
76
|
+
repo = server.source_repo
|
62
77
|
# TODO: Make this configurable.
|
63
78
|
comment = 'Reviewed and approved.'
|
64
|
-
response =
|
79
|
+
response = server.add_comment(repo, request.number, comment)
|
65
80
|
if response[:body] == comment
|
66
81
|
puts 'Successfully approved request.'
|
67
82
|
else
|
@@ -71,7 +86,7 @@ module GitReview
|
|
71
86
|
|
72
87
|
# Accept a specified request by merging it into master.
|
73
88
|
def merge(number)
|
74
|
-
request = get_request_by_number(number)
|
89
|
+
request = server.get_request_by_number(number)
|
75
90
|
if request.head.repo
|
76
91
|
message = "Accept request ##{request.number} " +
|
77
92
|
"and merge changes into \"#{local.target}\""
|
@@ -85,108 +100,144 @@ module GitReview
|
|
85
100
|
puts
|
86
101
|
puts git_call(command)
|
87
102
|
else
|
88
|
-
print_repo_deleted
|
103
|
+
print_repo_deleted request
|
89
104
|
end
|
90
105
|
end
|
91
106
|
|
92
107
|
# Close a specified request.
|
93
108
|
def close(number)
|
94
|
-
request = get_request_by_number(number)
|
95
|
-
repo =
|
96
|
-
|
97
|
-
unless
|
109
|
+
request = server.get_request_by_number(number)
|
110
|
+
repo = server.source_repo
|
111
|
+
server.close_issue(repo, request.number)
|
112
|
+
unless server.request_exists?('open', request.number)
|
98
113
|
puts 'Successfully closed request.'
|
99
114
|
end
|
100
115
|
end
|
101
116
|
|
102
117
|
# Prepare local repository to create a new request.
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
118
|
+
# NOTE:
|
119
|
+
# People should work on local branches, but especially for single commit
|
120
|
+
# changes, more often than not, they don't. Therefore this is called
|
121
|
+
# automatically before creating a pull request, such that we create a
|
122
|
+
# proper feature branch for them, to be able to use code review the way it
|
123
|
+
# is intended.
|
124
|
+
def prepare(force_new_branch = false, feature_name = nil)
|
125
|
+
current_branch = local.source_branch
|
126
|
+
if force_new_branch || !local.on_feature_branch?
|
127
|
+
feature_name ||= get_branch_name
|
128
|
+
feature_branch = move_local_changes(
|
129
|
+
current_branch, local.sanitize_branch_name(feature_name)
|
130
|
+
)
|
112
131
|
else
|
113
|
-
|
132
|
+
feature_branch = current_branch
|
114
133
|
end
|
115
|
-
[
|
134
|
+
[current_branch, feature_branch]
|
116
135
|
end
|
117
136
|
|
118
137
|
# Create a new request.
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
# prepare original_branch and local_branch
|
138
|
+
def create(upstream = false)
|
139
|
+
# Prepare original_branch and local_branch.
|
140
|
+
# TODO: Allow to use the same switches and parameters that prepare takes.
|
123
141
|
original_branch, local_branch = prepare
|
124
|
-
#
|
125
|
-
|
142
|
+
# Don't create request with uncommitted changes in current branch.
|
143
|
+
if local.uncommitted_changes?
|
126
144
|
puts 'You have uncommitted changes.'
|
127
145
|
puts 'Please stash or commit before creating the request.'
|
128
146
|
return
|
129
147
|
end
|
130
|
-
if
|
131
|
-
|
132
|
-
|
133
|
-
if github.request_exists_for_branch?(upstream)
|
148
|
+
if local.new_commits?(upstream)
|
149
|
+
# Feature branch differs from local or upstream master.
|
150
|
+
if server.request_exists_for_branch?(upstream)
|
134
151
|
puts 'A pull request already exists for this branch.'
|
135
152
|
puts 'Please update the request directly using `git push`.'
|
136
153
|
return
|
137
154
|
end
|
138
|
-
#
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
155
|
+
# Push latest commits to the remote branch (create if necessary).
|
156
|
+
remote = local.remote_for_branch(local_branch) || 'origin'
|
157
|
+
git_call(
|
158
|
+
"push --set-upstream #{remote} #{local_branch}", debug_mode, true
|
159
|
+
)
|
160
|
+
server.send_pull_request upstream
|
161
|
+
# Return to the user's original branch.
|
162
|
+
git_call "checkout #{original_branch}"
|
163
|
+
else
|
164
|
+
puts 'Nothing to push to remote yet. Commit something first.'
|
144
165
|
end
|
145
166
|
end
|
146
167
|
|
147
|
-
#
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
168
|
+
# Remove remotes with 'review' prefix (left over from previous reviews).
|
169
|
+
# Prune all existing remotes and delete obsolete branches (left over from
|
170
|
+
# already closed requests).
|
171
|
+
def clean(number = nil, force = false, all = false)
|
172
|
+
git_call "checkout #{local.target_branch}"
|
173
|
+
local.prune_remotes
|
174
|
+
# Determine strategy to clean.
|
152
175
|
if all
|
153
176
|
local.clean_all
|
154
177
|
else
|
155
178
|
local.clean_single(number, force)
|
156
179
|
end
|
180
|
+
# Remove al review remotes without existing local branches.
|
181
|
+
local.clean_remotes
|
157
182
|
end
|
158
183
|
|
159
184
|
# Start a console session (used for debugging)
|
160
|
-
def console
|
185
|
+
def console(number = nil)
|
161
186
|
puts 'Entering debug console.'
|
162
|
-
|
163
|
-
|
164
|
-
|
187
|
+
request = server.get_request_by_number(number) if number
|
188
|
+
|
189
|
+
if RUBY_VERSION.to_f >= 2
|
190
|
+
begin
|
191
|
+
require 'byebug'
|
192
|
+
byebug
|
193
|
+
rescue LoadError => e
|
194
|
+
puts
|
195
|
+
puts 'Missing debugger, please install byebug:'
|
196
|
+
puts ' gem install byebug'
|
197
|
+
puts
|
198
|
+
end
|
165
199
|
else
|
166
|
-
|
167
|
-
|
168
|
-
|
200
|
+
begin
|
201
|
+
require 'ruby-debug'
|
202
|
+
Debugger.start
|
203
|
+
debugger
|
204
|
+
rescue LoadError => e
|
205
|
+
puts
|
206
|
+
puts 'Missing debugger, please install ruby-debug:'
|
207
|
+
puts ' gem install ruby-debug'
|
208
|
+
puts
|
209
|
+
end
|
169
210
|
end
|
170
211
|
puts 'Leaving debug console.'
|
171
212
|
end
|
172
213
|
|
173
|
-
private
|
174
214
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
line =
|
179
|
-
line <<
|
180
|
-
line <<
|
181
|
-
line <<
|
182
|
-
|
215
|
+
private
|
216
|
+
|
217
|
+
def request_summary(request)
|
218
|
+
line = request.number.to_s.review_ljust(8)
|
219
|
+
line << request.updated_at.review_time.review_ljust(11)
|
220
|
+
line << server.comments_count(request).to_s.review_ljust(10)
|
221
|
+
line << request.title.review_ljust(91)
|
222
|
+
line
|
223
|
+
end
|
224
|
+
|
225
|
+
def print_requests(requests, reverse=false)
|
226
|
+
# put all output lines in a hash first, keyed by request number
|
227
|
+
# this is to make sure the order is still correct even if we use
|
228
|
+
# multi-threading to retrieve the requests
|
229
|
+
output = {}
|
230
|
+
requests.each { |req| output[req.number] = request_summary(req) }
|
231
|
+
numbers = output.keys.sort
|
232
|
+
numbers.reverse! if reverse
|
233
|
+
numbers.each { |n| puts output[n] }
|
183
234
|
end
|
184
235
|
|
185
236
|
def print_request_details(request)
|
186
|
-
comments_count =
|
237
|
+
comments_count = server.comments_count(request)
|
187
238
|
puts 'ID : ' + request.number.to_s
|
188
239
|
puts 'Label : ' + request.head.label
|
189
|
-
puts 'Updated : ' +
|
240
|
+
puts 'Updated : ' + request.updated_at.review_time
|
190
241
|
puts 'Comments : ' + comments_count.to_s
|
191
242
|
puts
|
192
243
|
puts request.title
|
@@ -200,7 +251,7 @@ module GitReview
|
|
200
251
|
def print_request_discussions(request)
|
201
252
|
puts 'Progress :'
|
202
253
|
puts
|
203
|
-
puts
|
254
|
+
puts server.discussion(request.number)
|
204
255
|
end
|
205
256
|
|
206
257
|
# someone deleted the source repo
|
@@ -221,111 +272,45 @@ module GitReview
|
|
221
272
|
# @return [String] sanitized branch name
|
222
273
|
def get_branch_name
|
223
274
|
puts 'Please provide a name for the branch:'
|
224
|
-
|
225
|
-
|
275
|
+
local.sanitize_branch_name gets.chomp
|
276
|
+
end
|
277
|
+
|
278
|
+
# @return [String] the complete feature branch name
|
279
|
+
def create_feature_name(new_branch)
|
280
|
+
"review_#{Time.now.strftime("%y%m%d")}_#{new_branch}"
|
226
281
|
end
|
227
282
|
|
228
|
-
#
|
283
|
+
# Move uncommitted changes from original_branch to a feature_branch.
|
229
284
|
# @return [String] the new local branch uncommitted changes are moved to
|
230
|
-
def
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
#
|
235
|
-
|
236
|
-
|
285
|
+
def move_local_changes(original_branch, feature_name)
|
286
|
+
feature_branch = create_feature_name(feature_name)
|
287
|
+
# By checking out the feature branch, the commits on the original branch
|
288
|
+
# are copied over. That way we only need to remove pending (local) commits
|
289
|
+
# from the original branch.
|
290
|
+
git_call "checkout -b #{feature_branch}"
|
291
|
+
if local.source_branch == feature_branch
|
292
|
+
# Save any uncommitted changes, to be able to reapply them later.
|
237
293
|
save_uncommitted_changes = local.uncommitted_changes?
|
238
294
|
git_call('stash') if save_uncommitted_changes
|
239
|
-
#
|
240
|
-
git_call("checkout #{
|
241
|
-
|
242
|
-
|
295
|
+
# Go back to original branch and get rid of pending (local) commits.
|
296
|
+
git_call("checkout #{original_branch}")
|
297
|
+
remote = local.remote_for_branch(original_branch)
|
298
|
+
remote += '/' if remote
|
299
|
+
git_call("reset --hard #{remote}#{original_branch}")
|
300
|
+
git_call("checkout #{feature_branch}")
|
243
301
|
git_call('stash pop') if save_uncommitted_changes
|
244
|
-
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
def create_pull_request(to_upstream=false)
|
249
|
-
target_repo = local.target_repo(to_upstream)
|
250
|
-
head = local.head
|
251
|
-
base = local.target_branch
|
252
|
-
title, body = create_title_and_body(base)
|
253
|
-
|
254
|
-
# gather information before creating pull request
|
255
|
-
lastest_number = github.latest_request_number(target_repo)
|
256
|
-
|
257
|
-
# create the actual pull request
|
258
|
-
github.create_pull_request(target_repo, base, head, title, body)
|
259
|
-
# switch back to target_branch and check for success
|
260
|
-
git_call("checkout #{base}")
|
261
|
-
|
262
|
-
# make sure the new pull request is indeed created
|
263
|
-
new_number = github.request_number_by_title(title, target_repo)
|
264
|
-
if new_number && new_number > lastest_number
|
265
|
-
puts "Successfully created new request ##{new_number}"
|
266
|
-
puts "https://github.com/#{target_repo}/pull/#{new_number}"
|
267
|
-
else
|
268
|
-
puts "Pull request was not created for #{target_repo}."
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
|
273
|
-
# @return [Array(String, String)] the title and the body of pull request
|
274
|
-
def create_title_and_body(target_branch)
|
275
|
-
source = local.source
|
276
|
-
login = github.github.login
|
277
|
-
commits = git_call("log --format='%H' HEAD...#{target_branch}").
|
278
|
-
lines.count
|
279
|
-
puts "commits: #{commits}"
|
280
|
-
if commits == 1
|
281
|
-
# we can create a really specific title and body
|
282
|
-
title = git_call("log --format='%s' HEAD...#{target_branch}").chomp
|
283
|
-
body = git_call("log --format='%b' HEAD...#{target_branch}").chomp
|
284
|
-
else
|
285
|
-
title = "[Review] Request from '#{login}' @ '#{source}'"
|
286
|
-
body = "Please review the following changes:\n"
|
287
|
-
body += git_call("log --oneline HEAD...#{target_branch}").
|
288
|
-
lines.map{|l| " * #{l.chomp}"}.join("\n")
|
302
|
+
feature_branch
|
289
303
|
end
|
290
|
-
edit_title_and_body(title, body)
|
291
304
|
end
|
292
305
|
|
293
|
-
|
294
|
-
|
295
|
-
tmpfile = Tempfile.new('git-review')
|
296
|
-
tmpfile.write(title + "\n\n" + body)
|
297
|
-
tmpfile.flush
|
298
|
-
editor = ENV['TERM_EDITOR'] || ENV['EDITOR']
|
299
|
-
unless editor
|
300
|
-
warn 'Please set $EDITOR or $TERM_EDITOR in your .bash_profile.'
|
301
|
-
end
|
302
|
-
|
303
|
-
system("#{editor || 'open'} #{tmpfile.path}")
|
304
|
-
|
305
|
-
tmpfile.rewind
|
306
|
-
lines = tmpfile.read.lines.to_a
|
307
|
-
puts lines.inspect
|
308
|
-
title = lines.shift.chomp
|
309
|
-
lines.shift if lines[0].chomp.empty?
|
310
|
-
body = lines.join
|
311
|
-
tmpfile.unlink
|
312
|
-
[title, body]
|
313
|
-
end
|
314
|
-
|
315
|
-
def github
|
316
|
-
@github ||= ::GitReview::Github.instance
|
306
|
+
def server
|
307
|
+
@server ||= ::GitReview::Server.instance
|
317
308
|
end
|
318
309
|
|
319
310
|
def local
|
320
311
|
@local ||= ::GitReview::Local.instance
|
321
312
|
end
|
322
313
|
|
323
|
-
def get_request_by_number(request_number)
|
324
|
-
request = github.request_exists?(request_number)
|
325
|
-
request || (raise ::GitReview::InvalidRequestIDError)
|
326
|
-
end
|
327
|
-
|
328
314
|
end
|
329
315
|
|
330
316
|
end
|
331
|
-
|