jbarnette-johnson 1.0.0.200806240111

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.
Files changed (137) hide show
  1. data/CHANGELOG +5 -0
  2. data/MANIFEST +385 -0
  3. data/MINGW32.mk +124 -0
  4. data/README.rdoc +51 -0
  5. data/Rakefile +166 -0
  6. data/bin/johnson +107 -0
  7. data/cross-compile.txt +38 -0
  8. data/ext/spidermonkey/context.c +122 -0
  9. data/ext/spidermonkey/context.h +19 -0
  10. data/ext/spidermonkey/conversions.c +286 -0
  11. data/ext/spidermonkey/conversions.h +18 -0
  12. data/ext/spidermonkey/debugger.c +208 -0
  13. data/ext/spidermonkey/debugger.h +9 -0
  14. data/ext/spidermonkey/extconf.rb +25 -0
  15. data/ext/spidermonkey/extensions.c +37 -0
  16. data/ext/spidermonkey/extensions.h +12 -0
  17. data/ext/spidermonkey/global.c +40 -0
  18. data/ext/spidermonkey/global.h +11 -0
  19. data/ext/spidermonkey/idhash.c +16 -0
  20. data/ext/spidermonkey/idhash.h +8 -0
  21. data/ext/spidermonkey/immutable_node.c.erb +522 -0
  22. data/ext/spidermonkey/immutable_node.h +22 -0
  23. data/ext/spidermonkey/jroot.h +187 -0
  24. data/ext/spidermonkey/js_land_proxy.c +609 -0
  25. data/ext/spidermonkey/js_land_proxy.h +20 -0
  26. data/ext/spidermonkey/ruby_land_proxy.c +537 -0
  27. data/ext/spidermonkey/ruby_land_proxy.h +17 -0
  28. data/ext/spidermonkey/runtime.c +304 -0
  29. data/ext/spidermonkey/runtime.h +25 -0
  30. data/ext/spidermonkey/spidermonkey.c +20 -0
  31. data/ext/spidermonkey/spidermonkey.h +29 -0
  32. data/js/johnson/browser.js +9 -0
  33. data/js/johnson/browser/env.js +687 -0
  34. data/js/johnson/browser/jquery.js +3444 -0
  35. data/js/johnson/browser/xmlsax.js +1564 -0
  36. data/js/johnson/browser/xmlw3cdom.js +4189 -0
  37. data/js/johnson/cli.js +30 -0
  38. data/js/johnson/prelude.js +80 -0
  39. data/js/johnson/template.js +29 -0
  40. data/lib/hoe.rb +748 -0
  41. data/lib/johnson.rb +46 -0
  42. data/lib/johnson/cli.rb +7 -0
  43. data/lib/johnson/cli/options.rb +56 -0
  44. data/lib/johnson/error.rb +4 -0
  45. data/lib/johnson/nodes.rb +7 -0
  46. data/lib/johnson/nodes/binary_node.rb +64 -0
  47. data/lib/johnson/nodes/for.rb +14 -0
  48. data/lib/johnson/nodes/for_in.rb +12 -0
  49. data/lib/johnson/nodes/function.rb +13 -0
  50. data/lib/johnson/nodes/list.rb +27 -0
  51. data/lib/johnson/nodes/node.rb +68 -0
  52. data/lib/johnson/nodes/ternary_node.rb +20 -0
  53. data/lib/johnson/parser.rb +21 -0
  54. data/lib/johnson/parser/syntax_error.rb +13 -0
  55. data/lib/johnson/runtime.rb +55 -0
  56. data/lib/johnson/spidermonkey/context.rb +10 -0
  57. data/lib/johnson/spidermonkey/debugger.rb +67 -0
  58. data/lib/johnson/spidermonkey/immutable_node.rb +280 -0
  59. data/lib/johnson/spidermonkey/js_land_proxy.rb +62 -0
  60. data/lib/johnson/spidermonkey/mutable_tree_visitor.rb +233 -0
  61. data/lib/johnson/spidermonkey/ruby_land_proxy.rb +52 -0
  62. data/lib/johnson/spidermonkey/runtime.rb +94 -0
  63. data/lib/johnson/version.rb +4 -0
  64. data/lib/johnson/visitable.rb +16 -0
  65. data/lib/johnson/visitors.rb +4 -0
  66. data/lib/johnson/visitors/dot_visitor.rb +167 -0
  67. data/lib/johnson/visitors/ecma_visitor.rb +315 -0
  68. data/lib/johnson/visitors/enumerating_visitor.rb +115 -0
  69. data/lib/johnson/visitors/sexp_visitor.rb +172 -0
  70. data/lib/rails/init.rb +37 -0
  71. data/test/assets/index.html +38 -0
  72. data/test/assets/jquery_test.html +186 -0
  73. data/test/helper.rb +58 -0
  74. data/test/johnson/browser_test.rb +38 -0
  75. data/test/johnson/conversions/array_test.rb +32 -0
  76. data/test/johnson/conversions/boolean_test.rb +17 -0
  77. data/test/johnson/conversions/callable_test.rb +34 -0
  78. data/test/johnson/conversions/file_test.rb +15 -0
  79. data/test/johnson/conversions/nil_test.rb +20 -0
  80. data/test/johnson/conversions/number_test.rb +34 -0
  81. data/test/johnson/conversions/regexp_test.rb +24 -0
  82. data/test/johnson/conversions/string_test.rb +26 -0
  83. data/test/johnson/conversions/struct_test.rb +15 -0
  84. data/test/johnson/conversions/symbol_test.rb +19 -0
  85. data/test/johnson/conversions/thread_test.rb +24 -0
  86. data/test/johnson/error_test.rb +9 -0
  87. data/test/johnson/extensions_test.rb +56 -0
  88. data/test/johnson/nodes/array_literal_test.rb +57 -0
  89. data/test/johnson/nodes/array_node_test.rb +26 -0
  90. data/test/johnson/nodes/binary_node_test.rb +61 -0
  91. data/test/johnson/nodes/bracket_access_test.rb +16 -0
  92. data/test/johnson/nodes/delete_test.rb +11 -0
  93. data/test/johnson/nodes/do_while_test.rb +12 -0
  94. data/test/johnson/nodes/dot_accessor_test.rb +15 -0
  95. data/test/johnson/nodes/export_test.rb +9 -0
  96. data/test/johnson/nodes/for_test.rb +54 -0
  97. data/test/johnson/nodes/function_test.rb +71 -0
  98. data/test/johnson/nodes/if_test.rb +41 -0
  99. data/test/johnson/nodes/import_test.rb +13 -0
  100. data/test/johnson/nodes/label_test.rb +19 -0
  101. data/test/johnson/nodes/object_literal_test.rb +110 -0
  102. data/test/johnson/nodes/return_test.rb +16 -0
  103. data/test/johnson/nodes/semi_test.rb +8 -0
  104. data/test/johnson/nodes/switch_test.rb +55 -0
  105. data/test/johnson/nodes/ternary_test.rb +25 -0
  106. data/test/johnson/nodes/throw_test.rb +9 -0
  107. data/test/johnson/nodes/try_node_test.rb +59 -0
  108. data/test/johnson/nodes/typeof_test.rb +11 -0
  109. data/test/johnson/nodes/unary_node_test.rb +23 -0
  110. data/test/johnson/nodes/void_test.rb +11 -0
  111. data/test/johnson/nodes/while_test.rb +26 -0
  112. data/test/johnson/nodes/with_test.rb +10 -0
  113. data/test/johnson/prelude_test.rb +56 -0
  114. data/test/johnson/runtime_test.rb +46 -0
  115. data/test/johnson/spidermonkey/context_test.rb +21 -0
  116. data/test/johnson/spidermonkey/immutable_node_test.rb +34 -0
  117. data/test/johnson/spidermonkey/js_land_proxy_test.rb +236 -0
  118. data/test/johnson/spidermonkey/ruby_land_proxy_test.rb +225 -0
  119. data/test/johnson/spidermonkey/runtime_test.rb +17 -0
  120. data/test/johnson/version_test.rb +13 -0
  121. data/test/johnson/visitors/dot_visitor_test.rb +39 -0
  122. data/test/johnson/visitors/enumerating_visitor_test.rb +12 -0
  123. data/test/johnson_test.rb +16 -0
  124. data/test/jquery_units/test.js +27 -0
  125. data/test/jquery_units/test_helper.js +197 -0
  126. data/test/jquery_units/units/ajax.js +795 -0
  127. data/test/jquery_units/units/core.js +1563 -0
  128. data/test/jquery_units/units/event.js +299 -0
  129. data/test/jquery_units/units/fx.js +427 -0
  130. data/test/jquery_units/units/offset.js +112 -0
  131. data/test/jquery_units/units/selector.js +224 -0
  132. data/test/jspec/helper.js +7 -0
  133. data/test/jspec/jspec.js +192 -0
  134. data/test/jspec/simple_spec.js +68 -0
  135. data/test/parser_test.rb +276 -0
  136. data/todo/.keep +0 -0
  137. metadata +501 -0
