Skip to content

Commit

Permalink
Pull in plugin work
Browse files Browse the repository at this point in the history
Merge remote branch 'origin/plugins'
  • Loading branch information
jhs committed Nov 4, 2010
2 parents c61f35c + 91ade96 commit a4401d2
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 130 deletions.
14 changes: 14 additions & 0 deletions README.md
Expand Up @@ -158,6 +158,20 @@ Want to build [GeoCouch][geocouch]? No problem.

rake git="git://github.com/vmx/couchdb geocouch"

### CouchDB Plugins

Any CouchDB plugin can be loaded remotely from Git, built, and installed
into the final CouchDB system.

rake plugin="git://github.com/vmx/couchdb origin/gc-separate"

Multiple plugins can be processed together:

rake plugins="git://github.com/vmx/couchdb origin/gc-separate,git://github.com/somebody/whatever some_tag"

(Both `plugin` and `plugins` supports comma-separated lists; use whichever
you remember better.)

### Install CouchDB somewhere besides `build/`.

Add a `couchdb_build` parameter to place the final couchdb binaries anywhere.
Expand Down
52 changes: 27 additions & 25 deletions tasks/couchdb.rake
Expand Up @@ -12,7 +12,7 @@ namespace :couchdb do
task :dependencies => :deps

desc 'Build CouchDB'
task :build => couchdb_build_deps + [COUCH_BIN]
task :build => couchdb_build_deps + [:plugins, COUCH_BIN]

desc 'Build CouchDB and then clean out unnecessary things like autotools'
task :clean_install => :build do
Expand All @@ -25,33 +25,19 @@ namespace :couchdb do
end
end

directory "#{BUILD}/var/run/couchdb"

file COUCH_BIN => [AUTOCONF_259, "#{BUILD}/var/run/couchdb"] do
source = "#{DEPS}/couchdb"
file COUCH_SOURCE => :known_distro do
git_checkout(ENV['git']) if ENV['git']
end

if ENV['git']
remote, commit = ENV['git'].split
checkout = "#{HERE}/git-build/#{URI.escape(remote, /[\/:]/)}"
task :plugins => COUCH_SOURCE do
# This task will be assigned dependencies dynamically, see the "plugins" stuff below.
puts "Plugins done"
end

if File.directory?(checkout) || File.symlink?(checkout)
puts "Using #{checkout} for build from Git"
elsif File.exists? checkout
raise "Don't know what to do with #{checkout}"
else
sh "git clone '#{remote}' '#{checkout}'"
end
directory "#{BUILD}/var/run/couchdb"

Dir.chdir checkout do
sh "git checkout #{commit}"
sh "git reset --hard"
sh "git clean -f -d"
rm = (DISTRO[0] == :solaris) ? 'rm' : 'rm -v'
sh "git ls-files --others -i --exclude-standard | xargs #{rm} || true"
end

source = checkout
end
file COUCH_BIN => [COUCH_SOURCE, AUTOCONF_259, "#{BUILD}/var/run/couchdb"] do
source = COUCH_SOURCE

begin
Dir.chdir(source) do
Expand Down Expand Up @@ -92,4 +78,20 @@ namespace :couchdb do
end
end

# Determine what plugins are desired and have them built.
plugins = (ENV['plugin'] || "") + "," + (ENV['plugins'] || "")
plugins.split(',').select{|x| ! x.strip.empty? }.each do |git_plugin|
remote, commit = git_plugin.split
plugin_mark = "#{COUCH_BUILD}/lib/build-couchdb/plugins/#{git_checkout_name remote}/#{commit}"

task :plugins => plugin_mark
file plugin_mark => 'environment:path' do
source = git_checkout(git_plugin)
Dir.chdir(source) do
ENV['COUCH_SRC'] = "#{COUCH_SOURCE}/src/couchdb"
gmake
end
end
end

end
60 changes: 4 additions & 56 deletions tasks/distro.rake
@@ -1,57 +1,5 @@

task :known_distro => [ :known_mac, :known_ubuntu, :known_debian, :known_redhat, :known_opensuse, :known_slf, :known_solaris ] do
raise 'Unknown distribution, build not supported' unless Object.const_defined? 'DISTRO'
end

task :known_mac do
DISTRO = [:osx, 10.0] if `uname`.chomp == 'Darwin'
end

task :known_ubuntu do
if File.exist? '/etc/lsb-release'
info = Hash[ *File.new('/etc/lsb-release').lines.map{ |x| x.split('=').map { |y| y.chomp } }.flatten ]
if info['DISTRIB_ID'] == 'Ubuntu'
DISTRO = [:ubuntu, info['DISTRIB_RELEASE']]
end
end
end

