jbarnette-johnson 1.0.0.200806240111

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