reap 9.3.5 → 9.4.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/CHANGES +10 -0
- data/MANIFEST +37 -21
- data/NOTES +13 -11
- data/bin/reap-announce +40 -2
- data/bin/reap-check-load +20 -2
- data/bin/reap-check-syntax +20 -2
- data/bin/reap-clean +24 -2
- data/bin/reap-clobber +17 -2
- data/bin/reap-doc +12 -2
- data/bin/reap-doc-rdoc +17 -2
- data/bin/reap-doc-ri +16 -2
- data/bin/reap-doc-spec +18 -0
- data/bin/reap-init +9 -0
- data/bin/reap-inspect +20 -2
- data/bin/reap-install +13 -2
- data/bin/reap-install-gem +14 -2
- data/bin/reap-log +15 -2
- data/bin/reap-log-changes +15 -2
- data/bin/reap-log-notes +20 -2
- data/bin/reap-make +16 -2
- data/bin/reap-make-clean +10 -2
- data/bin/reap-make-distclean +18 -2
- data/bin/reap-make-extconf +14 -2
- data/bin/reap-make-static +14 -2
- data/bin/reap-package +25 -2
- data/bin/reap-package-gem +14 -2
- data/bin/reap-package-tgz +14 -2
- data/bin/reap-package-zip +14 -2
- data/bin/reap-prepare +21 -2
- data/bin/reap-publish +25 -2
- data/bin/reap-release +22 -2
- data/bin/reap-rollout +32 -2
- data/bin/reap-scaffold +16 -2
- data/bin/reap-scm-branch +13 -2
- data/bin/reap-scm-tag +13 -2
- data/bin/reap-spec +14 -2
- data/bin/reap-stats +21 -2
- data/bin/reap-test +14 -2
- data/bin/reap-test-cross +23 -2
- data/bin/reap-test-load +17 -2
- data/bin/reap-test-solo +19 -2
- data/bin/reap-uninstall +14 -2
- data/bin/reap-uninstall-gem +17 -2
- data/bin/reap-version +10 -2
- data/lib/reap/announcement.rb +136 -0
- data/lib/reap/application.rb +3 -1
- data/lib/reap/default.yaml +12 -12
- data/lib/reap/defaults.rb +49 -0
- data/lib/reap/emailer.rb +189 -0
- data/lib/reap/extensions.rb +1 -2
- data/lib/reap/hosts.rb +4 -0
- data/lib/reap/hosts/host.rb +69 -0
- data/lib/reap/hosts/mailinglist.rb +83 -0
- data/lib/reap/{systems → hosts}/rubyforge.rb +72 -60
- data/lib/reap/hosts/rubytalk.rb +39 -0
- data/lib/reap/iobject.rb +5 -3
- data/lib/reap/metadata.rb +31 -4
- data/lib/reap/project.rb +101 -41
- data/lib/reap/project/announce.rb +50 -180
- data/lib/reap/project/check.rb +1 -1
- data/lib/reap/project/gem.rb +32 -68
- data/lib/reap/project/log.rb +12 -7
- data/lib/reap/project/make.rb +0 -1
- data/lib/reap/project/package.rb +228 -75
- data/lib/reap/project/rdoc.rb +9 -8
- data/lib/reap/project/release.rb +52 -6
- data/lib/reap/project/scm.rb +40 -25
- data/lib/reap/project/spec.rb +3 -3
- data/lib/reap/project/test.rb +1 -2
- data/lib/reap/project/version.rb +18 -4
- data/lib/reap/runmodes.rb +24 -0
- data/lib/reap/settings.rb +3 -14
- data/lib/reap/systems.rb +4 -0
- data/lib/reap/systems/git.rb +0 -0
- data/lib/reap/systems/hg.rb +0 -0
- data/lib/reap/systems/{subversion.rb → svn.rb} +47 -16
- data/lib/reap/systems/system.rb +53 -0
- data/lib/reap/tool.rb +38 -0
- data/lib/reap/utilities.rb +43 -86
- data/log/{Changelog.txt → changelog.rdoc} +56 -0
- data/log/fixme.rdoc +25 -0
- data/log/todo.rdoc +85 -0
- data/meta/project.yaml +13 -2
- data/meta/version +1 -0
- data/setup.rb +74 -64
- data/task/allshare.rb +109 -0
- data/task/clean +13 -0
- data/task/compile +28 -0
- data/task/configure +372 -0
- data/task/install +1481 -0
- data/test/case/test_init.rb +32 -0
- data/test/case/test_scaffold.rb +32 -0
- data/test/data/scaffold/meta/project.yaml +28 -0
- data/test/lib/case_testable.rb +23 -0
- metadata +64 -31
- data/bin/reap-spec-doc +0 -8
- data/demo/README +0 -15
- data/demo/lib/foo/foo.rb +0 -7
- data/demo/meta/VERSION +0 -1
- data/demo/meta/project.yaml +0 -21
- data/lib/reap/project/rubyforge.rb +0 -71
- data/lib/reap/project/svn.rb +0 -76
- data/log/Fixme.txt +0 -22
- data/log/Todo.txt +0 -84
- data/meta/VERSION +0 -1
@@ -0,0 +1,49 @@
|
|
1
|
+
module Reap
|
2
|
+
|
3
|
+
class Project
|
4
|
+
|
5
|
+
# = Project Settings Defaults
|
6
|
+
#
|
7
|
+
# Provides an inteface to default values for Settings.
|
8
|
+
# The default values are loaded from a .yaml file.
|
9
|
+
|
10
|
+
class Defaults < Hash
|
11
|
+
|
12
|
+
DEFAULT_FILE = File.join(File.dirname(__FILE__), 'default.yaml')
|
13
|
+
|
14
|
+
attr :metadata
|
15
|
+
|
16
|
+
# FIXME: when using the settings, I think nil should be considered a none entry and
|
17
|
+
# so false would be required to actually mean "off". This means assigning each key value par one a time?
|
18
|
+
|
19
|
+
def initialize(metadata)
|
20
|
+
super()
|
21
|
+
@metadata = metadata
|
22
|
+
defaults = File.read(DEFAULT_FILE)
|
23
|
+
defaults = instance_eval("<<-XXXXXXXXXXXXX\n#{defaults}\nXXXXXXXXXXXXX")
|
24
|
+
defaults = YAML::load(defaults)
|
25
|
+
#settings = defaults.dup
|
26
|
+
#data.each do |key, value|
|
27
|
+
# settings[key] ||= {}
|
28
|
+
# settings[key].update(value) if value
|
29
|
+
#end
|
30
|
+
update(defaults)
|
31
|
+
end
|
32
|
+
|
33
|
+
# open hash
|
34
|
+
|
35
|
+
def method_missing(s, *a)
|
36
|
+
if s =~ /=$/
|
37
|
+
self[s] = a[0]
|
38
|
+
elsif a.empty?
|
39
|
+
self[s]
|
40
|
+
else
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
data/lib/reap/emailer.rb
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'facets/openhash'
|
2
|
+
|
3
|
+
module Reap
|
4
|
+
|
5
|
+
# Emailer class makes it easy send out an email.
|
6
|
+
#
|
7
|
+
# Settings:
|
8
|
+
#
|
9
|
+
# subject Subject of email message.
|
10
|
+
# from Message FROM address [email].
|
11
|
+
# to Email address to send announcemnt.
|
12
|
+
# server Email server to route message.
|
13
|
+
# port Email server's port.
|
14
|
+
# port_secure Email server's port.
|
15
|
+
# domain Email server's domain name.
|
16
|
+
# account Email account name if needed.
|
17
|
+
# password Password for login..
|
18
|
+
# login Login type: plain, cram_md5 or login [plain].
|
19
|
+
# secure Uses TLS security, true or false? [false]
|
20
|
+
# message Mesage to send -or-
|
21
|
+
# file File that contains message.
|
22
|
+
#
|
23
|
+
class Emailer
|
24
|
+
|
25
|
+
class << self
|
26
|
+
# Used for caching password between usages.
|
27
|
+
attr_accessor :password
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_accessor :server
|
31
|
+
attr_accessor :port
|
32
|
+
attr_accessor :account
|
33
|
+
attr_accessor :passwd
|
34
|
+
attr_accessor :login
|
35
|
+
attr_accessor :secure
|
36
|
+
attr_accessor :domain
|
37
|
+
attr_accessor :from
|
38
|
+
attr_accessor :mailto
|
39
|
+
attr_accessor :subject
|
40
|
+
attr_accessor :message
|
41
|
+
|
42
|
+
#
|
43
|
+
|
44
|
+
def self.load_with_environment(options, defaults={})
|
45
|
+
options = options.rekey
|
46
|
+
defaults = defaults.rekey
|
47
|
+
environ = environment_options
|
48
|
+
|
49
|
+
options[:server] ||= environ[:server]
|
50
|
+
options[:from] ||= environ[:from]
|
51
|
+
options[:account] ||= environ[:account]
|
52
|
+
options[:password] ||= environ[:password]
|
53
|
+
options[:port] ||= environ[:port]
|
54
|
+
options[:domain] ||= environ[:domain]
|
55
|
+
options[:login] ||= environ[:login]
|
56
|
+
options[:secure] ||= environ[:secure]
|
57
|
+
|
58
|
+
options[:server] ||= defaults[:server]
|
59
|
+
options[:from] ||= defaults[:from]
|
60
|
+
options[:account] ||= defaults[:account] || defaults[:from]
|
61
|
+
options[:port] ||= defaults[:port].to_i
|
62
|
+
options[:domain] ||= defaults[:domain]
|
63
|
+
options[:login] ||= defaults[:login]
|
64
|
+
options[:secure] ||= defaults[:secure].to_b
|
65
|
+
|
66
|
+
new(options)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.environment_options
|
70
|
+
options = {}
|
71
|
+
|
72
|
+
options[:server] ||= ENV['EMAIL_SERVER']
|
73
|
+
options[:from] ||= ENV['EMAIL_FROM']
|
74
|
+
options[:account] ||= ENV['EMAIL_ACCOUNT'] || options[:from]
|
75
|
+
options[:password] ||= ENV['EMAIL_PASSWORD']
|
76
|
+
options[:port] ||= ENV['EMAIL_PORT'].to_i
|
77
|
+
options[:domain] ||= ENV['EMAIL_DOMAIN']
|
78
|
+
options[:login] ||= ENV['EMAIL_LOGIN']
|
79
|
+
options[:secure] ||= ENV['EMAIL_SECURE'].to_b
|
80
|
+
|
81
|
+
options
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
|
86
|
+
def initialize(options)
|
87
|
+
options = options.to_ostruct
|
88
|
+
|
89
|
+
@server = options.server
|
90
|
+
@account = options.account || options.from
|
91
|
+
@passwd = options.password || self.class.password
|
92
|
+
@login = options.login
|
93
|
+
@secure = options.secure
|
94
|
+
@domain = options.domain || options.server
|
95
|
+
|
96
|
+
@from = options.from
|
97
|
+
@subject = options.subject
|
98
|
+
@mailto = options.mailto || options.to
|
99
|
+
@message = options.message
|
100
|
+
|
101
|
+
if options.port
|
102
|
+
@port = options.port
|
103
|
+
else
|
104
|
+
@port = secure ? 465 : 25
|
105
|
+
end
|
106
|
+
|
107
|
+
@account ||= @from
|
108
|
+
|
109
|
+
@login ||= :plain
|
110
|
+
@login = @login.to_sym
|
111
|
+
|
112
|
+
# save the password for later use
|
113
|
+
self.class.password = @password
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
|
118
|
+
def email(options={})
|
119
|
+
options.rekey
|
120
|
+
|
121
|
+
message = options[:message] || message()
|
122
|
+
subject = options[:subject] || subject()
|
123
|
+
from = options[:from] || from()
|
124
|
+
mailto = options[:mailto] || options[:to] || mailto()
|
125
|
+
|
126
|
+
raise ArgumentError, "missing email field -- server" unless server
|
127
|
+
raise ArgumentError, "missing email field -- account" unless account
|
128
|
+
|
129
|
+
raise ArgumentError, "missing email field -- from" unless from
|
130
|
+
raise ArgumentError, "missing email field -- mailto" unless mailto
|
131
|
+
raise ArgumentError, "missing email field -- subject" unless subject
|
132
|
+
|
133
|
+
passwd ||= password("#{account} password:")
|
134
|
+
|
135
|
+
mailto = [mailto].flatten.compact
|
136
|
+
|
137
|
+
msg = ""
|
138
|
+
msg << "From: #{from}\n"
|
139
|
+
msg << "To: #{mailto.join(';')}\n"
|
140
|
+
msg << "Subject: #{subject}\n"
|
141
|
+
msg << ""
|
142
|
+
msg << message
|
143
|
+
|
144
|
+
if secure
|
145
|
+
Net::SMTP.send(:include, Net::SMTP::TLS)
|
146
|
+
Net::SMTP.enable_tls #if secure #if Net::SMTP.respond_to?(:enable_tls) and secure
|
147
|
+
end
|
148
|
+
|
149
|
+
begin
|
150
|
+
Net::SMTP.start(server, port, domain, account, passwd, login, secure) do |smtp|
|
151
|
+
smtp.send_message(msg, from, mailto)
|
152
|
+
end
|
153
|
+
puts "Email sent successfully to #{mailto.join(';')}."
|
154
|
+
true
|
155
|
+
rescue Exception => e
|
156
|
+
if $DEBUG
|
157
|
+
raise e
|
158
|
+
else
|
159
|
+
abort "Email delivery failed with #{e}"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# Ask for a password.
|
165
|
+
#
|
166
|
+
# FIXME: Does not hide password.
|
167
|
+
|
168
|
+
def password(msg=nil)
|
169
|
+
msg ||= "Enter Password: "
|
170
|
+
inp = ''
|
171
|
+
|
172
|
+
$stdout << msg
|
173
|
+
|
174
|
+
inp = STDIN.gets.chomp
|
175
|
+
|
176
|
+
#begin
|
177
|
+
# system "stty -echo"
|
178
|
+
# inp = gets.chomp
|
179
|
+
#ensure
|
180
|
+
# system "stty echo"
|
181
|
+
#end
|
182
|
+
|
183
|
+
return inp
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
data/lib/reap/extensions.rb
CHANGED
data/lib/reap/hosts.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'reap/tool'
|
2
|
+
|
3
|
+
module Reap
|
4
|
+
module Hosts
|
5
|
+
|
6
|
+
def self.registry
|
7
|
+
@registry ||= {}
|
8
|
+
end
|
9
|
+
|
10
|
+
# = Host
|
11
|
+
#
|
12
|
+
# Base class for Hosts.
|
13
|
+
|
14
|
+
class Host < Tool
|
15
|
+
|
16
|
+
def self.registry
|
17
|
+
Hosts.registry
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.register(*uris)
|
21
|
+
uris.each do |uri|
|
22
|
+
registry[uri] = self
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.inherited(base)
|
27
|
+
scm = base.basename.downcase
|
28
|
+
registry[scm] = base
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.factory(name)
|
32
|
+
registry[name]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Generic announce confirmation.
|
36
|
+
|
37
|
+
def announce_confirm?(options={})
|
38
|
+
return true if force?
|
39
|
+
ans = ask("Announce to #{self.class.basename.downcase}?", "yN")
|
40
|
+
case ans.downcase
|
41
|
+
when 'y', 'yes'
|
42
|
+
true
|
43
|
+
else
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Generic announce confirmation.
|
49
|
+
|
50
|
+
def release_confirm?(options={})
|
51
|
+
return true if force?
|
52
|
+
ans = ask("Release to #{self.class.basename.downcase}?", "yN")
|
53
|
+
case ans.downcase
|
54
|
+
when 'y', 'yes'
|
55
|
+
true
|
56
|
+
else
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def inspect
|
62
|
+
"<#{self.class}>"
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'reap/hosts/host'
|
2
|
+
require 'reap/emailer'
|
3
|
+
|
4
|
+
module Reap
|
5
|
+
module Hosts
|
6
|
+
|
7
|
+
# = Mailinglist
|
8
|
+
#
|
9
|
+
# Gerneic Mailing list "host". Mailinglist hosts
|
10
|
+
# support the @announce@ task.
|
11
|
+
|
12
|
+
class Mailinglist < Host
|
13
|
+
|
14
|
+
register('mailinglist')
|
15
|
+
|
16
|
+
# Email message. Options are:
|
17
|
+
#
|
18
|
+
# message Message to send.
|
19
|
+
# mailto Email address to whom to mail.
|
20
|
+
# from Email address from whom.
|
21
|
+
# subject Subject line (default is "ANN: project version").
|
22
|
+
# server Email server
|
23
|
+
# port Emails server port (default is usually correct).
|
24
|
+
# account Email account name (defaults to from).
|
25
|
+
# domain User domain (not sure why SMTP requires this?)
|
26
|
+
# login Login type (plain, login)
|
27
|
+
# secure Use TLS/SSL true or false?
|
28
|
+
|
29
|
+
def announce(options)
|
30
|
+
options = announce_options(options)
|
31
|
+
|
32
|
+
subject = options[:subject]
|
33
|
+
mailto = options[:mailto] || options[:to]
|
34
|
+
to = [mailto].flatten.join(", ")
|
35
|
+
|
36
|
+
if dryrun?
|
37
|
+
puts "email '#{subject}' to #{to}"
|
38
|
+
else
|
39
|
+
emailer = Emailer.new(options)
|
40
|
+
emailer.email
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Confirm announcement
|
45
|
+
|
46
|
+
def announce_confirm?(options)
|
47
|
+
options = announce_options(options)
|
48
|
+
|
49
|
+
if mailto = options[:mailto] || options[:to]
|
50
|
+
return true if force?
|
51
|
+
to = [mailto].flatten.join(", ")
|
52
|
+
ans = ask("Announce to #{to}?", "yN")
|
53
|
+
case ans.downcase
|
54
|
+
when 'y', 'yes'
|
55
|
+
true
|
56
|
+
else
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
|
64
|
+
def announce_options(options)
|
65
|
+
options = options.rekey
|
66
|
+
environ = Emailer.environment_options
|
67
|
+
defaults = project.defaults['email'].rekey
|
68
|
+
|
69
|
+
result = {}
|
70
|
+
result.update(defaults)
|
71
|
+
result.update(environ)
|
72
|
+
result.update(options)
|
73
|
+
|
74
|
+
result[:subject] = (result[:subject] % [metadata.unixname, metadata.version])
|
75
|
+
|
76
|
+
result
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
@@ -6,28 +6,35 @@ require 'ostruct'
|
|
6
6
|
require 'httpclient'
|
7
7
|
require 'tmpdir'
|
8
8
|
|
9
|
-
require 'facets
|
9
|
+
require 'facets' #/hash/rekey'
|
10
10
|
require 'facets/kernel/ask'
|
11
11
|
|
12
|
+
require 'reap/hosts/host'
|
13
|
+
|
12
14
|
module Reap
|
15
|
+
module Hosts
|
13
16
|
|
17
|
+
# = Rubyforge
|
18
|
+
#
|
14
19
|
# Interface with the RubyForge hosting service.
|
15
|
-
#
|
20
|
+
# Supports the following tasks:
|
16
21
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
22
|
+
# * release - Upload release packages.
|
23
|
+
# * announce - Post news announcement.
|
24
|
+
# * touch - Test connection.
|
25
|
+
#
|
26
|
+
# TODO: Handle publish tasks to upload website files (currently this is handled separately)
|
21
27
|
|
22
|
-
class Rubyforge
|
28
|
+
class Rubyforge < Host
|
29
|
+
#include FileUtils
|
23
30
|
|
24
|
-
|
31
|
+
register('rubyforge', 'rubyforge.org')
|
25
32
|
|
26
33
|
#HOME = ENV["HOME"] || ENV["HOMEPATH"] || File.expand_path("~")
|
27
34
|
|
35
|
+
DOMAIN = "rubyforge.org"
|
28
36
|
COOKIEJAR = File::join(Dir.tmpdir, 'reap', 'cookie.dat')
|
29
|
-
|
30
|
-
REPORT = /<h\d><span style="color:red">(.*?)<\/span><\/h\d>/
|
37
|
+
REPORT = /<h\d><span style="color:red">(.*?)<\/span><\/h\d>/
|
31
38
|
|
32
39
|
# URI = http:// + domain name
|
33
40
|
# TODO Deal with https, and possible other protocols too.
|
@@ -37,53 +44,42 @@ module Reap
|
|
37
44
|
# for use even if they arn't used.
|
38
45
|
attr :username
|
39
46
|
attr :password
|
47
|
+
attr :domain
|
40
48
|
|
41
|
-
#
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
# New RubyForge tasks.
|
47
|
-
def initialize(options)
|
48
|
-
options = options.dup.rekey
|
49
|
+
# New RubyForge object.
|
50
|
+
#
|
51
|
+
def initialize(project, options={})
|
52
|
+
options = options.rekey
|
49
53
|
|
50
|
-
|
51
|
-
@trace = options[:trace]
|
54
|
+
super(project, options)
|
52
55
|
|
53
|
-
|
54
|
-
@uri
|
56
|
+
@domain = options[:domain] || DOMAIN
|
57
|
+
@uri = URI.parse("http://" + domain)
|
55
58
|
|
56
59
|
@username = options[:username] || ENV['RUBYFORGE_USERNAME']
|
57
|
-
@password = options[:password]
|
60
|
+
@password = options[:password] || ENV['RUBYFORGE_PASSWORD']
|
61
|
+
@unixname = options[:project] || project.metadata.unixname
|
62
|
+
@version = project.metadata.version
|
58
63
|
|
59
|
-
|
60
|
-
@cookie_jar = COOKIEJAR
|
61
|
-
|
62
|
-
@project = options[:project]
|
63
|
-
@group_id = options[:group_id] || options[:groupid]
|
64
|
+
@group_id = options[:group] || options[:group_id] || options[:groupid]
|
64
65
|
|
65
66
|
@package_ids = {}
|
66
67
|
@release_ids = {}
|
67
|
-
@file_ids
|
68
|
+
@file_ids = {}
|
68
69
|
|
69
|
-
|
70
|
-
end
|
70
|
+
project.mkdir_p(File.dirname(COOKIEJAR))
|
71
71
|
|
72
|
-
|
73
|
-
@dryrun
|
72
|
+
#load_project
|
74
73
|
end
|
75
74
|
|
76
|
-
|
77
|
-
|
75
|
+
#
|
76
|
+
|
77
|
+
def cookie_jar
|
78
|
+
COOKIEJAR
|
78
79
|
end
|
79
80
|
|
80
81
|
public
|
81
82
|
|
82
|
-
#
|
83
|
-
def domain
|
84
|
-
"rubyforge.org"
|
85
|
-
end
|
86
|
-
|
87
83
|
# Website location on server.
|
88
84
|
def siteroot
|
89
85
|
"/var/www/gforge-projects"
|
@@ -95,8 +91,11 @@ module Reap
|
|
95
91
|
%w{ touch release publish post }
|
96
92
|
end
|
97
93
|
|
94
|
+
# Project unixname.
|
95
|
+
attr_accessor :unixname
|
96
|
+
|
98
97
|
# Project name.
|
99
|
-
attr_accessor :
|
98
|
+
attr_accessor :version
|
100
99
|
|
101
100
|
# Project's group id number.
|
102
101
|
attr_accessor :group_id
|
@@ -107,6 +106,8 @@ module Reap
|
|
107
106
|
# Login to website.
|
108
107
|
|
109
108
|
def login # :yield:
|
109
|
+
load_project_cached
|
110
|
+
|
110
111
|
page = @uri + "/account/login.php"
|
111
112
|
page.scheme = 'https'
|
112
113
|
page = URI.parse(page.to_s) # set SSL port correctly
|
@@ -119,12 +120,14 @@ module Reap
|
|
119
120
|
}
|
120
121
|
html = http_post(page, form)
|
121
122
|
|
122
|
-
|
123
|
+
if not html[/Personal Page/]
|
123
124
|
puts "Login failed."
|
124
125
|
re1 = Regexp.escape(%{<h2 style="color:red">})
|
125
126
|
re2 = Regexp.escape(%{</h2>})
|
126
127
|
html[/#{re1}(.*?)#{re2}/]
|
127
128
|
raise $1
|
129
|
+
else
|
130
|
+
@printed_project_name ||= (puts "Project: #{unixname}"; true)
|
128
131
|
end
|
129
132
|
|
130
133
|
if block_given?
|
@@ -164,7 +167,7 @@ module Reap
|
|
164
167
|
# files package files to release.
|
165
168
|
# exclude Package formats to exclude from files.
|
166
169
|
# (from those created by pack)
|
167
|
-
#
|
170
|
+
# unixname Project name on host.
|
168
171
|
# package Package to which this release belongs (defaults to project)
|
169
172
|
# release Release name (default is version number)
|
170
173
|
# version Version of release
|
@@ -190,9 +193,9 @@ module Reap
|
|
190
193
|
changelog = options[:changelog]
|
191
194
|
notelog = options[:notelog]
|
192
195
|
|
193
|
-
|
194
|
-
package = options[:package] ||
|
195
|
-
release = options[:release] || version
|
196
|
+
unixname = options[:unixname] || unixname()
|
197
|
+
package = options[:package] || unixname()
|
198
|
+
release = options[:release] || version()
|
196
199
|
name = options[:name] || package
|
197
200
|
files = options[:file] || []
|
198
201
|
date = options[:date] || Time::now.strftime('%Y-%m-%d %H:%M')
|
@@ -201,8 +204,7 @@ module Reap
|
|
201
204
|
|
202
205
|
is_public = options[:is_public].nil? ? true : options[:is_public]
|
203
206
|
|
204
|
-
raise ArgumentError, "missing
|
205
|
-
raise ArgumentError, "missing project" unless project
|
207
|
+
raise ArgumentError, "missing unixname" unless unixname
|
206
208
|
raise ArgumentError, "missing package" unless package
|
207
209
|
raise ArgumentError, "missing release" unless release
|
208
210
|
|
@@ -232,6 +234,8 @@ module Reap
|
|
232
234
|
|
233
235
|
login do
|
234
236
|
|
237
|
+
raise ArgumentError, "missing group_id" unless group_id
|
238
|
+
|
235
239
|
unless package_id = package?(package)
|
236
240
|
if dryrun?
|
237
241
|
puts "Package '#{package}' does not exist."
|
@@ -311,7 +315,7 @@ module Reap
|
|
311
315
|
# options = options.rekey
|
312
316
|
#
|
313
317
|
# #domain = options[:domain] || DOMAIN
|
314
|
-
# root = File.join(siteroot,
|
318
|
+
# root = File.join(siteroot, unixname)
|
315
319
|
# root = File.join(root, options[:root]) if options[:root]
|
316
320
|
#
|
317
321
|
# options.update(
|
@@ -324,7 +328,7 @@ module Reap
|
|
324
328
|
|
325
329
|
# Submit a news item.
|
326
330
|
|
327
|
-
def
|
331
|
+
def announce(options)
|
328
332
|
options = options.rekey
|
329
333
|
|
330
334
|
if file = options[:file]
|
@@ -338,8 +342,7 @@ module Reap
|
|
338
342
|
end
|
339
343
|
|
340
344
|
if dryrun?
|
341
|
-
puts "
|
342
|
-
puts "\n#{message}\n\n"
|
345
|
+
puts "announce-rubyforge: #{subject}"
|
343
346
|
else
|
344
347
|
post_news(subject, message)
|
345
348
|
puts "News item posted!"
|
@@ -353,8 +356,8 @@ module Reap
|
|
353
356
|
|
354
357
|
def http_post(page, form, extheader={})
|
355
358
|
client = HTTPClient::new ENV["HTTP_PROXY"]
|
356
|
-
client.debug_dev = STDERR if ENV["
|
357
|
-
client.set_cookie_store(
|
359
|
+
client.debug_dev = STDERR if ENV["REAP_DEBUG"] || $DEBUG
|
360
|
+
client.set_cookie_store(cookie_jar)
|
358
361
|
client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
359
362
|
|
360
363
|
# HACK to fix http-client redirect bug/feature
|
@@ -382,12 +385,16 @@ module Reap
|
|
382
385
|
return response
|
383
386
|
end
|
384
387
|
|
388
|
+
#
|
389
|
+
|
390
|
+
def load_project_cached
|
391
|
+
@load_project_cache ||= load_project
|
392
|
+
end
|
393
|
+
|
385
394
|
# Loads information for project: group_id, package_ids and release_ids.
|
386
395
|
|
387
396
|
def load_project
|
388
|
-
|
389
|
-
|
390
|
-
html = URI.parse("http://#{domain}/projects/#{project}/index.html").read
|
397
|
+
html = URI.parse("http://#{domain}/projects/#{unixname}/index.html").read
|
391
398
|
|
392
399
|
group_id = html[/(frs|tracker)\/\?group_id=\d+/][/\d+/].to_i
|
393
400
|
@group_id = group_id
|
@@ -445,7 +452,7 @@ module Reap
|
|
445
452
|
restr = ''
|
446
453
|
restr << Regexp.escape( package_name )
|
447
454
|
restr << '\s*'
|
448
|
-
restr << Regexp.escape(
|
455
|
+
restr << Regexp.escape( '<a href="/frs/monitor.php?filemodule_id=' )
|
449
456
|
restr << '(\d+)'
|
450
457
|
restr << Regexp.escape( %{&group_id=#{group_id}} )
|
451
458
|
re = Regexp.new( restr )
|
@@ -606,7 +613,7 @@ module Reap
|
|
606
613
|
restr = ''
|
607
614
|
#restr << Regexp.escape( package )
|
608
615
|
#restr << '\s*'
|
609
|
-
restr << Regexp.escape(
|
616
|
+
restr << Regexp.escape( '<a href="/frs/download.php/' )
|
610
617
|
restr << '(\d+)'
|
611
618
|
restr << Regexp.escape( %{/#{file}} )
|
612
619
|
re = Regexp.new(restr)
|
@@ -672,6 +679,8 @@ module Reap
|
|
672
679
|
def post_news(subject, body)
|
673
680
|
page = "/news/submit.php"
|
674
681
|
|
682
|
+
subject % [unixname, version]
|
683
|
+
|
675
684
|
form = {
|
676
685
|
"group_id" => group_id,
|
677
686
|
"post_changes" => "y",
|
@@ -680,7 +689,9 @@ module Reap
|
|
680
689
|
"submit" => "Submit"
|
681
690
|
}
|
682
691
|
|
683
|
-
|
692
|
+
login do
|
693
|
+
http_post(page, form)
|
694
|
+
end
|
684
695
|
end
|
685
696
|
|
686
697
|
# Constant for file types accepted by Rubyforge
|
@@ -745,4 +756,5 @@ module Reap
|
|
745
756
|
end
|
746
757
|
|
747
758
|
end
|
759
|
+
end
|
748
760
|
|