Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[SCRIPT] auto rubyforge releasing

0 views
Skip to first unread message

Ara.T.Howard

unread,
Nov 4, 2005, 12:27:49 AM11/4/05
to

this is one of the ugliest, but most useful, things i've written in a while.
thought someone else might enjoy it too.

save the attachment to a file named 'rubyforge'.

you can then do

rubyforge login
rubyforge create_package package_name
rubyforge add_release package_id release_name file.ext

for example, i just relased a new traits lib using

rubyforge login
rubyforge create_package traits
rubyforge add_release traits 0.8.0 traits-0.8.0.tgz
rubyforge add_release traits 0.8.0 traits-0.8.0.gem

you will need to customize the config section to contain your username,
password, main group_id, and shortcuts for your package_ids so you can
reference them by name. there are no docs and no help, but it's pretty easy
reading. i'd like to do more with it but probably won't for quite a while -
so, if anyone is itching for a head start on writing a rubyforge interface ;-)


file: rubyforge

#! /usr/bin/env ruby
#
# libs
#
$VERBOSE = nil
require "getoptlong"
require "enumerator"
require "http-access2"
#
# config
#
config = {
"username" => "username", # this must be your username
"password" => "password", # this must be your password

"group_id" => 1024, # this is codeforpeople. it's just a default...

"package_ids" => { # configure shortcuts for your packages here
"traits" => 1241,
"lockfile" => 1242,
},

"uri" => "http://rubyforge.org",
"cookie_jar" => File::join(File::expand_path("~"), ".rubyforge.cookie_jar"),
}

opts =
GetoptLong::new(
[ "--username" , "-u" , GetoptLong::REQUIRED_ARGUMENT ] ,
[ "--password" , "-p" , GetoptLong::REQUIRED_ARGUMENT ] ,
[ "--cookie_jar" , "-c" , GetoptLong::REQUIRED_ARGUMENT ]
).enum_for.inject({}){|h,kv| h.update Hash[*kv]}

username = opts['username'] || config['username']
password = opts['password'] || config['password']
cookie_jar = opts["cookie_jar"] || config['cookie_jar']
#
# setup
#
mode = ARGV.shift
abort "#{ $0 } [login|create_package (package_name)|add_package (package_id release_name release.ext)]" unless mode

page, form, method = nil
extheader = {}

case mode

when %r/login/
page = "/account/login.php"
method = "post_content"

form = {
"return_to" => "",
"form_loginname" => username,
"form_pw" => password,
"login" => "Login"
}

when %r/create_package/
page = "/frs/admin/index.php"
method = "post_content"

opts =
GetoptLong::new(
[ "--group_id" , "-g" , GetoptLong::REQUIRED_ARGUMENT ] ,
[ "--is_private" , "-P" , GetoptLong::REQUIRED_ARGUMENT ]
).enum_for.inject({}){|h,kv| h.update Hash[*kv]}

package_name = ARGV.shift
abort "#{ $0 } package_name" unless package_name

group_id = opts["group_id"] || config["group_id"]
is_public = opts["is_private"] ? 0 : 1

form = {
"group_id" => group_id,
"package_name" => package_name,
"func" => "add_package",
"is_public" => is_public,
"submit" => "Create This Package",
}

when %r/add_release/
page = "/frs/admin/qrs.php"
method = "post_content"

opts =
GetoptLong::new(
[ "--group_id" , "-g" , GetoptLong::REQUIRED_ARGUMENT ] ,
[ "--release_date" , "-r" , GetoptLong::REQUIRED_ARGUMENT ] ,
[ "--type_id" , "-t" , GetoptLong::REQUIRED_ARGUMENT ] ,
[ "--processor_id" , "-P" , GetoptLong::REQUIRED_ARGUMENT ] ,
[ "--release_nots" , "-n" , GetoptLong::REQUIRED_ARGUMENT ] ,
[ "--release_changes" , "-a" , GetoptLong::REQUIRED_ARGUMENT ]
).enum_for.inject({}){|h,kv| h.update Hash[*kv]}

package_id, release_name, userfile, ignored = ARGV
abort "#{ $0 } package_name" unless
package_id and release_name and userfile

package_id = config["package_ids"][package_id] unless
package_id =~ %r/^\d+$/

group_id = opts["group_id"] || config["group_id"]
release_date = opts["release_date"] || Time::now.strftime('%Y-%m-%d %H:%M')

