pure 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES.rdoc +7 -0
- data/MANIFEST +44 -20
- data/README.rdoc +553 -16
- data/Rakefile +25 -2
- data/devel/jumpstart.rb +606 -253
- data/install.rb +1 -2
- data/lib/pure.rb +38 -16
- data/lib/pure/bundled_parsers.rb +4 -0
- data/lib/pure/bundled_plugin.rb +49 -0
- data/lib/pure/compiler/ruby_parser.rb +63 -0
- data/lib/pure/delegate.rb +16 -0
- data/lib/pure/driver.rb +33 -0
- data/lib/pure/dsl.rb +2 -0
- data/lib/pure/dsl_definition.rb +11 -0
- data/lib/pure/error.rb +89 -0
- data/lib/pure/extracted_functions.rb +11 -0
- data/lib/pure/extractor.rb +59 -0
- data/lib/pure/names.rb +9 -0
- data/lib/pure/native_worker.rb +27 -0
- data/lib/pure/parser/impl/base_parser.rb +21 -0
- data/lib/pure/parser/impl/internal.rb +31 -0
- data/lib/pure/parser/impl/ripper.rb +96 -0
- data/lib/pure/parser/impl/ruby_parser.rb +77 -0
- data/lib/pure/parser/internal.rb +4 -0
- data/lib/pure/parser/ripper.rb +2 -0
- data/lib/pure/parser/ruby_parser.rb +2 -0
- data/lib/pure/pure.rb +32 -0
- data/lib/pure/pure_module.rb +141 -0
- data/lib/pure/util.rb +15 -0
- data/lib/pure/version.rb +4 -0
- data/spec/compiler_ruby_parser_spec.rb +79 -0
- data/spec/compute_overrides_spec.rb +99 -0
- data/spec/compute_spec.rb +86 -0
- data/spec/compute_thread_spec.rb +29 -0
- data/spec/compute_timed_spec.rb +40 -0
- data/spec/delegate_spec.rb +141 -0
- data/spec/fstat_example.rb +26 -0
- data/spec/parser_sexp_spec.rb +100 -0
- data/spec/parser_spec.rb +18 -31
- data/spec/pure_combine_spec.rb +77 -0
- data/spec/pure_def_spec.rb +186 -0
- data/spec/pure_define_method_spec.rb +24 -0
- data/spec/pure_eval_spec.rb +18 -0
- data/spec/pure_fun_spec.rb +243 -0
- data/spec/pure_nested_spec.rb +35 -0
- data/spec/pure_parser_spec.rb +50 -0
- data/spec/pure_spec.rb +81 -0
- data/spec/pure_spec_base.rb +106 -0
- data/spec/pure_splat_spec.rb +18 -0
- data/spec/pure_two_defs_spec.rb +20 -0
- data/spec/pure_worker_spec.rb +33 -0
- data/spec/readme_spec.rb +36 -32
- data/spec/splat_spec.rb +12 -11
- data/spec/worker_spec.rb +89 -0
- metadata +157 -41
- data/devel/jumpstart/lazy_attribute.rb +0 -38
- data/devel/jumpstart/ruby.rb +0 -44
- data/devel/jumpstart/simple_installer.rb +0 -85
- data/lib/pure/pure_private/creator.rb +0 -27
- data/lib/pure/pure_private/driver.rb +0 -48
- data/lib/pure/pure_private/error.rb +0 -32
- data/lib/pure/pure_private/extractor.rb +0 -79
- data/lib/pure/pure_private/extractor_ripper.rb +0 -95
- data/lib/pure/pure_private/extractor_ruby_parser.rb +0 -47
- data/lib/pure/pure_private/function_database.rb +0 -10
- data/lib/pure/pure_private/singleton_features.rb +0 -67
- data/lib/pure/pure_private/util.rb +0 -23
- data/spec/basic_spec.rb +0 -38
- data/spec/combine_spec.rb +0 -62
- data/spec/common.rb +0 -44
- data/spec/error_spec.rb +0 -146
- data/spec/fun_spec.rb +0 -122
- data/spec/lazy_spec.rb +0 -22
- data/spec/subseqent_spec.rb +0 -42
- data/spec/timed_spec.rb +0 -30
    
        data/Rakefile
    CHANGED
    
    | @@ -1,10 +1,33 @@ | |
| 1 | 
            -
            $LOAD_PATH.unshift "devel"
         | 
| 2 1 |  | 
| 2 | 
            +
            $LOAD_PATH.unshift "devel"
         | 
| 3 3 | 
             
            require "jumpstart"
         | 
| 4 4 |  | 
| 5 5 | 
             
            Jumpstart.new "pure" do |s|
         | 
| 6 6 | 
             
              s.developer("James M. Lawrence", "quixoticsycophant@gmail.com")
         | 
| 7 | 
            -
              s.dependency("comp_tree", ">= 0.7.6")
         | 
| 8 7 | 
             
              s.rubyforge_user = "quix"
         | 
| 9 8 | 
             
              s.rubyforge_name = "purefunctional"
         | 
| 9 | 
            +
              s.dependency("comp_tree", ">= 1.0.0")
         | 
| 10 | 
            +
              s.dependency("ruby_parser", ">= 2.0.4")
         | 
| 11 | 
            +
              s.extra_dev_deps = [
         | 
| 12 | 
            +
                ["ruby2ruby", ">= 1.2.2"],
         | 
| 13 | 
            +
                ["rspec", ">= 1.2.6"],
         | 
| 14 | 
            +
              ]
         | 
| 15 | 
            +
              s.rdoc_files = %w[
         | 
| 16 | 
            +
                lib/pure/pure.rb
         | 
| 17 | 
            +
                lib/pure/pure_module.rb
         | 
| 18 | 
            +
                lib/pure/dsl.rb
         | 
| 19 | 
            +
                lib/pure/dsl_definition.rb
         | 
| 20 | 
            +
              ]
         | 
| 21 | 
            +
            end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            readme = "README.rdoc"
         | 
| 24 | 
            +
            task readme do
         | 
| 25 | 
            +
              re = %r!(The\s+default\s+worker\s+looks\s+like\s+this:).*?(?=^\S)!m
         | 