task :known_debian do
ver = '/etc/debian_version'
DISTRO = [:debian, File.new(ver).readline.chomp] if !File.exist?('/etc/lsb-release') && File.exist?(ver)
end

task :known_redhat do
if File.exist? '/etc/fedora-release'
release = File.new('/etc/fedora-release').readline.match(/Fedora release (\d+)/)[1]
DISTRO = [:fedora, release]
end
if File.exist? '/etc/redhat-release'
release = File.new('/etc/redhat-release').readline.match(/Red Hat Enterprise Linux Server release (\d+)/)[1]
DISTRO = [:fedora, release]
end
end

task :known_slf do
if File.exist? '/etc/redhat-release'
release = File.new('/etc/redhat-release').readline.match(/Scientific Linux SLF release (\d+)/)[1]
DISTRO = [:slf, release]

if RUBY_VERSION <= '1.8.7'
raise 'Version of ruby is too old. Consider installing a more recent version'
end
end
end

task :known_opensuse do
if File.exist? '/etc/SuSE-release'
release = File.new('/etc/SuSE-release').readline.match(/openSUSE (\d+)/)[1]
DISTRO = [:opensuse, release]
end
end

task :known_solaris do
if `uname`.chomp == "SunOS"
DISTRO = [:solaris, `uname -r`.chomp]
end
task :known_distro do
distro = detect_distro()
raise 'Unknown distribution, build not supported' unless distro
DISTRO = distro
end
55 changes: 55 additions & 0 deletions tasks/distros.rb
@@ -0,0 +1,55 @@
# Distribution (platform) detection

def detect_distro
# OSX
if `uname`.chomp == 'Darwin'
return [:osx, 10.0]
end

# Solaris
if `uname`.chomp == "SunOS"
return [:solaris, `uname -r`.chomp]
end

# Ubuntu
if File.exist? '/etc/lsb-release'
info = Hash[ *File.new('/etc/lsb-release').lines.map{ |x| x.split('=').map { |y| y.chomp } }.flatten ]
if info['DISTRIB_ID'] == 'Ubuntu'
return [:ubuntu, info['DISTRIB_RELEASE']]
end
end

# Debian
ver = '/etc/debian_version'
return [:debian, File.new(ver).readline.chomp] if !File.exist?('/etc/lsb-release') && File.exist?(ver)

# Fedora
if File.exist? '/etc/fedora-release'
release = File.new('/etc/fedora-release').readline.match(/Fedora release (\d+)/)[1]
return [:fedora, release]
end

# Red Hat
if File.exist? '/etc/redhat-release'
release = File.new('/etc/redhat-release').readline.match(/Red Hat Enterprise Linux Server release (\d+)/)[1]
return [:fedora, release]
end

# Scientific Linux
if File.exist? '/etc/redhat-release'
release = File.new('/etc/redhat-release').readline.match(/Scientific Linux SLF release (\d+)/)[1]
return [:slf, release]

if RUBY_VERSION <= '1.8.7'
raise 'Version of ruby is too old. Consider installing a more recent version'
end
end

# OpenSUSE
if File.exist? '/etc/SuSE-release'
release = File.new('/etc/SuSE-release').readline.match(/openSUSE (\d+)/)[1]
return [:opensuse, release]
end

nil
end
134 changes: 86 additions & 48 deletions tasks/lib.rb
Expand Up @@ -9,70 +9,77 @@
log_filename = "rake.log"
File.unlink(log_filename) if File.exists?(log_filename)

["$stdout", "$stderr"].each do |std|
rd, wr = IO.pipe
if fork
rd.close
wr.sync = true
eval "#{std}.reopen(wr)"
eval "#{std}.sync = true"
#Process.wait
else
# Child
wr.close
begin
# Input must be forked.
label = std[1..-1].upcase
File.open(log_filename, 'a') do |f|
f.sync = true
while(line = rd.gets)
eval "#{std}_old.puts(line)"
f.puts([label, line].join(' '))
unless ARGV[0] == 'environment:shell'
["$stdout", "$stderr"].each do |std|
rd, wr = IO.pipe
if fork
rd.close
wr.sync = true
eval "#{std}.reopen(wr)"
eval "#{std}.sync = true"
#Process.wait
else
# Child
wr.close
begin
# Input must be forked.
label = std[1..-1].upcase
File.open(log_filename, 'a') do |f|
f.sync = true
while(line = rd.gets)
eval "#{std}_old.puts(line)"
f.puts([label, line].join(' '))
end
end
ensure
rd.close
exit
end
ensure
rd.close
exit
end
end
end

require File.dirname(__FILE__) + '/places'
require File.dirname(__FILE__) + '/distros'