type_id = opts['type_id'] || userfile[%r|\.[^\./]+$|]
type_id = {
".deb" => 1000,
".rpm" => 2000,
".zip" => 3000,
".bz2" => 3100,
".gz" => 3110,
".src.zip" => 5000,
".src.bz2" => 5010,
".src.gz" => 5020,
".src.rpm" => 5100,
".src" => 5900,
".jpg" => 8000,
".txt" => 8100,
".text" => 8100,
".htm" => 8200,
".html" => 8200,
".pdf" => 8300,
".oth" => 9999,
".ebuild" => 1300,
".exe" => 1100,
".dmg" => 1200,
".tar.gz" => 5000,
".tgz" => 5000,
".gem" => 1400,
".pgp" => 8150,
".sig" => 8150,
}[type_id]

processor_id = opts['processor_id'] || 'Any'
processor_id = {
"i386" => 1000,
"IA64" => 6000,
"Alpha" => 7000,
"Any" => 8000,
"PPC" => 2000,
"MIPS" => 3000,
"Sparc" => 4000,
"UltraSparc" => 5000,
"Other" => 9999,
}[processor_id]

release_notes = opts['release_notes'] || nil
release_notes = open(release_notes) if release_notes

release_changes = opts['release_changes'] || nil
release_changes = open(release_changes) if release_changes

userfile = open(userfile)

preformatted = '1'

form = {
"group_id" => group_id,
"package_id" => package_id,
"release_name" => release_name,
"release_date" => release_date,
"type_id" => type_id,
"processor_id" => processor_id,
"preformatted" => preformatted,
"userfile" => userfile,
"submit" => "Release File"
}

boundary = Array::new(8){ "%2.2d" % rand(42) }.join('__')
extheader['content-type'] = "multipart/form-data; boundary=___#{ boundary }___"


else
abort "#{ $0 } login create_package add_release"

end
#
# http transaction
#
client = HTTPAccess2::Client::new ENV['HTTP_PROXY']
client.debug_dev = STDERR if ENV['DEBUG']

client.set_cookie_store 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
end

response = client.send "#{ method }", "#{ config['uri'] }/#{ page }", form, extheader

client.save_cookie_store


# fixes http-access2 bug
BEGIN {
require "http-access2"
module WebAgent::CookieUtils
def domain_match(host, domain)
case domain
when /\d+\.\d+\.\d+\.\d+/
return (host == domain)
when '.'
return true
when /^\./
#return tail_match?(domain, host)
return tail_match?(host, domain)
else
return (host == domain)
end
end
end
}

enjoy.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| anything that contradicts experience and logic should be abandoned.
| -- h.h. the 14th dalai lama
===============================================================================

Trans

unread,
Nov 4, 2005, 1:25:51 AM11/4/05
to
Thanks Ara, I've been needing that!

FYI I talked to Tom Copeland recently. He says that when they upgarde
RubyForge to next version we may get SOAP interface, which would be
great.

I had been waiting on the SOAP but now that you've written a sweet
little script use it until then. Yea!

Thanks,
T.

Edgardo Hames

unread,
Nov 4, 2005, 9:09:24 AM11/4/05
to
On 11/4/05, Ara.T.Howard <Ara.T....@noaa.gov> wrote:
>
> this is one of the ugliest, but most useful, things i've written in a while.
> thought someone else might enjoy it too.
>
>
> file: rubyforge

>
> # config
> #
> config = {
> "username" => "username", # this must be your username
> "password" => "password", # this must be your password
>
> "group_id" => 1024, # this is codeforpeople. it's just a default...
>
> "package_ids" => { # configure shortcuts for your packages here
> "traits" => 1241,
> "lockfile" => 1242,
> },
>
> "uri" => "http://rubyforge.org",
> "cookie_jar" => File::join(File::expand_path("~"), ".rubyforge.cookie_jar"),
> }


How about getting this from a YAML file? I'd love to post the patch
but I don't have ruby to test it on this PC.

Just thinking,
Ed
--
Encontrá a "Tu psicópata favorito" http://tuxmaniac.blogspot.com

Thou shalt study thy libraries and strive not to reinvent them without cause,
that thy code may be short and readable and thy days pleasant and productive.
-- Seventh commandment for C programmers


0 new messages