| 26 | 
            +
              contents = File.read(readme).sub(re) { |sentence|
         | 
| 27 | 
            +
                $1 + "\n" + 
         | 
| 28 | 
            +
                File.read("lib/pure/native_worker.rb").
         | 
| 29 | 
            +
                gsub(%r!^!, "  ").
         | 
| 30 | 
            +
                sub(%r!  \#:nodoc:!, "") + "\n"
         | 
| 31 | 
            +
              }
         | 
| 32 | 
            +
              File.open(readme, "w") { |f| f.print contents }
         | 
| 10 33 | 
             
            end
         | 
    
        data/devel/jumpstart.rb
    CHANGED
    
    | @@ -1,281 +1,544 @@ | |
| 1 | 
            -
            $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
         | 
| 2 | 
            -
            $LOAD_PATH.unshift File.dirname(__FILE__)
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            require 'rubygems'
         | 
| 5 | 
            -
            require 'ostruct'
         | 
| 6 | 
            -
            require 'rbconfig'
         | 
| 7 | 
            -
             | 
| 8 | 
            -
            require 'rake/gempackagetask'
         | 
| 9 | 
            -
            require 'rake/contrib/sshpublisher'
         | 
| 10 | 
            -
            require 'rake/clean'
         | 
| 11 | 
            -
             | 
| 12 | 
            -
            require 'rdoc/rdoc'
         | 
| 13 | 
            -
             | 
| 14 | 
            -
            require 'jumpstart/ruby'
         | 
| 15 | 
            -
            require 'jumpstart/lazy_attribute'
         | 
| 16 | 
            -
            require 'jumpstart/simple_installer'
         | 
| 17 1 |  | 
| 18 2 | 
             
            class Jumpstart
         | 
| 19 | 
            -
               | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
                   | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
                     | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 3 | 
            +
              class SimpleInstaller
         | 
| 4 | 
            +
                def initialize
         | 
| 5 | 
            +
                  require 'fileutils'
         | 
| 6 | 
            +
                  require 'rbconfig'
         | 
| 7 | 
            +
                  require 'find'
         | 
| 8 | 
            +
                  dest_root = Config::CONFIG["sitelibdir"]
         | 
| 9 | 
            +
                  sources = []
         | 
| 10 | 
            +
                  Find.find("./lib") { |source|
         | 
| 11 | 
            +
                    if install_file?(source)
         | 
| 12 | 
            +
                      sources << source
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
                  }
         | 
| 15 | 
            +
                  @spec = sources.inject(Array.new) { |acc, source|
         | 
| 16 | 
            +
                    if source == "./lib"
         | 
| 17 | 
            +
                      acc
         | 
| 18 | 
            +
                    else
         | 
| 19 | 
            +
                      dest = File.join(dest_root, source.sub(%r!\A\./lib!, ""))
         | 
| 20 | 
            +
              
         | 
| 21 | 
            +
                      install = lambda {
         | 
| 22 | 
            +
                        if File.directory?(source)
         | 
| 23 | 
            +
                          unless File.directory?(dest)
         | 
| 24 | 
            +
                            puts "mkdir #{dest}"
         | 
| 25 | 
            +
                            FileUtils.mkdir(dest)
         | 
| 26 | 
            +
                          end
         | 
| 37 27 | 
             
                        else
         | 
| 38 | 
            -
                           | 
| 28 | 
            +
                          puts "install #{source} --> #{dest}"
         | 
| 29 | 
            +
                          FileUtils.install(source, dest)
         | 
| 39 30 | 
             
                        end
         | 
| 40 | 
            -
                       | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 31 | 
            +
                      }
         | 
| 32 | 
            +
                        
         | 
| 33 | 
            +
                      uninstall = lambda {
         | 
| 34 | 
            +
                        if File.directory?(source)
         | 
| 35 | 
            +
                          if File.directory?(dest)
         | 
| 36 | 
            +
                            puts "rmdir #{dest}"
         | 
| 37 | 
            +
                            FileUtils.rmdir(dest)
         | 
| 38 | 
            +
                          end
         | 
| 39 | 
            +
                        else
         | 
| 40 | 
            +
                          if File.file?(dest)
         | 
| 41 | 
            +
                            puts "rm #{dest}"
         | 
| 42 | 
            +
                            FileUtils.rm(dest)
         | 
| 43 | 
            +
                          end
         | 
| 44 | 
            +
                        end
         | 
| 45 | 
            +
                      }
         | 
| 46 | 
            +
              
         | 
| 47 | 
            +
                      acc << {
         | 
| 48 | 
            +
                        :source => source,
         | 
| 49 | 
            +
                        :dest => dest,
         | 
| 50 | 
            +
                        :install => install,
         | 
| 51 | 
            +
                        :uninstall => uninstall,
         | 
| 52 | 
            +
                      }
         | 
| 44 53 | 
             
                    end
         | 
| 45 | 
            -
                   | 
| 46 | 
            -
                    "0.0.0"
         | 
| 47 | 
            -
                  end
         | 
| 54 | 
            +
                  }
         | 
| 48 55 | 
             
                end
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                 | 
| 51 | 
            -
                   | 
| 56 | 
            +
              
         | 
| 57 | 
            +
                def install_file?(source)
         | 
| 58 | 
            +
                  File.directory?(source) or
         | 
| 59 | 
            +
                  (File.file?(source) and File.extname(source) == ".rb")
         | 
| 52 60 | 
             
                end
         | 
| 53 61 |  | 
| 54 | 
            -
                 | 
| 55 | 
            -
                   | 
| 62 | 
            +
                def install
         | 
| 63 | 
            +
                  @spec.each { |entry|
         | 
| 64 | 
            +
                    entry[:install].call
         | 
| 65 | 
            +
                  }
         | 
| 56 66 | 
             
                end
         | 
| 57 | 
            -
             | 
| 58 | 
            -
                 | 
| 59 | 
            -
                   | 
| 67 | 
            +
              
         | 
| 68 | 
            +
                def uninstall
         | 
| 69 | 
            +
                  @spec.reverse.each { |entry|
         | 
| 70 | 
            +
                    entry[:uninstall].call
         | 
| 71 | 
            +
                  }
         | 
| 60 72 | 
             
                end
         | 
| 61 73 |  | 
| 62 | 
            -
                 | 
| 63 | 
            -
                   | 
| 74 | 
            +
                def run(args = ARGV)
         | 
| 75 | 
            +
                  if args.empty?
         | 
| 76 | 
            +
                    install
         | 
| 77 | 
            +
                  elsif args.size == 1 and args.first == "--uninstall"
         | 
| 78 | 
            +
                    uninstall
         | 
| 79 | 
            +
                  else
         | 
| 80 | 
            +
                    raise "unrecognized arguments: #{args.inspect}"
         | 
| 81 | 
            +
                  end
         | 
| 64 82 | 
             
                end
         | 
| 83 | 
            +
              end
         | 
| 65 84 |  | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 85 | 
            +
              module AttrLazy
         | 
| 86 | 
            +
                def attr_lazy(name, &block)
         | 
| 87 | 
            +
                  AttrLazy.define_reader(class << self ; self ; end, name, &block)
         | 
| 68 88 | 
             
                end
         | 
| 69 89 |  | 
| 70 | 
            -
                 | 
| 71 | 
            -
                   | 
| 90 | 
            +
                def attr_lazy_accessor(name, &block)
         | 
| 91 | 
            +
                  attr_lazy(name, &block)
         | 
| 92 | 
            +
                  AttrLazy.define_writer(class << self ; self ; end, name, &block)
         | 
| 72 93 | 
             
                end
         | 
| 73 94 |  | 
| 74 | 
            -
                 | 
| 75 | 
            -
                   | 
| 76 | 
            -
             | 
| 95 | 
            +
                class << self
         | 
| 96 | 
            +
                  def included(mod)
         | 
| 97 | 
            +
                    (class << mod ; self ; end).class_eval do
         | 
| 98 | 
            +
                      def attr_lazy(name, &block)
         | 
| 99 | 
            +
                        AttrLazy.define_reader(self, name, &block)
         | 
| 100 | 
            +
                      end
         | 
| 77 101 |  | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 102 | 
            +
                      def attr_lazy_accessor(name, &block)
         | 
| 103 | 
            +
                        attr_lazy(name, &block)
         | 
| 104 | 
            +
                        AttrLazy.define_writer(self, name, &block)
         | 
| 105 | 
            +
                      end
         | 
| 106 | 
            +
                    end
         | 
| 107 | 
            +
                  end
         | 
| 81 108 |  | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 109 | 
            +
                  def define_evaluated_reader(instance, name, value)
         | 
| 110 | 
            +
                    (class << instance ; self ; end).class_eval do
         | 
| 111 | 
            +
                      remove_method name rescue nil
         | 
| 112 | 
            +
                      define_method name do
         | 
| 113 | 
            +
                        value
         | 
| 114 | 
            +
                      end
         | 
| 115 | 
            +
                    end
         | 
| 116 | 
            +
                  end
         | 
| 85 117 |  | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 118 | 
            +
                  def define_reader(klass, name, &block)
         | 
| 119 | 
            +
                    klass.class_eval do
         | 
| 120 | 
            +
                      remove_method name rescue nil
         | 
| 121 | 
            +
                      define_method name do
         | 
| 122 | 
            +
                        value = instance_eval(&block)
         | 
| 123 | 
            +
                        AttrLazy.define_evaluated_reader(self, name, value)
         | 
| 124 | 
            +
                        value
         | 
| 125 | 
            +
                      end
         | 
| 126 | 
            +
                    end
         | 
| 89 127 | 
             
                  end
         | 
| 90 | 
            -
                }
         | 