data/js/johnson/cli.js ADDED
@@ -0,0 +1,30 @@
1
+ Ruby.require("uri");
2
+ Ruby.require("open-uri");
3
+
4
+ function load() {
5
+ for (var i = 0; i < arguments.length; ++i)
6
+ Johnson.require(arguments[i]);
7
+ }
8
+
9
+ function print() {
10
+ for (var i = 0; i < arguments.length; ++i)
11
+ Ruby.puts(arguments[i]);
12
+ }
13
+
14
+ // NOTE: the Rhino version takes an optional encoding
15
+ function readFile(path) {
16
+ return Ruby.IO.read(path);
17
+ }
18
+
19
+ // NOTE: the Rhino version takes an optional encoding
20
+ function readUrl(url) {
21
+ return Ruby.URI.parse(url).read();
22
+ }
23
+
24
+ function quit() {
25
+ Ruby.exit();
26
+ }
27
+
28
+ function version() {
29
+ return Ruby.Johnson.VERSION;
30
+ }
@@ -0,0 +1,80 @@
1
+ var Johnson = {};
2
+
3
+ Johnson.Symbol = function(string) {
4
+ this.string = string;
5
+ };
6
+
7
+ Johnson.Symbol.prototype = {
8
+ toString: function() {
9
+ return this.string;
10
+ },
11
+
12
+ inspect: function() {
13
+ return ":" + this.toString();
14
+ }
15
+ };
16
+
17
+ Johnson.symbolCache = {};
18
+
19
+ Johnson.symbolize = function(string) {
20
+ if (!Johnson.symbolCache[string])
21
+ Johnson.symbolCache[string] = new Johnson.Symbol(string);
22
+
23
+ return Johnson.symbolCache[string];
24
+ };
25
+
26
+ Object.defineProperty(String.prototype, "toSymbol", function() {
27
+ return Johnson.symbolize(this.toString());
28
+ }, Object.READ_ONLY | Object.NON_DELETABLE);
29
+
30
+ Johnson.Generator = function(enumerableProxy) {
31
+ this.items = enumerableProxy.toArray();
32
+ this.index = 0;
33
+ };
34
+
35
+ Johnson.Generator.prototype.hasNext = function() {
36
+ var len = this.items.length;
37
+ if (typeof len != 'number') len = this.items.length();
38
+ return this.index < len;
39
+ }
40
+
41
+ Johnson.Generator.prototype.next = function() {
42
+ if (this.hasNext()) {
43
+ return this.items[this.index++];
44
+ }
45
+ throw StopIteration;
46
+ }
47
+
48
+ Johnson.Generator.create = function() {
49
+ return new Johnson.Generator(this);
50
+ }
51
+
52
+ Johnson.required = {};
53
+
54
+ Johnson.require = function(file) {
55
+ file = Ruby.File.join(Ruby.File.dirname(file),
56
+ Ruby.File.basename(file, ".js") + ".js");
57
+
58
+ if(Johnson.required[file]) return false;
59
+
60
+ for(var directory in Ruby["$LOAD_PATH"]) {
61
+ var path = Ruby.File.join(directory, file);
62
+
63
+ if(Ruby.File.send("file?", path)) {
64
+ Johnson.required[file] = true;
65
+ Johnson.runtime.load(path);
66
+
67
+ return true;
68
+ }
69
+ }
70
+
71
+ throw Ruby.LoadError;
72
+ }
73
+
74
+ this.__defineGetter__("__FILE__", function() {
75
+ try { throw new Error; } catch(e) {
76
+ return e.stack.split("\n")[2].split("@")[1].split(":").slice(0,-1).join(":");
77
+ }
78
+ })
79
+
80
+ null; // no need to marshal a result
@@ -0,0 +1,29 @@
1
+ Johnson.templatize = function (template, begin, end) {
2
+ var begin = begin || "<%"
3
+ var end = end || "%>"
4
+ var rebegin = begin.replace(/([\]{}[\\])/g, '\\$1');
5
+ var reend = end.replace(/([\]{}[\\])/g, '\\$1');
6
+
7
+ var code = "_context = _context || {}; with (_context) {" +
8
+ "var _result = '';" +
9
+ template
10
+ .replace(/[\t\r\n]/g, ' ')
11
+ .replace(/^(.*)$/, end + '$1' + begin)
12
+ .replace(new RegExp(reend + "(.*?)" + rebegin, "g"), function (text) {
13
+ return text
14
+ .replace(new RegExp("^" + reend + "(.*)" + rebegin + "$"), "$1")
15
+ .replace(/\\/g, "\\\\")
16
+ .replace(/'/g, "\\'")
17
+ .replace(/^(.*)$/,
18
+ function(sub, m) {
19
+ return end + (m == "" ? "" : "_result += '" + m + "';") + begin;
20
+ });
21
+ })
22
+ .replace(new RegExp(rebegin + "=(.*?)" + reend, "g"), "_result += ($1);")
23
+ .replace(new RegExp(rebegin + "(.*?)" + reend, "g"), ' $1 ')
24
+ .replace(new RegExp("^" + reend + "(.*)" + rebegin + "$"), '$1') +
25
+ "return _result;" +
26
+ "}";
27
+
28
+ return new Function("_context", code);
29
+ };
data/lib/hoe.rb ADDED
@@ -0,0 +1,748 @@
1
+ # -*- ruby -*-
2
+
3
+ # Copyright (c) Ryan Davis, Zen Spider Software
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ require 'rubygems'
25
+ require 'rake'
26
+ require 'rake/gempackagetask'
27
+ require 'rake/rdoctask'
28
+ require 'rake/testtask'
29
+ require 'rbconfig'
30
+ require 'rubyforge'
31
+ require 'yaml'
32
+
33
+ class Hoe #:nodoc:
34
+ VERSION = '1.5.3'
35
+
36
+ ruby_prefix = Config::CONFIG['prefix']
37
+ sitelibdir = Config::CONFIG['sitelibdir']
38
+
39
+ ##
40
+ # Used to specify a custom install location (for rake install).
41
+
42
+ PREFIX = ENV['PREFIX'] || ruby_prefix
43
+
44
+ ##
45
+ # Used to add extra flags to RUBY_FLAGS.
46
+
47
+ RUBY_DEBUG = ENV['RUBY_DEBUG']
48
+
49
+ default_ruby_flags = "-w -I#{%w(lib ext bin test).join(File::PATH_SEPARATOR)}" +
50
+ (RUBY_DEBUG ? " #{RUBY_DEBUG}" : '')
51
+
52
+ ##
53
+ # Used to specify flags to ruby [has smart default].
54
+
55
+ RUBY_FLAGS = ENV['RUBY_FLAGS'] || default_ruby_flags
56
+
57
+ ##
58
+ # Used to add flags to test_unit (e.g., -n test_borked).
59
+
60
+ FILTER = ENV['FILTER'] # for tests (eg FILTER="-n test_blah")
61
+
62
+ # :stopdoc:
63
+
64
+ RUBYLIB = if PREFIX == ruby_prefix then
65
+ sitelibdir
66
+ else
67
+ File.join(PREFIX, sitelibdir[ruby_prefix.size..-1])
68
+ end
69
+
70
+ DLEXT = Config::CONFIG['DLEXT']
71
+
72
+ WINDOZE = /djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM unless defined? WINDOZE
73
+
74
+ DIFF = if WINDOZE
75
+ 'diff.exe'
76
+ else
77
+ if system("gdiff", __FILE__, __FILE__)
78
+ 'gdiff' # solaris and kin suck
79
+ else
80
+ 'diff'
81
+ end
82
+ end unless defined? DIFF
83
+
84
+ # :startdoc:
85
+
86
+ ##
87
+ # *Recommended*: The author(s) of the package. (can be array)
88
+ # Really. Set this or we'll tease you.
89
+
90
+ attr_accessor :author
91
+
92
+ ##
93
+ # Populated automatically from the manifest. List of executables.
94
+
95
+ attr_accessor :bin_files # :nodoc:
96
+
97
+ ##
98
+ # Optional: A description of the release's latest changes. Auto-populates.
99
+
100
+ attr_accessor :changes
101
+
102
+ ##
103
+ # Optional: An array of file patterns to delete on clean.
104
+
105
+ attr_accessor :clean_globs
106
+
107
+ ##
108
+ # Optional: A description of the project. Auto-populates.
109
+
110
+ attr_accessor :description
111
+
112
+ ##
113
+ # Optional: What sections from the readme to use for auto-description. Defaults to %w(description).
114
+
115
+ attr_accessor :description_sections
116
+
117
+ ##
118
+ # *Recommended*: The author's email address(es). (can be array)
119
+
120
+ attr_accessor :email
121
+
122
+ ##
123
+ # Optional: An array of rubygem dependencies.
124
+
125
+ attr_accessor :extra_deps
126
+
127
+ ##
128
+ # Populated automatically from the manifest. List of library files.
129
+
130
+ attr_accessor :lib_files # :nodoc:
131
+
132
+ ##
133
+ # Optional: Array of incompatible versions for multiruby filtering. Used as a regex.
134
+
135
+ attr_accessor :multiruby_skip
136
+
137
+ ##
138
+ # *MANDATORY*: The name of the release.
139
+
140
+ attr_accessor :name
141
+
142
+ ##
143
+ # Optional: Should package create a tarball? [default: true]
144
+
145
+ attr_accessor :need_tar
146
+
147
+ ##
148
+ # Optional: Should package create a zipfile? [default: false]
149
+
150
+ attr_accessor :need_zip
151
+
152
+ ##
153
+ # Optional: A post-install message to be displayed when gem is installed.
154
+
155
+ attr_accessor :post_install_message
156
+
157
+ ##
158
+ # Optional: A regexp to match documentation files against the manifest.
159
+
160
+ attr_accessor :rdoc_pattern
161
+
162
+ ##
163
+ # Optional: Name of RDoc destination directory on Rubyforge. [default: +name+]
164
+
165
+ attr_accessor :remote_rdoc_dir
166
+
167
+ ##
168
+ # Optional: Flags for RDoc rsync. [default: "-av --delete"]
169
+
170
+ attr_accessor :rsync_args
171
+
172
+ ##
173
+ # Optional: The name of the rubyforge project. [default: name.downcase]
174
+
175
+ attr_accessor :rubyforge_name
176
+
177
+ ##
178
+ # The Gem::Specification.
179
+
180
+ attr_accessor :spec # :nodoc:
181
+
182
+ ##
183
+ # Optional: A hash of extra values to set in the gemspec. Value may be a proc.
184
+
185
+ attr_accessor :spec_extras
186
+
187
+ ##
188
+ # Optional: A short summary of the project. Auto-populates.
189
+
190
+ attr_accessor :summary
191
+
192
+ ##
193
+ # Optional: Number of sentences from description for summary. Defaults to 1.
194
+
195
+ attr_accessor :summary_sentences
196
+
197
+ ##
198
+ # Populated automatically from the manifest. List of tests.
199
+
200
+ attr_accessor :test_files # :nodoc:
201
+
202
+ ##
203
+ # Optional: An array of test file patterns [default: test/**/test_*.rb]
204
+
205
+ attr_accessor :test_globs
206
+
207
+ ##
208
+ # Optional: The url(s) of the project. (can be array). Auto-populates.
209
+
210
+ attr_accessor :url
211
+
212
+ ##
213
+ # *MANDATORY*: The version. Don't hardcode! use a constant in the project.
214
+
215
+ attr_accessor :version
216
+
217
+ def initialize(name, version) # :nodoc:
218
+ self.name = name
219
+ self.version = version
220
+
221
+ # Defaults
222
+ self.author = []
223
+ self.clean_globs = %w(diff diff.txt email.txt ri
224
+ *.gem *~ **/*~ *.rbc **/*.rbc)
225
+ self.description_sections = %w(description)
226
+ self.email = []
227
+ self.extra_deps = []
228
+ self.multiruby_skip = []
229
+ self.need_tar = true
230
+ self.need_zip = false
231
+ self.rdoc_pattern = /^(lib|bin|ext)|(rdoc|txt)$/
232
+ self.remote_rdoc_dir = name
233
+ self.rsync_args = '-av --delete'
234
+ self.rubyforge_name = name.downcase
235
+ self.spec_extras = {}
236
+ self.summary_sentences = 1
237
+ self.test_globs = ['test/**/test_*.rb']
238
+ self.post_install_message = nil
239
+
240
+ yield self if block_given?
241
+
242
+ # Intuit values:
243
+
244
+ def missing name
245
+ warn "** #{name} is missing or in the wrong format for auto-intuiting."
246
+ warn " run `sow blah` and look at its text files"
247
+ end
248
+
249
+ readme = File.read("README.rdoc").split(/^(=+ .*)$/)[1..-1] rescue ''
250
+ unless readme.empty? then
251
+ sections = readme.map { |s|
252
+ s =~ /^=/ ? s.strip.downcase.chomp(':').split.last : s.strip
253
+ }
254
+ sections = Hash[*sections]
255
+ desc = sections.values_at(*description_sections).join("\n\n")
256
+ summ = desc.split(/\.\s+/).first(summary_sentences).join(". ")
257
+
258
+ self.description ||= desc
259
+ self.summary ||= summ
260
+ self.url ||= readme[1].gsub(/^\* /, '').split(/\n/).grep(/\S+/)
261
+ else
262
+ missing 'README.rdoc'
263
+ end
264
+
265
+ self.changes ||= begin
266
+ h = File.read("CHANGELOG")
267
+ h.split(/^(===.*)/)[1..2].join.strip
268
+ rescue
269
+ missing 'CHANGELOG'
270
+ ''
271
+ end
272
+
273
+ %w(email author).each do |field|
274
+ value = self.send(field)
275
+ if value.nil? or value.empty? then
276
+ if Time.now < Time.local(2008, 4, 1) then
277
+ warn "Hoe #{field} value not set - Fix by 2008-04-01!"
278
+ self.send "#{field}=", "doofus"
279
+ else
280
+ abort "Hoe #{field} value not set. aborting"
281
+ end
282
+ end
283
+ end
284
+
285
+ self.extra_deps = Array(extra_deps).map { |o| String === o ? [o] : o }
286
+
287
+ define_tasks
288
+ end
289
+
290
+ def developer name, email
291
+ self.author << name
292
+ self.email << email
293
+ end
294
+
295
+ def define_tasks # :nodoc:
296
+ def with_config # :nodoc:
297
+ rc = File.expand_path("~/.hoerc")
298
+ exists = File.exist? rc
299
+ config = exists ? YAML.load_file(rc) : {}
300
+ yield(config, rc)
301
+ end
302
+
303
+ desc 'Run the default tasks.'
304
+ task :default => :test
305
+
306
+ desc 'Run the test suite. Use FILTER to add to the command line.'
307
+ task :test do
308
+ run_tests
309
+ end
310
+
311
+ desc 'Show which test files fail when run alone.'
312
+ task :test_deps do
313
+ tests = Dir["test/**/test_*.rb"] + Dir["test/**/*_test.rb"]
314
+
315
+ tests.each do |test|
316
+ if not system "ruby -Ibin:lib:test #{test} &> /dev/null" then
317
+ puts "Dependency Issues: #{test}"
318
+ end
319
+ end
320
+ end
321
+
322
+ desc 'Run the test suite using multiruby.'
323
+ task :multi do
324
+ run_tests :multi
325
+ end
326
+
327
+ ############################################################
328
+ # Packaging and Installing
329
+
330
+ signing_key = nil
331
+ cert_chain = []
332
+
333
+ with_config do |config, path|
334
+ break unless config['signing_key_file'] and config['signing_cert_file']
335
+ key_file = File.expand_path config['signing_key_file'].to_s
336
+ signing_key = key_file if File.exist? key_file
337
+
338
+ cert_file = File.expand_path config['signing_cert_file'].to_s
339
+ cert_chain << cert_file if File.exist? cert_file
340
+ end
341
+
342
+ self.spec = Gem::Specification.new do |s|
343
+ s.name = name
344
+ s.version = version
345
+ s.summary = summary
346
+ case author
347
+ when Array
348
+ s.authors = author
349
+ else
350
+ s.author = author
351
+ end
352
+ s.email = email
353
+ s.homepage = Array(url).first
354
+ s.rubyforge_project = rubyforge_name
355
+
356
+ s.description = description
357
+
358
+ extra_deps.each do |dep|
359
+ s.add_dependency(*dep)
360
+ end
361
+
362
+ s.files = File.read("MANIFEST").delete("\r").split(/\n/)
363
+ s.executables = s.files.grep(/^bin/) { |f| File.basename(f) }
364
+
365
+ s.bindir = "bin"
366
+ dirs = Dir['{lib,ext}']
367
+ s.require_paths = dirs unless dirs.empty?
368
+
369
+ s.rdoc_options = ['--main', 'README.rdoc']
370
+ s.extra_rdoc_files = s.files.grep(/(txt|rdoc)$/)
371
+ s.has_rdoc = true
372
+
373
+ s.post_install_message = post_install_message
374
+
375
+ if test ?f, "test/test_all.rb" then
376
+ s.test_file = "test/test_all.rb"
377
+ else
378
+ s.test_files = Dir[*test_globs]
379
+ end
380
+
381
+ if signing_key and cert_chain then
382
+ s.signing_key = signing_key
383
+ s.cert_chain = cert_chain
384
+ end
385
+
386
+ ############################################################
387
+ # Allow automatic inclusion of compiled extensions
388
+ if ENV['INLINE'] then
389
+ s.platform = ENV['FORCE_PLATFORM'] || Gem::Platform::CURRENT
390
+ # name of the extension is CamelCase
391
+ alternate_name = if name =~ /[A-Z]/ then
392
+ name.gsub(/([A-Z])/, '_\1').downcase.sub(/^_/, '')
393
+ elsif name =~ /_/ then
394
+ name.capitalize.gsub(/_([a-z])/) { $1.upcase }
395
+ end
396
+
397
+ # Try collecting Inline extensions for +name+
398
+ if defined?(Inline) then
399
+ directory 'lib/inline'
400
+
401
+ extensions = Dir.chdir(Inline::directory) {
402
+ Dir["Inline_{#{name},#{alternate_name}}_*.#{DLEXT}"]
403
+ }
404
+ extensions.each do |ext|
405
+ # add the inlined extension to the spec files
406
+ s.files += ["lib/inline/#{ext}"]
407
+
408
+ # include the file in the tasks
409
+ file "lib/inline/#{ext}" => ["lib/inline"] do
410
+ cp File.join(Inline::directory, ext), "lib/inline"
411
+ end
412
+ end
413
+ end
414
+ end
415
+
416
+ # Do any extra stuff the user wants
417
+ spec_extras.each do |msg, val|
418
+ case val
419
+ when Proc
420
+ val.call(s.send(msg))
421
+ else
422
+ s.send "#{msg}=", val
423
+ end
424
+ end
425
+ end
426
+
427
+ desc 'Show information about the gem.'
428
+ task :debug_gem do
429
+ puts spec.to_ruby
430
+ end
431
+
432
+ desc "Generate #{name}.gemspec"
433
+ task :gemspec do
434
+ File.open("#{name}.gemspec", "w") do |f|
435
+ f.write spec.to_ruby
436
+ end
437
+ end
438
+
439
+ self.lib_files = spec.files.grep(/^(lib|ext)/)
440
+ self.bin_files = spec.files.grep(/^bin/)
441
+ self.test_files = spec.files.grep(/^test/)
442
+
443
+ Rake::GemPackageTask.new spec do |pkg|
444
+ pkg.need_tar = @need_tar
445
+ pkg.need_zip = @need_zip
446
+ end
447
+
448
+ desc 'Install the package as a gem.'
449
+ task :install_gem => [:clean, :package] do
450
+ sh "#{'sudo ' unless WINDOZE}gem install --local pkg/*.gem"
451
+ end
452
+
453
+ desc 'Package and upload the release to rubyforge.'
454
+ task :release => [:clean, :package] do |t|
455
+ v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
456
+ abort "Versions don't match #{v} vs #{version}" if v != version
457
+ pkg = "pkg/#{name}-#{version}"
458
+
459
+ if $DEBUG then
460
+ puts "release_id = rf.add_release #{rubyforge_name.inspect}, #{name.inspect}, #{version.inspect}, \"#{pkg}.tgz\""
461
+ puts "rf.add_file #{rubyforge_name.inspect}, #{name.inspect}, release_id, \"#{pkg}.gem\""
462
+ end
463
+
464
+ rf = RubyForge.new.configure
465
+ puts "Logging in"
466
+ rf.login
467
+
468
+ c = rf.userconfig
469
+ c["release_notes"] = description if description
470
+ c["release_changes"] = changes if changes
471
+ c["preformatted"] = true
472
+
473
+ files = [(@need_tar ? "#{pkg}.tgz" : nil),
474
+ (@need_zip ? "#{pkg}.zip" : nil),
475
+ "#{pkg}.gem"].compact
476
+
477
+ puts "Releasing #{name} v. #{version}"
478
+ rf.add_release rubyforge_name, name, version, *files
479
+ end
480
+
481
+ ############################################################
482
+ # Doco
483
+
484
+ Rake::RDocTask.new(:docs) do |rd|
485
+ rd.main = "README.rdoc"
486
+ rd.options << '-d' if RUBY_PLATFORM !~ /win32/ and `which dot` =~ /\/dot/ and not ENV['NODOT']
487
+ rd.rdoc_dir = 'doc'
488
+ files = spec.files.grep(rdoc_pattern)
489
+ files -= ['MANIFEST', 'lib/hoe.rb']
490
+ rd.rdoc_files.push(*files)
491
+
492
+ title = "#{name}-#{version} Documentation"
493
+ title = "#{rubyforge_name}'s " + title if rubyforge_name != name
494
+
495
+ rd.options << "-t #{title}"
496
+ end
497
+
498
+ desc 'Generate ri locally for testing.'
499
+ task :ridocs => :clean do
500
+ sh %q{ rdoc --ri -o ri . }
501
+ end
502
+
503
+ desc 'Publish RDoc to RubyForge.'
504
+ task :publish_docs => [:clean, :docs] do
505
+ config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
506
+ host = "#{config["username"]}@rubyforge.org"
507
+
508
+ remote_dir = "/var/www/gforge-projects/#{rubyforge_name}/#{remote_rdoc_dir}"
509
+ local_dir = 'doc'
510
+
511
+ sh %{rsync #{rsync_args} #{local_dir}/ #{host}:#{remote_dir}}
512
+ end
513
+
514
+ # no doco for this one
515
+ task :publish_on_announce do
516
+ with_config do |config, _|
517
+ Rake::Task['publish_docs'].invoke if config["publish_on_announce"]
518
+ end
519
+ end
520
+
521
+ ############################################################
522
+ # Misc/Maintenance:
523
+
524
+ desc 'Run ZenTest against the package.'
525
+ task :audit do
526
+ libs = %w(lib test ext).join(File::PATH_SEPARATOR)
527
+ sh "zentest -I=#{libs} #{spec.files.grep(/^(lib|test)/).join(' ')}"
528
+ end
529
+
530
+ desc 'Clean up all the extras.'
531
+ task :clean => [ :clobber_docs, :clobber_package ] do
532
+ clean_globs.each do |pattern|
533
+ files = Dir[pattern]
534
+ rm_rf files, :verbose => true unless files.empty?
535
+ end
536
+ end
537
+
538
+ desc 'Create a fresh ~/.hoerc file.'
539
+ task :config_hoe do
540
+ with_config do |config, path|
541
+ default_config = {
542
+ "exclude" => /tmp$|CVS|\.svn/,
543
+ "publish_on_announce" => false,
544
+ "signing_key_file" => "~/.gem/gem-private_key.pem",
545
+ "signing_cert_file" => "~/.gem/gem-public_cert.pem",
546
+ "blogs" => [ {
547
+ "user" => "user",
548
+ "url" => "url",
549
+ "extra_headers" => {
550
+ "mt_convert_breaks" => "markdown"
551
+ },
552
+ "blog_id" => "blog_id",
553
+ "password"=>"password",
554
+ } ],
555
+ }
556
+ File.open(path, "w") do |f|
557
+ YAML.dump(default_config.merge(config), f)
558
+ end
559
+
560
+ editor = ENV['EDITOR'] || 'vi'
561
+ system "#{editor} #{path}" if ENV['SHOW_EDITOR'] != 'no'
562
+ end
563
+ end
564
+
565
+ desc 'Generate email announcement file.'
566
+ task :email do
567
+ require 'rubyforge'
568
+ subject, title, body, urls = announcement
569
+
570
+ File.open("email.txt", "w") do |mail|
571
+ mail.puts "Subject: [ANN] #{subject}"
572
+ mail.puts
573
+ mail.puts title
574
+ mail.puts
575
+ mail.puts urls
576
+ mail.puts
577
+ mail.puts body
578
+ mail.puts
579
+ mail.puts urls
580
+ end
581
+ puts "Created email.txt"
582
+ end
583
+
584
+ desc 'Post announcement to blog.'
585
+ task :post_blog do
586
+ require 'xmlrpc/client'
587
+
588
+ with_config do |config, path|
589
+ break unless config['blogs']
590
+
591
+ subject, title, body, urls = announcement
592
+ body += "\n\n#{urls}"
593
+
594
+ config['blogs'].each do |site|
595
+ server = XMLRPC::Client.new2(site['url'])
596
+ content = site['extra_headers'].merge(:title => title,
597
+ :description => body)
598
+ result = server.call('metaWeblog.newPost',
599
+ site['blog_id'],
600
+ site['user'],
601
+ site['password'],
602
+ content,
603
+ true)
604
+ end
605
+ end
606
+ end
607
+
608
+ desc 'Post announcement to rubyforge.'
609
+ task :post_news do
610
+ require 'rubyforge'
611
+ subject, title, body, urls = announcement
612
+
613
+ rf = RubyForge.new.configure
614
+ rf.login
615
+ rf.post_news(rubyforge_name, subject, "#{title}\n\n#{body}")
616
+ puts "Posted to rubyforge"
617
+ end
618
+
619
+ desc 'Create news email file and post to rubyforge.'
620
+ task :announce => [:email, :post_news, :post_blog, :publish_on_announce ]
621
+
622
+ desc 'Verify the manifest.'
623
+ task :check_manifest => :clean do
624
+ f = "Manifest.tmp"
625
+ require 'find'
626
+ files = []
627
+ with_config do |config, _|
628
+ exclusions = config["exclude"]
629
+ abort "exclude entry missing from .hoerc. Aborting." if exclusions.nil?
630
+ Find.find '.' do |path|
631
+ next unless File.file? path
632
+ next if path =~ exclusions
633
+ files << path[2..-1]
634
+ end
635
+ files = files.sort.join "\n"
636
+ File.open f, 'w' do |fp| fp.puts files end
637
+ system "#{DIFF} -du MANIFEST #{f}"
638
+ rm f
639
+ end
640
+ end
641
+
642
+ desc 'Generate a key for signing your gems.'
643
+ task :generate_key do
644
+ email = spec.email
645
+ abort "No email in your gemspec" if email.nil? or email.empty?
646
+
647
+ key_file = with_config { |config, _| config['signing_key_file'] }
648
+ cert_file = with_config { |config, _| config['signing_cert_file'] }
649
+
650
+ if key_file.nil? or cert_file.nil? then
651
+ ENV['SHOW_EDITOR'] ||= 'no'
652
+ Rake::Task['config_hoe'].invoke
653
+
654
+ key_file = with_config { |config, _| config['signing_key_file'] }
655
+ cert_file = with_config { |config, _| config['signing_cert_file'] }
656
+ end
657
+
658
+ key_file = File.expand_path key_file
659
+ cert_file = File.expand_path cert_file
660
+
661
+ unless File.exist? key_file or File.exist? cert_file then
662
+ sh "gem cert --build #{email}"
663
+ mv "gem-private_key.pem", key_file, :verbose => true
664
+ mv "gem-public_cert.pem", cert_file, :verbose => true
665
+
666
+ puts "Installed key and certificate."
667
+
668
+ rf = RubyForge.new.configure
669
+ rf.login
670
+
671
+ cert_package = "#{rubyforge_name}-certificates"
672
+
673
+ begin
674
+ rf.lookup 'package', cert_package
675
+ rescue
676
+ rf.create_package rubyforge_name, cert_package
677
+ end
678
+
679
+ begin
680
+ rf.lookup('release', cert_package)['certificates']
681
+ rf.add_file rubyforge_name, cert_package, 'certificates', cert_file
682
+ rescue
683
+ rf.add_release rubyforge_name, cert_package, 'certificates', cert_file
684
+ end
685
+
686
+ puts "Uploaded certificate to release \"certificates\" in package #{cert_package}"
687
+ else
688
+ puts "Keys already exist."
689
+ end
690
+ end
691
+
692
+ end # end define
693
+
694
+ def announcement # :nodoc:
695
+ changes = self.changes.rdoc_to_markdown
696
+
697
+ subject = "#{name} #{version} Released"
698
+ title = "#{name} version #{version} has been released!"
699
+ body = "#{description}\n\nChanges:\n\n#{changes}".rdoc_to_markdown
700
+ urls = Array(url).map { |s| "* <#{s.strip.rdoc_to_markdown}>" }.join("\n")
701
+
702
+ return subject, title, body, urls
703
+ end
704
+
705
+ def run_tests(multi=false) # :nodoc:
706
+ msg = multi ? :sh : :ruby
707
+ cmd = if test ?f, 'test/test_all.rb' then
708
+ "#{RUBY_FLAGS} test/test_all.rb #{FILTER}"
709
+ else
710
+ tests = ['test/unit'] + test_globs.map { |g| Dir.glob(g) }.flatten
711
+ tests.map! {|f| %Q(require "#{f}")}
712
+ "#{RUBY_FLAGS} -e '#{tests.join("; ")}' #{FILTER}"
713
+ end
714
+
715
+ excludes = multiruby_skip.join(":")
716
+ ENV['EXCLUDED_VERSIONS'] = excludes
717
+ cmd = "multiruby #{cmd}" if multi
718
+
719
+ send msg, cmd
720
+ end
721
+
722
+ ##
723
+ # Reads a file at +path+ and spits out an array of the +paragraphs+ specified.
724
+ #
725
+ # changes = p.paragraphs_of('CHANGELOG', 0..1).join("\n\n")
726
+ # summary, *description = p.paragraphs_of('README.rdoc', 3, 3..8)
727
+
728
+ def paragraphs_of(path, *paragraphs)
729
+ File.read(path).delete("\r").split(/\n\n+/).values_at(*paragraphs)
730
+ end
731
+ end
732
+
733
+ # :enddoc:
734
+
735
+ class ::Rake::SshDirPublisher # :nodoc:
736
+ attr_reader :host, :remote_dir, :local_dir
737
+ end
738
+
739
+ class String
740
+ def rdoc_to_markdown
741
+ self.gsub(/^mailto:/, '').gsub(/^(=+)/) { "#" * $1.size }
742
+ end
743
+ end
744
+
745
+ if $0 == __FILE__ then
746
+ out = `rake -T | egrep -v "redocs|repackage|clobber|trunk"`
747
+ puts out.gsub(/\#/, '-').gsub(/^rake /, '# * ')
748
+ end