rubyforge 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/bin/rubyforge CHANGED
@@ -1,477 +1,220 @@
1
1
  #! /usr/bin/env ruby
2
- $VERBOSE = nil
3
- #
4
- # add local lib dir to load path - http-access2 is included here for
5
- # convenience.
6
- #
7
- $:.unshift(File::join(File::dirname(File::dirname(__FILE__)), "lib"))
8
- #
9
- # load gems/libs
10
- #
11
- %w( getoptlong enumerator http-access2 yaml fileutils ).each do |l|
12
- begin require "rubygems"; require_gem l; rescue LoadError; require l end
13
- end
14
- #
15
- # hack to fix http-access2 cookie selection bug
16
- #
17
- module WebAgent::CookieUtils
18
- def domain_match(host, domain)
19
- case domain
20
- when /\d+\.\d+\.\d+\.\d+/
21
- return (host == domain)
22
- when '.'
23
- return true
24
- when /^\./
25
- #return tail_match?(domain, host)
26
- return tail_match?(host, domain)
27
- else
28
- return (host == domain)
29
- end
30
- end
31
- end
32
- #
33
- # defaults
34
- #
35
- PROGRAM = File::basename $0
36
- HOME = ENV["HOME"] || ENV["HOMEPATH"] || File::expand_path("~")
37
- RUBYFORGE_D = File::join HOME, ".rubyforge"
38
- CONFIG_F = File::join RUBYFORGE_D, "config.yml"
39
- COOKIE_F = File::join RUBYFORGE_D, "cookie.dat"
40
- #
41
- # usage
42
- #
43
- USAGE = <<-txt
44
- SYNOPSIS
45
-
46
- #{ PROGRAM } [options]* mode [mode_args]*
47
-
48
- DESCRIPTION
49
-
50
- simplistic script which automates a limited set of rubyforge operations
51
-
52
- MODES
53
-
54
- setup()
55
- initializes your .rubyforge directory. you need to run this first before
56
- doing anything else.
57
-
58
- example :
59
- #{ PROGRAM } setup
60
-
61
- login()
62
- sends username and password from config.yml (or --username/--password
63
- options) and stores login cookie in cookie.dat. this is required for
64
- subsquent operations work.
65
-
66
- example :
67
- #{ PROGRAM } login
68
- #{ PROGRAM } login --username zaphod --password 42
69
-
70
- create_package(group_id, package_name)
71
- creates the named package under the specified group.
72
-
73
- example :
74
- #{ PROGRAM } create_package 1024 traits
75
- #{ PROGRAM } login && #{ PROGRAM } create_package codeforpeople.com traits
76
-
77
- notes :
78
- in order to use group_ids by name, rather than number, you must edit the
79
- rubyforge[group_ids] translation table in your config.yml.
80
-
81
- add_release(group_id, package_id, release_name, userfile)
82
- release a file as release_name under the specified group_id and
83
- package_id.
84
-
85
- example :
86
- #{ PROGRAM } add_release codeforpeople.com traits 0.8.0 traits-0.8.0.gem
87
- #{ PROGRAM } add_release codeforpeople.com traits 0.8.0 traits-0.8.0.tgz
88
- #{ PROGRAM } add_release 1024 1242 0.8.0 traits-0.8.0.gem
89
- #{ PROGRAM } login && #{ PROGRAM } add_release 1024 1242 0.8.0 traits-0.8.0.gem
90
-
91
- notes :
92
- in order to use group_ids and package_ids by name, rather than number,
93
- you must edit the rubyforge[group_ids] and rubyforge[package_ids]
94
- translation tables in your config.yml.
95
-
96
- delete_package(group_id, package_name)
97
- deletes a package and all it's files.
98
-
99
- example :
100
- #{ PROGRAM } delete_package codeforpeople.com traits
101
- #{ PROGRAM } delete_package 1024 traits
102
-
103
- NOTES
104
-
105
- - you can determine the group_id and package_id of projects and packages by
106
-
107
- login ->
108
- my page tab ->
109
- select a project link from 'my projects' ->
110
- files tab ->
111
- admin link (not the admin tab!) ->
112
-
113
- now you'll be at page listing your packages in this project.
114
- near the bottom you'll see links to 'add a release' or 'edit a
115
- release' - hover over the url and you'll notice the query
116
- string, which looks something like
117
-
118
- ?package_id=1242&group_id=1024
119
-
120
- and that's what you need to know
121
-
122
- - don't forget to login! logging in will store a cookie in your
123
- .rubyforge directory which expires after a time. always run the login
124
- command before any operation that requires authentication, such as
125
- uploading a package.
126
-
127
- TODO
128
-
129
- - scrape rubyforge to auto-configure group_id and package_ids.
130
-
131
- - objectify the script. it's procedural butchery attm.
132
-
133
- - add error checking. this requires screen scraping to see of an operation
134
- succeeded since 200 is returned from rubyforge even for failed operations
135
- and only the html text reveals the status.
136
-
137
- - add more functionality.
138
-
139
- OPTIONS
140
-
141
- global :
142
- --help , -h
143
- this message
144
- --config , -c
145
- specify a config file (default #{ CONFIG_F })
146
- --username , -u
147
- specify username, taken from config otherwise
148
- --password , -p
149
- specify password, taken from config otherwise
150
- --cookie_jar , -C
151
- specify cookie storage file (default #{ COOKIE_F })
152
-
153
- add_release :
154
- --is_private , -P
155
- if true, release is not public
156
- --release_date , -r
157
- specify time of release (default 'now')
158
- --type_id , -t
159
- specify filetype code (default determined by ext)
160
- --processor_id , -o
161
- specify processor (default 'Any')
162
- --release_notes , -n
163
- specify release notes as string or file
164
- --release_changes , -a
165
- specify release changes as string or file
166
- --preformatted , -f
167
- specify whether release_notes/changes are preformatted
168
-
169
- txt
170
- USAGE.gsub! %r|^#{ USAGE[%r/^\s*/] }|, ''
171
- #
172
- # config
173
- #
174
- CONFIG = <<-yml
175
- #
176
- # base rubyforge uri - store in #{ CONFIG_F }
177
- #
178
- uri : http://rubyforge.org
179
- #
180
- # this must be your username
181
- #
182
- username : username
183
- #
184
- # this must be your password
185
- #
186
- password : password
187
- #
188
- # defaults for some values
189
- #
190
- defaults :
191
- cookie_jar : #{ COOKIE_F }
192
- is_private : false
193
- #
194
- # server side rubyforge configuration
195
- #
196
- rubyforge :
197
- #
198
- # map your package names to their rubyforge ids
199
- #
200
- package_ids :
201
- traits : 1241
202
- #
203
- # map your group names to their rubyforge ids
204
- #
205
- group_ids :
206
- codeforpeople.com : 1024
207
- #
208
- # mapping file exts to rubyforge ids
209
- #
210
- type_ids :
211
- .deb : 1000
212
- .rpm : 2000
213
- .zip : 3000
214
- .bz2 : 3100
215
- .gz : 3110
216
- .src.zip : 5000
217
- .src.bz2 : 5010
218
- .src.tar.bz2 : 5010
219
- .src.gz : 5020
220
- .src.tar.gz : 5020
221
- .src.rpm : 5100
222
- .src : 5900
223
- .jpg : 8000
224
- .txt : 8100
225
- .text : 8100
226
- .htm : 8200
227
- .html : 8200
228
- .pdf : 8300
229
- .oth : 9999
230
- .ebuild : 1300
231
- .exe : 1100
232
- .dmg : 1200
233
- .tar.gz : 5000
234
- .tgz : 5000
235
- .gem : 1400
236
- .pgp : 8150
237
- .sig : 8150
238
- #
239
- # map processor names to rubyforge ids
240
- #
241
- processor_ids :
242
- i386 : 1000
243
- IA64 : 6000
244
- Alpha : 7000
245
- Any : 8000
246
- PPC : 2000
247
- MIPS : 3000
248
- Sparc : 4000
249
- UltraSparc : 5000
250
- Other : 9999
251
- yml
252
- CONFIG.gsub! %r|^#{ CONFIG[%r/^\s*/] }|, ''
253
- #
254
- # load mode, global opts, and config
255
- #
256
- mode = ARGV.shift
257
-
258
- opts = GetoptLong::new(
259
- [ "--help" , "-h" , GetoptLong::REQUIRED_ARGUMENT ] ,
260
- [ "--config" , "-c" , GetoptLong::REQUIRED_ARGUMENT ] ,
261
- [ "--username" , "-u" , GetoptLong::REQUIRED_ARGUMENT ] ,
262
- [ "--password" , "-p" , GetoptLong::REQUIRED_ARGUMENT ] ,
263
- [ "--cookie_jar" , "-C" , GetoptLong::REQUIRED_ARGUMENT ] ,
264
-
265
- [ "--is_private", "-P", GetoptLong::REQUIRED_ARGUMENT ],
266
-
267
- [ "--release_date" , "-r" , GetoptLong::REQUIRED_ARGUMENT ] ,
268
- [ "--type_id" , "-t" , GetoptLong::REQUIRED_ARGUMENT ] ,
269
- [ "--processor_id" , "-o" , GetoptLong::REQUIRED_ARGUMENT ] ,
270
- [ "--release_notes" , "-n" , GetoptLong::REQUIRED_ARGUMENT ] ,
271
- [ "--release_changes" , "-a" , GetoptLong::REQUIRED_ARGUMENT ] ,
272
- [ "--preformatted" , "-f" , GetoptLong::NO_ARGUMENT ]
273
- ).enum_for.inject({}){|h,kv| h.update kv.first.delete('-') => kv.last}
274
-
275
- config = opts["config"] || CONFIG_F
276
- config = test(?e, config) ? IO::read(config) : CONFIG
277
- config = YAML::load config
278
-
279
- username = opts["username"] || config["username"]
280
- password = opts["password"] || config["password"]
281
- cookie_jar = opts["cookie_jar"] || config["defaults"]["cookie_jar"]
282
-
283
- abort "no <username>" unless username
284
- abort "no <password>" unless password
285
- abort "no <cookie_jar>" unless cookie_jar
286
-
287
- mode = "help" if opts["help"]
288
- #
289
- # run based on mode
290
- #
291
- msg, page, form, extheader = nil, nil, nil, {}
292
-
293
- case mode
294
- #
295
- # help mode
296
- #
297
- when %r/help/
298
- USAGE.display
299
- exit
300
- #
301
- # setup mode
302
- #
303
- when %r/setup/
304
- FileUtils::mkdir_p RUBYFORGE_D
305
- test ?e, CONFIG_F and FileUtils::mv CONFIG_F, "#{ CONFIG_F }.bak"
306
- open(CONFIG_F,"w"){|f| f.write CONFIG}
307
- FileUtils::touch COOKIE_F
308
- edit = (ENV["EDITOR"] || ENV["EDIT"] || "gvim") + " #{ CONFIG_F }"
309
- system edit or puts "edit #{ CONFIG_F }"
310
- exit
311
- #
312
- # login mode
313
- #
314
- when %r/login/
315
- page, msg = "/account/login.php", "post_content"
316
-
317
- form = {
318
- "return_to" => "",
319
- "form_loginname" => username,
320
- "form_pw" => password,
321
- "login" => "Login"
322
- }
323
- #
324
- # create_package mode
325
- #
326
- when %r/create_package/
327
- page, msg = "/frs/admin/index.php", "post_content"
328
-
329
- group_id, package_name = ARGV
330
-
331
- abort "no <group_id>" unless group_id
332
- abort "no <package_name>" unless package_name
333
-
334
- unless group_id.to_s =~ %r/^\d+$/
335
- key = group_id.to_s
336
- group_id = config["rubyforge"]["group_ids"][key]
337
- abort "no <group_id> configured for <#{ key }>" unless group_id
338
- end
339
-
340
- is_private = opts["is_private"] || config["defaults"]["is_private"]
341
- is_public = is_private ? 0 : 1
342
-
343
- form = {
344
- "func" => "add_package",
345
- "group_id" => group_id,
346
- "package_name" => package_name,
347
- "is_public" => is_public,
348
- "submit" => "Create This Package",
349
- }
350
- #
351
- # delete_package mode
352
- #
353
- when %r/delete_package/
354
- page, msg = "/frs/admin/index.php", "post_content"
355
-
356
- group_id, package_id = ARGV
357
-
358
- abort "no <group_id>" unless group_id
359
- abort "no <package_id>" unless package_id
360
-
361
- unless group_id.to_s =~ %r/^\d+$/
362
- key = group_id.to_s
363
- group_id = config["rubyforge"]["group_ids"][key]
364
- abort "no <group_id> configured for <#{ key }>" unless group_id
365
- end
366
-
367
- unless package_id.to_s =~ %r/^\d+$/
368
- key = package_id.to_s
369
- package_id = config["rubyforge"]["package_ids"][key]
370
- abort "no <package_id> configured for <#{ key }>" unless package_id
371
- end
372
-
373
- form = {
374
- "func" => "delete_package",
375
- "group_id" => group_id,
376
- "package_id" => package_id,
377
- "sure" => "1",
378
- "really_sure" => "1",
379
- "submit" => "Delete",
380
- }
381
- #
382
- # add_release mode
383
- #
384
- when %r/add_release/
385
- page, msg = "/frs/admin/qrs.php", "post_content"
386
-
387
- group_id, package_id, release_name, userfile = ARGV
388
-
389
- abort "no <group_id>" unless group_id
390
- abort "no <package_id>" unless package_id
391
- abort "no <release_name>" unless release_name
392
- abort "no <userfile>" unless userfile
393
-
394
- unless group_id.to_s =~ %r/^\d+$/
395
- key = group_id.to_s
396
- group_id = config["rubyforge"]["group_ids"][key]
397
- abort "no <group_id> configured for <#{ key }>" unless group_id
398
- end
399
-
400
- unless package_id.to_s =~ %r/^\d+$/
401
- key = package_id.to_s
402
- package_id = config["rubyforge"]["package_ids"][key]
403
- abort "no <package_id> configured for <#{ key }>" unless package_id
404
- end
405
-
406
- userfile = open userfile
407
-
408
- release_date = opts["release_date"]
409
- type_id = opts["type_id"]
410
- processor_id = opts["processor_id"]
411
- release_notes = opts["release_notes"]
412
- release_changes = opts["release_changes"]
413
- preformatted = opts["preformatted"]
414
-
415
- release_date ||= Time::now.strftime("%Y-%m-%d %H:%M")
416
-
417
- type_id ||= userfile.path[%r|\.[^\./]+$|]
418
- unless type_id.to_s =~ %r/^\d+$/
419
- key = type_id.to_s
420
- type_id = config["rubyforge"]["type_ids"][key]
421
- abort "no <type_id> configured for <#{ key }>" unless type_id
422
- end
423
-
424
- processor_id ||= "Any"
425
- unless processor_id.to_s =~ %r/^\d+$/
426
- key = processor_id.to_s
427
- processor_id = config["rubyforge"]["processor_ids"][key]
428
- abort "no <processor_id> configured for <#{ key }>" unless processor_id
429
- end
430
-
431
- release_notes = IO::read(release_notes) if release_notes and test(?e, release_notes)
432
-
433
- release_changes = IO::read(release_changes) if release_changes and test(?e, release_changes)
434
-
435
- preformatted = preformatted ? 1 : 0
436
-
437
- form = {
438
- "group_id" => group_id,
439
- "package_id" => package_id,
440
- "release_name" => release_name,
441
- "release_date" => release_date,
442
- "type_id" => type_id,
443
- "processor_id" => processor_id,
444
- "release_notes" => release_notes,
445
- "release_changes" => release_changes,
446
- "preformatted" => preformatted,
447
- "userfile" => userfile,
448
- "submit" => "Release File"
449
- }
450
-
451
- boundary = Array::new(8){ "%2.2d" % rand(42) }.join('__')
452
- extheader['content-type'] = "multipart/form-data; boundary=___#{ boundary }___"
453
- #
454
- # bad mode
455
- #
456
- else
457
- abort USAGE
458
- end
459
- #
460
- # commit http transaction
461
- #
462
- if [msg, page, form].all?
463
- client = HTTPAccess2::Client::new ENV["HTTP_PROXY"]
464
- client.debug_dev = STDERR if ENV["RUBYFORGE_DEBUG"] || ENV["DEBUG"]
465
- client.set_cookie_store cookie_jar
466
- #
467
- # hack to fix http-access2 redirect bug/feature
468
- #
469
- client.redirect_uri_callback = lambda do |res|
470
- page = res.header['location'].first
471
- page =~ %r/http/ ? page : "#{ config['uri'] }/#{ page }"
472
- end
473
- response = client.send "#{ msg }", "#{ config['uri'] }/#{ page }", form, extheader
474
- client.save_cookie_store
475
- end
476
-
477
- exit 0
2
+
3
+ $VERBOSE = true
4
+
5
+ $:.unshift(File::join(File::dirname(File::dirname(__FILE__)), "lib"))
6
+
7
+ require 'getoptlong'
8
+ require 'rubyforge'
9
+
10
+ PROGRAM = File::basename $0
11
+
12
+ USAGE = <<-EOL
13
+ SYNOPSIS
14
+
15
+ #{ PROGRAM } [options]* mode [mode_args]*
16
+
17
+ DESCRIPTION
18
+
19
+ simplistic script which automates a limited set of rubyforge operations
20
+
21
+ MODES
22
+
23
+ setup()
24
+ initializes your .rubyforge directory. you need to run this first before
25
+ doing anything else.
26
+
27
+ example :
28
+ #{ PROGRAM } setup
29
+
30
+ config()
31
+ Helps you populate your config.yml file by scraping rubyforge and
32
+ getting your groups, projects, and releases.
33
+
34
+ example :
35
+ #{ PROGRAM } config
36
+
37
+ names()
38
+ Prints out the names of your configured groups and projects.
39
+
40
+ example :
41
+ #{ PROGRAM } names
42
+
43
+ login()
44
+ sends username and password from config.yml (or --username/--password
45
+ options) and stores login cookie in cookie.dat. this is required for
46
+ subsquent operations work.
47
+
48
+ example :
49
+ #{ PROGRAM } login
50
+ #{ PROGRAM } login --username zaphod --password 42
51
+
52
+ create_package(group_id, package_name)
53
+ creates the named package under the specified group.
54
+
55
+ example :
56
+ #{ PROGRAM } create_package 1024 traits
57
+ #{ PROGRAM } login && #{ PROGRAM } create_package codeforpeople.com traits
58
+
59
+ add_release(group_id, package_id, release_name, userfile)
60
+ release a file as release_name under the specified group_id and
61
+ package_id.
62
+
63
+ example :
64
+ #{ PROGRAM } add_release codeforpeople.com traits 0.8.0 traits-0.8.0.gem
65
+ #{ PROGRAM } add_release codeforpeople.com traits 0.8.0 traits-0.8.0.tgz
66
+ #{ PROGRAM } add_release 1024 1242 0.8.0 traits-0.8.0.gem
67
+ #{ PROGRAM } login && #{ PROGRAM } add_release 1024 1242 0.8.0 traits-0.8.0.gem
68
+
69
+ add_file(group_id, package_id, release_id, userfile)
70
+ add a file to an existing release under the specified group_id,
71
+ package_id, and release_id
72
+
73
+ example :
74
+ #{ PROGRAM } add_file codeforpeople.com traits 0.8.0 traits-0.8.0.gem
75
+ #{ PROGRAM } add_file codeforpeople.com traits 0.8.0 traits-0.8.0.tgz
76
+ #{ PROGRAM } add_file 1024 1242 0.8.0 traits-0.8.0.gem
77
+
78
+ delete_package(group_id, package_name)
79
+ deletes a package and all its files.
80
+
81
+ example :
82
+ #{ PROGRAM } delete_package codeforpeople.com traits
83
+ #{ PROGRAM } delete_package 1024 traits
84
+
85
+ NOTES
86
+
87
+ - In order to use group_id, package_id, or release_id by name,
88
+ rather than number, you must edit the rubyforge[group_ids] and
89
+ rubyforge[package_ids] translation tables in your config.yml. See
90
+ the config command for more information and help.
91
+
92
+ - don\'t forget to login! logging in will store a cookie in your
93
+ .rubyforge directory which expires after a time. always run the login
94
+ command before any operation that requires authentication, such as
95
+ uploading a package.
96
+
97
+ TODO
98
+
99
+ - add error checking. this requires screen scraping to see of an operation
100
+ succeeded since 200 is returned from rubyforge even for failed operations
101
+ and only the html text reveals the status.
102
+
103
+ OPTIONS
104
+
105
+ global :
106
+ --help , -h
107
+ this message
108
+ --config , -c
109
+ specify a config file (default #{ RubyForge::CONFIG_F })
110
+ --username , -u
111
+ specify username, taken from config otherwise
112
+ --password , -p
113
+ specify password, taken from config otherwise
114
+ --cookie_jar , -C
115
+ specify cookie storage file (default #{ RubyForge::COOKIE_F })
116
+
117
+ add_release :
118
+ --is_private , -P
119
+ if true, release is not public
120
+ --release_date , -r
121
+ specify time of release (default 'now')
122
+ --type_id , -t
123
+ specify filetype code (default determined by ext)
124
+ --processor_id , -o
125
+ specify processor (default 'Any')
126
+ --release_notes , -n
127
+ specify release notes as string or file
128
+ --release_changes , -a
129
+ specify release changes as string or file
130
+ --preformatted , -f
131
+ specify whether release_notes/changes are preformatted
132
+
133
+ EOL
134
+
135
+ mode = ARGV.shift
136
+
137
+ opts = GetoptLong::new(
138
+ [ "--help" , "-h" , GetoptLong::REQUIRED_ARGUMENT ] ,
139
+ [ "--config" , "-c" , GetoptLong::REQUIRED_ARGUMENT ] ,
140
+ [ "--username" , "-u" , GetoptLong::REQUIRED_ARGUMENT ] ,
141
+ [ "--password" , "-p" , GetoptLong::REQUIRED_ARGUMENT ] ,
142
+ [ "--cookie_jar" , "-C" , GetoptLong::REQUIRED_ARGUMENT ] ,
143
+ [ "--is_private" , "-P" , GetoptLong::REQUIRED_ARGUMENT ],
144
+ [ "--release_date" , "-r" , GetoptLong::REQUIRED_ARGUMENT ] ,
145
+ [ "--type_id" , "-t" , GetoptLong::REQUIRED_ARGUMENT ] ,
146
+ [ "--processor_id" , "-o" , GetoptLong::REQUIRED_ARGUMENT ] ,
147
+ [ "--release_notes" , "-n" , GetoptLong::REQUIRED_ARGUMENT ] ,
148
+ [ "--release_changes" , "-a" , GetoptLong::REQUIRED_ARGUMENT ] ,
149
+ [ "--preformatted" , "-f" , GetoptLong::NO_ARGUMENT ]
150
+ ).enum_for.inject({}){|h,kv| h.update kv.first.delete('-') => kv.last}
151
+
152
+ rubyforge = RubyForge.new(opts["config"] || RubyForge::CONFIG_F, opts)
153
+
154
+ mode = "help" if opts["help"]
155
+
156
+ case mode
157
+ when %r/help/
158
+ USAGE.display
159
+ when %r/setup/
160
+ rubyforge.setup
161
+ when %r/config/
162
+ puts "Add the following to #{RubyForge::CONFIG_F}"
163
+ puts
164
+ username = ARGV.shift || rubyforge.config['username']
165
+ y "rubyforge" => rubyforge.scrape_config(username)
166
+ when %r/names/
167
+ rf = rubyforge.config["rubyforge"]
168
+ puts "groups : #{rf["group_ids"].keys.sort.join(", ")}"
169
+ puts "packages: #{rf["package_ids"].keys.sort.join(", ")}"
170
+ when %r/login/
171
+ rubyforge.login
172
+ when %r/create_package/
173
+ page, msg = "/frs/admin/index.php", "post_content"
174
+
175
+ group_id, package_name = ARGV
176
+
177
+ abort "no <group_id>" unless group_id
178
+ abort "no <package_name>" unless package_name
179
+
180
+ group_id = Integer(group_id) rescue group_id
181
+
182
+ rubyforge.create_package group_id, package_name
183
+ when %r/delete_package/
184
+ group_id, package_id = ARGV
185
+
186
+ abort "no <group_id>" unless group_id
187
+ abort "no <package_id>" unless package_id
188
+
189
+ group_id = Integer(group_id) rescue group_id
190
+ package_id = Integer(package_id) rescue package_id
191
+
192
+ rubyforge.delete_package group_id, package_id
193
+ when %r/add_release/
194
+ group_id, package_id, release_name, userfile = ARGV
195
+
196
+ abort "no <group_id>" unless group_id
197
+ abort "no <package_id>" unless package_id
198
+ abort "no <release_name>" unless release_name
199
+ abort "no <userfile>" unless userfile
200
+
201
+ group_id = Integer(group_id) rescue group_id
202
+ package_id = Integer(package_id) rescue package_id
203
+
204
+ rubyforge.add_release group_id, package_id, release_name, userfile
205
+ when %r/add_file/
206
+ group_id, package_id, release_id, userfile = ARGV
207
+
208
+ abort "no <group_id>" unless group_id
209
+ abort "no <package_id>" unless package_id
210
+ abort "no <release_id>" unless release_id
211
+ abort "no <userfile>" unless userfile
212
+
213
+ group_id = Integer(group_id) rescue group_id
214
+ package_id = Integer(package_id) rescue package_id
215
+ release_id = Integer(release_id) rescue release_id
216
+
217
+ rubyforge.add_file group_id, package_id, release_id, userfile
218
+ else
219
+ abort USAGE
220
+ end