| 91 128 |  | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
                       | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 129 | 
            +
                  def define_writer(klass, name, &block)
         | 
| 130 | 
            +
                    klass.class_eval do
         | 
| 131 | 
            +
                      writer = "#{name}="
         | 
| 132 | 
            +
                      remove_method writer rescue nil
         | 
| 133 | 
            +
                      define_method writer do |value|
         | 
| 134 | 
            +
                        AttrLazy.define_evaluated_reader(self, name, value)
         | 
| 135 | 
            +
                        value
         | 
| 136 | 
            +
                      end
         | 
| 99 137 | 
             
                    end
         | 
| 100 | 
            -
                   | 
| 138 | 
            +
                  end
         | 
| 101 139 | 
             
                end
         | 
| 140 | 
            +
              end
         | 
| 102 141 |  | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
                
         | 
| 107 | 
            -
             | 
| 108 | 
            -
                  "MANIFEST"
         | 
| 109 | 
            -
                end
         | 
| 142 | 
            +
              module Ruby
         | 
| 143 | 
            +
                module_function
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                def executable
         | 
| 146 | 
            +
                  require 'rbconfig'
         | 
| 110 147 |  | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
                     | 
| 148 | 
            +
                  name = File.join(
         | 
| 149 | 
            +
                    Config::CONFIG["bindir"],
         | 
| 150 | 
            +
                    Config::CONFIG["RUBY_INSTALL_NAME"]
         | 
| 151 | 
            +
                  )
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                  if Config::CONFIG["host"] =~ %r!(mswin|cygwin|mingw)! and
         | 
| 154 | 
            +
                      File.basename(name) !~ %r!\.(exe|com|bat|cmd)\Z!i
         | 
| 155 | 
            +
                    name + Config::CONFIG["EXEEXT"]
         | 
| 114 156 | 
             
                  else
         | 
| 115 | 
            -
                     | 
| 157 | 
            +
                    name
         | 
| 158 | 
            +
                  end
         | 
| 159 | 
            +
                end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                def run(*args)
         | 
| 162 | 
            +
                  cmd = [executable, *args]
         | 
| 163 | 
            +
                  unless system(*cmd)
         | 
| 164 | 
            +
                    cmd_str = cmd.map { |t| "'#{t}'" }.join(", ")
         | 
| 165 | 
            +
                    raise "system(#{cmd_str}) failed with status #{$?.exitstatus}"
         | 
| 116 166 | 
             
                  end
         | 
| 117 167 | 
             
                end
         | 
| 118 168 |  | 
| 119 | 
            -
                 | 
| 120 | 
            -
                   | 
| 169 | 
            +
                def run_code_and_capture(code)
         | 
| 170 | 
            +
                  IO.popen(%{"#{executable}"}, "r+") { |pipe|
         | 
| 171 | 
            +
                    pipe.print(code)
         | 
| 172 | 
            +
                    pipe.flush
         | 
| 173 | 
            +
                    pipe.close_write
         | 
| 174 | 
            +
                    pipe.read
         | 
| 175 | 
            +
                  }
         | 
| 121 176 | 
             
                end
         | 
| 122 | 
            -
             | 
| 123 | 
            -
                 | 
| 124 | 
            -
                   | 
| 125 | 
            -
                     | 
| 126 | 
            -
                   | 
| 127 | 
            -
             | 
| 177 | 
            +
             | 
| 178 | 
            +
                def run_file_and_capture(file)
         | 
| 179 | 
            +
                  unless File.file? file
         | 
| 180 | 
            +
                    raise "file does not exist: `#{file}'"
         | 
| 181 | 
            +
                  end
         | 
| 182 | 
            +
                  IO.popen(%{"#{executable}" "#{file}"}, "r") { |pipe|
         | 
| 183 | 
            +
                    pipe.read
         | 
| 184 | 
            +
                  }
         | 
| 185 | 
            +
                end
         | 
| 186 | 
            +
                  
         | 
| 187 | 
            +
                def with_warnings(value = true)
         | 
| 188 | 
            +
                  previous = $VERBOSE
         | 
| 189 | 
            +
                  $VERBOSE = value
         | 
| 190 | 
            +
                  begin
         | 
| 191 | 
            +
                    yield
         | 
| 192 | 
            +
                  ensure
         | 
| 193 | 
            +
                    $VERBOSE = previous
         | 
| 128 194 | 
             
                  end
         | 
| 129 195 | 
             
                end
         | 
| 196 | 
            +
                  
         | 
| 197 | 
            +
                def no_warnings(&block)
         | 
| 198 | 
            +
                  with_warnings(nil, &block)
         | 
| 199 | 
            +
                end
         | 
| 200 | 
            +
              end
         | 
| 130 201 |  | 
| 131 | 
            -
             | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
                   "--title", "#{name}: #{summary}",
         | 
