lib/core/build.rb in buildr-0.19.0 vs lib/core/build.rb in buildr-0.20.0
- old
+ new
@@ -6,17 +6,17 @@
desc "Build the project"
Project.local_task("build") { |name| "Building #{name}" }
desc "Clean files generated during a build"
Project.local_task("clean") { |name| "Cleaning #{name}" }
desc "Create packages"
- Project.local_task("package") { |name| "Packaging #{name}" }
+ Project.local_task("package"=>"build") { |name| "Packaging #{name}" }
desc "Install packages created by the project"
- Project.local_task("install") { |name| "Installing packages from #{name}" }
+ Project.local_task("install"=>"package") { |name| "Installing packages from #{name}" }
desc "Remove previously installed packages"
Project.local_task("uninstall") { |name| "Uninstalling packages from #{name}" }
desc "Deploy packages created by the project"
- Project.local_task("deploy") { |name| "Deploying packages from #{name}" }
+ Project.local_task("deploy"=>"package") { |name| "Deploying packages from #{name}" }
[ :build, :clean, :package, :install, :uninstall, :deploy ].each do |name|
Project.on_define { |project| project.recursive_task name }
end
@@ -43,131 +43,137 @@
end
desc "The default task it build"
task "default"=>"build"
- class Release #:nodoc:
- VERSION_NUMBER_PATTERN = /VERSION_NUMBER\s*=\s*(["'])(.*)\1/
- NEXT_VERSION_PATTERN = /NEXT_VERSION\s*=\s*(["'])(.*)\1/
+ class Release
+ THIS_VERSION_PATTERN = /THIS_VERSION|VERSION_NUMBER\s*=\s*(["'])(.*)\1/
+ NEXT_VERSION_PATTERN = /NEXT_VERSION\s*=\s*(["'])(.*)\1/
+
class << self
- def svn_ignores()
- @ignores = (@ignores || []).map { |pat| pat.is_a?(Regexp) ? pat : Regexp.new("^.*\s+#{Regexp.escape pat}$") }
+
+ # :call-seq:
+ # make()
+ #
+ # Make a release.
+ def make()
+ check
+ version = with_next_version { |filename, version| sh "rake deploy --rakefile #{filename}" }
+ tag version
+ commit version + "-SNAPSHOT"
end
- end
- def initialize(rakefile = nil)
- @rakefile = rakefile || Rake.application.rakefile
- end
+ protected
- attr_reader :rakefile
+ # :call-seq:
+ # check()
+ #
+ # Check that we don't have any local changes in the working copy. Fails if it finds anything
+ # in the working copy that is not checked into source control.
+ def check()
+ # Status check reveals modified file, but also SVN externals which we can safely ignore.
+ status = svn("status", "--ignore-externals").reject { |line| line =~ /^X\s/ }
+ fail "Uncommitted SVN files violate the First Principle Of Release!\n#{status}" unless
+ status.empty?
+ end
+
+ # :call-seq:
+ # with_next_version() { |filename| ... } => version
+ #
+ # Yields to block with upgraded version number, before committing to use it. Returns the *new*
+ # current version number.
+ #
+ # We need a Rakefile with upgraded version numbers to run the build, but we don't want the
+ # Rakefile modified unless the build succeeds. So this method updates the version numbers in
+ # a separate (Rakefile.next) file, yields to the block with that filename, and if successful
+ # copies the new file over the existing one.
+ #
+ # Version numbers are updated as follows. The next release version becomes the current one,
+ # and the next version is upgraded by one to become the new next version. So:
+ # THIS_VERSION = 1.1.0
+ # NEXT_VERSION = 1.2.0
+ # becomes:
+ # THIS_VERSION = 1.2.0
+ # NEXT_VERSION = 1.2.1
+ # and the method will return 1.2.0.
+ def with_next_version()
+ new_filename = Rake.application.rakefile + ".next"
+ modified = change_version do |this_version, next_version|
+ one_after = next_version.split(".")
+ one_after[-1] = one_after[-1].to_i + 1
+ [ next_version, one_after.join(".") ]
+ end
+ File.open(new_filename, "w") { |file| file.write modified }
+ begin
+ yield new_filename
+ mv new_filename, Rake.application.rakefile
+ ensure
+ rm new_filename rescue nil
+ end
+ File.read(Rake.application.rakefile).scan(THIS_VERSION_PATTERN)[0][1]
+ end
- def invoke()
- # Make sure we don't have anything uncommitted in SVN.
- check_status
- # Update current version to next version before deploying.
- next_ver = update_version
- # Run the deployment externally using the new version number
- # (from the modified Rakefile).
- sh "rake deploy"
- # Update the next version as well to the next increment and commit.
- update_next_version next_ver
- # Tag the repository for this release.
- tag_repository next_ver
- # Update the next version to end with -SNAPSHOT.
- update_version_to_snapshot next_ver
- end
+ # :call-seq:
+ # change_version() { |this, next| ... } => rakefile
+ #
+ # Change version numbers in the current Rakefile, but without writing a new file (yet).
+ # Returns the contents of the Rakefile with the modified version numbers.
+ #
+ # This method yields to the block with the current (this) and next version numbers and expects
+ # an array with the new this and next version numbers.
+ def change_version()
+ rakefile = File.read(Rake.application.rakefile)
+ this_version = rakefile.scan(THIS_VERSION_PATTERN)[0][1] or
+ fail "Looking for THIS_VERSION = \"...\" in your Rakefile, none found"
+ next_version = rakefile.scan(NEXT_VERSION_PATTERN)[0][1] or
+ fail "Looking for NEXT_VERSION = \"...\" in your Rakefile, none found"
+ this_version, next_version = yield(this_version, next_version)
+ if verbose
+ puts "Upgrading version numbers:"
+ puts " This: #{this_version}"
+ puts " Next: #{next_version}"
+ end
+ rakefile.gsub(THIS_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{this_version}"}) }.
+ gsub(NEXT_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{next_version}"}) }
+ end
- def check_status()
- ignores = Release.svn_ignores
- status = svn("status", "--ignore-externals", :verbose=>false).
- reject { |line| line =~ /^X\s/ || ignores.any? { |pat| line =~ pat } }
- fail "Uncommitted SVN files violate the First Principle Of Release!\n#{status}" unless
- status.empty?
- end
+ # :call-seq:
+ # tag(version)
+ #
+ # Tags the current working copy with the release version number.
+ def tag(version)
+ url = svn("info").scan(/URL: (.*)/)[0][0].sub(/trunk$/, "tags/#{version}")
+ svn "remove", url, "-m", "Removing old copy" rescue nil
+ svn "copy", Dir.pwd, url, "-m", "Release #{version}"
+ end
- # Change the Rakefile and update the current version number to the
- # next version number (VERSION_NUMBER = NEXT_VERSION). We need this
- # before making a release with the next version. Return the next version.
- def update_version()
- rakefile = read_rakefile
- version = rakefile.scan(VERSION_NUMBER_PATTERN)[0][1] or
- fail "Looking for VERSION_NUMBER = \"...\" in your Rakefile, none found"
- next_ver = rakefile.scan(NEXT_VERSION_PATTERN)[0][1] or
- fail "Looking for NEXT_VERSION = \"...\" in your Rakefile, none found"
- if verbose
- puts "Current version: #{version}"
- puts "Next version: #{next_ver}"
+ # :call-seq:
+ # commit(version)
+ #
+ # Last, we commit what we currently have in the working copy.
+ def commit(version)
+ rakefile = File.read(Rake.application.rakefile).
+ gsub(THIS_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{version}"}) }.
+ File.open(Rake.application.rakefile, "w") { |file| file.write rakefile }
+ svn "commit", "-m", "Changed version number to #{version}", Rake.application.rakefile
end
- # Switch version numbers.
- write_rakefile rakefile.gsub(VERSION_NUMBER_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{next_ver}"}) }
- next_ver
- end
- # Change the Rakefile and update the next version number to one after
- # (NEXT_VERSION = NEXT_VERSION + 1). We do this to automatically increment
- # future version number after each successful release.
- def update_next_version(version)
- # Update to new version number.
- nums = version.split(".")
- nums[-1] = nums[-1].to_i + 1
- next_ver = nums.join(".")
- write_rakefile read_rakefile.gsub(NEXT_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{next_ver}"}) }
- # Commit new version number.
- svn "commit", "-m", "Changed version number to #{version}", rakefile
- end
-
- # Create a tag in the SVN repository.
- def tag_repository(version)
- # Copy to tag.
- cur_url = svn("info").scan(/URL: (.*)/)[0][0]
- new_url = cur_url.sub(/trunk$/, "tags/#{version}")
- svn "remove", new_url, "-m", "Removing old copy" rescue nil
- svn "copy", cur_url, new_url, "-m", "Release #{version}"
- end
-
- def update_version_to_snapshot(version)
- version += "-SNAPSHOT"
- write_rakefile read_rakefile.gsub(VERSION_NUMBER_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{version}"}) }
- # Commit new version number.
- svn "commit", "-m", "Changed version number to #{version}", rakefile
- end
-
- protected
-
- def read_rakefile()
- File.read(rakefile)
- end
-
- def write_rakefile(contents)
- File.open(rakefile, "w") { |file| file.write contents }
- end
-
- def svn(*args)
- if Hash === args.last
- options = args.pop
- else
- options = { :verbose=>verbose }
+ # :call-seq:
+ # svn(*args)
+ #
+ # Executes SVN command and returns the output.
+ def svn(*args)
+ cmd = "svn " + args.map { |arg| arg[" "] ? %Q{"#{arg}"} : arg }.join(" ")
+ puts cmd if verbose
+ `#{cmd}`.tap { fail "SVN command failed" unless $?.exitstatus == 0 }
end
- puts ["svn", *args].join(" ") if options[:verbose]
- Open3.popen3("svn", *args) do |stdin, stdout, stderr|
- stdin.close
- error = stderr.read
- fail error unless error.empty?
- stdout.read.tap { |output| puts output if Rake.application.options.trace }
- end
end
end
-
desc "Make a release"
- task("release").tap do |task|
- class << task
- def release()
- @release ||= Release.new
- end
- end
- task.enhance { task.release.invoke }
+ task "release" do |task|
+ Release.make
end
end