#!/usr/bin/env ruby require 'reap/task' require 'shellwords' # ___ _ _ _ _ _____ _ # | _ \_ _| |__| (_)__| |_ |_ _|_ _ __| |__ # | _/ || | '_ \ | (_-< ' \ | |/ _` (_-< / / # |_| \_,_|_.__/_|_/__/_||_| |_|\__,_/__/_\_\ # # = Publish Task class Reap::Publish < Reap::Task task_desc "Publish documents to the web or host." task_help %{ reap publish Publish documents to hosting service. Three means of publishing are current supported, ftp uploading, scp, and web convenience option that recognizes particular hosts (only RubyForge is currently supported). type Type of publishing, 'web', 'scp' or 'ftp'. host Host server, default is 'rubyforge.org' username Username for host. dir Directory of files to publish. Or, copy Files to publish using from and to. project Project name (used for Rubyforge) If the type is 'scp' or 'ftp' you will also need to provide the root directory parameter. root Document root directory at host. The dir parameter allows you to simply specify a local directory, the contents of which will be published to host's document root location (directory tree intact). If you need more control over which files to publish where, you can use the copy parameter instead. Provide an array of pattern strings in the form of "{from} {to}". If the desitination is the host's document root you do not need to specify the {to} part. For example: copy: [ 'web/*', 'doc/api/* doc/api' ] The first copies the files under your project's web directory to the host's document root. The second copies your projects doc/api files to the doc/api location on the host. When using the 'scp' type the internal template used for the outbound destination is 'username@host:root/'. } #attr_accessor :host, :type, :dir, :project, :username #attr_accessor :exclude # not using yet alias_method :pub, :task # Run the publishing task. def run( target=nil, copy_from=nil, copy_to=nil ) return nil if target and target != pub.target # setup pub.type ||= 'web' pub.host ||= 'rubyforge.org' pub.root ||= 'var/www/gforge-projects/' pub.project ||= master.rubyforge.project || master.name pub.username ||= master.rubyforge.username pub.copy ||= [ "#{pub.dir}/*" ] if copy_from pub.copy = [ "#{copy_from} #{copy_to}".strip ] end # validate unless pub.project puts "Project not specified." ; return nil end unless pub.username puts "Username not specified." ; return nil end # publish puts "Reap is passing off publishing work..." case pub.type when 'web', 'www' case pub.host when 'rubyforge', 'rubyforge.org' pub.host = "rubyforge.org" pub.root = "/var/www/gforge-projects/#{pub.project}" run_scp else puts %{Unrecognized publishing host '#{pub.host}'. Skipped.} return nil end when 'scp' run_scp when 'ftp' run_ftp else puts %{Unrecognized publishing type '#{pub.type}'. Skipped.} return nil end end private #-- # SHELL OUT! Need a net/ssh library to fix. #++ def run_scp pub.copy.each { |c| from, to = *Shellwords.shellwords(c) to = '' if to.nil? to = to[1..-1] if to[0,1] == '/' cmd = "scp -r #{from} #{pub.username}@#{pub.host}:#{pub.root}/#{to}" sh( cmd ) } end def run_ftp require 'net/ftp' return if $PRETEND Net::FTP.open( pub.host ) do |ftp| ftp.login( pub.username ) ftp.chdir( pub.root ) pub.copy.each { |c| from, to = *Shellwords.shellwords(c) to = '' if to.nil? to = to[1..-1] if to[0,1] == '/' from.sub('*', '**/*') unless from =~ /\*\*/ files = FileList.new( from ) files.each { |f| t = File.join( to, f.basename ) ftp.putbinaryfile( f, t, 1024 ) } } end end end # Rake interface. if defined?(Rake) #require 'reap/rake/adapter' module Rake ReapPublish = ::Reap::RakeAdapter( ::Reap::Publish ) end end