rake_commit 0.1.0

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