reap 6.0.2 → 9.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|