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 CHANGED
@@ -2,9 +2,28 @@
2
2
 
3
3
  # Plunger
4
4
 
5
- Plumber is code review tool.
5
+ Plunger is code review tool for Google Code Reviews.
6
6
 
7
- Its ruby wrapper for [Rietveld Code Review, hosted on Google App Engine](http://code.google.com/p/rietveld/)
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 ~/.gem/plumber
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
@@ -0,0 +1,17 @@
1
+ require 'plunger/changeset/git'
2
+
3
+ module Plunger
4
+ module Changeset
5
+
6
+ class << self
7
+ def classes
8
+ [Git]
9
+ end
10
+
11
+ def detect_class
12
+ self.classes.find { |klass| klass.detected? }
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -13,59 +13,38 @@ module Plunger
13
13
  end
14
14
 
15
15
  def autorun?
16
- !File.exists?(config_path)
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', 'Code review server', 'coderev.railsware.com'],
28
- ['python_bin', 'Path to python v2 binary', 'python']
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
- configure_option(*args)
30
+ configure(*args)
31
31
  end
32
32
 
33
- save_configuration
34
- ui.say "Configuration saved to #{config_path}"
35
- end
36
-
37
- protected
33
+ Plunger::Config.save
38
34
 
39
- def ui
40
- @ui ||= Gem::ConsoleUI.new
41
- end
35
+ Command.ui.say "Configuration saved to #{Plunger::Config.path}"
42
36
 
43
- def config_path
44
- self.class.config_path
37
+ true
45
38
  end
46
39
 
47
- def configuration
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
- File.open(config_path, 'w') do |f|
65
- f.write configuration.to_yaml
66
- end
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
@@ -16,7 +16,52 @@ module Plunger
16
16
  end
17
17
 
18
18
  def run
19
- p "PUSH"
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
- false
16
+ true
15
17
  end
16
18
  end
17
19
 
18
20
  def run
19
- p "UPGRADE"
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
@@ -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
+
@@ -37,7 +37,7 @@ module Plunger
37
37
  end
38
38
 
39
39
  Command.autorun
40
- Command.run(@command)
40
+ Command.run(@command) or abort
41
41
  end
42
42
 
43
43
  end
@@ -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
+
@@ -1,3 +1,3 @@
1
1
  module Plunger
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/plunger.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  require "plunger/version"
2
2
 
3
3
  module Plunger
4
- autoload :Runner, 'plunger/runner'
5
- autoload :Command, 'plunger/command'
6
- autoload :Utils, 'plunger/utils'
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
@@ -18,5 +18,5 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.add_dependency "grit", "2.4.1"
21
+ s.add_dependency "posix-spawn", "0.3.6"
22
22
  end
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.1
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-18 00:00:00.000000000Z
12
+ date: 2011-10-19 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: grit
16
- requirement: &19227280 !ruby/object:Gem::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: 2.4.1
21
+ version: 0.3.6
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *19227280
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