rake_commit 0.1.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/README.rdoc ADDED
@@ -0,0 +1,69 @@
1
+ = rake_commit_tasks
2
+
3
+ This plugin contains a set of rake tasks for checking your project into source control (git or subversion). The most important is:
4
+
5
+ rake commit
6
+
7
+ which does the following, depending on source control:
8
+
9
+ ==== git
10
+
11
+ 1. Resets soft back to origin/branch (in order to collapse changes into one commit)
12
+ 2. Adds new files to git and removes deleted files
13
+ 3. Prompts for a commit message
14
+ 4. Commits to git
15
+ 5. Pulls changes from origin (and does a rebase to keep a linear history)
16
+ 6. Runs the default rake task (which should run the tests)
17
+ 7. Checks cruisecontrol.rb to see if the build is passing
18
+ 8. Pushes the commit to origin
19
+
20
+ ==== git-svn
21
+
22
+ 1. Adds new files to git and removes deleted files
23
+ 2. Prompts for a commit message
24
+ 3. Commits to local git
25
+ 4. Pulls changes from SVN
26
+ 5. Runs the default rake task (which should run the tests)
27
+ 6. Checks cruisecontrol.rb to see if the build is passing
28
+ 7. Pushes the commit to SVN
29
+
30
+ ==== subversion
31
+
32
+ 1. Prompts for a commit message
33
+ 2. Adds new files to subversion
34
+ 3. Deletes missing files from subversion
35
+ 4. svn update
36
+ 5. Runs the default rake task (which should run the tests)
37
+ 6. Checks cruisecontrol.rb to see if the build is passing
38
+ 7. Checks in the code
39
+
40
+
41
+ The first version started with the code posted at Jay Field's Blog: http://blog.jayfields.com/2006/12/ruby-rake-commit.html.
42
+ Improvements have been added in from several more projects.
43
+
44
+ == Installation
45
+
46
+ git clone git://github.com/pgr0ss/rake_commit_tasks.git vendor/plugins/rake_commit_tasks
47
+ rake commit
48
+
49
+ == Customization
50
+
51
+ === Preventing checkins on broken builds
52
+
53
+ If you want the build to check your cruisecontrol.rb instance and prompt you
54
+ before checking in on a broken build, set CCRB_RSS to the location of the RSS feed.
55
+
56
+ For example, in your Rakefile:
57
+
58
+ CCRB_RSS = 'http://example.com:3333/projects.rss'
59
+
60
+ === Automatically merging from branch to trunk (subversion)
61
+
62
+ If you want the build to automatically merge changes to the trunk when checking in on the branch, set PATH_TO_TRUNK_WORKING_COPY to the location of the checked out trunk working copy.
63
+
64
+ For example, in your Rakefile:
65
+
66
+ PATH_TO_TRUNK_WORKING_COPY = "/Users/someone/my_project_trunk"
67
+
68
+ Now, if you have a branch checked out into /Users/someone/my_project_1.1 and you do a rake commit, the checkin will be merged into the trunk after the change is committed to the branch. Then, you can "cd /Users/someone/my_project_trunk" and check in the merged changes in the trunk. This behavior is described in more depth at http://www.pgrs.net/2007/10/16/automatically-merge-changes-from-branch-to-trunk
69
+
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require "rake/testtask"
2
+
3
+ task :default => :test
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.pattern = "test/**/*_test.rb"
7
+ end
8
+
9
+ desc "clean"
10
+ task :clean do
11
+ rm_f Dir.glob("*.gem")
12
+ end
13
+
14
+ namespace :gem do
15
+ desc "build the gem"
16
+ task :build => :clean do
17
+ sh "gem build rake_commit.gemspec"
18
+ end
19
+ end
data/bin/rake_commit ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.dirname(__FILE__) + "/../lib/commit"
4
+
5
+ Commit.new.commit
data/lib/commit.rb ADDED
@@ -0,0 +1,58 @@
1
+ require 'rexml/document'
2
+
3
+ Dir.glob(File.expand_path(File.dirname(__FILE__) + '/*.rb')) do |file|
4
+ require file
5
+ end
6
+
7
+ class Commit
8
+ def git?
9
+ `git symbolic-ref HEAD 2>/dev/null`
10
+ $?.success?
11
+ end
12
+
13
+ def git_svn?
14
+ `git svn info 2> /dev/null`
15
+ $?.success?
16
+ end
17
+
18
+ def commit
19
+ if git_svn?
20
+ GitSvn.new.commit
21
+ elsif git?
22
+ Git.new.commit
23
+ else
24
+ Svn.new.commit
25
+ end
26
+ end
27
+ end
28
+
29
+
30
+ def ok_to_check_in?
31
+ return true unless self.class.const_defined?(:CCRB_RSS)
32
+ cruise_status = CruiseStatus.new(CCRB_RSS)
33
+ cruise_status.pass? ? true : are_you_sure?( "Build FAILURES: #{cruise_status.failures.join(', ')}" )
34
+ end
35
+
36
+ def git_commit_with_message
37
+ commit_message = CommitMessage.new
38
+ sh_with_output("git config user.name #{commit_message.pair.inspect}")
39
+ message = "#{commit_message.feature} - #{commit_message.message}"
40
+ sh_with_output("git commit -m #{message.inspect}")
41
+ end
42
+
43
+ def are_you_sure?(message)
44
+ puts "\n", message
45
+ input = ""
46
+ while (input.strip.empty?)
47
+ input = Readline.readline("Are you sure you want to check in? (y/n): ")
48
+ end
49
+ return input.strip.downcase[0,1] == "y"
50
+ end
51
+
52
+ def sh_with_output(command)
53
+ puts command
54
+ output = `#{command}`
55
+ puts output
56
+ raise unless $?.success?
57
+ output
58
+ end
@@ -0,0 +1,14 @@
1
+ class CommitMessage
2
+
3
+ attr_reader :pair, :feature, :message
4
+
5
+ def initialize
6
+ @pair = PromptLine.new("pair").prompt
7
+ @feature = PromptLine.new("feature").prompt
8
+ @message = PromptLine.new("message").prompt
9
+ end
10
+
11
+ def joined_message
12
+ [@pair, @feature, @message].join(' - ')
13
+ end
14
+ end
@@ -0,0 +1,25 @@
1
+ require 'rexml/document'
2
+ require "open-uri"
3
+
4
+ class CruiseStatus
5
+
6
+ def initialize(feed_url)
7
+ project_feed = open(feed_url).read
8
+ @doc = REXML::Document.new(project_feed)
9
+ rescue Exception => e
10
+ @failures = [e.message]
11
+ @doc = REXML::Document.new("")
12
+ end
13
+
14
+ def pass?
15
+ failures.empty?
16
+ end
17
+
18
+ def failures
19
+ @failures ||= REXML::XPath.match(@doc, "//item/title").select { |element|
20
+ element.text =~ /failed$/
21
+ }.map do |element|
22
+ element.text.gsub( /(.*) build (.+) failed$/, '\1' )
23
+ end
24
+ end
25
+ end
data/lib/git.rb ADDED
@@ -0,0 +1,70 @@
1
+ class Git
2
+ def commit
3
+ collapse_git_commits if collapse_git_commits?
4
+
5
+ Shell.system("rake")
6
+
7
+ if ok_to_check_in?
8
+ push
9
+ end
10
+ end
11
+
12
+ def collapse_git_commits?
13
+ return true unless merge_commits?
14
+ status
15
+ input = Readline.readline("Do you want to collapse merge commits? (y/n): ").chomp
16
+ input == "y"
17
+ end
18
+
19
+ def collapse_git_commits
20
+ add
21
+ temp_commit
22
+ reset_soft
23
+ status
24
+ commit_message = CommitMessage.new
25
+ Shell.system("git config user.name #{commit_message.pair.inspect}")
26
+ message = "#{commit_message.feature} - #{commit_message.message}"
27
+ Shell.system("git commit -m #{message.inspect}")
28
+ pull_rebase
29
+ end
30
+
31
+ def status
32
+ Shell.system "git status"
33
+ end
34
+
35
+ def add
36
+ Shell.system "git add -A ."
37
+ end
38
+
39
+ def reset_soft
40
+ raise "Could not determine branch" unless git_branch
41
+ Shell.system "git reset --soft #{merge_base}"
42
+ end
43
+
44
+ def pull_rebase
45
+ Shell.system "git pull --rebase"
46
+ end
47
+
48
+ def push
49
+ Shell.system "git push origin #{git_branch}"
50
+ end
51
+
52
+ def temp_commit
53
+ Shell.system "git commit -m 'rake_commit backup commit'"
54
+ end
55
+
56
+ def git_branch
57
+ @git_branch ||= begin
58
+ output = Shell.backtick("git symbolic-ref HEAD")
59
+ output.gsub('refs/heads/', '').strip
60
+ end
61
+ end
62
+
63
+ def merge_commits?
64
+ Shell.backtick("git log --merges #{merge_base}..HEAD").any?
65
+ end
66
+
67
+ def merge_base
68
+ @merge_base ||= Shell.backtick("git merge-base #{git_branch} origin/#{git_branch}").strip
69
+ end
70
+ end
data/lib/git_svn.rb ADDED
@@ -0,0 +1,27 @@
1
+ class GitSvn
2
+ def commit
3
+ git = Git.new
4
+ git.add
5
+ git.status
6
+ git_svn_commit_with_message
7
+ rebase
8
+ Shell.system "rake"
9
+ if ok_to_check_in?
10
+ dcommit
11
+ end
12
+ end
13
+
14
+ def git_svn_commit_with_message
15
+ commit_message = CommitMessage.new
16
+ message = "#{commit_message.pair} - #{commit_message.feature} - #{commit_message.message}"
17
+ Shell.system "git commit -m #{message.inspect}"
18
+ end
19
+
20
+ def rebase
21
+ Shell.system "git svn rebase"
22
+ end
23
+
24
+ def dcommit
25
+ Shell.system "git svn dcommit"
26
+ end
27
+ end
@@ -0,0 +1,46 @@
1
+ require 'readline'
2
+ require 'tmpdir'
3
+
4
+ class PromptLine
5
+
6
+ def initialize(attribute)
7
+ @attribute = attribute
8
+ end
9
+
10
+ def prompt
11
+ input = nil
12
+ loop do
13
+ input = Readline.readline(message).chomp
14
+ break unless (input.empty? && saved_data.empty?)
15
+ end
16
+
17
+ if input.any?
18
+ save(input)
19
+ return input
20
+ end
21
+
22
+ puts "using: #{saved_data}"
23
+ return saved_data
24
+ end
25
+
26
+ def message
27
+ previous = saved_data
28
+ message = "\n"
29
+ message += "previous #{@attribute}: #{previous}\n" if previous.any?
30
+ message + "#{@attribute}: "
31
+ end
32
+
33
+ def save(input)
34
+ File.open(path(@attribute), "w") {|f| f.write(input) }
35
+ end
36
+
37
+ private
38
+ def saved_data
39
+ @saved_data ||= File.exists?(path(@attribute)) ? File.read(path(@attribute)) : ""
40
+ end
41
+
42
+ def path(attribute)
43
+ File.expand_path(Dir.tmpdir + "/#{attribute}.data")
44
+ end
45
+
46
+ end
data/lib/shell.rb ADDED
@@ -0,0 +1,11 @@
1
+ class Shell
2
+ def self.system(cmd)
3
+ Kernel.system(cmd) or raise
4
+ end
5
+
6
+ def self.backtick(cmd)
7
+ output = `#{cmd}`
8
+ raise unless $?.success?
9
+ output
10
+ end
11
+ end
data/lib/svn.rb ADDED
@@ -0,0 +1,85 @@
1
+ require 'fileutils'
2
+
3
+ class Svn
4
+ def commit
5
+ if files_to_check_in?
6
+ message = CommitMessage.new.joined_message
7
+ add
8
+ delete
9
+ up
10
+ Shell.system "rake"
11
+
12
+ if ok_to_check_in?
13
+ output = Shell.backtick "#{commit_command(message)}"
14
+ puts output
15
+ revision = output.match(/Committed revision (\d+)\./)[1]
16
+ merge_to_trunk(revision) if Shell.backtick("svn info").include?("branches") && self.class.const_defined?(:PATH_TO_TRUNK_WORKING_COPY)
17
+ end
18
+ else
19
+ puts "Nothing to commit"
20
+ end
21
+ end
22
+
23
+ def commit_command(message)
24
+ "svn ci -m #{message.inspect}"
25
+ end
26
+
27
+ def files_to_check_in?
28
+ Shell.backtick("svn st --ignore-externals").split("\n").reject {|line| line[0,1] == "X"}.any?
29
+ end
30
+
31
+ def status
32
+ Shell.system "svn st"
33
+ end
34
+
35
+ def up
36
+ output = Shell.backtick "svn up"
37
+ puts output
38
+ output.each do |line|
39
+ raise "SVN conflict detected. Please resolve conflicts before proceeding." if line[0,1] == "C"
40
+ end
41
+ end
42
+
43
+ def add
44
+ Shell.backtick("svn st").split("\n").each do |line|
45
+ if new_file?(line) && !svn_conflict_file?(line)
46
+ file = line[7..-1].strip
47
+ Shell.system "svn add #{file.inspect}"
48
+ end
49
+ end
50
+ end
51
+
52
+ def new_file?(line)
53
+ line[0,1] == "?"
54
+ end
55
+
56
+ def svn_conflict_file?(line)
57
+ line =~ /\.r\d+$/ || line =~ /\.mine$/
58
+ end
59
+
60
+ def delete
61
+ Shell.backtick("svn st").split("\n").each do |line|
62
+ if line[0,1] == "!"
63
+ file = line[7..-1].strip
64
+ Shell.backtick "svn up #{file.inspect} && svn rm #{file.inspect}"
65
+ puts %[removed #{file}]
66
+ end
67
+ end
68
+ end
69
+
70
+ def revert_all
71
+ Shell.system "svn revert -R ."
72
+ Shell.backtick("svn st").split("\n").each do |line|
73
+ next unless line[0,1] == '?'
74
+ filename = line[1..-1].strip
75
+ puts "removed #{filename}"
76
+ FileUtils.rm_r filename
77
+ end
78
+ end
79
+
80
+ def merge_to_trunk(revision)
81
+ puts "Merging changes into trunk. Don't forget to check these in."
82
+ Shell.system "svn up #{PATH_TO_TRUNK_WORKING_COPY.inspect}"
83
+ Shell.system "svn merge -c #{revision} . #{PATH_TO_TRUNK_WORKING_COPY.inspect}"
84
+ end
85
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rake_commit
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Paul Gross
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-09 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: See http://github.com/pgr0ss/rake_commit_tasks
22
+ email: pgross@gmail.com
23
+ executables:
24
+ - rake_commit
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - README.rdoc
31
+ - Rakefile
32
+ - lib/commit.rb
33
+ - lib/commit_message.rb
34
+ - lib/cruise_status.rb
35
+ - lib/git.rb
36
+ - lib/git_svn.rb
37
+ - lib/prompt_line.rb
38
+ - lib/shell.rb
39
+ - lib/svn.rb
40
+ has_rdoc: true
41
+ homepage: http://github.com/pgr0ss/rake_commit_tasks
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options: []
46
+
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ requirements: []
64
+
65
+ rubyforge_project: rake_commit
66
+ rubygems_version: 1.3.6
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: A gem which helps with checking in code
70
+ test_files: []
71
+