reap 6.0.2 → 9.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/CHANGES +6 -0
- data/COPYING +666 -395
- data/MANIFEST +139 -0
- data/NOTES +12 -0
- data/README +19 -163
- data/bin/reap-announce +7 -0
- data/bin/reap-check-load +8 -0
- data/bin/reap-check-syntax +7 -0
- data/bin/reap-clean +7 -0
- data/bin/reap-clobber +7 -0
- data/bin/reap-doc +7 -0
- data/bin/reap-doc-rdoc +7 -0
- data/bin/reap-doc-ri +7 -0
- data/bin/reap-init +69 -0
- data/bin/reap-inspect +7 -0
- data/bin/reap-install +8 -0
- data/bin/reap-install-gem +8 -0
- data/bin/reap-log +7 -0
- data/bin/reap-log-changes +8 -0
- data/bin/reap-log-notes +8 -0
- data/bin/reap-make +7 -0
- data/bin/reap-make-clean +7 -0
- data/bin/reap-make-distclean +7 -0
- data/bin/reap-make-extconf +7 -0
- data/bin/reap-make-static +8 -0
- data/bin/reap-package +8 -0
- data/bin/reap-package-gem +7 -0
- data/bin/reap-package-tgz +7 -0
- data/bin/reap-package-zip +7 -0
- data/bin/reap-prepare +7 -0
- data/bin/reap-publish +7 -0
- data/bin/reap-release +7 -0
- data/bin/reap-scaffold +8 -0
- data/bin/reap-scm-branch +7 -0
- data/bin/reap-scm-tag +7 -0
- data/bin/reap-spec +7 -0
- data/bin/reap-spec-doc +8 -0
- data/bin/reap-stamp +7 -0
- data/bin/reap-stats +7 -0
- data/bin/reap-test +7 -0
- data/bin/reap-test-cross +7 -0
- data/bin/reap-test-load +9 -0
- data/bin/reap-test-solo +7 -0
- data/bin/reap-uninstall +7 -0
- data/bin/reap-uninstall-gem +7 -0
- data/data/reap/base/CHANGES +19 -0
- data/data/reap/base/COPYING +674 -0
- data/data/reap/base/NOTES +12 -0
- data/data/reap/base/README +8 -0
- data/data/reap/build/rake/Rakefile +130 -0
- data/{forge/reference/installers → data/reap/build/rake}/setup.rb +155 -97
- data/data/reap/build/rake-lite/install.rb +79 -0
- data/data/reap/build/tasks/task/rdoc +211 -0
- data/data/reap/{setup.rb → build/tasks/task/setup} +248 -200
- data/data/reap/build/tasks/task/test +38 -0
- data/data/reap/init/meta/project.yaml +21 -0
- data/demo/README +15 -0
- data/demo/lib/foo/foo.rb +7 -0
- data/demo/meta/VERSION +1 -0
- data/demo/meta/project.yaml +21 -0
- data/lib/reap/application.rb +80 -0
- data/lib/reap/default.yaml +77 -0
- data/lib/reap/extensions/array.rb +50 -0
- data/lib/reap/extensions/hash.rb +63 -0
- data/lib/reap/extensions/string.rb +31 -0
- data/lib/reap/extensions.rb +6 -0
- data/lib/reap/iobject.rb +264 -0
- data/lib/reap/manager/announce.rb +193 -0
- data/lib/reap/manager/check.rb +109 -0
- data/lib/reap/manager/clean.rb +58 -0
- data/lib/reap/manager/gem.rb +200 -0
- data/lib/reap/manager/html.rb +69 -0
- data/lib/reap/manager/log.rb +214 -0
- data/lib/reap/manager/make.rb +109 -0
- data/lib/reap/manager/pack.rb +232 -0
- data/lib/reap/manager/publish.rb +72 -0
- data/lib/reap/manager/rdoc.rb +194 -0
- data/lib/reap/manager/release.rb +78 -0
- data/lib/reap/manager/rubyforge.rb +44 -0
- data/lib/reap/manager/scaffold.rb +138 -0
- data/lib/reap/manager/scm.rb +66 -0
- data/lib/reap/manager/site.rb +27 -0
- data/lib/reap/manager/spec.rb +94 -0
- data/lib/reap/manager/stats.rb +145 -0
- data/lib/reap/manager/svn.rb +76 -0
- data/lib/reap/manager/test.rb +389 -0
- data/lib/reap/manager.rb +74 -0
- data/lib/reap/metadata.rb +603 -0
- data/lib/reap/project.rb +165 -0
- data/lib/reap/settings.rb +67 -0
- data/lib/reap/systems/rubyforge.rb +737 -0
- data/lib/reap/systems/subversion.rb +333 -0
- data/lib/reap/utilities/fileutils.rb +304 -0
- data/lib/reap/utilities/netutils.rb +221 -0
- data/lib/reap/utilities/setuputils.rb +124 -0
- data/lib/reap/utilities/shellutils.rb +175 -0
- data/log/Changelog.txt +107 -0
- data/log/FIXME.txt +25 -0
- data/log/TODO.txt +72 -0
- data/meta/VERSION +1 -0
- data/meta/description +4 -0
- data/meta/project.yaml +20 -0
- data/task/man +14 -0
- data/task/rdoc +20 -0
- data/{data/reap/scaffold/standard/setup.rb → task/setup} +248 -200
- metadata +225 -153
- data/ProjectInfo +0 -105
- data/bin/reap +0 -5
- data/bin/rubytest +0 -5
- data/data/reap/install.rb +0 -62
- data/data/reap/scaffold/standard/COPYING +0 -403
- data/data/reap/scaffold/standard/ChangeLog +0 -0
- data/data/reap/scaffold/standard/INSTALL +0 -14
- data/data/reap/scaffold/standard/ProjectInfo +0 -77
- data/data/reap/scaffold/standard/README +0 -3
- data/data/reap/scaffold/standard/Rakefile +0 -10
- data/data/reap/scaffold/standard/TODO +0 -0
- data/data/reap/scaffold/subversion/trunk/COPYING +0 -403
- data/data/reap/scaffold/subversion/trunk/ChangeLog +0 -0
- data/data/reap/scaffold/subversion/trunk/INSTALL +0 -14
- data/data/reap/scaffold/subversion/trunk/ProjectInfo +0 -76
- data/data/reap/scaffold/subversion/trunk/README +0 -3
- data/data/reap/scaffold/subversion/trunk/Rakefile +0 -10
- data/data/reap/scaffold/subversion/trunk/TODO +0 -0
- data/data/reap/scaffold/subversion/trunk/setup.rb +0 -1568
- data/forge/ProjectInfo +0 -38
- data/forge/ProjectInfo.rb +0 -76
- data/forge/TODO +0 -10
- data/forge/installer.rb +0 -250
- data/forge/reference/Rakefile +0 -124
- data/forge/reference/Rakefile.htm +0 -69
- data/forge/reference/aRakefile +0 -60
- data/forge/reference/compositepublisher.rb +0 -24
- data/forge/reference/ftptools.rb +0 -139
- data/forge/reference/installers/package.rb +0 -629
- data/forge/reference/license-each.rb +0 -85
- data/forge/reference/publisher.rb +0 -75
- data/forge/reference/rubyforge.rb +0 -247
- data/forge/reference/rubyforgepublisher.rb +0 -18
- data/forge/reference/sshpublisher.rb +0 -47
- data/forge/reference/suby-cvs.rb +0 -46
- data/forge/scaffold.rb +0 -126
- data/forge/unit_runner/README +0 -6
- data/forge/unit_runner/commentrunner.rb +0 -62
- data/forge/unit_runner/cunit.rb +0 -17
- data/forge/unit_runner/forkedrunner.rb +0 -91
- data/forge/unit_runner/sample.rb +0 -16
- data/lib/reap/bin/reap.rb +0 -230
- data/lib/reap/bin/rubytest.rb +0 -53
- data/lib/reap/class/announce.rb +0 -220
- data/lib/reap/class/doap.rb +0 -80
- data/lib/reap/class/extest.rb +0 -146
- data/lib/reap/class/filer.rb +0 -62
- data/lib/reap/class/manifest.rb +0 -68
- data/lib/reap/class/package.rb +0 -576
- data/lib/reap/class/publish.rb +0 -152
- data/lib/reap/class/rdoc.rb +0 -123
- data/lib/reap/class/test.rb +0 -264
- data/lib/reap/projectinfo.rb +0 -208
- data/lib/reap/rake.rb +0 -42
- data/lib/reap/reap.rb +0 -89
- data/lib/reap/tasks.rb +0 -756
- data/lib/reap/taskutils.rb +0 -122
- data/note/LATEST +0 -44
- data/note/doap.xml +0 -28
- data/note/history/Rakefile-0.1 +0 -308
- data/sample/ProjectInfo +0 -96
- data/sample/Rakefile +0 -9
- data/sample/Reapfile +0 -11
- data/sample/task/demo.rb +0 -15
- data/setup.rb +0 -1568
- data/web/ProjectInfo.html +0 -75
- data/web/images/grape.jpg +0 -0
- data/web/index.html +0 -312
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
require 'reap/utilities/shellutils'
|
|
2
|
+
require 'reap/utilities/fileutils'
|
|
3
|
+
|
|
4
|
+
module Reap
|
|
5
|
+
|
|
6
|
+
class Subversion
|
|
7
|
+
include Utilities::ShellUtils
|
|
8
|
+
include Utilities::FileUtils
|
|
9
|
+
|
|
10
|
+
# Project name (for repository).
|
|
11
|
+
|
|
12
|
+
attr_accessor :project
|
|
13
|
+
|
|
14
|
+
# Current version of project.
|
|
15
|
+
|
|
16
|
+
attr_accessor :version
|
|
17
|
+
|
|
18
|
+
# Developers URL to repository. Defaults to Rubyforge address.
|
|
19
|
+
|
|
20
|
+
attr_accessor :repository
|
|
21
|
+
|
|
22
|
+
# Username. Defaults to ENV['RUBYFORGE_USERNAME'].
|
|
23
|
+
|
|
24
|
+
attr_accessor :username
|
|
25
|
+
|
|
26
|
+
# The URL protocol to use. Defaults to "svn+ssh".
|
|
27
|
+
|
|
28
|
+
attr_accessor :protocol
|
|
29
|
+
|
|
30
|
+
# Prefix to use on tag folder. Default is no prefix.
|
|
31
|
+
|
|
32
|
+
attr_accessor :prefix
|
|
33
|
+
|
|
34
|
+
# Optional commit message. This is intended for commandline
|
|
35
|
+
# usage. (Use -m for shorthand).
|
|
36
|
+
|
|
37
|
+
attr_accessor :message
|
|
38
|
+
|
|
39
|
+
# Directory to store tags. Defaults to tags/.
|
|
40
|
+
|
|
41
|
+
attr_accessor :tagpath
|
|
42
|
+
|
|
43
|
+
# Directory to store branches. Defaults to branches/.
|
|
44
|
+
|
|
45
|
+
attr_accessor :branchpath
|
|
46
|
+
|
|
47
|
+
# Operate in dryrun mode.
|
|
48
|
+
|
|
49
|
+
attr_accessor :dryrun
|
|
50
|
+
|
|
51
|
+
# New Subversion object.
|
|
52
|
+
#
|
|
53
|
+
# TODO: Perhaps format prefix, like:
|
|
54
|
+
# prefix = prefix + '_' if prefix && prefix !~ /[_-]$/
|
|
55
|
+
|
|
56
|
+
def initialize(options={})
|
|
57
|
+
options.each do |k,v|
|
|
58
|
+
send("#{k}=", v) if respond_to?("#{k}=")
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# defaults are for rubyforge
|
|
62
|
+
@repository ||= "rubyforge.org/var/svn/#{project}"
|
|
63
|
+
@username ||= ENV['RUBYFORGE_USERNAME']
|
|
64
|
+
@protocol ||= "svn+ssh"
|
|
65
|
+
@tagpath ||= "tags"
|
|
66
|
+
@branchpath ||= "branches"
|
|
67
|
+
|
|
68
|
+
if i = @repository.index('//')
|
|
69
|
+
@repository = @repository[i+2..-1]
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Developer domain is "username@repository".
|
|
74
|
+
|
|
75
|
+
def developer_domain
|
|
76
|
+
"#{username}@#{repository}"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Branch current version.
|
|
80
|
+
#
|
|
81
|
+
# message Optional commit message. This is intended for commandline
|
|
82
|
+
# usage. (Use -m for shorthand).
|
|
83
|
+
#
|
|
84
|
+
def branch(options={})
|
|
85
|
+
msg = options['message'] || options['m']
|
|
86
|
+
name = "#{prefix}#{version}"
|
|
87
|
+
path = branchpath.to_s
|
|
88
|
+
|
|
89
|
+
if path == '.' or path.empty?
|
|
90
|
+
url = "#{protocol}://" + File.join(developer_domain, name)
|
|
91
|
+
else
|
|
92
|
+
url = "#{protocol}://" + File.join(developer_domain, path, name)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
case ask("Branch: #{url} ? [yN]").strip.downcase
|
|
96
|
+
when 'y', 'yes'
|
|
97
|
+
#sh "svn copy #{protocol}://#{username}@#{repository}/trunk #{url}"
|
|
98
|
+
sh "svn copy . #{url}"
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Tag current version.
|
|
103
|
+
#
|
|
104
|
+
# message Optional commit message. This is intended for commandline
|
|
105
|
+
# usage. (Use -m for shorthand).
|
|
106
|
+
#
|
|
107
|
+
def tag(options={})
|
|
108
|
+
msg = options['message'] || options['m']
|
|
109
|
+
name = "#{prefix}#{version}"
|
|
110
|
+
path = tagpath.to_s
|
|
111
|
+
|
|
112
|
+
if path == '.' or path.empty?
|
|
113
|
+
url = "#{protocol}://" + File.join(developer_domain, name)
|
|
114
|
+
else
|
|
115
|
+
url = "#{protocol}://" + File.join(developer_domain, path, name)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
case ask("Tag: #{url} ? [yN]").strip.downcase
|
|
119
|
+
when 'y', 'yes'
|
|
120
|
+
#sh "svn copy #{protocol}://#{username}@#{repository}/trunk #{url}"
|
|
121
|
+
sh "svn copy . #{url}"
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Create a change log.
|
|
126
|
+
#
|
|
127
|
+
# change File name to store rdoc formated changelog. Default is 'changelog.txt'.
|
|
128
|
+
#
|
|
129
|
+
# output Path to store rdoc formated changelog. Default is 'log'.
|
|
130
|
+
#
|
|
131
|
+
# xmlchange File name to store XML formated changelog. Default is 'changelog.xml'.
|
|
132
|
+
# This also creates a file, if needed, by the same name but with .xsl extension.
|
|
133
|
+
#
|
|
134
|
+
# xmloutput Path to store XML-formated changelog. Default is 'doc/log'.
|
|
135
|
+
#
|
|
136
|
+
# If change or xmlchange contain a path separator ('/', not '\'), then it is assumed they
|
|
137
|
+
# provide their own path and the output fields will not be used. This allows you to set
|
|
138
|
+
# +change+ to "./CHANGES" for instance, without effecting the location of other logs.
|
|
139
|
+
# You can also set change or xmlchange to 'false' to supress creation altogether.
|
|
140
|
+
#
|
|
141
|
+
# TODO: Allow for a way to dump the text-based Changelog to standard out. "$stdout" as the filename?
|
|
142
|
+
# TODO: How to apply naming policy from here?
|
|
143
|
+
|
|
144
|
+
def log(file=nil)
|
|
145
|
+
#txtlog = file #options['change'] || 'changelog.txt'
|
|
146
|
+
#txtdir = options['output'] || 'log'
|
|
147
|
+
#xmllog = options['xmlchange'] || 'changelog.xml'
|
|
148
|
+
#xmldir = options['xmloutput'] || 'doc/log'
|
|
149
|
+
#txtlog = File.join(txtdir, txtlog) unless xmllog.include?('/')
|
|
150
|
+
#xmllog = File.join(xmldir, xmllog) unless xmllog.include?('/')
|
|
151
|
+
text = changelog_text
|
|
152
|
+
if dryrun?
|
|
153
|
+
puts "svn log > #{file}"
|
|
154
|
+
elsif file
|
|
155
|
+
mkdir_p(File.dirname(file))
|
|
156
|
+
File.open(file, 'w'){|f| f << text }
|
|
157
|
+
puts "Updated #{file}"
|
|
158
|
+
else
|
|
159
|
+
puts text
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
#
|
|
164
|
+
|
|
165
|
+
def log_xml(file)
|
|
166
|
+
#xmldir = options['xmloutput'] || 'doc/log'
|
|
167
|
+
|
|
168
|
+
xslfile = file.chomp(File.extname(file)) + '.xsl'
|
|
169
|
+
log_xsl(xslfile)
|
|
170
|
+
|
|
171
|
+
text = changelog_xml
|
|
172
|
+
i = text.index("?>\n")
|
|
173
|
+
text.insert(i+2, "\n" + %[<?xml-stylesheet href="#{xslfile}" type="text/xsl" ?>])
|
|
174
|
+
|
|
175
|
+
if dryrun?
|
|
176
|
+
puts "svn log --xml > #{file}"
|
|
177
|
+
elsif file
|
|
178
|
+
mkdir_p(File.dirname(file))
|
|
179
|
+
File.open(file, 'w'){ |f| f << text }
|
|
180
|
+
puts "Updated #{file}"
|
|
181
|
+
else
|
|
182
|
+
puts text
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
private
|
|
187
|
+
|
|
188
|
+
def changelog_xml
|
|
189
|
+
@changelog_xml ||= `svn log --xml`
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def changelog_text
|
|
193
|
+
@changelog_text ||= log_format(log_organize(log_parse(changelog_xml)))
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Parse xml log into rdoc markup.
|
|
197
|
+
|
|
198
|
+
def log_parse(xml)
|
|
199
|
+
require "rexml/document"
|
|
200
|
+
changes = []
|
|
201
|
+
doc = REXML::Document.new(xml)
|
|
202
|
+
doc.root.elements.each do |element|
|
|
203
|
+
revision = element.attributes["revision"]
|
|
204
|
+
author = element.elements["author"].text
|
|
205
|
+
date = element.elements["date"].text
|
|
206
|
+
message = element.elements["msg"].text
|
|
207
|
+
|
|
208
|
+
revision = revision.strip
|
|
209
|
+
author = author.strip
|
|
210
|
+
date = Date.parse(date)
|
|
211
|
+
message = message.strip
|
|
212
|
+
|
|
213
|
+
changes << [ date, author, revision, message ]
|
|
214
|
+
end
|
|
215
|
+
changes
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
#
|
|
219
|
+
|
|
220
|
+
def log_organize(changes)
|
|
221
|
+
mapped = {}
|
|
222
|
+
changes.each do |date, who, rev, text|
|
|
223
|
+
mapped[[date, who]] ||= []
|
|
224
|
+
mapped[[date, who]] << [text, rev]
|
|
225
|
+
end
|
|
226
|
+
sorted = []
|
|
227
|
+
mapped.each do |(date, who), entries|
|
|
228
|
+
sorted << [ date, who, entries ]
|
|
229
|
+
end
|
|
230
|
+
sorted.sort{ |a,b| b[0] <=> a[0] }
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
#
|
|
234
|
+
|
|
235
|
+
def log_format(sorted)
|
|
236
|
+
string = "= Subversion Changelog\n\n"
|
|
237
|
+
sorted.each do |date, who, entries|
|
|
238
|
+
string << "== #{date} #{who}\n\n" # no email :(
|
|
239
|
+
entries.each do |entry|
|
|
240
|
+
string << "* #{entry.first} (#{entry.last})\n"
|
|
241
|
+
end
|
|
242
|
+
string << "\n"
|
|
243
|
+
end
|
|
244
|
+
string
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
#
|
|
248
|
+
|
|
249
|
+
def log_xsl(xslfile)
|
|
250
|
+
if force? or not File.exist?(xslfile)
|
|
251
|
+
mkdir_p(File.dirname(xslfile))
|
|
252
|
+
if dryrun?
|
|
253
|
+
puts "touch #{xslfile}"
|
|
254
|
+
else
|
|
255
|
+
File.open(xslfile, 'w') do |f|
|
|
256
|
+
f << DEFAULT_LOG_XSL
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
DEFAULT_LOG_XSL = <<-END
|
|
263
|
+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
264
|
+
|
|
265
|
+
<xsl:output cdata-section-elements="script"/>
|
|
266
|
+
|
|
267
|
+
<xsl:template match="/">
|
|
268
|
+
<html>
|
|
269
|
+
<head>
|
|
270
|
+
<title>Changelog</title>
|
|
271
|
+
<link REL='SHORTCUT ICON' HREF="../img/ruby-sm.png" />
|
|
272
|
+
<style>
|
|
273
|
+
td { font-family: sans-serif; padding: 0px 10px; }
|
|
274
|
+
</style>
|
|
275
|
+
</head>
|
|
276
|
+
<body>
|
|
277
|
+
<div class="container">
|
|
278
|
+
<h1>Changelog</h1>
|
|
279
|
+
<table style="width: 100%;">
|
|
280
|
+
<xsl:apply-templates />
|
|
281
|
+
</table>
|
|
282
|
+
</div>
|
|
283
|
+
</body>
|
|
284
|
+
</html>
|
|
285
|
+
</xsl:template>
|
|
286
|
+
|
|
287
|
+
<xsl:template match="logentry">
|
|
288
|
+
<tr>
|
|
289
|
+
<td><b><pre><xsl:value-of select="msg"/></pre></b></td>
|
|
290
|
+
<td><xsl:value-of select="author"/></td>
|
|
291
|
+
<td><xsl:value-of select="date"/></td>
|
|
292
|
+
</tr>
|
|
293
|
+
</xsl:template>
|
|
294
|
+
|
|
295
|
+
</xsl:stylesheet>
|
|
296
|
+
END
|
|
297
|
+
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
=begin
|
|
305
|
+
#
|
|
306
|
+
|
|
307
|
+
def svn_repository_configuration(options, *entries)
|
|
308
|
+
entries << 'svn'
|
|
309
|
+
options = configure_options(options, *entries)
|
|
310
|
+
|
|
311
|
+
options['repository'] ||= metadata.repository
|
|
312
|
+
options['protocol'] ||= 'svn+ssh'
|
|
313
|
+
options['message'] ||= options.delete('m')
|
|
314
|
+
options['tagpath'] ||= 'tags'
|
|
315
|
+
|
|
316
|
+
unless repository
|
|
317
|
+
rubyforge = configuration['rubyforge'] || {}
|
|
318
|
+
projectname = rubyforge['project'] || metadata.name
|
|
319
|
+
options['repository'] = "rubyforge.org/var/svn/#{projectname}"
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
if i = options['repository'].index('//')
|
|
323
|
+
options['repository'] = options['repository'][i+2..-1]
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
if /rubyforge.org/i =~ options['repository']
|
|
327
|
+
options['username'] ||= ENV['RUBYFORGE_USERNAME']
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
return options
|
|
331
|
+
end
|
|
332
|
+
=end
|
|
333
|
+
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# = TITLE:
|
|
2
|
+
#
|
|
3
|
+
# File Utitlies
|
|
4
|
+
#
|
|
5
|
+
# = COPYING:
|
|
6
|
+
#
|
|
7
|
+
# Copyright (c) 2007,2008 Tiger Ops
|
|
8
|
+
#
|
|
9
|
+
# This file is part of the Reap program.
|
|
10
|
+
#
|
|
11
|
+
# Reap is free software: you can redistribute it and/or modify
|
|
12
|
+
# it under the terms of the GNU General Public License as published by
|
|
13
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
14
|
+
# (at your option) any later version.
|
|
15
|
+
#
|
|
16
|
+
# Reap is distributed in the hope that it will be useful,
|
|
17
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
18
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
19
|
+
# GNU General Public License for more details.
|
|
20
|
+
#
|
|
21
|
+
# You should have received a copy of the GNU General Public License
|
|
22
|
+
# along with Reap. If not, see <http://www.gnu.org/licenses/>.
|
|
23
|
+
#
|
|
24
|
+
# TODO:
|
|
25
|
+
#
|
|
26
|
+
# - Move out_of_data? and safe? to Facets FileTest extensions.
|
|
27
|
+
|
|
28
|
+
require 'fileutils'
|
|
29
|
+
require 'facets/ziputils'
|
|
30
|
+
|
|
31
|
+
require 'reap/extensions'
|
|
32
|
+
|
|
33
|
+
#
|
|
34
|
+
module Reap
|
|
35
|
+
module Utilities
|
|
36
|
+
|
|
37
|
+
module FileUtils
|
|
38
|
+
|
|
39
|
+
# Delegate access to FileUtils.
|
|
40
|
+
|
|
41
|
+
def fileutils
|
|
42
|
+
dryrun? ? ::FileUtils::DryRun : ::FileUtils
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Add FileUtils Features
|
|
46
|
+
|
|
47
|
+
::FileUtils.private_instance_methods(false).each do |meth|
|
|
48
|
+
next if meth =~ /^fu_/
|
|
49
|
+
module_eval %{
|
|
50
|
+
def #{meth}(*a,&b)
|
|
51
|
+
fileutils.#{meth}(*a,&b)
|
|
52
|
+
end
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Add FileTest Features
|
|
57
|
+
|
|
58
|
+
::FileTest.private_instance_methods(false).each do |meth|
|
|
59
|
+
next if meth =~ /^fu_/
|
|
60
|
+
module_eval %{
|
|
61
|
+
def #{meth}(*a,&b)
|
|
62
|
+
FileTest.#{meth}(*a,&b)
|
|
63
|
+
end
|
|
64
|
+
}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Specific.
|
|
68
|
+
|
|
69
|
+
def rm_r(*a)
|
|
70
|
+
if dryrun?
|
|
71
|
+
puts "rm_r #{a.join(' ')}"
|
|
72
|
+
else
|
|
73
|
+
fileutils.rm_r(*a)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Bonus FileUtils features.
|
|
78
|
+
|
|
79
|
+
def cd(*a,&b)
|
|
80
|
+
puts "cd #{a}" if dryrun? or trace?
|
|
81
|
+
fileutils.chdir(*a,&b)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Read file.
|
|
85
|
+
|
|
86
|
+
def file_read(path)
|
|
87
|
+
File.read(path)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Write file.
|
|
91
|
+
|
|
92
|
+
def file_write(path, text)
|
|
93
|
+
if dryrun?
|
|
94
|
+
puts "write #{path}"
|
|
95
|
+
else
|
|
96
|
+
File.open(path, 'w'){ |f| f << text }
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Assert that a path exists.
|
|
101
|
+
|
|
102
|
+
def exists?(path)
|
|
103
|
+
paths = Dir.glob(path)
|
|
104
|
+
paths.not_empty?
|
|
105
|
+
end
|
|
106
|
+
alias_method :exist?, :exists? ; module_function :exist?
|
|
107
|
+
alias_method :path?, :exists? ; module_function :path?
|
|
108
|
+
|
|
109
|
+
# Assert that a path exists.
|
|
110
|
+
|
|
111
|
+
def exists!(*paths)
|
|
112
|
+
abort "path not found #{path}" unless paths.any?{|path| exists?(path)}
|
|
113
|
+
end
|
|
114
|
+
alias_method :exist!, :exists! ; module_function :exist!
|
|
115
|
+
alias_method :path!, :exists! ; module_function :path!
|
|
116
|
+
|
|
117
|
+
# Is a given path a regular file? If +path+ is a glob
|
|
118
|
+
# then checks to see if all matches are refular files.
|
|
119
|
+
|
|
120
|
+
def file?(path)
|
|
121
|
+
paths = Dir.glob(path)
|
|
122
|
+
paths.not_empty? && paths.all?{ |f| FileTest.file?(f) }
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Assert that a given path is a file.
|
|
126
|
+
|
|
127
|
+
def file!(*paths)
|
|
128
|
+
abort "file not found #{path}" unless paths.any?{|path| file?(path)}
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Is a given path a directory? If +path+ is a glob
|
|
132
|
+
# checks to see if all matches are directories.
|
|
133
|
+
|
|
134
|
+
def dir?(path)
|
|
135
|
+
paths = Dir.glob(path)
|
|
136
|
+
paths.not_empty? && paths.all?{ |f| FileTest.directory?(f) }
|
|
137
|
+
end
|
|
138
|
+
alias_method :directory?, :dir? ; module_function :directory?
|
|
139
|
+
|
|
140
|
+
# Assert that a given path is a directory.
|
|
141
|
+
|
|
142
|
+
def dir!(*paths)
|
|
143
|
+
paths.each do |path|
|
|
144
|
+
abort "Directory not found: '#{path}'." unless dir?(path)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
alias_method :directory!, :dir! ; module_function :directory!
|
|
148
|
+
|
|
149
|
+
# # Okay, I'm being a dork, but 'fold' seems like a better word
|
|
150
|
+
# # then 'dir', 'folder', or 'directory'.
|
|
151
|
+
#
|
|
152
|
+
# def fold?(path)
|
|
153
|
+
# paths = Dir.glob(path)
|
|
154
|
+
# paths.not_empty? && paths.all?{ |f| FileTest.directory?(f) }
|
|
155
|
+
# end
|
|
156
|
+
#
|
|
157
|
+
# # Assert that a given path is a fold (ie. a folder).
|
|
158
|
+
#
|
|
159
|
+
# def fold!(*paths)
|
|
160
|
+
# abort "fold not found #{path}" unless paths.any?{|path| fold?(path)}
|
|
161
|
+
# end
|
|
162
|
+
|
|
163
|
+
# Return a cached list of the PATH environment variable.
|
|
164
|
+
# This is a support method used by #bin?
|
|
165
|
+
|
|
166
|
+
def command_paths
|
|
167
|
+
@command_paths ||= ENV['PATH'].split(/[:;]/)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Is a file a command executable?
|
|
171
|
+
#
|
|
172
|
+
# TODO: Make more robust. Probably needs to be fixed for Windows.
|
|
173
|
+
|
|
174
|
+
def bin?(fname)
|
|
175
|
+
#@command_paths ||= ENV['PATH'].split(/[:;]/)
|
|
176
|
+
is_bin = command_paths.any? do |f|
|
|
177
|
+
FileTest.exist?(File.join(f, fname))
|
|
178
|
+
end
|
|
179
|
+
#is_bin ? File.basename(fname) : false
|
|
180
|
+
is_bin ? fname : false
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Is a path considered reasonably "safe"?
|
|
184
|
+
#
|
|
185
|
+
# TODO: Make more robust.
|
|
186
|
+
|
|
187
|
+
def safe?(path)
|
|
188
|
+
case path
|
|
189
|
+
when *[ '/', '/*', '/**/*' ]
|
|
190
|
+
return false
|
|
191
|
+
end
|
|
192
|
+
true
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Does a path need updating, based on given +sources+?
|
|
196
|
+
# This compares mtimes of give paths. Returns false
|
|
197
|
+
# if the path needs to be updated.
|
|
198
|
+
|
|
199
|
+
def out_of_date?(path, *sources)
|
|
200
|
+
return true unless File.exist?(path)
|
|
201
|
+
|
|
202
|
+
sources = sources.collect{ |source| Dir.glob(source) }.flatten
|
|
203
|
+
mtimes = sources.collect{ |file| File.mtime(file) }
|
|
204
|
+
|
|
205
|
+
return true if mtimes.empty? # TODO: This the way to go here?
|
|
206
|
+
|
|
207
|
+
File.mtime(path) < mtimes.max
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Glob files.
|
|
211
|
+
|
|
212
|
+
def glob(*args, &blk)
|
|
213
|
+
Dir.glob(*args, &blk)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def multiglob(*args, &blk)
|
|
217
|
+
Dir.multiglob(*args, &blk)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def multiglob_r(*args, &blk)
|
|
221
|
+
Dir.multiglob_r(*args, &blk)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Stage package by hard linking included files to a stage directory.
|
|
225
|
+
# Stage files in a directory.
|
|
226
|
+
#
|
|
227
|
+
# stage_directory Stage directory.
|
|
228
|
+
# files Files to link to stage.
|
|
229
|
+
|
|
230
|
+
def stage(stage_directory, files)
|
|
231
|
+
return stage_directory if dryrun? # Don't link to stage if dryrun.
|
|
232
|
+
|
|
233
|
+
if File.directory?(stage_directory) # Ensure existance of staging area.
|
|
234
|
+
#raise(???Error, stage_directory) unless force?
|
|
235
|
+
rm_r(stage_directory)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
mkdir_p(stage_directory) #dir = File.expand_path(stage)
|
|
239
|
+
|
|
240
|
+
#files = package.filelist #+ [package.manifest_file]
|
|
241
|
+
|
|
242
|
+
# TODO Dryrun test here or before folder creation?
|
|
243
|
+
files.each do |f| # Link files into staging area.
|
|
244
|
+
file = File.join(stage_directory, f)
|
|
245
|
+
if File.directory?(f)
|
|
246
|
+
mkdir_p(file)
|
|
247
|
+
else
|
|
248
|
+
unless File.exist?(file) and File.mtime(file) >= File.mtime(f)
|
|
249
|
+
ln(f, file) #safe_ln ?
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
# stage meanifest ?
|
|
255
|
+
|
|
256
|
+
return stage_directory
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# Create manifest for a directory.
|
|
260
|
+
#
|
|
261
|
+
# TODO: Do this programatically rather then via shell.
|
|
262
|
+
|
|
263
|
+
def stage_manifest(directory)
|
|
264
|
+
cd(directory) do
|
|
265
|
+
sh 'manifest up'
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Delegate access to ZipUtils.
|
|
270
|
+
|
|
271
|
+
def ziputils
|
|
272
|
+
dryrun? ? ::ZipUtils::DryRun : ::ZipUtils
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Zip folder into file.
|
|
276
|
+
|
|
277
|
+
def zip(folder, file=nil, options={})
|
|
278
|
+
ziputils.zip(folder, file, options)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# BZip and tarball folder into file.
|
|
282
|
+
|
|
283
|
+
def tar_bzip(folder, file=nil, options={})
|
|
284
|
+
ziputils.tar_bzip(folder, file, options)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# GZip and tarball folder into file. Shortcut for ziputils.tgz.
|
|
288
|
+
|
|
289
|
+
def tgz(folder, file=nil, options={})
|
|
290
|
+
ziputils.tgz(folder, file, options)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# # Is a file a task?
|
|
294
|
+
#
|
|
295
|
+
# def task?(path)
|
|
296
|
+
# task = File.dirname($0) + "/#{path}"
|
|
297
|
+
# task.chomp!('!')
|
|
298
|
+
# task if FileTest.file?(task) && FileTest.executable?(task)
|
|
299
|
+
# end
|
|
300
|
+
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
end
|
|
304
|
+
end
|