| 138 | 
            -
                  ] + (files - rdoc_files).inject(Array.new) { |acc, file|
         | 
| 139 | 
            -
                    acc + ["--exclude", file]
         | 
| 202 | 
            +
              module Util
         | 
| 203 | 
            +
                module_function
         | 
| 204 | 
            +
             | 
| 205 | 
            +
                def run_ruby_on_each(*files)
         | 
| 206 | 
            +
                  files.each { |file|
         | 
| 207 | 
            +
                    Ruby.run("-w", file)
         | 
| 140 208 | 
             
                  }
         | 
| 141 209 | 
             
                end
         | 
| 142 210 |  | 
| 143 | 
            -
                 | 
| 144 | 
            -
                   | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
             | 
| 150 | 
            -
                     | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 157 | 
            -
                   | 
| 158 | 
            -
             | 
| 159 | 
            -
             | 
| 160 | 
            -
             | 
| 161 | 
            -
                  Gem::Specification.new { |g|
         | 
| 162 | 
            -
                    g.has_rdoc = true
         | 
| 163 | 
            -
                    %w[
         | 
| 164 | 
            -
                      name
         | 
| 165 | 
            -
                      authors
         | 
| 166 | 
            -
                      email
         | 
| 167 | 
            -
                      summary
         | 
| 168 | 
            -
                      version
         | 
| 169 | 
            -
                      description
         | 
| 170 | 
            -
                      files
         | 
| 171 | 
            -
                      extra_rdoc_files
         | 
| 172 | 
            -
                      rdoc_options
         | 
| 173 | 
            -
                    ].each { |param|
         | 
| 174 | 
            -
                      value = send(param) and (
         | 
| 175 | 
            -
                        g.send("#{param}=", value)
         | 
| 176 | 
            -
                      )
         | 
| 211 | 
            +
                def to_camel_case(str)
         | 
| 212 | 
            +
                  str.split('_').map { |t| t.capitalize }.join
         | 
| 213 | 
            +
                end
         | 
| 214 | 
            +
             | 
| 215 | 
            +
                def write_file(file)
         | 
| 216 | 
            +
                  contents = yield
         | 
| 217 | 
            +
                  File.open(file, "wb") { |out|
         | 
| 218 | 
            +
                    out.print(contents)
         | 
| 219 | 
            +
                  }
         | 
| 220 | 
            +
                  contents
         | 
| 221 | 
            +
                end
         | 
| 222 | 
            +
             | 
| 223 | 
            +
                def replace_file(file)
         | 
| 224 | 
            +
                  old_contents = File.read(file)
         | 
| 225 | 
            +
                  new_contents = yield(old_contents)
         | 
| 226 | 
            +
                  if old_contents != new_contents
         | 
| 227 | 
            +
                    File.open(file, "wb") { |output|
         | 
| 228 | 
            +
                      output.print(new_contents)
         | 
| 177 229 | 
             
                    }
         | 
| 230 | 
            +
                  end
         | 
| 231 | 
            +
                  new_contents
         | 
| 232 | 
            +
                end
         | 
| 233 | 
            +
              end
         | 
| 178 234 |  | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
                    end
         | 
| 235 | 
            +
              module InstanceEvalWithArgs
         | 
| 236 | 
            +
                module_function
         | 
| 182 237 |  | 
| 183 | 
            -
             | 
| 184 | 
            -
             | 
| 238 | 
            +
                def with_temp_method(instance, method_name, method_block)
         | 
| 239 | 
            +
                  (class << instance ; self ; end).class_eval do
         | 
| 240 | 
            +
                    define_method(method_name, &method_block)
         | 
| 241 | 
            +
                    begin
         | 
| 242 | 
            +
                      yield method_name
         | 
| 243 | 
            +
                    ensure
         | 
| 244 | 
            +
                      remove_method(method_name)
         | 
| 185 245 | 
             
                    end
         | 
| 246 | 
            +
                  end
         | 
| 247 | 
            +
                end
         | 
| 186 248 |  | 
| 187 | 
            -
             | 
| 188 | 
            -
             | 
| 189 | 
            -
                     | 
| 190 | 
            -
             | 
| 191 | 
            -
                    extra_dev_deps.each { |dep|
         | 
| 192 | 
            -
                      g.add_development_dependency(*dep)
         | 
| 193 | 
            -
                    }
         | 
| 249 | 
            +
                def call_temp_method(instance, method_name, *args, &method_block)
         | 
| 250 | 
            +
                  with_temp_method(instance, method_name, method_block) {
         | 
| 251 | 
            +
                    instance.send(method_name, *args)
         | 
| 194 252 | 
             
                  }
         | 
| 195 253 | 
             
                end
         | 
| 196 254 |  | 
| 197 | 
            -
                 | 
| 198 | 
            -
                   | 
| 255 | 
            +
                def instance_eval_with_args(instance, *args, &block)
         | 
| 256 | 
            +
                  call_temp_method(instance, :__temp_method, *args, &block)
         | 
| 199 257 | 
             
                end
         | 
| 200 | 
            -
             | 
| 201 | 
            -
             | 
| 202 | 
            -
             | 
| 203 | 
            -
             | 
| 204 | 
            -
             | 
| 205 | 
            -
             | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 208 | 
            -
             | 
| 209 | 
            -
             | 
| 258 | 
            +
              end
         | 
| 259 | 
            +
             | 
| 260 | 
            +
              include AttrLazy
         | 
| 261 | 
            +
              include Util
         | 
| 262 | 
            +
             | 
| 263 | 
            +
              def initialize(project_name)
         | 
| 264 | 
            +
                $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
         | 
| 265 | 
            +
                $LOAD_PATH.unshift File.dirname(__FILE__)
         | 
| 266 | 
            +
             | 
| 267 | 
            +
                require 'rake/gempackagetask'
         | 
| 268 | 
            +
                require 'rake/clean'
         | 
| 269 | 
            +
             | 
| 270 | 
            +
                @project_name = project_name
         | 
| 271 | 
            +
             | 
| 272 | 
            +
                yield self
         | 
| 273 | 
            +
             | 
| 274 | 
            +
                self.class.instance_methods(false).select { |t|
         | 
| 275 | 
            +
                  t.to_s =~ %r!\Adefine_!
         | 
| 276 | 
            +
                }.each { |method_name|
         | 
| 277 | 
            +
                  send(method_name)
         | 
| 278 | 
            +
                }
         | 
| 279 | 
            +
              end
         | 
| 280 | 
            +
             | 
| 281 | 
            +
              class << self
         | 
| 282 | 
            +
                alias_method :attribute, :attr_lazy_accessor
         | 
| 283 | 
            +
              end
         | 
| 284 | 
            +
             | 
| 285 | 
            +
              attribute :name do
         | 
| 286 | 
            +
                @project_name
         | 
| 287 | 
            +
              end
         | 
| 288 | 
            +
             | 
| 289 | 
            +
              attribute :version_constant_name do
         | 
| 290 | 
            +
                "VERSION"
         | 
| 291 | 
            +
              end
         | 
| 292 | 
            +
             | 
| 293 | 
            +
              attribute :version do
         | 
| 294 | 
            +
                require name
         | 
| 295 | 
            +
                mod_name = to_camel_case(name)
         | 
| 296 | 
            +
                begin
         | 
| 297 | 
            +
                  mod = Kernel.const_get(mod_name)
         | 
| 298 | 
            +
                  if mod.constants.include?(version_constant_name)
         | 
| 299 | 
            +
                    mod.const_get(version_constant_name)
         | 
| 300 | 
            +
                  else
         | 
| 301 | 
            +
                    raise
         | 
| 210 302 | 
             
                  end
         | 
| 303 | 
            +
                rescue
         | 
| 304 | 
            +
                  "0.0.0"
         | 
| 211 305 | 
             
                end
         | 
| 306 | 
            +
              end
         | 
| 307 | 
            +
              
         | 
| 308 | 
            +
              attribute :rubyforge_name do
         | 
| 309 | 
            +
                name.gsub('_', '')
         | 
| 310 | 
            +
              end
         | 
| 311 | 
            +
             | 
| 312 | 
            +
              attribute :rubyforge_user do
         | 
| 313 | 
            +
                email.first[%r!^.*(?=@)!]
         | 
| 314 | 
            +
              end
         | 
| 315 | 
            +
              
         | 
| 316 | 
            +
              attribute :readme_file do
         | 
| 317 | 
            +
                "README.rdoc"
         | 
| 318 | 
            +
              end
         | 
| 319 | 
            +
              
         | 
| 320 | 
            +
              attribute :history_file do
         | 
| 321 | 
            +
                "CHANGES.rdoc"
         | 
| 322 | 
            +
              end
         | 
| 323 | 
            +
              
         | 
| 324 | 
            +
              attribute :doc_dir do
         | 
| 325 | 
            +
                "documentation"
         | 
| 326 | 
            +
              end
         | 
| 327 | 
            +
              
         | 
| 328 | 
            +
              attribute :spec_files do
         | 
| 329 | 
            +
                Dir["./spec/*_{spec,example}.rb"]
         | 
| 330 | 
            +
              end
         | 
| 331 | 
            +
              
         | 
| 332 | 
            +
              attribute :test_files do
         | 
| 333 | 
            +
                (Dir["./test/test_*.rb"] + Dir["./test/*_test.rb"]).uniq
         | 
| 334 | 
            +
              end
         | 
| 335 | 
            +
              
         | 
| 336 | 
            +
              attribute :rcov_dir do
         | 
| 337 | 
            +
                "coverage"
         | 
| 338 | 
            +
              end
         | 
| 339 | 
            +
              
         | 
| 340 | 
            +
              attribute :spec_output_dir do
         | 
| 341 | 
            +
                "rspec_output"
         | 
| 342 | 
            +
              end
         | 
| 343 | 
            +
             | 
| 344 | 
            +
              attribute :spec_output_file do
         | 
| 345 | 
            +
                "spec.html"
         | 
| 346 | 
            +
              end
         | 
| 347 | 
            +
             | 
| 348 | 
            +
              attr_lazy :spec_output do
         | 
| 349 | 
            +
                "#{spec_output_dir}/#{spec_output_file}"
         | 
| 350 | 
            +
              end
         | 
| 212 351 |  | 
| 213 | 
            -
             | 
| 214 | 
            -
             | 
| 352 | 
            +
              [:gem, :tgz].each { |ext|
         | 
| 353 | 
            +
                attribute ext do
         | 
| 354 | 
            +
                  "pkg/#{name}-#{version}.#{ext}"
         | 
| 215 355 | 
             
                end
         | 
| 356 | 
            +
              }
         | 
| 216 357 |  | 
| 217 | 
            -
             | 
| 218 | 
            -
             | 
| 358 | 
            +
              attribute :rcov_options do
         | 
| 359 | 
            +
                # workaround for the default rspec task
         | 
| 360 | 
            +
                Dir["*"].select { |f| File.directory? f }.inject(Array.new) { |acc, dir|
         | 
| 361 | 
            +
                  if dir == "lib"
         | 
| 362 | 
            +
                    acc
         | 
| 363 | 
            +
                  else
         | 
| 364 | 
            +
                    acc + ["--exclude", dir + "/"]
         | 
| 365 | 
            +
                  end
         | 
| 366 | 
            +
                } + ["--text-report"]
         | 
| 367 | 
            +
              end
         | 
| 368 | 
            +
             | 
| 369 | 
            +
              attribute :readme_file do
         | 
| 370 | 
            +
                "README.rdoc"
         | 
| 371 | 
            +
              end
         | 
| 372 | 
            +
                
         | 
| 373 | 
            +
              attribute :manifest_file do
         | 
| 374 | 
            +
                "MANIFEST"
         | 
| 375 | 
            +
              end
         | 
| 376 | 
            +
             | 
| 377 | 
            +
              attribute :generated_files do
         | 
| 378 | 
            +
                []
         | 
| 379 | 
            +
              end
         | 
| 380 | 
            +
             | 
| 381 | 
            +
              attribute :files do
         | 
| 382 | 
            +
                if File.exist?(manifest_file)
         | 
| 383 | 
            +
                  File.read(manifest_file).split("\n")
         | 
| 384 | 
            +
                else
         | 
| 385 | 
            +
                  `git ls-files`.split("\n") + [manifest_file] + generated_files
         | 
| 219 386 | 
             
                end
         | 
| 387 | 
            +
              end
         | 
| 220 388 |  | 
| 221 | 
            -
             | 
| 222 | 
            -
             | 
| 389 | 
            +
              attribute :rdoc_files do
         | 
| 390 | 
            +
                Dir["lib/**/*.rb"]
         | 
| 391 | 
            +
              end
         | 
| 392 | 
            +
                
         | 
| 393 | 
            +
              attribute :extra_rdoc_files do
         | 
| 394 | 
            +
                if File.exist?(readme_file)
         | 
| 395 | 
            +
                  [readme_file]
         | 
| 396 | 
            +
                else
         | 
| 397 | 
            +
                  []
         | 
| 223 398 | 
             
                end
         | 
| 399 | 
            +
              end
         | 
| 224 400 |  | 
| 225 | 
            -
             | 
| 226 | 
            -
             | 
| 401 | 
            +
              attribute :rdoc_options do
         | 
| 402 | 
            +
                if File.exist?(readme_file)
         | 
| 403 | 
            +
                  ["--main", readme_file]
         | 
| 404 | 
            +
                else
         | 
| 405 | 
            +
                  []
         | 
| 406 | 
            +
                end + [
         | 
| 407 | 
            +
                 "--title", "#{name}: #{summary}",
         | 
| 408 | 
            +
                ] + (files - rdoc_files).inject(Array.new) { |acc, file|
         | 
| 409 | 
            +
                  acc + ["--exclude", file]
         | 
| 410 | 
            +
                }
         | 
| 411 | 
            +
              end
         | 
| 412 | 
            +
             | 
| 413 | 
            +
              attribute :browser do
         | 
| 414 | 
            +
                require 'rbconfig'
         | 
| 415 | 
            +
                if Config::CONFIG["host"] =~ %r!darwin!
         | 
| 416 | 
            +
                  app = %w[Firefox Safari].map { |t|
         | 
| 417 | 
            +
                    "/Applications/#{t}.app"
         | 
| 418 | 
            +
                  }.select { |t|
         | 
| 419 | 
            +
                    File.exist? t
         | 
| 420 | 
            +
                  }.first
         | 
| 421 | 
            +
                  if app
         | 
| 422 | 
            +
                    ["open", app]
         | 
| 423 | 
            +
                  else
         | 
| 424 | 
            +
                    raise "need to set `browser'"
         | 
| 425 | 
            +
                  end
         | 
| 426 | 
            +
                else
         | 
| 427 | 
            +
                  "firefox"
         | 
| 227 428 | 
             
                end
         | 
| 228 | 
            -
             | 
| 229 | 
            -
             | 
| 230 | 
            -
             | 
| 231 | 
            -
             | 
| 232 | 
            -
             | 
| 233 | 
            -
             | 
| 234 | 
            -
             | 
| 235 | 
            -
             | 
| 236 | 
            -
             | 
| 237 | 
            -
                     | 
| 238 | 
            -
             | 
| 239 | 
            -
                     | 
| 429 | 
            +
              end
         | 
| 430 | 
            +
             | 
| 431 | 
            +
              attribute :gemspec do
         | 
| 432 | 
            +
                Gem::Specification.new { |g|
         | 
| 433 | 
            +
                  g.has_rdoc = true
         | 
| 434 | 
            +
                  %w[
         | 
| 435 | 
            +
                    name
         | 
| 436 | 
            +
                    authors
         | 
| 437 | 
            +
                    email
         | 
| 438 | 
            +
                    summary
         | 
| 439 | 
            +
                    version
         | 
| 440 | 
            +
                    description
         | 
| 441 | 
            +
                    files
         | 
| 442 | 
            +
                    extra_rdoc_files
         | 
| 443 | 
            +
                    rdoc_options
         | 
| 444 | 
            +
                  ].each { |param|
         | 
| 445 | 
            +
                    value = send(param) and (
         | 
| 446 | 
            +
                      g.send("#{param}=", value)
         | 
| 447 | 
            +
                    )
         | 
| 448 | 
            +
                  }
         | 
| 449 | 
            +
             | 
| 450 | 
            +
                  if rubyforge_name
         | 
| 451 | 
            +
                    g.rubyforge_project = rubyforge_name
         | 
| 452 | 
            +
                  end
         | 
| 453 | 
            +
             | 
| 454 | 
            +
                  if url
         | 
| 455 | 
            +
                    g.homepage = url
         | 
| 240 456 | 
             
                  end
         | 
| 457 | 
            +
             | 
| 458 | 
            +
                  extra_deps.each { |dep|
         | 
| 459 | 
            +
                    g.add_dependency(*dep)
         | 
| 460 | 
            +
                  }
         | 
| 461 | 
            +
             | 
| 462 | 
            +
                  extra_dev_deps.each { |dep|
         | 
| 463 | 
            +
                    g.add_development_dependency(*dep)
         | 
| 464 | 
            +
                  }
         | 
| 241 465 | 
             
                }
         | 
| 466 | 
            +
              end
         | 
| 467 | 
            +
             | 
| 468 | 
            +
              attribute :readme_contents do
         | 
| 469 | 
            +
                File.read(readme_file) rescue "FIXME: readme_file"
         | 
| 470 | 
            +
              end
         | 
| 471 | 
            +
              
         | 
| 472 | 
            +
              attribute :sections do
         | 
| 473 | 
            +
                require 'enumerator'
         | 
| 474 | 
            +
                begin
         | 
| 475 | 
            +
                  data = readme_contents.split(%r!^==\s*(.*?)\s*$!)
         | 
| 476 | 
            +
                  pairs = data[1..-1].enum_slice(2).map { |section, contents|
         | 
| 477 | 
            +
                    [section.downcase, contents.strip]
         | 
| 478 | 
            +
                  }
         | 
| 479 | 
            +
                  Hash[*pairs.flatten]
         | 
| 480 | 
            +
                rescue
         | 
| 481 | 
            +
                  nil
         | 
| 482 | 
            +
                end
         | 
| 483 | 
            +
              end
         | 
| 484 | 
            +
             | 
| 485 | 
            +
              attribute :description_section do
         | 
| 486 | 
            +
                "description"
         | 
| 487 | 
            +
              end
         | 
| 488 | 
            +
             | 
| 489 | 
            +
              attribute :summary_section do
         | 
| 490 | 
            +
                "summary"
         | 
| 491 | 
            +
              end
         | 
| 492 | 
            +
             | 
| 493 | 
            +
              attribute :description_sentences do
         | 
| 494 | 
            +
                1
         | 
| 495 | 
            +
              end
         | 
| 242 496 |  | 
| 243 | 
            -
             | 
| 497 | 
            +
              attribute :summary_sentences do
         | 
| 498 | 
            +
                1
         | 
| 499 | 
            +
              end
         | 
| 500 | 
            +
              
         | 
| 501 | 
            +
              [:summary, :description].each { |section|
         | 
| 502 | 
            +
                attribute section do
         | 
| 244 503 | 
             
                  begin
         | 
| 245 | 
            -
                     | 
| 504 | 
            +
                    sections[send("#{section}_section")].
         | 
| 505 | 
            +
                    gsub("\n", " ").
         | 
| 506 | 
            +
                    split(%r!\.\s*!m).
         | 
| 507 | 
            +
                    first(send("#{section}_sentences")).
         | 
| 508 | 
            +
                    join(".  ") << "."
         | 
| 246 509 | 
             
                  rescue
         | 
| 247 | 
            -
                    " | 
| 510 | 
            +
                    "FIXME: #{section}"
         | 
| 248 511 | 
             
                  end
         | 
| 249 512 | 
             
                end
         | 
| 513 | 
            +
              }
         | 
| 250 514 |  | 
| 251 | 
            -
             | 
| 252 | 
            -
             | 
| 253 | 
            -
             | 
| 254 | 
            -
             | 
| 255 | 
            -
             | 
| 256 | 
            -
                  []
         | 
| 515 | 
            +
              attribute :url do
         | 
| 516 | 
            +
                begin
         | 
| 517 | 
            +
                  readme_contents.match(%r!^\*.*?(http://\S+)!)[1]
         | 
| 518 | 
            +
                rescue
         | 
| 519 | 
            +
                  "http://#{rubyforge_name}.rubyforge.org"
         | 
| 257 520 | 
             
                end
         | 
| 521 | 
            +
              end
         | 
| 258 522 |  | 
| 259 | 
            -
             | 
| 523 | 
            +
              attribute :extra_deps do
         | 
| 524 | 
            +
                []
         | 
| 525 | 
            +
              end
         | 
| 260 526 |  | 
| 261 | 
            -
             | 
| 262 | 
            -
             | 
| 263 | 
            -
                }.each { |method_name|
         | 
| 264 | 
            -
                  send(method_name)
         | 
| 265 | 
            -
                }
         | 
| 527 | 
            +
              attribute :extra_dev_deps do
         | 
| 528 | 
            +
                []
         | 
| 266 529 | 
             
              end
         | 
| 267 530 |  | 
| 268 | 
            -
               | 
| 269 | 
            -
                 | 
| 270 | 
            -
                self.email << email
         | 
| 531 | 
            +
              attribute :authors do
         | 
| 532 | 
            +
                Array.new
         | 
| 271 533 | 
             
              end
         | 
| 272 534 |  | 
| 273 | 
            -
               | 
| 274 | 
            -
                 | 
| 535 | 
            +
              attribute :email do
         | 
| 536 | 
            +
                Array.new
         | 
| 275 537 | 
             
              end
         | 
| 276 538 |  | 
| 277 | 
            -
              def email
         | 
| 278 | 
            -
                 | 
| 539 | 
            +
              def developer(name, email)
         | 
| 540 | 
            +
                authors << name
         | 
| 541 | 
            +
                self.email << email
         | 
| 279 542 | 
             
              end
         | 
| 280 543 |  | 
| 281 544 | 
             
              def dependency(name, version)
         | 
| @@ -301,7 +564,9 @@ class Jumpstart | |
| 301 564 |  | 
| 302 565 | 
             
              def define_spec
         | 
| 303 566 | 
             
                unless spec_files.empty?
         | 
| 304 | 
            -
                   | 
| 567 | 
            +
                  Ruby.no_warnings {
         | 
| 568 | 
            +
                    require 'spec/rake/spectask'
         | 
| 569 | 
            +
                  }
         | 
| 305 570 |  | 
| 306 571 | 
             
                  desc "run specs"
         | 
| 307 572 | 
             
                  Spec::Rake::SpecTask.new('spec') do |t|
         | 
| @@ -322,6 +587,8 @@ class Jumpstart | |
| 322 587 | 
             
                    t.spec_opts = ["-fh:#{spec_output}"]
         | 
| 323 588 | 
             
                  end
         | 
| 324 589 |  | 
| 590 | 
            +
                  suppress_task_warnings :spec, :full_spec, :text_spec
         | 
| 591 | 
            +
             | 
| 325 592 | 
             
                  desc "run full_spec then open browser"
         | 
| 326 593 | 
             
                  task :show_spec => :full_spec do
         | 
| 327 594 | 
             
                    open_browser(spec_output, rcov_dir + "/index.html")
         | 
| @@ -335,7 +602,7 @@ class Jumpstart | |
| 335 602 | 
             
                  task :prerelease => [:spec, :spec_deps]
         | 
| 336 603 | 
             
                  task :default => :spec
         | 
| 337 604 |  | 
| 338 | 
            -
                  CLEAN.include  | 
| 605 | 
            +
                  CLEAN.include spec_output_dir
         | 
| 339 606 | 
             
                end
         | 
| 340 607 | 
             
              end
         | 
| 341 608 |  | 
| @@ -377,6 +644,7 @@ class Jumpstart | |
| 377 644 | 
             
              def define_doc
         | 
| 378 645 | 
             
                desc "run rdoc"
         | 
| 379 646 | 
             
                task :doc => :clean_doc do
         | 
| 647 | 
            +
                  require 'rdoc/rdoc'
         | 
| 380 648 | 
             
                  args = (
         | 
| 381 649 | 
             
                    gemspec.rdoc_options +
         | 
| 382 650 | 
             
                    gemspec.require_paths.clone +
         | 
| @@ -403,6 +671,7 @@ class Jumpstart | |
| 403 671 | 
             
              def define_publish
         | 
| 404 672 | 
             
                desc "upload docs"
         | 
| 405 673 | 
             
                task :publish => [:clean_doc, :doc] do
         | 
| 674 | 
            +
                  require 'rake/contrib/sshpublisher'
         | 
| 406 675 | 
             
                  Rake::SshDirPublisher.new(
         | 
| 407 676 | 
             
                    "#{rubyforge_user}@rubyforge.org",
         | 
| 408 677 | 
             
                    "/var/www/gforge-projects/#{rubyforge_name}",
         | 
| @@ -445,9 +714,10 @@ class Jumpstart | |
| 445 714 | 
             
                  end
         | 
| 446 715 |  | 
| 447 716 | 
             
                  def debug_info(enable)
         | 
| 717 | 
            +
                    require 'find'
         | 
| 448 718 | 
             
                    Find.find("lib", "test") { |path|
         | 
| 449 719 | 
             
                      if path =~ %r!\.rb\Z!
         | 
| 450 | 
            -
                         | 
| 720 | 
            +
                        replace_file(path) { |contents|
         | 
| 451 721 | 
             
                          result = comment_regions(!enable, contents, "debug")
         | 
| 452 722 | 
             
                          comment_lines(!enable, result, "trace")
         | 
| 453 723 | 
             
                        }
         | 
| @@ -485,13 +755,13 @@ class Jumpstart | |
| 485 755 | 
             
                task :comments do
         | 
| 486 756 | 
             
                  file = "comments.txt"
         | 
| 487 757 | 
             
                  write_file(file) {
         | 
| 488 | 
            -
                    Array.new | 
| 489 | 
            -
             | 
| 490 | 
            -
             | 
| 491 | 
            -
             | 
| 492 | 
            -
                        }
         | 
| 758 | 
            +
                    result = Array.new
         | 
| 759 | 
            +
                    (["Rakefile"] + Dir["**/*.{rb,rake}"]).each { |f|
         | 
| 760 | 
            +
                      File.read(f).scan(%r!\#[^\{].*$!) { |match|
         | 
| 761 | 
            +
                        result << match
         | 
| 493 762 | 
             
                      }
         | 
| 494 | 
            -
                    } | 
| 763 | 
            +
                    }
         | 
| 764 | 
            +
                    result.join("\n")
         | 
| 495 765 | 
             
                  }
         | 
| 496 766 | 
             
                  CLEAN.include file
         | 
| 497 767 | 
             
                end
         | 
| @@ -507,6 +777,7 @@ class Jumpstart | |
| 507 777 |  | 
| 508 778 | 
             
              def define_ping
         | 
| 509 779 | 
             
                task :ping do
         | 
| 780 | 
            +
                  require 'rbconfig'
         | 
| 510 781 | 
             
                  %w[github.com rubyforge.org].each { |server|
         | 
| 511 782 | 
             
                    cmd = "ping " + (
         | 
| 512 783 | 
             
                      if Config::CONFIG["host"] =~ %r!darwin!
         | 
| @@ -548,28 +819,29 @@ class Jumpstart | |
| 548 819 | 
             
                }
         | 
| 549 820 | 
             
              end
         | 
| 550 821 |  | 
| 551 | 
            -
              def rubyforge( | 
| 552 | 
            -
                 | 
| 553 | 
            -
                  "rubyforge",
         | 
| 554 | 
            -
                  command,
         | 
| 822 | 
            +
              def rubyforge(mode, file, *options)
         | 
| 823 | 
            +
                command = ["rubyforge", mode] + options + [
         | 
| 555 824 | 
             
                  rubyforge_name,
         | 
| 556 825 | 
             
                  rubyforge_name,
         | 
| 557 826 | 
             
                  version.to_s,
         | 
| 558 | 
            -
                  file
         | 
| 559 | 
            -
                 | 
| 827 | 
            +
                  file,
         | 
| 828 | 
            +
                ]
         | 
| 829 | 
            +
                sh(*command)
         | 
| 560 830 | 
             
              end
         | 
| 561 831 |  | 
| 562 832 | 
             
              def define_release
         | 
| 563 | 
            -
                task :prerelease => [:clean, :check_directory, :ping]
         | 
| 833 | 
            +
                task :prerelease => [:clean, :check_directory, :ping, history_file]
         | 
| 564 834 |  | 
| 565 835 | 
             
                task :finish_release do
         | 
| 566 836 | 
             
                  gem_md5, tgz_md5 = [gem, tgz].map { |file|
         | 
| 567 | 
            -
                    "#{file}.md5" | 
| 568 | 
            -
             | 
| 569 | 
            -
                     | 
| 837 | 
            +
                    md5 = "#{file}.md5"
         | 
| 838 | 
            +
                    sh("md5sum #{file} > #{md5}")
         | 
| 839 | 
            +
                    md5
         | 
| 570 840 | 
             
                  }
         | 
| 571 841 |  | 
| 572 | 
            -
                  rubyforge( | 
| 842 | 
            +
                  rubyforge(
         | 
| 843 | 
            +
                    "add_release", gem, "--release_changes", history_file, "--preformatted"
         | 
| 844 | 
            +
                  )
         | 
| 573 845 | 
             
                  [gem_md5, tgz, tgz_md5].each { |file|
         | 
| 574 846 | 
             
                    rubyforge("add_file", file)
         | 
| 575 847 | 
             
                  }
         | 
| @@ -591,44 +863,125 @@ class Jumpstart | |
| 591 863 | 
             
                sh(*([browser].flatten + files))
         | 
| 592 864 | 
             
              end
         | 
| 593 865 |  | 
| 594 | 
            -
              def  | 
| 595 | 
            -
                 | 
| 596 | 
            -
                   | 
| 597 | 
            -
                     | 
| 866 | 
            +
              def suppress_task_warnings(*task_names)
         | 
| 867 | 
            +
                task_names.each { |task_name|
         | 
| 868 | 
            +
                  Rake::Task[task_name].actions.map! { |action|
         | 
| 869 | 
            +
                    lambda { |*args|
         | 
| 870 | 
            +
                      Ruby.no_warnings {
         | 
| 871 | 
            +
                        action.call(*args)
         | 
| 872 | 
            +
                      }
         | 
| 873 | 
            +
                    }
         | 
| 598 874 | 
             
                  }
         | 
| 599 875 | 
             
                }
         | 
| 600 876 | 
             
              end
         | 
| 601 877 |  | 
| 602 | 
            -
               | 
| 603 | 
            -
                 | 
| 604 | 
            -
             | 
| 605 | 
            -
                }
         | 
| 606 | 
            -
              end
         | 
| 878 | 
            +
              class << self
         | 
| 879 | 
            +
                include Util
         | 
| 880 | 
            +
                include InstanceEvalWithArgs
         | 
| 607 881 |  | 
| 608 | 
            -
             | 
| 609 | 
            -
                 | 
| 610 | 
            -
             | 
| 882 | 
            +
                # From minitest, part of the Ruby source; by Ryan Davis.
         | 
| 883 | 
            +
                def capture_io
         | 
| 884 | 
            +
                  require 'stringio'
         | 
| 611 885 |  | 
| 612 | 
            -
             | 
| 613 | 
            -
             | 
| 614 | 
            -
                   | 
| 615 | 
            -
             | 
| 616 | 
            -
             | 
| 617 | 
            -
             | 
| 618 | 
            -
             | 
| 619 | 
            -
             | 
| 886 | 
            +
                  orig_stdout, orig_stderr         = $stdout, $stderr
         | 
| 887 | 
            +
                  captured_stdout, captured_stderr = StringIO.new, StringIO.new
         | 
| 888 | 
            +
                  $stdout, $stderr                 = captured_stdout, captured_stderr
         | 
| 889 | 
            +
             | 
| 890 | 
            +
                  yield
         | 
| 891 | 
            +
             | 
| 892 | 
            +
                  return captured_stdout.string, captured_stderr.string
         | 
| 893 | 
            +
                ensure
         | 
| 894 | 
            +
                  $stdout = orig_stdout
         | 
| 895 | 
            +
                  $stderr = orig_stderr
         | 
| 896 | 
            +
                end
         | 
| 897 | 
            +
             | 
| 898 | 
            +
                def run_doc_code(code, expected, index, instance, &block)
         | 
| 899 | 
            +
                  lib = File.expand_path(File.dirname(__FILE__) + "/../lib")
         | 
| 900 | 
            +
                  header = %{
         | 
| 901 | 
            +
                    $LOAD_PATH.unshift "#{lib}"
         | 
| 902 | 
            +
                    begin
         | 
| 903 | 
            +
                  }
         | 
| 904 | 
            +
                  footer = %{
         | 
| 905 | 
            +
                    rescue Exception => __jumpstart_exception
         | 
| 906 | 
            +
                      puts "raises \#{__jumpstart_exception.class}"
         | 
| 620 907 | 
             
                    end
         | 
| 621 908 | 
             
                  }
         | 
| 909 | 
            +
                  final_code = header + code + footer
         | 
| 910 | 
            +
             | 
| 911 | 
            +
                  # Sometimes code is required to be inside a file.
         | 
| 912 | 
            +
                  actual = nil
         | 
| 913 | 
            +
                  require 'tempfile'
         | 
| 914 | 
            +
                  Tempfile.open("run-rdoc-code") { |temp_file|
         | 
| 915 | 
            +
                    temp_file.print(final_code)
         | 
| 916 | 
            +
                    temp_file.close
         | 
| 917 | 
            +
                    actual = Ruby.run_file_and_capture(temp_file.path).chomp
         | 
| 918 | 
            +
                  }
         | 
| 919 | 
            +
             | 
| 920 | 
            +
                  instance_eval_with_args(instance, expected, actual, index, &block)
         | 
| 921 | 
            +
                end
         | 
| 922 | 
            +
             | 
| 923 | 
            +
                def run_doc_section(file, section, instance, &block)
         | 
| 924 | 
            +
                  contents = File.read(file)
         | 
| 925 | 
            +
                  re = %r!^=+[ \t]#{Regexp.quote(section)}.*?\n(.*?)^=!m
         | 
| 926 | 
            +
                  if section_contents = contents[re, 1]
         | 
| 927 | 
            +
                    index = 0
         | 
| 928 | 
            +
                    section_contents.scan(%r!^(  \S.*?)(?=(^\S|\Z))!m) { |indented, unused|
         | 
| 929 | 
            +
                      code_sections = indented.split(%r!^  \#\#\#\# output:\s*$!)
         | 
| 930 | 
            +
                      code, expected = (
         | 
| 931 | 
            +
                        case code_sections.size
         | 
| 932 | 
            +
                        when 1
         | 
| 933 | 
            +
                          [indented, indented.scan(%r!\# => (.*?)\n!).flatten.join("\n")]
         | 
| 934 | 
            +
                        when 2
         | 
| 935 | 
            +
                          code_sections
         | 
| 936 | 
            +
                        else
         | 
| 937 | 
            +
                          raise "parse error"
         | 
| 938 | 
            +
                        end
         | 
| 939 | 
            +
                      )
         | 
| 940 | 
            +
                      run_doc_code(code, expected, index, instance, &block)
         | 
| 941 | 
            +
                      index += 1
         | 
| 942 | 
            +
                    }
         | 
| 943 | 
            +
                  else
         | 
| 944 | 
            +
                    raise "couldn't find section `#{section}' of `#{file}'"
         | 
| 945 | 
            +
                  end
         | 
| 946 | 
            +
                end
         | 
| 947 | 
            +
             | 
| 948 | 
            +
                def doc_to_spec(file, *sections, &block)
         | 
| 949 | 
            +
                  jump = self
         | 
| 950 | 
            +
                  describe file do
         | 
| 951 | 
            +
                    sections.each { |section|
         | 
| 952 | 
            +
                      describe "section `#{section}'" do
         | 
| 953 | 
            +
                        it "should run as claimed" do
         | 
| 954 | 
            +
                          if block
         | 
| 955 | 
            +
                            jump.run_doc_section(file, section, self, &block)
         | 
| 956 | 
            +
                          else
         | 
| 957 | 
            +
                            jump.run_doc_section(file, section, self) {
         | 
| 958 | 
            +
                              |expected, actual, index|
         | 
| 959 | 
            +
                              actual.should == expected
         | 
| 960 | 
            +
                            }
         | 
| 961 | 
            +
                          end
         | 
| 962 | 
            +
                        end
         | 
| 963 | 
            +
                      end
         | 
| 964 | 
            +
                    }
         | 
| 965 | 
            +
                  end
         | 
| 622 966 | 
             
                end
         | 
| 623 | 
            -
              end
         | 
| 624 | 
            -
            end
         | 
| 625 967 |  | 
| 626 | 
            -
             | 
| 627 | 
            -
             | 
| 628 | 
            -
             | 
| 629 | 
            -
             | 
| 630 | 
            -
             | 
| 968 | 
            +
                def doc_to_test(file, *sections, &block)
         | 
| 969 | 
            +
                  jump = self
         | 
| 970 | 
            +
                  klass = Class.new Test::Unit::TestCase do
         | 
| 971 | 
            +
                    sections.each { |section|
         | 
| 972 | 
            +
                      define_method "test_#{file}_#{section}" do
         | 
| 973 | 
            +
                        if block
         | 
| 974 | 
            +
                          jump.run_doc_section(file, section, self, &block)
         | 
| 975 | 
            +
                        else
         | 
| 976 | 
            +
                          jump.run_doc_section(file, section, self) {
         | 
| 977 | 
            +
                            |expected, actual, index|
         | 
| 978 | 
            +
                            assert_equal expected, actual
         | 
| 979 | 
            +
                          }
         | 
| 980 | 
            +
                        end
         | 
| 981 | 
            +
                      end
         | 
| 982 | 
            +
                    }
         | 
| 983 | 
            +
                  end
         | 
| 984 | 
            +
                  Object.const_set("Test#{file}".gsub(".", ""), klass)
         | 
| 631 985 | 
             
                end
         | 
| 632 986 | 
             
              end
         | 
| 633 987 | 
             
            end
         | 
| 634 | 
            -
             |