Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

447 lines (345 sloc) 12.354 kB
# ===========================================================================
# Project: Abbot - SproutCore Build Tools
# Copyright: ©2009 Apple Inc.
# portions copyright @2006-2009 Sprout Systems, Inc.
# and contributors
# ===========================================================================
# Rakefile used to build the SproutCore Gem. Requires Jeweler to function.
ROOT_PATH = File.dirname(__FILE__)
# files to ignore changes in
IGNORE_CHANGES = %w[.gitignore .gitmodules .DS_Store .gemspec VERSION.yml ^pkg ^tmp ^coverage]
# Get the DISTRIBUTION info
require 'yaml'
DIST_PATH = File.expand_path(File.join(ROOT_PATH, 'DISTRIBUTION.yml'))
DIST = YAML.load File.read(DIST_PATH)
LOCAL_DIST_PATH = File.expand_path(File.join(ROOT_PATH, 'LOCAL.yml'))
if File.exists? LOCAL_DIST_PATH
# merged each item in the top level hash. This allows for key-by-key
# overrides
(YAML.load(File.read(LOCAL_DIST_PATH)) || {}).each do |key, opts|
if DIST[key]
DIST[key].merge! opts
else
DIST[KEY] = opts
end
end
puts "Using local overrides for distribution"
end
REMOTE_NAME = 'dist' # used by git
# Make empty to not use sudo
SUDO = 'sudo'
################################################
## LOAD DEPENDENCIES
##
# Core dependencies. Just warn if these are not available
begin
require 'rubygems'
require 'extlib'
require 'fileutils'
require 'spec/rake/spectask'
$:.unshift(ROOT_PATH / 'lib')
require 'sproutcore'
rescue LoadError => e
$stderr.puts "WARN: some required gems are not installed (try rake init to setup)"
$stderr.puts e
end
################################################
## JEWELER PROJECT DESCRIPTION
##
namespace :gem do
task :clean do
system "rm *.gem"
end
desc "build the sproutcore gem"
task :build => :clean do
system "gem build sproutcore.gemspec"
end
desc "install the sproutcore gem to the system"
task :install => :build do
gem = Dir["*.gem"][0]
system "gem install #{gem}"
end
desc "push the sproutcore gem to rubygems.org"
task :push => :build do
gem = Dir["*.gem"][0]
system "gem push #{gem}"
end
end
################################################
## CORE TASKS
##
# git helper used to run git from within rake.
def git(path, cmd, log=true)
$stdout.puts("#{path.sub(ROOT_PATH, '')}: git #{cmd}") if log
git_path = path / '.git'
git_index = git_path / 'index'
# The env can become polluted; breaking git. This will avoid that.
%x[GIT_DIR=#{git_path}; GIT_WORK_TREE=#{path}; GIT_INDEX_FILE=#{git_index}; git #{cmd}]
end
desc "performs an initial setup on the tools. Installs gems, checkout"
task :init => [:install_gems, 'dist:init']
desc "verifies that all required gems are installed"
task :install_gems do
$stdout.puts "Installing gems (may ask for password)"
gem_names = %w(rack json json_pure extlib erubis thor jeweler gemcutter rspec)
gem_install = []
gem_update = []
# detect which ones are installed and update those
gem_names.each do |name|
if %x[gem list #{name}] =~ /#{Regexp.escape(name)} \(/
gem_update << name
else
gem_install << name
end
end
$stdout.puts "installing gems #{gem_install * ' '}" if gem_install.size>0
$stdout.puts "updating gems #{gem_update * ' '}" if gem_update.size>0
# install missing gems - updating known gems
# this is faster than just installing all gems
system %[#{SUDO} gem install #{gem_install * ' '}]
system %[#{SUDO} gem update #{gem_update * ' '}]
end
namespace :dist do
desc "checkout any frameworks in the distribution"
task :init do
$stdout.puts "Setup distribution"
DIST.each do |rel_path, opts|
path = ROOT_PATH / rel_path
repo_url = opts['repo']
dist_branch = opts['branch'] || 'master'
# if the .git repository does not exist yet, create it
if !File.exists?(path / ".git")
$stdout.puts " Creating repo for #{rel_path}"
FileUtils.mkdir_p path
$stdout.puts "\n> git clone #{repo_url} #{path}"
system "GIT_DIR=#{path / '.git'}; GIT_WORK_TREE=#{path}; git init"
end
# if git exists, make sure a "dist" remote exists and matches the named
# remote
remote = git(path, 'remote -v').split("\n").find do |l|
l =~ /^#{REMOTE_NAME}.+\(fetch\)/
end
if remote
cur_repo_url = remote.match(/^#{REMOTE_NAME}(.+)\(fetch\)/)[1].strip
if (cur_repo_url != repo_url)
$stdout.puts "ERROR: #{rel_path} has a 'dist' remote pointing to a different repo. Please remove the 'dist' remote and try again"
exit(1)
else
$stdout.puts "Found #{rel_path}:dist => #{repo_url}"
end
# remote does not yet exist, add it...
else
$stdout.puts git(path,"remote add dist #{repo_url}")
end
$stdout.puts git(path, "fetch dist")
# Make sure a "dist" branch exists.. if not checkout against the
# dist branch
if git(path, 'branch') =~ /dist\n/
$stdout.puts "WARN: #{rel_path}:dist branch already exists. delete branch and try again if you aren't sure it is setup properly"
else
git(path,"branch dist remotes/dist/#{dist_branch}")
end
git(path, "checkout dist")
end
end
desc "Make sure each repository in the distribute is set to the target remote branch and up-to-date"
task :update => 'dist:init' do
$stdout.puts "Setup distribution"
DIST.each do |rel_path, opts|
path = ROOT_PATH / rel_path
branch = opts['branch'] || 'master'
if File.exists?(path / ".git")
$stdout.puts "\n> git checkout dist"
$stdout.puts git(path, "checkout dist")
$stdout.puts "\n> git fetch dist"
$stdout.puts git(path, 'fetch dist')
$stdout.puts "\n> git rebase remotes/dist/#{branch}"
$stdout.puts git(path, "rebase remotes/dist/#{branch}")
else
$stdout.puts "WARN: cannot fix version for #{rel_path}"
end
end
end
desc "make the version of each distribution item match the one in VERSION"
task :freeze => 'dist:init' do
$stdout.puts "Setup distribution"
# Use this to get the commit hash
version_file = ROOT_PATH / 'VERSION.yml'
if File.exist?(version_file)
versions = YAML.load File.read(version_file)
versions = (versions['dist'] || versions[:dist]) if versions
versions ||= {}
end
DIST.each do |rel_path, opts|
path = ROOT_PATH / rel_path
if File.exists?(path / ".git") && versions[rel_path]
sha = versions[rel_path]
$stdout.puts "\n> git fetch"
$stdout.puts git(path, 'fetch')
if sha
$stdout.puts "\n> git checkout #{sha}"
$stdout.puts git(path, "checkout #{sha}")
end
else
$stdout.puts "WARN: cannot fix version for #{rel_path}"
end
end
end
end
namespace :release do
desc "tags the current repository and any distribution repositories. if you can push to distribution, then push tag as well"
task :tag => :update_version do
tag_name = "REL-#{RELEASE_VERSION}"
DIST.keys.push('abbot').each do |rel_path|
full_path = rel_path=='abbot' ? ROOT_PATH : (ROOT_PATH / rel_path)
git(full_path, "tag -f #{tag_name}")
end
end
task :push_tags => :tag do
tag_name = "REL-#{RELEASE_VERSION}"
DIST.keys.push('abbot').each do |rel_path|
full_path = rel_path=='abbot' ? ROOT_PATH : (ROOT_PATH / rel_path)
git(full_path, "push origin #{tag_name}")
end
end
desc "prepare release. verify clean, update version, tag"
task :prepare => ['git:verify_clean', :update_version, :tag, :push_tags]
desc "release to rubyforge for old skool folks"
task :rubyforge => [:prepare, 'rubyforge:release']
desc "release to gemcutter for new skool kids"
task :gemcutter => [:prepare, 'gemcutter:release']
desc "one release to rule them all"
task :all => [:prepare, 'release:gemcutter']
end
desc "computes the current hash of the code. used to autodetect build changes"
task :hash_content do
require 'yaml'
require 'digest/md5'
ignore = IGNORE_CHANGES.map do |x|
if x =~ /^\^/
/^#{Regexp.escape(ROOT_PATH / x[1..-1])}/
else
/#{Regexp.escape(x)}/
end
end
# First, get the hashinfo if it exists. use this to decide if we need to
# rehash
hashinfo_path = ROOT_PATH / '.hashinfo.yml'
hash_date = 0
hash_digest = nil
if File.exist?(hashinfo_path)
yaml = YAML.load_file(hashinfo_path)
hash_date = yaml['date'] || yaml[:date] || hash_date
hash_digest = yaml['digest'] || yaml[:digest] || hash_digest
end
# paths to search
paths = Dir.glob(File.join(ROOT_PATH, '**', '*')).reject do |path|
File.directory?(path) || (ignore.find { |i| path =~ i })
end
cur_date = 0
paths.each do |path|
mtime = File.mtime(path)
mtime = mtime.nil? ? 0 : mtime.to_i
$stdout.puts "detected file change: #{path.gsub(ROOT_PATH,'')}" if mtime > hash_date
cur_date = mtime if mtime > cur_date
end
if hash_digest.nil? || (cur_date != hash_date)
digests = paths.map do |path|
Digest::SHA1.hexdigest(File.read(path))
end
digests.compact!
hash_digest = Digest::SHA1.hexdigest(digests.join)
end
hash_date = cur_date
# write cache
File.open(hashinfo_path, 'w+') do |f|
YAML.dump({ :date => hash_date, :digest => hash_digest }, f)
end
# finally set the hash
CONTENT_HASH = hash_digest
$stdout.puts "CONTENT_HASH = #{CONTENT_HASH}"
end
desc "updates the VERSION file, bumbing the build rev if the current commit has changed"
task :update_version => 'hash_content' do
path = ROOT_PATH / 'VERSION.yml'
require 'yaml'
# first, load the current yaml if possible
major = 1
minor = 0
build = 99
rev = '-0-'
dist = {}
if File.exist?(path)
yaml = YAML.load_file(path)
major = yaml['major'] || yaml[:major] || major
minor = yaml['minor'] || yaml[:minor] || minor
build = yaml['patch'] || yaml[:patch] || build
rev = yaml['digest'] || yaml[:digest] || rev
end
build += 1 if rev != CONTENT_HASH #increment if needed
rev = CONTENT_HASH
# Update distribution versions
DIST.each do |rel_path, ignored|
dist_path = ROOT_PATH / rel_path
if File.exists?(dist_path)
dist_rev = git(dist_path, "log HEAD^..HEAD")
dist_rev = dist_rev.split("\n").first.scan(/commit ([^\s]+)/)
dist_rev = ((dist_rev || []).first || []).first
if dist_rev.nil?
$stdout.puts " WARN: cannot find revision for #{rel_path}"
else
dist[rel_path] = dist_rev
end
end
end
$stdout.puts "write version #{[major, minor, build].join('.')} => #{path}"
File.open(path, 'w+') do |f|
YAML.dump({
:major => major,
:minor => minor,
:patch => build,
:digest => rev,
:dist => dist
}, f)
end
RELEASE_VERSION = "#{major}.#{minor}.#{build}"
end
desc "cleanup the pkg dir"
task :clean do
path = ROOT_PATH / 'pkg'
FileUtils.rm_r(path) if File.directory?(path)
`rm #{ROOT_PATH / '*.gem'}`
end
namespace :git do
desc "verifies there are no pending changes to commit to git"
task :verify_clean do
DIST.keys.push('abbot').each do |repo_name|
full_path = repo_name=='abbot' ? ROOT_PATH : (ROOT_PATH / repo_name)
result = git(full_path, 'status')
if !(result =~ /nothing to commit \(working directory clean\)/)
if (repo_name != 'abbot') ||
(!(result =~ /#\n#\tmodified: VERSION.yml\n#\n/))
$stderr.puts "\nFATAL: Cannot complete task: changes are still pending in the '#{repo_name}' repository."
$stderr.puts " Commit your changes to git to continue.\n\n"
exit(1)
end
end
end
end
desc "Collects the current SHA1 commit hash into COMMIT_ID"
task :collect_commit do
log = `git log HEAD^..HEAD`
COMMIT_ID = log.split("\n").first.match(/commit ([\w]+)/).to_a[1]
if COMMIT_ID.empty?
$stderr.puts "\nFATAL: Cannot discover current commit id"
exit(1)
else
$stdout.puts "COMMIT_ID = #{COMMIT_ID}"
end
end
end
# Write a new version everytime we generate
task 'gemspec:generate' => :update_version
task 'rubyforge:setup' => :update_version
Spec::Rake::SpecTask.new
# EOF
Jump to Line
Something went wrong with that request. Please try again.