def package_dep opts
# Unfortunately the dependency must be defined after the OS is detected,
# Even if this task is a no-op, if other tasks depend on it, they will re-run
# if this task runs. Therefore it must not be defined at all for un-requested
# distros. That means calling detect_distro() now and presumably later in :known_distro.
distro = detect_distro()

only_distro = opts.delete :distro
only_distros = opts.delete :distros
only_distros ||= [only_distro]
if only_distro && only_distro != distro[0]
puts "#{distro[0]} does not need #{opts.inspect}"
return "/" # Return a file dependency that will presumably always work.
end

puts "Package dependency for #{distro[0]}: #{opts.inspect}"
program_file, package = opts.to_a.first

Rake.application.in_explicit_namespace(':') do
task "package:#{package}" => :known_distro do
if only_distros.empty? || only_distros.include?(DISTRO[0])
puts "Package dependency for #{DISTRO[0]}: #{program_file} => #{package}"
case DISTRO[0]
when :ubuntu, :debian
installed = `dpkg --list`.split("\n").map { |x| x.split[1] } # Hm, this is out of scope if defined outside.
if installed.none? { |pkg| pkg == package }
sh "sudo apt-get -y install #{package}"
end
when :solaris
installed = `pkg-get -l`.split("\n")
if installed.none? { |pkg| pkg == package }
sh "sudo pkg-get install #{package}"
end
when :osx
installed = `brew list`.split("\n")
if installed.none? { |pkg| pkg == package }
sh "sudo brew install #{package}"
end
else
puts "Skipping package requirement '#{package}' on an unsupported platform"
end
file program_file => :known_distro do
case DISTRO[0]
when :ubuntu, :debian
installed = `dpkg --list`.split("\n").map { |x| x.split[1] } # Hm, this is out of scope if defined outside.
if installed.none? { |pkg| pkg == package }
sh "sudo apt-get -y install #{package}"
end
when :solaris
installed = `pkg-get -l`.split("\n")
if installed.none? { |pkg| pkg == package }
sh "sudo pkg-get install #{package}"
end
when :osx
installed = `brew list`.split("\n")
if installed.none? { |pkg| pkg == package }
sh "sudo brew install #{package}"
end
else
puts "Skipping package requirement '#{package}' on an unsupported platform"
end
end

file program_file => "package:#{package}"
end

program_file
Expand Down Expand Up @@ -222,6 +229,37 @@ def configure_cmd(source, opts={})
return "env #{env} #{source}/configure #{prefix} --with-erlang=#{BUILD}/lib/erlang/usr/include"
end

def git_checkout_name(url)
URI.escape(url, /[\/:]/)
end

def git_checkout(url_and_commit, opts={})
remote, commit = url_and_commit.split
checkout = "#{HERE}/git-build/#{git_checkout_name remote}"
return checkout if opts[:noop]

fetch = false
if File.directory?(checkout) || File.symlink?(checkout)
puts "Using #{checkout} for build from Git"
fetch = true
elsif File.exists? checkout
raise "Don't know what to do with #{checkout}"
else
sh "git clone '#{remote}' '#{checkout}'"
end

Dir.chdir checkout do
sh "git fetch origin" if fetch
sh "git checkout #{commit}"
sh "git reset --hard"
sh "git clean -f -d"
rm = (DISTRO[0] == :solaris) ? 'rm' : 'rm -v'
sh "git ls-files --others -i --exclude-standard | xargs #{rm} || true"
end

return checkout
end

module Rake
module TaskManager
def in_explicit_namespace(name)
Expand Down
1 change: 1 addition & 0 deletions tasks/places.rb
Expand Up @@ -3,6 +3,7 @@
JS_LIB = "#{BUILD}/bin/js-config"
ERL_BIN = "#{BUILD}/bin/erl"
ICU_BIN = "#{BUILD}/bin/icu-config"
COUCH_SOURCE = ENV['git'] ? git_checkout(ENV['git'], :noop => true) : "#{DEPS}/couchdb"
COUCH_BUILD = ENV['couchdb_build'] || BUILD
COUCH_BIN = "#{COUCH_BUILD}/bin/couchdb"
MANIFESTS = "#{BUILD}/manifests"
Expand Down
5 changes: 4 additions & 1 deletion tasks/shortcuts.rake
@@ -1,6 +1,9 @@
desc Rake::Task['couchdb:build'].comment
desc Rake::Task['couchdb:clean_install'].comment
task :default => 'couchdb:clean_install'

desc Rake::Task['couchdb:build'].comment
task :couchdb => 'couchdb:build'

desc Rake::Task['environment:shell'].comment
task :sh => 'environment:shell'

Expand Down

0 comments on commit a4401d2

Please sign in to comment.