reviewr 0.1.3 → 0.2.0
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/Manifest.txt +3 -0
- data/README.md +50 -27
- data/lib/reviewr/cli.rb +2 -0
- data/lib/reviewr/cli/accept.rb +33 -0
- data/lib/reviewr/cli/command.rb +55 -0
- data/lib/reviewr/cli/help.rb +3 -7
- data/lib/reviewr/cli/main.rb +17 -38
- data/lib/reviewr/cli/request.rb +5 -20
- data/lib/reviewr/git.rb +27 -2
- data/lib/reviewr/project.rb +38 -7
- data/lib/reviewr/templates/accept_email.erb +6 -0
- data/lib/reviewr/version.rb +1 -1
- metadata +7 -4
data/Manifest.txt
CHANGED
@@ -9,8 +9,11 @@ lib/reviewr/git.rb
|
|
9
9
|
lib/reviewr/mailer.rb
|
10
10
|
lib/reviewr/project.rb
|
11
11
|
lib/reviewr/version.rb
|
12
|
+
lib/reviewr/cli/accept.rb
|
13
|
+
lib/reviewr/cli/command.rb
|
12
14
|
lib/reviewr/cli/help.rb
|
13
15
|
lib/reviewr/cli/main.rb
|
14
16
|
lib/reviewr/cli/request.rb
|
17
|
+
lib/reviewr/templates/accept_email.erb
|
15
18
|
lib/reviewr/templates/commit_msg.erb
|
16
19
|
lib/reviewr/templates/request_email.erb
|
data/README.md
CHANGED
@@ -6,7 +6,28 @@ git and github.com for version control.
|
|
6
6
|
# Installation
|
7
7
|
gem install reviewr
|
8
8
|
|
9
|
-
#
|
9
|
+
# Usage
|
10
|
+
|
11
|
+
Reviewr is designed to simplify code reviews for projects that revolve
|
12
|
+
around a single 'master' repository with multiple contributors (i.e. a
|
13
|
+
project that is hosted on github). It does this by providing a default
|
14
|
+
work-flow that all developers can use.
|
15
|
+
|
16
|
+
The general work-flow (at the moment) is:
|
17
|
+
|
18
|
+
1. The coder issues a code review request through the 'request'
|
19
|
+
command.
|
20
|
+
2. The reviewer(s) review the code and comment on it through github
|
21
|
+
3. If the code is good enough to merge it can be pulled into the
|
22
|
+
master branch through the 'accept' command
|
23
|
+
|
24
|
+
While this documentation is up to date (as of version 0.2.0) I am
|
25
|
+
still experimenting with an ideal work-flow for these type of code
|
26
|
+
reviews, so this code is subject to heavy change. If you have any
|
27
|
+
suggestions send me an email or comment in the issue tracker as I
|
28
|
+
would love further opinions.
|
29
|
+
|
30
|
+
## Requesting a code review
|
10
31
|
reviewr request <email>
|
11
32
|
This will result in the following actions:
|
12
33
|
|
@@ -15,41 +36,37 @@ This will result in the following actions:
|
|
15
36
|
* Push the code review branch to the remote repository
|
16
37
|
* Send an email to <email> requesting a code review of the branch
|
17
38
|
The email will include a link to Github's compare view for the
|
18
|
-
changes
|
39
|
+
changes
|
19
40
|
|
20
|
-
##
|
41
|
+
## Accepting changes from a code review
|
42
|
+
reviewr accept <branch_name>
|
43
|
+
This will result in the following actions:
|
21
44
|
|
22
|
-
*
|
23
|
-
|
45
|
+
* Create a branch for the reviewed code
|
46
|
+
* Rebase the reviewed code on the current branch
|
47
|
+
* Merge in the commits
|
48
|
+
* Push the merged branch
|
49
|
+
* Delete the code review branch from the remote repo
|
50
|
+
* Send an email to the requester of the review saying the changes have been
|
51
|
+
merged
|
24
52
|
|
25
|
-
#
|
53
|
+
# Contributing
|
54
|
+
|
55
|
+
## Reporting Bugs
|
26
56
|
|
27
|
-
|
57
|
+
Bugs are being managed using Github's issue tracking
|
28
58
|
|
29
|
-
|
59
|
+
http://github.com/rhburrows/reviewr/issues
|
30
60
|
|
31
|
-
|
32
|
-
request email@site.com`. This causes reviewr to:
|
61
|
+
## Contributing Code
|
33
62
|
|
34
|
-
|
35
|
-
is the SHA of the current commit
|
36
|
-
* Add a commit to the branch with metadata about the request
|
37
|
-
(requester name/email etc).
|
38
|
-
* push the branch to the origin repository
|
39
|
-
* generate a github review url from the current head to the pushed
|
40
|
-
review branch
|
41
|
-
* Send an email to `email@site.com` with a nice message and the url
|
63
|
+
Just fork the project on github and submit a pull request
|
42
64
|
|
43
|
-
|
44
|
-
|
45
|
-
|
65
|
+
http://github.com/rhburrows/reviewr
|
66
|
+
|
67
|
+
# TODO
|
46
68
|
|
47
|
-
|
48
|
-
* attempt to merge the reviewed branch into the master
|
49
|
-
* if it fails an error will be raised and execution will stop
|
50
|
-
* if is succeeds the merged master will be pushed
|
51
|
-
* the remote review branch will be deleted.
|
52
|
-
* an email will be sent to the review requester saying the code was accepted
|
69
|
+
## Add a reject code review command
|
53
70
|
|
54
71
|
If the code the reviewer is checking is not acceptable, upon finishing
|
55
72
|
comments on github the reviewer can run `reviewr reject
|
@@ -58,3 +75,9 @@ review_0f38ef31`. reviewr will:
|
|
58
75
|
* Re-generate the github url for comparing to the current master
|
59
76
|
* Send an email to the requester of the review saying the code has
|
60
77
|
been rejected and to please see the comments on the linked page
|
78
|
+
|
79
|
+
# Limitations
|
80
|
+
|
81
|
+
* Email can only be sent from a Gmail (or Google Apps for my domain)
|
82
|
+
address
|
83
|
+
* Only tested with git 1.7.0
|
data/lib/reviewr/cli.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Reviewr
|
2
|
+
module CLI
|
3
|
+
class Accept < Command
|
4
|
+
def execute
|
5
|
+
merge_branch = project.current_branch
|
6
|
+
|
7
|
+
project.review_branch = arguments.first
|
8
|
+
prompt_for_user
|
9
|
+
project.fetch_review_branch
|
10
|
+
project.fetch_master
|
11
|
+
project.create_review_branch("origin/#{arguments.first}")
|
12
|
+
|
13
|
+
unless project.rebase_review
|
14
|
+
output.print "Branch '#{arguments.first}' won't merge cleanly"
|
15
|
+
else
|
16
|
+
# This must be run while on the review branch
|
17
|
+
project.to = project.requester_email
|
18
|
+
|
19
|
+
project.change_branch(merge_branch)
|
20
|
+
project.merge_commits
|
21
|
+
project.push_branch(merge_branch)
|
22
|
+
project.delete_remote_review_branch
|
23
|
+
|
24
|
+
Mailer.new(project).send(email_body)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def email_body
|
29
|
+
read_template('accept_email.erb')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Reviewr
|
2
|
+
module CLI
|
3
|
+
class Command
|
4
|
+
attr_reader :project
|
5
|
+
attr_accessor :input, :output, :arguments
|
6
|
+
|
7
|
+
def initialize(project, input = STDIN, output = STDOUT)
|
8
|
+
@project = project
|
9
|
+
@input, @output = input, output
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
execute
|
14
|
+
end
|
15
|
+
|
16
|
+
def prompt_for_user
|
17
|
+
output.print("Email (default #{project.user_email}): ")
|
18
|
+
email = input.gets.chomp
|
19
|
+
project.user_email = email unless email.empty?
|
20
|
+
|
21
|
+
output.print("Email password: ")
|
22
|
+
no_echo(input) do
|
23
|
+
project.email_password = input.gets.chomp
|
24
|
+
end
|
25
|
+
output.print("\n")
|
26
|
+
|
27
|
+
output.print("Remote repository (default origin): ")
|
28
|
+
repo = input.gets.chomp
|
29
|
+
project.remote_repo = repo unless repo.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
def read_template(name)
|
33
|
+
@templates ||= {}
|
34
|
+
@templates[name] ||= ERB.new(File.read(File.join(File.dirname(__FILE__),
|
35
|
+
'..',
|
36
|
+
'templates',
|
37
|
+
name)))
|
38
|
+
@templates[name].result(binding)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def no_echo(input)
|
44
|
+
oldt = Termios.tcgetattr(input)
|
45
|
+
newt = oldt.dup
|
46
|
+
newt.lflag &= ~Termios::ECHO
|
47
|
+
Termios.tcsetattr(input, Termios::TCSANOW, newt)
|
48
|
+
|
49
|
+
yield
|
50
|
+
|
51
|
+
Termios.tcsetattr(input, Termios::TCSANOW, oldt)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/reviewr/cli/help.rb
CHANGED
data/lib/reviewr/cli/main.rb
CHANGED
@@ -3,54 +3,33 @@ require 'termios'
|
|
3
3
|
module Reviewr
|
4
4
|
module CLI
|
5
5
|
class Main
|
6
|
-
attr_reader :command
|
7
|
-
attr_accessor :
|
6
|
+
attr_reader :command, :c
|
7
|
+
attr_accessor :arguments
|
8
8
|
|
9
9
|
def initialize(args, input = STDIN, output = STDOUT)
|
10
10
|
@command = args.shift
|
11
|
-
@
|
11
|
+
@arguments = args
|
12
12
|
@input, @output = input, output
|
13
13
|
end
|
14
14
|
|
15
15
|
def run
|
16
|
-
|
17
|
-
when "request"
|
18
|
-
prompt_for_user(@input, @output)
|
19
|
-
Request.new(project).call
|
20
|
-
else
|
21
|
-
#FIXME
|
22
|
-
Help.new.call(project.to)
|
23
|
-
end
|
16
|
+
build_command.call
|
24
17
|
end
|
25
18
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
19
|
+
def build_command
|
20
|
+
unless @c
|
21
|
+
case command
|
22
|
+
when "request"
|
23
|
+
@c = Request.new(Project.new, @input, @output)
|
24
|
+
when "accept"
|
25
|
+
@c = Accept.new(Project.new, @input, @output)
|
26
|
+
else
|
27
|
+
@c = Help.new(Project.new, @input, @output)
|
28
|
+
end
|
29
|
+
|
30
|
+
@c.arguments = arguments
|
34
31
|
end
|
35
|
-
|
36
|
-
|
37
|
-
output.print("Remote repository (default origin): ")
|
38
|
-
repo = input.gets.chomp
|
39
|
-
project.remote_repo = repo unless repo.empty?
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
#TODO, should this be somewhere better?
|
45
|
-
def no_echo(input)
|
46
|
-
oldt = Termios.tcgetattr(input)
|
47
|
-
newt = oldt.dup
|
48
|
-
newt.lflag &= ~Termios::ECHO
|
49
|
-
Termios.tcsetattr(input, Termios::TCSANOW, newt)
|
50
|
-
|
51
|
-
yield
|
52
|
-
|
53
|
-
Termios.tcsetattr(input, Termios::TCSANOW, oldt)
|
32
|
+
@c
|
54
33
|
end
|
55
34
|
end
|
56
35
|
end
|
data/lib/reviewr/cli/request.rb
CHANGED
@@ -3,16 +3,12 @@ require 'forwardable'
|
|
3
3
|
|
4
4
|
module Reviewr
|
5
5
|
module CLI
|
6
|
-
class Request
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@project = project
|
11
|
-
end
|
12
|
-
|
13
|
-
def call
|
6
|
+
class Request < Command
|
7
|
+
def execute
|
8
|
+
project.to = arguments.first
|
9
|
+
prompt_for_user
|
14
10
|
original_branch = project.current_branch
|
15
|
-
project.create_review_branch
|
11
|
+
project.create_review_branch(original_branch)
|
16
12
|
project.create_review_commit(commit_msg)
|
17
13
|
project.push_review_branch
|
18
14
|
Mailer.new(project).send(email_body)
|
@@ -31,17 +27,6 @@ module Reviewr
|
|
31
27
|
def email_body
|
32
28
|
read_template('request_email.erb')
|
33
29
|
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def read_template(name)
|
38
|
-
@templates ||= {}
|
39
|
-
@templates[name] ||= ERB.new(File.read(File.join(File.dirname(__FILE__),
|
40
|
-
'..',
|
41
|
-
'templates',
|
42
|
-
name)))
|
43
|
-
@templates[name].result(binding)
|
44
|
-
end
|
45
30
|
end
|
46
31
|
end
|
47
32
|
end
|
data/lib/reviewr/git.rb
CHANGED
@@ -20,8 +20,17 @@ module Reviewr
|
|
20
20
|
execute('git show --pretty=format:"%H" HEAD').split("\n")[0]
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
execute("git
|
23
|
+
def rebase(base, branch)
|
24
|
+
conflict = execute("git rebase #{base} #{branch}").to_s.
|
25
|
+
include?("CONFLICT")
|
26
|
+
if conflict
|
27
|
+
execute('git rebase --abort')
|
28
|
+
end
|
29
|
+
!conflict
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_branch(branch_name, base)
|
33
|
+
execute("git branch #{branch_name} #{base}")
|
25
34
|
end
|
26
35
|
|
27
36
|
def commit(msg)
|
@@ -37,6 +46,10 @@ module Reviewr
|
|
37
46
|
execute("git checkout #{branch_name}")
|
38
47
|
end
|
39
48
|
|
49
|
+
def fetch(branch_name)
|
50
|
+
execute("git fetch #{remote_repo} #{branch_name}")
|
51
|
+
end
|
52
|
+
|
40
53
|
def user_email
|
41
54
|
email = execute('git config user.email')
|
42
55
|
email && email.chomp
|
@@ -56,6 +69,18 @@ module Reviewr
|
|
56
69
|
r && r.split(/\s+/)[0]
|
57
70
|
end
|
58
71
|
|
72
|
+
def cherry(from, to)
|
73
|
+
execute("git cherry #{from} #{to}")
|
74
|
+
end
|
75
|
+
|
76
|
+
def cherry_pick(commit)
|
77
|
+
execute("git cherry-pick -s #{commit}")
|
78
|
+
end
|
79
|
+
|
80
|
+
def log(n)
|
81
|
+
execute("git log -n #{n}")
|
82
|
+
end
|
83
|
+
|
59
84
|
def execute(cmd)
|
60
85
|
`#{cmd}`
|
61
86
|
end
|
data/lib/reviewr/project.rb
CHANGED
@@ -4,19 +4,32 @@ module Reviewr
|
|
4
4
|
class Project
|
5
5
|
extend Forwardable
|
6
6
|
|
7
|
-
attr_reader :
|
8
|
-
attr_accessor :email_password
|
9
|
-
attr_writer :user_email
|
7
|
+
attr_reader :git, :email_server
|
8
|
+
attr_accessor :email_password, :to
|
9
|
+
attr_writer :user_email, :review_branch
|
10
10
|
|
11
11
|
def_delegators :git, :push_branch, :origin_location, :remote_repo,
|
12
12
|
:remote_repo=, :current_branch, :change_branch
|
13
13
|
|
14
|
-
def initialize(
|
15
|
-
@
|
14
|
+
def initialize(git = Git.instance)
|
15
|
+
@git = git
|
16
16
|
end
|
17
17
|
|
18
|
-
def create_review_branch
|
19
|
-
git.create_branch(review_branch)
|
18
|
+
def create_review_branch(base = 'master')
|
19
|
+
git.create_branch(review_branch, base)
|
20
|
+
git.change_branch(review_branch)
|
21
|
+
end
|
22
|
+
|
23
|
+
def rebase_review
|
24
|
+
git.rebase(current_branch, review_branch)
|
25
|
+
end
|
26
|
+
|
27
|
+
def fetch_review_branch
|
28
|
+
git.fetch(review_branch)
|
29
|
+
end
|
30
|
+
|
31
|
+
def fetch_master
|
32
|
+
git.fetch('master')
|
20
33
|
end
|
21
34
|
|
22
35
|
def create_review_commit(msg)
|
@@ -46,5 +59,23 @@ module Reviewr
|
|
46
59
|
def email_server
|
47
60
|
@email_server ||= user_email.split('@')[1]
|
48
61
|
end
|
62
|
+
|
63
|
+
def merge_commits
|
64
|
+
git.cherry(current_branch, review_branch).split(/\n/).each do |line|
|
65
|
+
git.cherry_pick(line.split(/\s/)[1])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def delete_remote_review_branch
|
70
|
+
git.push_branch(":#{review_branch}")
|
71
|
+
end
|
72
|
+
|
73
|
+
def requester_email
|
74
|
+
msg = git.log(1)
|
75
|
+
if msg
|
76
|
+
m = msg.match(/requested_by: ([^\s]+)/)
|
77
|
+
m && m[1]
|
78
|
+
end
|
79
|
+
end
|
49
80
|
end
|
50
81
|
end
|
data/lib/reviewr/version.rb
CHANGED
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ryan Burrows
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-28 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -85,9 +85,12 @@ files:
|
|
85
85
|
- lib/reviewr/mailer.rb
|
86
86
|
- lib/reviewr/project.rb
|
87
87
|
- lib/reviewr/version.rb
|
88
|
+
- lib/reviewr/cli/accept.rb
|
89
|
+
- lib/reviewr/cli/command.rb
|
88
90
|
- lib/reviewr/cli/help.rb
|
89
91
|
- lib/reviewr/cli/main.rb
|
90
92
|
- lib/reviewr/cli/request.rb
|
93
|
+
- lib/reviewr/templates/accept_email.erb
|
91
94
|
- lib/reviewr/templates/commit_msg.erb
|
92
95
|
- lib/reviewr/templates/request_email.erb
|
93
96
|
has_rdoc: true
|