plunger 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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