plunger 0.0.1 → 0.0.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/README.md +36 -4
- data/lib/plunger/changeset/git.rb +62 -0
- data/lib/plunger/changeset.rb +17 -0
- data/lib/plunger/command/configure.rb +18 -39
- data/lib/plunger/command/push.rb +46 -1
- data/lib/plunger/command/upgrade.rb +20 -2
- data/lib/plunger/command.rb +10 -0
- data/lib/plunger/config.rb +32 -0
- data/lib/plunger/runner.rb +1 -1
- data/lib/plunger/uploader.rb +98 -0
- data/lib/plunger/version.rb +1 -1
- data/lib/plunger.rb +6 -3
- data/plunger.gemspec +1 -1
- metadata +10 -6
data/README.md
CHANGED
@@ -2,9 +2,28 @@
|
|
2
2
|
|
3
3
|
# Plunger
|
4
4
|
|
5
|
-
|
5
|
+
Plunger is code review tool for Google Code Reviews.
|
6
6
|
|
7
|
-
|
7
|
+
Basically it's ruby wrapper for [Rietveld](http://code.google.com/p/rietveld/) upload.py tool.
|
8
|
+
|
9
|
+
## Goals
|
10
|
+
|
11
|
+
* Automated original upload tool installation and configuration
|
12
|
+
* Automated changeset generation with description/title/reviewers etc...
|
13
|
+
|
14
|
+
Supported VCS:
|
15
|
+
|
16
|
+
* git
|
17
|
+
|
18
|
+
## Install
|
19
|
+
|
20
|
+
Install tool:
|
21
|
+
|
22
|
+
gem install plunger
|
23
|
+
|
24
|
+
Configure google code review for your organization:
|
25
|
+
|
26
|
+
See [Using Code Reviews with Google Apps](http://code.google.com/p/rietveld/wiki/CodeReviewHelp#Using_Code_Reviews_with_Google_Apps)
|
8
27
|
|
9
28
|
## Commands
|
10
29
|
|
@@ -12,10 +31,23 @@ To see all commands:
|
|
12
31
|
|
13
32
|
plunger --help
|
14
33
|
|
15
|
-
### Configure
|
34
|
+
### Configure command
|
16
35
|
|
17
36
|
Synopsis:
|
18
37
|
|
19
38
|
plunger configure
|
20
39
|
|
21
|
-
It will ask your about required options and store configuration to
|
40
|
+
It will ask your about required options and store configuration to *~/.gem/plunger*
|
41
|
+
|
42
|
+
### Push command
|
43
|
+
|
44
|
+
Synopsis:
|
45
|
+
|
46
|
+
plunger push
|
47
|
+
|
48
|
+
## Developer Flow
|
49
|
+
|
50
|
+
* Go to your VCS project and optionally switch to your working branch.
|
51
|
+
* Finish feature/fix implementation.
|
52
|
+
* Type ``plunger push``.
|
53
|
+
* Follow instructions and it generate and push changeset to codereview server.
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'posix/spawn'
|
2
|
+
|
3
|
+
module Plunger
|
4
|
+
module Changeset
|
5
|
+
class Git
|
6
|
+
class << self
|
7
|
+
def detected?
|
8
|
+
Dir.exists?('.git')
|
9
|
+
end
|
10
|
+
|
11
|
+
def command
|
12
|
+
Config.data['git_bin'] || 'git'
|
13
|
+
end
|
14
|
+
|
15
|
+
def initial_revision
|
16
|
+
'origin/master'
|
17
|
+
end
|
18
|
+
|
19
|
+
def final_revision
|
20
|
+
revision = Command.spawn_result("#{command} symbolic-ref -q HEAD").strip.split('/').last
|
21
|
+
"origin/#{revision}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(initial, final)
|
26
|
+
@range = "#{initial}..#{final}"
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :range
|
30
|
+
|
31
|
+
def repository_name
|
32
|
+
@repository_name ||= File.split(File.expand_path('.')).last
|
33
|
+
end
|
34
|
+
|
35
|
+
def message
|
36
|
+
@message ||= "[#{repository_name}] #{range}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def description
|
40
|
+
@description ||= Command.spawn_result("#{self.class.command} log --pretty='%s' #{range}")
|
41
|
+
end
|
42
|
+
|
43
|
+
def empty?
|
44
|
+
description.empty?
|
45
|
+
end
|
46
|
+
|
47
|
+
def author_emails
|
48
|
+
@author_emails ||= Command.spawn_result("#{self.class.command} log --pretty='%ae' #{range}").
|
49
|
+
split("\n").
|
50
|
+
map { |email| email.strip }.
|
51
|
+
uniq
|
52
|
+
end
|
53
|
+
|
54
|
+
def commiter_emails
|
55
|
+
@commiter_emails ||= Command.spawn_result("#{self.class.command} log --pretty='%ce' #{range}").
|
56
|
+
split("\n").
|
57
|
+
map { |email| email.strip }.
|
58
|
+
uniq
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -13,59 +13,38 @@ module Plunger
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def autorun?
|
16
|
-
!
|
17
|
-
end
|
18
|
-
|
19
|
-
def config_path
|
20
|
-
@config_path ||= File.join(Gem.user_home, '.gem', 'plunger')
|
16
|
+
!Config.exists?
|
21
17
|
end
|
22
18
|
end
|
23
19
|
|
24
20
|
def run
|
25
|
-
ui.say "Please configure plunger"
|
21
|
+
Command.ui.say "Please configure plunger (enter nothing if you don't want to change option)"
|
22
|
+
|
26
23
|
[
|
27
|
-
['server',
|
28
|
-
['
|
24
|
+
['server', 'Code review server', 'coderev.railsware.com' ],
|
25
|
+
['domain', 'Google app domain', 'railsware.com' ],
|
26
|
+
['email', 'Google app email', 'vasya.pupkin@railsware.com'],
|
27
|
+
['python_bin', 'Path to python v2 binary', 'python' ],
|
28
|
+
['git_bin', 'Path to git binary', 'git' ]
|
29
29
|
].each do |args|
|
30
|
-
|
30
|
+
configure(*args)
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
|
-
ui.say "Configuration saved to #{config_path}"
|
35
|
-
end
|
36
|
-
|
37
|
-
protected
|
33
|
+
Plunger::Config.save
|
38
34
|
|
39
|
-
|
40
|
-
@ui ||= Gem::ConsoleUI.new
|
41
|
-
end
|
35
|
+
Command.ui.say "Configuration saved to #{Plunger::Config.path}"
|
42
36
|
|
43
|
-
|
44
|
-
self.class.config_path
|
37
|
+
true
|
45
38
|
end
|
46
39
|
|
47
|
-
|
48
|
-
@configuration ||= Gem.configuration.load_file(config_path)
|
49
|
-
end
|
50
|
-
|
51
|
-
def configure_option(name, description, default)
|
52
|
-
configuration[name] ||= default
|
53
|
-
value = configuration[name]
|
54
|
-
value = ui.ask("#{description} (#{value}):")
|
55
|
-
configuration[name] ||= default
|
56
|
-
configuration[name] = value unless value.empty?
|
57
|
-
end
|
58
|
-
|
59
|
-
def save_configuration
|
60
|
-
dirname = File.dirname(config_path)
|
61
|
-
|
62
|
-
Dir.mkdir(dirname) unless File.exists?(dirname)
|
40
|
+
protected
|
63
41
|
|
64
|
-
|
65
|
-
|
66
|
-
|
42
|
+
def configure(name, description, default)
|
43
|
+
Plunger::Config.data[name] ||= default
|
44
|
+
value = Plunger::Config.data[name]
|
45
|
+
value = Command.ui.ask("#{description} (#{value}):")
|
46
|
+
Plunger::Config.data[name] = value unless value.empty?
|
67
47
|
end
|
68
|
-
|
69
48
|
end
|
70
49
|
end
|
71
50
|
end
|
data/lib/plunger/command/push.rb
CHANGED
@@ -16,7 +16,52 @@ module Plunger
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def run
|
19
|
-
|
19
|
+
unless changeset_class = Changeset.detect_class
|
20
|
+
Command.ui.say("Can't detect SCM")
|
21
|
+
return false
|
22
|
+
end
|
23
|
+
|
24
|
+
revisions = [
|
25
|
+
[changeset_class.initial_revision, "initial" ],
|
26
|
+
[changeset_class.final_revision, "final" ]
|
27
|
+
].map do |default, description|
|
28
|
+
revision = Command.ui.ask("Specify #{description} revision or reference (#{default}):")
|
29
|
+
revision.empty? ? default : revision
|
30
|
+
end
|
31
|
+
|
32
|
+
changeset = changeset_class.new(*revisions)
|
33
|
+
|
34
|
+
changeset.empty? and abort("Changeset #{changeset.range} is empty")
|
35
|
+
|
36
|
+
message = changeset.title
|
37
|
+
description = changeset.description
|
38
|
+
reviewers = changeset.author_emails
|
39
|
+
|
40
|
+
if reviewers.empty?
|
41
|
+
Command.ui.say("No reviewers detected")
|
42
|
+
else
|
43
|
+
Command.ui.say("Found reviewers in the changeset:")
|
44
|
+
reviewers.each { |reviewer| Command.ui.say(reviewer) }
|
45
|
+
end
|
46
|
+
|
47
|
+
issue = Command.ui.ask("Issue number (omit to create new issue):")
|
48
|
+
|
49
|
+
reviewers +=
|
50
|
+
Command.ui.ask("Specify another reviewers (comma separated email addresses):").
|
51
|
+
split(',').
|
52
|
+
map { |reviewer| reviewer.strip }
|
53
|
+
|
54
|
+
Uploader.new.run({
|
55
|
+
'server' => Config.data['server'],
|
56
|
+
'email' => Config.data['email'],
|
57
|
+
'issue' => issue,
|
58
|
+
'send_mail' => true,
|
59
|
+
'message' => message,
|
60
|
+
'description' => description,
|
61
|
+
'reviewers' => reviewers.uniq.join(',')
|
62
|
+
}, [
|
63
|
+
changeset.range
|
64
|
+
])
|
20
65
|
end
|
21
66
|
end
|
22
67
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'rubygems/dependency_installer'
|
2
|
+
|
1
3
|
module Plunger
|
2
4
|
module Command
|
3
5
|
class Upgrade
|
@@ -11,12 +13,28 @@ module Plunger
|
|
11
13
|
end
|
12
14
|
|
13
15
|
def autorun?
|
14
|
-
|
16
|
+
true
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
18
20
|
def run
|
19
|
-
|
21
|
+
Command.ui.say("Checking plunger update ...")
|
22
|
+
|
23
|
+
req = Gem::Requirement.new(">#{Plunger::VERSION}")
|
24
|
+
dep = Gem::Dependency.new('plunger', req)
|
25
|
+
tuples = Gem::SpecFetcher.fetcher.fetch(dep)
|
26
|
+
|
27
|
+
if tuples.empty?
|
28
|
+
Command.ui.say("Plunger is up to date")
|
29
|
+
else
|
30
|
+
spec, source = tuples.first
|
31
|
+
Command.ui.say("Upgrading #{Plunger::VERSION} to #{spec.version}")
|
32
|
+
installer = Gem::DependencyInstaller.new
|
33
|
+
installer.install(spec.name, spec.version.to_s)
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
|
37
|
+
true
|
20
38
|
end
|
21
39
|
end
|
22
40
|
end
|
data/lib/plunger/command.rb
CHANGED
@@ -22,6 +22,16 @@ module Plunger
|
|
22
22
|
def command_class(name)
|
23
23
|
Plunger::Command.const_get(Utils.camelize(name))
|
24
24
|
end
|
25
|
+
|
26
|
+
def ui
|
27
|
+
@ui ||= Gem::ConsoleUI.new
|
28
|
+
end
|
29
|
+
|
30
|
+
def spawn_result(command)
|
31
|
+
result = POSIX::Spawn.`(command)
|
32
|
+
$?.success? or abort
|
33
|
+
result
|
34
|
+
end
|
25
35
|
end
|
26
36
|
end
|
27
37
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Plunger
|
2
|
+
class Config
|
3
|
+
class << self
|
4
|
+
def exists?
|
5
|
+
File.exists?(path)
|
6
|
+
end
|
7
|
+
|
8
|
+
def path
|
9
|
+
@path ||= File.join(Gem.user_home, '.gem', 'plunger')
|
10
|
+
end
|
11
|
+
|
12
|
+
def load
|
13
|
+
Gem.configuration.load_file(path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def save
|
17
|
+
dirname = File.dirname(path)
|
18
|
+
|
19
|
+
Dir.mkdir(dirname) unless File.exists?(dirname)
|
20
|
+
|
21
|
+
File.open(path, 'w') do |f|
|
22
|
+
f.write data.to_yaml
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def data
|
27
|
+
@data ||= self.load
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
data/lib/plunger/runner.rb
CHANGED
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'posix/spawn'
|
2
|
+
|
3
|
+
module Plunger
|
4
|
+
class Uploader
|
5
|
+
|
6
|
+
def command
|
7
|
+
Config.data['python_bin'] || 'python'
|
8
|
+
end
|
9
|
+
|
10
|
+
def script
|
11
|
+
File.expand_path('../../../python/upload.py', __FILE__)
|
12
|
+
end
|
13
|
+
|
14
|
+
def run(options, diff_options = nil)
|
15
|
+
argvs = [ script ]
|
16
|
+
|
17
|
+
options.each do |key, value|
|
18
|
+
case value
|
19
|
+
when true
|
20
|
+
argvs << "--#{key}"
|
21
|
+
when false
|
22
|
+
else
|
23
|
+
argvs << "--#{key}" << "#{value}" unless value.to_s.empty?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
diff_options = Array(diff_options)
|
28
|
+
|
29
|
+
unless diff_options.empty?
|
30
|
+
argvs << '--'
|
31
|
+
argvs += diff_options
|
32
|
+
end
|
33
|
+
|
34
|
+
POSIX::Spawn.system(command, *argvs)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
=begin
|
41
|
+
|
42
|
+
python2 python/upload.py -h
|
43
|
+
|
44
|
+
Usage: upload.py [options] [-- diff_options] [path...]
|
45
|
+
|
46
|
+
Options:
|
47
|
+
-h --help Show this help message and exit.
|
48
|
+
-y --assume_yes Assume that the answer to yes/no questions is 'yes'.
|
49
|
+
|
50
|
+
Logging options:
|
51
|
+
-q --quiet Print errors only.
|
52
|
+
-v --verbose Print info level logs.
|
53
|
+
--noisy Print all logs.
|
54
|
+
--print_diffs Print full diffs.
|
55
|
+
|
56
|
+
Review server options:
|
57
|
+
-s --server SERVER The server to upload to. The format is host[:port].
|
58
|
+
Defaults to 'codereview.appspot.com'.
|
59
|
+
-e --email EMAIL The username to use. Will prompt if omitted.
|
60
|
+
-H --host HOST Overrides the Host header sent with all RPCs.
|
61
|
+
--no_cookies Do not save authentication cookies to local disk.
|
62
|
+
--account_type TYPE Override the default account type (defaults to
|
63
|
+
'GOOGLE', valid choices are 'GOOGLE' and 'HOSTED').
|
64
|
+
|
65
|
+
Issue options:
|
66
|
+
-d --description DESCRIPTION
|
67
|
+
Optional description when creating an issue.
|
68
|
+
-f --description_file DESCRIPTION_FILE
|
69
|
+
Optional path of a file that contains the description
|
70
|
+
when creating an issue.
|
71
|
+
-r --reviewers REVIEWERS
|
72
|
+
Add reviewers (comma separated email addresses).
|
73
|
+
--cc CC Add CC (comma separated email addresses).
|
74
|
+
--private Make the issue restricted to reviewers and those CCed
|
75
|
+
|
76
|
+
Patch options:
|
77
|
+
-m --message MESSAGE A message to identify the patch. Will prompt if
|
78
|
+
omitted.
|
79
|
+
-i --issue ISSUE Issue number to which to add. Defaults to new issue.
|
80
|
+
--base_url BASE_URL Base URL path for files (listed as "Base URL" when
|
81
|
+
viewing issue). If omitted, will be guessed
|
82
|
+
automatically for SVN repos and left blank for others.
|
83
|
+
--download_base Base files will be downloaded by the server (side-by-
|
84
|
+
side diffs may not work on files with CRs).
|
85
|
+
--rev REV Base revision/branch/tree to diff against. Use
|
86
|
+
rev1:rev2 range to review already committed changeset.
|
87
|
+
--send_mail Send notification email to reviewers.
|
88
|
+
-p --send_patch Same as --send_mail, but include diff as an
|
89
|
+
attachment, and prepend email subject with 'PATCH:'.
|
90
|
+
--vcs VCS Version control system (optional, usually upload.py
|
91
|
+
already guesses the right VCS).
|
92
|
+
--emulate_svn_auto_props
|
93
|
+
Emulate Subversion's auto properties feature.
|
94
|
+
|
95
|
+
Use '--help -v' to show additional Perforce options.
|
96
|
+
|
97
|
+
=end
|
98
|
+
|
data/lib/plunger/version.rb
CHANGED
data/lib/plunger.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
require "plunger/version"
|
2
2
|
|
3
3
|
module Plunger
|
4
|
-
autoload :Runner,
|
5
|
-
autoload :
|
6
|
-
autoload :
|
4
|
+
autoload :Runner, 'plunger/runner'
|
5
|
+
autoload :Changeset, 'plunger/changeset'
|
6
|
+
autoload :Command, 'plunger/command'
|
7
|
+
autoload :Config, 'plunger/config'
|
8
|
+
autoload :Uploader, 'plunger/uploader'
|
9
|
+
autoload :Utils, 'plunger/utils'
|
7
10
|
end
|
data/plunger.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: plunger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,19 +9,19 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-10-
|
12
|
+
date: 2011-10-19 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
16
|
-
requirement: &
|
15
|
+
name: posix-spawn
|
16
|
+
requirement: &25420280 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - =
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 0.3.6
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *25420280
|
25
25
|
description: Ruby Wrapper for Rietveld Code Review, hosted on Google App Engine
|
26
26
|
email:
|
27
27
|
- andriy.yanko@gmail.com
|
@@ -37,11 +37,15 @@ files:
|
|
37
37
|
- Rakefile
|
38
38
|
- bin/plunger
|
39
39
|
- lib/plunger.rb
|
40
|
+
- lib/plunger/changeset.rb
|
41
|
+
- lib/plunger/changeset/git.rb
|
40
42
|
- lib/plunger/command.rb
|
41
43
|
- lib/plunger/command/configure.rb
|
42
44
|
- lib/plunger/command/push.rb
|
43
45
|
- lib/plunger/command/upgrade.rb
|
46
|
+
- lib/plunger/config.rb
|
44
47
|
- lib/plunger/runner.rb
|
48
|
+
- lib/plunger/uploader.rb
|
45
49
|
- lib/plunger/utils.rb
|
46
50
|
- lib/plunger/version.rb
|
47
51
|
- plunger.gemspec
|