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 +69 -0
- data/Rakefile +19 -0
- data/bin/rake_commit +5 -0
- data/lib/commit.rb +58 -0
- data/lib/commit_message.rb +14 -0
- data/lib/cruise_status.rb +25 -0
- data/lib/git.rb +70 -0
- data/lib/git_svn.rb +27 -0
- data/lib/prompt_line.rb +46 -0
- data/lib/shell.rb +11 -0
- data/lib/svn.rb +85 -0
- metadata +71 -0
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
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
|
data/lib/prompt_line.rb
ADDED
|
@@ -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
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
|
+
|