lib/reap/task/release.rb in reap-4.3.2 vs lib/reap/task/release.rb in reap-4.3.3

- old
+ new

@@ -1,16 +1,19 @@ -require 'reap/task' - require "enumerator" -require "http-access2" +require 'reap/task' +require "reap/vendor/http-access2" +# ___ _ _____ _ +# | _ \___| |___ __ _ ___ ___ |_ _|_ _ __| |__ +# | / -_) / -_) _` (_-</ -_) | |/ _` (_-< / / +# |_|_\___|_\___\__,_/__/\___| |_|\__,_/__/_\_\ # -# Release Task -# -# This Rake task releases files to RubyForge and other GForge instaces +# = Release Task +# +# This task releases files to RubyForge and other GForge instaces # or SourceForge clones. In its most simple usage it looks like: # # project = MetaProject::Project::XForge::RubyForge.new('xforge') # # Create a new release of the xforge project on Rubyforge. # task :release => [:gem] do @@ -61,67 +64,139 @@ # xf.execute # end class Reap::Release < Reap::Task + section_required true + task_desc "Release distribution files." - section_required true + task_help %{ - attr_accessor :project, :version - attr_accessor :host, :username, :password - attr_accessor :package, :packageid, :groupid, :private, :processor - attr_accessor :name, :changes, :notes, :changelog, :notelog - attr_accessor :cookiejar + reap release + Release distribution to Rubyforge, or other + GForge based service. + + host URL of host service + username Username of host service + project Project name at host + package Package name + groupid Group id number + architecture Architecture (Any, i386, PPC, etc.) + release Release name + private Private release? + changelog Change log file + notelog Release notes file + dir Distribution directory + exclude Distribution types to exclude + + } + + task_attr :rel + + #attr_accessor :project, :version + #attr_accessor :host, :username, :password + #attr_accessor :package, :packageid, :groupid, :private, :processor + #attr_accessor :name, :changes, :notes, :changelog, :notelog + #attr_accessor :cookiejar + def init - @project ||= master['rubyforge']['project'] || master['name'] - @version ||= master['version'] || master['date'] + #rel.version ||= master.date - @host ||= 'rubyforge.org' - @username ||= master['rubyforge']['username'] - @password ||= master['rubyforge']['password'] + rel.host ||= 'rubyforge.org' + rel.host.chomp!('/') - @package ||= master['rubyforge']['package'] - @packageid ||= master['rubyforge']['packageid'] - @groupid ||= master['rubyforge']['groupid'] - @private ||= false - @processor ||= 'Any' + rel.username ||= master.rubyforge.username + #rel.password ||= master.rubyforge.password - #@files ||= section['files'] - @name ||= master['version'] || master['date'] - @date ||= master['date'] || Time::now.strftime('%Y-%m-%d %H:%M') + rel.project ||= master.rubyforge.project || master.name + rel.package ||= master.rubyforge.package + #rel.packageid ||= master.rubyforge.packageid + rel.groupid ||= master.rubyforge.groupid + rel.private ||= false + rel.processor ||= 'Any' - @cookiejar ||= File::join(File::expand_path("~"), ".rubyforge.cookie_jar") + rel.date ||= Time::now.strftime('%Y-%m-%d %H:%M') + + rel.exclude ||= [] + rel.exclude << 'tar.gz' if rel.exclude.include?( 'tgz' ) + rel.exclude << 'tgz' if rel.exclude.include?( 'tar.gz' ) + rel.exclude << 'tar.bz2' if rel.exclude.include?( 'tbz' ) + rel.exclude << 'tbz' if rel.exclude.include?( 'tar.bz2' ) + + rel.cookie_jar ||= File::join(File::expand_path("~"), ".rubyforge.cookie_jar") + + # Do not inherit + rel.dir = section.dir || master.project.dir + rel.release = section.release || master.version || rel.date end - # run task + # Run release task. def run - abort "missing field -- package" unless @package - abort "missing field -- packageid" unless @packageid - abort "missing field -- groupid" unless @groupid + + abort "missing field -- package" unless rel.package + #abort "missing field -- packageid" unless rel.packageid + abort "missing field -- groupid" unless rel.groupid # add more... - case @host - when 'rubyforge', 'rubyforge.org' - else - puts %{Unrecognized release host '#{@host}'. Skipped.} - skip = true - end +# case rel.host +# when 'rubyforge', 'rubyforge.org' +# else +# puts %{Unrecognized release host '#{rel.host}'. Skipped.} +# skip = true +# end - unless skip - puts "Reap is preparing release ..." - @password = get_password - login - #create_package (doesn't fit) - add_release( @file.unshift ) - @files.each { |f| add_file( f ) } - add_release - end + puts "Reap is preparing release ..." + + rtypes = [ 'tgz', 'tbz', 'tar.gz', 'tar.bz2', 'deb', 'gem', 'ebuild' ] + rtypes -= rel.exclude + rtypes = rtypes.collect { |rt| Regexp.escape( rt ) } + re_rtypes = Regexp.new( '[.](' << rtypes.join('|') << ')$' ) + + dir = File.join( rel.dir, "#{rel.name}-#{rel.version}" ) + files = Dir.entries(dir).select { |f| + f =~ re_rtypes or f == 'PKGBUILD' + } + files = files.collect { |f| File.join( rel.dir, f ) } + + if files.empty? + puts "No files to release at #{dir}." + exit -1 + end + + # ask for password + print "Password for #{rel.username}: " + until passwd = $stdin.gets.strip ; sleep 1 ; end + @password = passwd + + login { + + unless package? +exit 0 + create_package + end + + if release? +exit 0 + files.each do |f| + remove_file( f ) if file?( f ) + add_file( f ) + end + else +exit 0 + add_release( files.unshift ) + files.each { |f| add_file( f ) } + end + + } + end +private + FILETYPES = { ".deb" => 1000, ".rpm" => 2000, ".zip" => 3000, ".bz2" => 3100, @@ -158,64 +233,121 @@ "Sparc" => 4000, "UltraSparc" => 5000, "Other" => 9999, } - # login - def login + def login( &block ) + # login page = "/account/login.php" method = "post_content" form = { - "return_to" => "", - "form_loginname" => @username, - "form_pw" => @password, - "login" => "Login" + "return_to" => "", + "form_loginname" => rel.username, + "form_pw" => @password, + "login" => "Login" } http_transaction( page, method, form ) + + # do whatever + block.call + + # logout + page = "/account/logout.php" + method = "" #"post_content" + form = {} + http_transaction( page, method, form ) end - # create a new package ( should be another task ) + # Package exists? + def package? + page = "/frs/" + method = "post_content" + form = { + "group_id" => rel.groupid + } + scrape = http_transaction( page, method, form ) + + restr = '' + restr << Regexp.escape( rel.package ) + restr << '\s*' + restr << Regexp.escape( %{<a href="/frs/monitor.php?filemodule_id=} ) + restr << '(\d+)' + restr << Regexp.escape( %{&group_id=#{rel.groupid}} ) + re = Regexp.new( restr ) + + md = re.match( scrape ) + if md + rel.packageid = md[1] + end + end + + # Create a new package. + def create_package page = "/frs/admin/index.php" method = "post_content" form = { - "group_id" => @groupid, - "package_name" => @package, + "group_id" => rel.groupid, + "package_name" => rel.package, "func" => "add_package", - "is_public" => (@private ? 0 : 1), - "submit" => "Create This Package", + "is_public" => (rel.private ? 0 : 1), + "submit" => "Create This Package" } http_transaction( page, method, form ) end - # add a new release + # Release exits? + def release? + page = "/frs/admin/showreleases.php" + method = "post_content" + form = { + "package_id" => rel.packageid, + "group_id" => rel.groupid + } + scrape = http_transaction( page, method, form ) + + restr = '' + restr << Regexp.escape( %{"editrelease.php?group_id=#{rel.groupid}} ) + restr << Regexp.escape( %{&amp;package_id=#{rel.packageid}} ) + restr << Regexp.escape( %{&amp;release_id=} ) + restr << '(\d+)' + restr << Regexp.escape( %{">#{rel.release}} ) + re = Regexp.new( restr ) + + md = re.match( scrape ) + if md + rel.releaseid = md[1] + end + end + + # Add a new release. + def add_release( userfile ) page = "/frs/admin/qrs.php" method = "post_content" - type_id = @type || userfile[%r|\.[^\./]+$|] + type_id = rel.type || userfile[%r|\.[^\./]+$|] type_id = FILETYPES[type_id] + proc_id = PROCESSORS[rel.processor] - proc_id = PROCESSORS[@processor] - # how to use these? - notes = @notes ? @notes : ( @notelog ? open(@notelog) : nil ) - changes = @changes ? @changes : ( @changelog ? open(@changelog) : nil ) + notes = rel.notes ? rel.notes : ( rel.notelog ? open(rel.notelog) : nil ) + changes = rel.changes ? rel.changes : ( rel.changelog ? open(rel.changelog) : nil ) - userfile = open(userfile) + userfile = open(rel.userfile) preformatted = '1' form = { - "group_id" => @groupid, - "package_id" => @packageid, - "release_name" => @name, - "release_date" => @date, + "group_id" => rel.groupid, + "package_id" => rel.packageid, + "release_name" => rel.name, + "release_date" => rel.date, "type_id" => type_id, "processor_id" => proc_id, "preformatted" => preformatted, "userfile" => userfile, "submit" => "Release File" @@ -225,38 +357,107 @@ extheader = { 'content-type'=>"multipart/form-data; boundary=___#{ boundary }___" } http_transaction( page, method, form, extheader ) end - # add file to release + # Does file exist? + # Note this is a little bit fragile. + # If two releases have the same exact file name in them + # there could be a problem --that's probably not likely, + # maybe even impossible, but as of yet, I can't yet rule it out. + + def file?( file ) + page = "/frs/" + method = "post_content" + form = { + "group_id" => rel.groupid + } + scrape = http_transaction( page, method, form ) + + restr = '' + restr << Regexp.escape( rel.package ) + restr << '\s*' + restr << Regexp.escape( %{<a href="/frs/download.php/} ) + restr << '(\d+)' + restr << Regexp.escape( %{/#{file}} ) + re = Regexp.new( restr ) + + md = re.match( scrape ) + if md + rel.fileid = md[1] + end + end + + # Remove file from release. + + def remove_file( file ) + page="/frs/admin/editrelease.php" + method = "post_content" + form = { + "group_id" => rel.groupid, + "package_id" => rel.packageid, + "release_id" => rel.releaseid, + "file_id" => rel.fileid, + "step3" => "Delete File", + "im_sure" => '1', + "submit" => "Delete File " + } + + http_transaction( page, method, form ) + end + + # Add file to release. + def add_file( userfile ) + page = '/frs/admin/editrelease.php' + method = "post_content" - # to do + type_id = rel.type || userfile[%r|\.[^\./]+$|] + type_id = FILETYPES[type_id] + proc_id = PROCESSORS[rel.processor] + userfile = open( userfile ) + + form = { + "group_id" => rel.groupid, + "package_id" => rel.packageid, + "release_id" => rel.releaseid, + "step2" => '1', + "userfile" => userfile, + "type_id" => type_id, + "processor_id" => proc_id, + "submit" => "Add This File" + } + + http_transaction( page, method, form ) #, extheader ) end # http transaction def http_transaction( page, method, form, extheader={} ) client = HTTPAccess2::Client::new ENV['HTTP_PROXY'] client.debug_dev = STDERR if ENV['DEBUG'] - client.set_cookie_store cookie_jar + client.set_cookie_store( rel.cookie_jar ) # fixes http-access2 bug client.redirect_uri_callback = lambda do |res| page = res.header['location'].first - page = page =~ %r/http/ ? page : "#{ config['uri'] }/#{ page }" + page = page =~ %r/http/ ? page : "http://#{ rel.host }/#{ page }" page end - response = client.send "#{ method }", "#{ config['uri'] }/#{ page }", form, extheader + page.sub!(/^\//, '') + uri = "http://#{ rel.host }/#{ page }" + response = client.send method, uri, form, extheader client.save_cookie_store + return response end +end # fixes http-access2 bug BEGIN { - require "http-access2" + require "reap/vendor/http-access2" module WebAgent::CookieUtils def domain_match(host, domain) case domain when /\d+\.\d+\.\d+\.\d+/ return (host == domain) @@ -269,5 +470,6 @@ return (host == domain) end end end } +