├── lib ├── finder.yml ├── finder │ ├── index.rb │ ├── import.rb │ ├── base.rb │ ├── site.rb │ ├── find.rb │ ├── gem.rb │ └── roll.rb └── finder.rb ├── demo ├── applique │ ├── ae.rb │ └── helper.rb ├── fixtures │ └── example.rb ├── 00_intro.md ├── 02_feature.md └── 01_load_path.md ├── work ├── deprecated │ ├── ruby │ │ ├── title │ │ ├── version │ │ ├── created │ │ ├── organization │ │ ├── summary │ │ ├── authors │ │ ├── copyrights │ │ ├── repositories │ │ ├── requirements │ │ ├── resources │ │ └── description │ └── config │ │ └── webme │ │ └── advert.html └── rubygems.rb ├── Gemfile ├── .gitignore ├── .yardopts ├── .travis.yml ├── Assembly ├── MANIFEST ├── Index.yml ├── LICENSE.txt ├── .index ├── HISTORY.md ├── README.md └── .gemspec /lib/finder.yml: -------------------------------------------------------------------------------- 1 | ../.index -------------------------------------------------------------------------------- /demo/applique/ae.rb: -------------------------------------------------------------------------------- 1 | require 'ae' 2 | -------------------------------------------------------------------------------- /work/deprecated/ruby/title: -------------------------------------------------------------------------------- 1 | Finder 2 | -------------------------------------------------------------------------------- /work/deprecated/ruby/version: -------------------------------------------------------------------------------- 1 | 0.1.0 2 | -------------------------------------------------------------------------------- /work/deprecated/ruby/created: -------------------------------------------------------------------------------- 1 | 2009-11-24 2 | -------------------------------------------------------------------------------- /work/deprecated/ruby/organization: -------------------------------------------------------------------------------- 1 | Rubyworks 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | gemspec 3 | -------------------------------------------------------------------------------- /demo/fixtures/example.rb: -------------------------------------------------------------------------------- 1 | $proof = "plugin loading worked" 2 | -------------------------------------------------------------------------------- /work/deprecated/ruby/summary: -------------------------------------------------------------------------------- 1 | Robust library file locator 2 | -------------------------------------------------------------------------------- /work/deprecated/ruby/authors: -------------------------------------------------------------------------------- 1 | --- 2 | - Trans 3 | 4 | -------------------------------------------------------------------------------- /work/deprecated/ruby/copyrights: -------------------------------------------------------------------------------- 1 | --- 2 | - 2009 Rubyworks (BSD-2-Clause) 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .reap/digest 2 | .yardoc 3 | log 4 | doc 5 | pkg 6 | tmp 7 | web 8 | *.lock 9 | -------------------------------------------------------------------------------- /work/deprecated/ruby/repositories: -------------------------------------------------------------------------------- 1 | --- 2 | upstream: git://github.com/rubyworks/finder.git 3 | 4 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --title Finder 2 | --output-dir doc 3 | --private 4 | --protected 5 | lib/ 6 | - 7 | [A-Z]*.* 8 | -------------------------------------------------------------------------------- /work/deprecated/ruby/requirements: -------------------------------------------------------------------------------- 1 | --- 2 | - detroit (build) 3 | - qed (test) 4 | - ae (test) 5 | 6 | -------------------------------------------------------------------------------- /demo/00_intro.md: -------------------------------------------------------------------------------- 1 | # Finder 2 | 3 | To use the Finder library first we need to require it. 4 | 5 | require 'finder' 6 | 7 | -------------------------------------------------------------------------------- /demo/applique/helper.rb: -------------------------------------------------------------------------------- 1 | require 'finder' 2 | 3 | # add the fixtures directory to the $LOAD_PATH 4 | $:.unshift(File.dirname(File.dirname(__FILE__)) + '/fixtures') 5 | 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | script: "bundle exec qed" 3 | rvm: 4 | - 1.8.7 5 | - 1.9.2 6 | - 1.9.3 7 | - rbx 8 | - rbx-19mode 9 | - jruby 10 | - jruby-19mode 11 | 12 | -------------------------------------------------------------------------------- /work/deprecated/ruby/resources: -------------------------------------------------------------------------------- 1 | --- 2 | home: http://rubyworks.github.com/finder 3 | code: http://github.com/rubyworks/finder 4 | mail: http://groups.google.com/rubyworks-mailinglist 5 | -------------------------------------------------------------------------------- /work/deprecated/ruby/description: -------------------------------------------------------------------------------- 1 | Finder is a general purpose file finder for Ruby. Finder can search 2 | RubyGems, Roll libraries and Ruby's standard $LOAD_PATH and system 3 | data directory for the active or the most current library files. 4 | It is especially useful for implmenting library-based plugin systems. 5 | 6 | -------------------------------------------------------------------------------- /Assembly: -------------------------------------------------------------------------------- 1 | --- 2 | github: 3 | gh_pages: web 4 | 5 | gem: 6 | active: true 7 | 8 | yard: 9 | active: true 10 | 11 | dnote: 12 | title: Source Notes 13 | output: log/notes.html 14 | 15 | announce: 16 | service: email 17 | mailto: 18 | - ruby-talk@ruby-lang.org 19 | - rubyworks-mailinglist@googlegroups.com 20 | 21 | 22 | -------------------------------------------------------------------------------- /work/deprecated/config/webme/advert.html: -------------------------------------------------------------------------------- 1 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | #!mast -x *.lock .index .ruby .rubyrc .yardopts bin demo lib man spec test *.md *.rdoc *.txt 2 | .index 3 | .yardopts 4 | demo/00_intro.md 5 | demo/01_load_path.md 6 | demo/02_feature.md 7 | demo/applique/ae.rb 8 | demo/applique/helper.rb 9 | demo/fixtures/example.rb 10 | lib/finder/base.rb 11 | lib/finder/find.rb 12 | lib/finder/gem.rb 13 | lib/finder/import.rb 14 | lib/finder/index.rb 15 | lib/finder/roll.rb 16 | lib/finder/site.rb 17 | lib/finder.rb 18 | lib/finder.yml 19 | HISTORY.md 20 | README.md 21 | LICENSE.txt 22 | -------------------------------------------------------------------------------- /lib/finder/index.rb: -------------------------------------------------------------------------------- 1 | module Finder 2 | 3 | # 4 | # Cached access to project metadata. 5 | # 6 | def index 7 | @index ||=( 8 | require 'yaml' 9 | file = File.expand_path('../finder.yml', File.dirname(__FILE__)) 10 | YAML.load_file(file) 11 | ) 12 | end 13 | 14 | # 15 | # Access to project metadata via constants. 16 | # 17 | # @example 18 | # Finder::VERSION #=> '0.2.0' 19 | # 20 | def const_missing(name) 21 | index[name.to_s.downcase] || super(name) 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /demo/02_feature.md: -------------------------------------------------------------------------------- 1 | # Feature Lookup 2 | 3 | We can use +Find.feature+ to seach for requireable files from within 4 | library load paths. The `feature` method returns relatvie paths 5 | by default and automatically handles extensions --just like `require`. 6 | 7 | files = Find.feature('example') 8 | file = files.first 9 | 10 | The +find+ method returns path name relative to the load path. 11 | 12 | file.assert == 'example.rb' 13 | 14 | We can use the `realtive` or `aboslute` options to get the full path. 15 | 16 | files = Find.feature('example', :absolute=>true) 17 | file = files.first 18 | 19 | File.expand_path(file).assert == file 20 | file.assert.end_with?('example.rb') 21 | 22 | -------------------------------------------------------------------------------- /demo/01_load_path.md: -------------------------------------------------------------------------------- 1 | # Load Path Lookup 2 | 3 | Use +Find.load_path+ to search for a file pattern of our 4 | choosing within library load paths. 5 | 6 | files = Find.load_path('example.rb', :relative=>true) 7 | file = files.first 8 | 9 | The +find+ method returns path name relative to the load path. 10 | 11 | file.assert == 'example.rb' 12 | 13 | We can use the `aboslute` option to get the full path. 14 | 15 | files = Find.load_path('example.rb', :absolute=>true) 16 | file = files.first 17 | 18 | File.expand_path(file).assert == file 19 | file.assert.end_with?('example.rb') 20 | 21 | As with any Ruby script we can require it. 22 | 23 | file = Find.load_path('example.rb').first 24 | require file 25 | 26 | Our example.rb script defines the global variable $proof. 27 | We can see that it loaded just fine. 28 | 29 | $proof.assert == "plugin loading worked" 30 | 31 | -------------------------------------------------------------------------------- /Index.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: finder 3 | version: 0.4.0 4 | title: Finder 5 | summary: Robust library file locator 6 | created: 2009-11-24 7 | 8 | description: 9 | Finder is a general purpose file finder for Ruby. Finder can search 10 | RubyGems, Roll libraries and Ruby's standard $LOAD_PATH and system 11 | data directory for the active or the most current library files. 12 | It is especially useful for implementing library-based plugin systems. 13 | 14 | repositories: 15 | upstream: git://github.com/rubyworks/finder.git 16 | 17 | authors: 18 | - Trans 19 | 20 | requirements: 21 | - detroit (build) 22 | - qed (test) 23 | - ae (test) 24 | 25 | resources: 26 | home: http://rubyworks.github.com/finder 27 | code: http://github.com/rubyworks/finder 28 | mail: http://groups.google.com/rubyworks-mailinglist 29 | 30 | organization: rubyworks 31 | 32 | copyrights: 33 | - 2009 Rubyworks (BSD-2-Clause) 34 | 35 | -------------------------------------------------------------------------------- /lib/finder/import.rb: -------------------------------------------------------------------------------- 1 | module Kernel 2 | 3 | private 4 | 5 | # 6 | # Evaluate script directly into current scope. 7 | # 8 | def import(feature) 9 | file = Find.feature(feature, :absolute=>true).first 10 | raise LoadError, "no such file -- #{feature}" unless file 11 | instance_eval(::File.read(file), file) if file 12 | end 13 | 14 | # 15 | # Evaluate script directly into current scope relative to 16 | # the current script. 17 | # 18 | # Note this is implemented via #caller.first. 19 | # 20 | def import_relative(fname) 21 | call = caller.first 22 | fail "Can't parse #{call}" unless call.rindex(/:\d+(:in `.*')?$/) 23 | path = $` # File.dirname(call) 24 | if /\A\((.*)\)/ =~ path # eval, etc. 25 | raise LoadError, "import_relative is called in #{$1}" 26 | end 27 | file = File.expand_path(fname, File.dirname(path)) 28 | 29 | raise LoadError, "no such file -- #{file}" unless File.file?(file) 30 | 31 | instance_eval(::File.read(file), file) #if file 32 | end 33 | 34 | end 35 | 36 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | BSD-2-Clause License 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 15 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 16 | COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 17 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 20 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 21 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 22 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | -------------------------------------------------------------------------------- /.index: -------------------------------------------------------------------------------- 1 | --- 2 | type: ruby 3 | revision: 2013 4 | sources: 5 | - Index.yml 6 | authors: 7 | - name: Trans 8 | email: transfire@gmail.com 9 | organizations: 10 | - name: rubyworks 11 | requirements: 12 | - groups: 13 | - build 14 | development: true 15 | name: detroit 16 | - groups: 17 | - test 18 | development: true 19 | name: qed 20 | - groups: 21 | - test 22 | development: true 23 | name: ae 24 | conflicts: [] 25 | alternatives: [] 26 | resources: 27 | - type: home 28 | uri: http://rubyworks.github.com/finder 29 | label: Homepage 30 | - type: code 31 | uri: http://github.com/rubyworks/finder 32 | label: Source Code 33 | - type: mail 34 | uri: http://groups.google.com/rubyworks-mailinglist 35 | label: Mailing List 36 | repositories: 37 | - name: upstream 38 | scm: git 39 | uri: git://github.com/rubyworks/finder.git 40 | categories: [] 41 | paths: 42 | load: 43 | - lib 44 | copyrights: 45 | - holder: Rubyworks 46 | year: '2009' 47 | license: BSD-2-Clause 48 | name: finder 49 | title: Finder 50 | version: 0.4.0 51 | summary: Robust library file locator 52 | created: '2009-11-24' 53 | description: Finder is a general purpose file finder for Ruby. Finder can search RubyGems, 54 | Roll libraries and Ruby's standard $LOAD_PATH and system data directory for the 55 | active or the most current library files. It is especially useful for implementing 56 | library-based plugin systems. 57 | date: '2012-12-24' 58 | -------------------------------------------------------------------------------- /lib/finder/base.rb: -------------------------------------------------------------------------------- 1 | module Finder 2 | module Find 3 | 4 | # Base module provides helper methods to other 5 | # finders. 6 | # 7 | module Base 8 | 9 | # 10 | # When included into a module, that module is atuomatically 11 | # self extended. 12 | # 13 | def self.included(mod) 14 | mod.extend(mod) 15 | end 16 | 17 | ## 18 | ## Like #load_path but searches only for requirable files. 19 | ## 20 | ## NOTE: This may be somewhat limited at the moment until we 21 | ## figure out how best to determine all possible extensions. 22 | ## 23 | #def require_path(match, options={}) 24 | # match = append_extensions(match, options) 25 | # load_path(match, options) 26 | #end 27 | 28 | # 29 | # Like #load_path but searches only for requirable feature files 30 | # and returns relative paths by default. 31 | # 32 | def feature(match, options={}) 33 | options[:relative] = true unless options.key?(:relative) or options.key?(:absolute) 34 | match = append_extensions(match, options) 35 | load_path(match, options) 36 | end 37 | 38 | private 39 | 40 | # 41 | # Validate and normalize load options. 42 | # 43 | # @param [Hash] options 44 | # 45 | def valid_load_options(options) 46 | if options.key?(:relative) && options.key?(:absolute) 47 | raise ArgumentError, "must be either relative or absolute" unless options[:relative] ^ options[:absolute] 48 | end 49 | 50 | options[:relative] = false if options[:absolute] 51 | 52 | options 53 | end 54 | 55 | # 56 | # Append requirable extensions to match glob. 57 | # 58 | # 59 | def append_extensions(match, options={}) 60 | unless Find::EXTENSIONS.include?(File.extname(match)) 61 | match = match + '{' + Find::EXTENSIONS.join(',') + '}' 62 | end 63 | match 64 | end 65 | 66 | end 67 | 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | # RELEASE HISTORY 2 | 3 | ## 0.4.0 / 2012-12-25 4 | 5 | New release adds Kernel#import and #import_relative core extensions. 6 | The methods load code directly into the calling scope, unlike 7 | the #require and #load methods which do so at the toplevel. 8 | 9 | Changes: 10 | 11 | * Add Kernel#import and #import_relative. 12 | * Add dynamic project metadata lookup. 13 | 14 | 15 | ## 0.3.0 / 2012-05-22 16 | 17 | This is a significant release in that the behavior of `Find.load_path` has 18 | changed to return absolute paths by default. To get relative paths set 19 | the `:relative` options to `true`. However, if you are doing that you 20 | likely want to use the new `Find.feature` method which specifically searches 21 | for requirable files and returns relative paths by default. 22 | 23 | Changes: 24 | 25 | * Find.load_path now returns absolute paths by default. 26 | * Adds option `:relative=>true` to get relative paths. 27 | * Adds new `Find.feature` for finding requirable files. 28 | * New Base module provides shared methods to all systems. 29 | 30 | 31 | ## 0.2.1 / 2012-03-15 32 | 33 | Fix Gem finder so that is places spec in Array, and catches 34 | error if gem is not found. 35 | 36 | Changes: 37 | 38 | * Fix Gem finder :from option to collect Array of spec. 39 | * Fix Gem finder to catch error when gem is not found. 40 | 41 | 42 | ## 0.2.0 / 2012-03-14 43 | 44 | This release adds the `:from` option which allows searching 45 | to be limited to a specific library/gem. It also fixes 46 | a bug with the Find.path method where one of the arguments 47 | was mis-named. 48 | 49 | Changes: 50 | 51 | * Add support for `:from` option. 52 | * Fix typo in `Find.path` arguments. 53 | 54 | 55 | ## 0.1.1 / 2012-02-11 56 | 57 | Fixes a few oversites in last release. 58 | 59 | Changes: 60 | 61 | * Fix Find.data_path arguments. 62 | * Add Roll.data_path method. 63 | 64 | 65 | ## 0.1.0 / 2012-02-11 66 | 67 | Finder is a new library built from the ashes of the old Plugin gem. 68 | Along with a new more fitting name, it has more robust and expanded 69 | capabilites! 70 | 71 | Changes: 72 | 73 | * Happy Rebirthday! 74 | 75 | -------------------------------------------------------------------------------- /work/rubygems.rb: -------------------------------------------------------------------------------- 1 | if defined?(Gem) 2 | 3 | module Gem 4 | 5 | # Search RubyGems for matching paths in current gem versions. 6 | # 7 | # For RubyGems older than version 1.7 (actually I don't know 8 | # the exact cut-off, so let me know if you discover otherwise) 9 | # then this search will return matches from ALL gems. 10 | # 11 | # For RubyGems 1.7+ it returns matches ONLY from active gems or 12 | # the latest versions of non-active gems. 13 | # 14 | # The later is proper functionality. But the API on the old version 15 | # of RubyGems is not condusive, and worse, now docs for it are hard 16 | # to find. 17 | # 18 | def self.search(match, options={}) 19 | return [] unless defined?(::Gem) 20 | if Gem::VERSION < '1.7' 21 | matches = Gem::find_files(match) 22 | else 23 | matches = [] 24 | Gem::Specification.current_specs.each do |spec| 25 | glob = File.join(spec.lib_dirs_glob, match) 26 | list = Dir[glob] #.map{ |f| f.untaint } 27 | matches.concat(list) 28 | end 29 | end 30 | matches.map{ |d| d.chomp('/') } 31 | end 32 | 33 | class Specification 34 | # Return a list of actives specs, or latest version if not active. 35 | # 36 | def self.current_specs 37 | named = Hash.new{|h,k| h[k] = [] } 38 | each{ |spec| named[spec.name] << spec } 39 | list = [] 40 | named.each do |name, vers| 41 | if spec = vers.find{ |s| s.activated? } 42 | list << spec 43 | else 44 | spec = vers.max{ |a,b| a.version <=> b.version } 45 | list << spec 46 | end 47 | end 48 | return list 49 | end 50 | 51 | # Return full path of requireable file given relative file name. 52 | # Returns +nil+ if there is no requirable file found by that name. 53 | # 54 | def find_requirable_file(file) 55 | root = full_gem_path 56 | 57 | require_paths.each do |lib| 58 | base = "#{root}/#{lib}/#{file}" 59 | Gem.suffixes.each do |suf| 60 | path = "#{base}#{suf}" 61 | return path if File.file? path 62 | end 63 | end 64 | 65 | return nil 66 | end 67 | end 68 | 69 | end 70 | 71 | end 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [Homepage](http://rubyworks.github.com/finder) / 2 | [Report Issue](http://github.com/rubyworks/finder/issues) / 3 | [Source Code](http://github.com/rubyworks/finder) 4 | ( [![Build Status](https://secure.travis-ci.org/rubyworks/finder.png)](http://travis-ci.org/rubyworks/finder) ) 5 | 6 | 7 | # Finder 8 | 9 | Finder is a straight-forward file finder for searching Ruby library paths. 10 | It can handle RubyGems, Rolls and Ruby's standard site locals. It is both 11 | more flexible and more robust the using Gem.find_files or searching the 12 | $LOAD_PATH manually. 13 | 14 | 15 | ## Instructions 16 | 17 | To find paths, simply provide a glob to the appropriate Finder function, 18 | and it will return all matches found within current or most recent 19 | versions of a library. 20 | 21 | For example, a common use case for plug-in enabled application is to 22 | require all the files found in library load paths: 23 | 24 | require 'finder' 25 | 26 | Find.feature('myapp/*').each do |file| 27 | require(file) 28 | end 29 | 30 | This is basically equivalent to: 31 | 32 | Find.load_path('myapp/*.rb', :relative=>true).each do |file| 33 | require(file) 34 | end 35 | 36 | Alternately you might load files only as needed. For instance, if a 37 | command-line option calls for it. 38 | 39 | In addition Finder has two optional Kernel extensions: `#import` 40 | and `#import_relative`. These methods can be used like `#require` 41 | and `#require_relative`, but load code directory into the 42 | current scope instead of the toplevel. 43 | 44 | require 'finder/import' 45 | 46 | module My 47 | import('abbrev.rb') 48 | emd 49 | 50 | My::Abbrev::abbrev(['ruby']) 51 | => {"rub"=>"ruby", "ru"=>"ruby", "r"=>"ruby", "ruby"=>"ruby"} 52 | 53 | It is important to be careful when using `#import` to make sure loaded 54 | scripts behave as intended. For example, if `abbrev.rb` were to define 55 | itself using `::` toplevel namespace indicators, i.e. `::Abbrev`, then 56 | the above import would not work as demonstrated. 57 | 58 | 59 | ## Copyrights 60 | 61 | Finder is copyrighted opensource software. 62 | 63 | Copyright (c) 2009 Rubyworks 64 | 65 | It can be modified and redistributed in accordance with the terms of 66 | the **BSD-2-Clause** license. 67 | 68 | See LICENSE.txt file for details. 69 | -------------------------------------------------------------------------------- /lib/finder.rb: -------------------------------------------------------------------------------- 1 | # Finder (http://rubyworks.github.com/finder) 2 | # 3 | # (c) 2012 Rubyworks 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # 1. Redistributions of source code must retain the above copyright notice, 9 | # this list of conditions and the following disclaimer. 10 | # 11 | # 2. Redistributions in binary form must reproduce the above copyright 12 | # notice, this list of conditions and the following disclaimer in the 13 | # documentation and/or other materials provided with the distribution. 14 | # 15 | # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 16 | # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 17 | # FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 18 | # COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 | # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | require 'finder/index' 27 | require 'finder/find' 28 | 29 | # TODO: Import is optional for the time bing. 30 | #require 'finder/import' 31 | 32 | module Finder 33 | 34 | # Clean module that can be included elsewhere, to proved #path, #load_path 35 | # and #data_path methods without including the Gem, Roll, and Site constants. 36 | # 37 | module Findable 38 | def path(match, options={}) 39 | Find.path(match, options) 40 | end 41 | 42 | def data_path(match, options={}) 43 | Find.data_path(match, options) 44 | end 45 | 46 | def load_path(match, options={}) 47 | Find.load_path(match, options) 48 | end 49 | 50 | def require_path(match, options={}) 51 | Find.require_path(match, options) 52 | end 53 | 54 | def feature(match, options={}) 55 | Find.feature(match, options) 56 | end 57 | end 58 | 59 | end 60 | 61 | module Find 62 | extend Finder::Find 63 | end 64 | 65 | -------------------------------------------------------------------------------- /lib/finder/site.rb: -------------------------------------------------------------------------------- 1 | module Finder 2 | module Find 3 | 4 | # System location finder methods. 5 | # 6 | module Site 7 | include Base 8 | 9 | # 10 | # System's data path. 11 | # 12 | DATA_PATH = RbConfig::CONFIG['datadir'] 13 | 14 | # TODO: Might this support `:from` option via 15 | # `File.join(options[:from], match)`? 16 | 17 | # 18 | # Search load path for matching patterns. 19 | # 20 | # @param [String] match 21 | # The file glob to match. 22 | # 23 | # @param [Hash] options 24 | # Search options. 25 | # 26 | # @return [Array] List of paths. 27 | # 28 | def path(match, options={}) 29 | return [] if options[:from] 30 | 31 | found = [] 32 | $LOAD_PATH.uniq.map do |path| 33 | list = Dir.glob(File.join(File.expand_path(path), match)) 34 | list = list.map{ |d| d.chomp('/') } 35 | found.concat(list) 36 | end 37 | found.concat(data_path(match, options)) 38 | found 39 | end 40 | 41 | # 42 | # Search load path for matching patterns. 43 | # 44 | # @param [String] match 45 | # The file glob to match. 46 | # 47 | # @param [Hash] options 48 | # Search options. 49 | # 50 | # @option options [true,false] :absolute 51 | # Return absolute paths instead of relative to load path. 52 | # 53 | # @return [Array] List of paths. 54 | # 55 | def load_path(match, options={}) 56 | return [] if options[:from] 57 | 58 | options = valid_load_options(options) 59 | 60 | found = [] 61 | $LOAD_PATH.uniq.each do |path| 62 | list = Dir.glob(File.join(File.expand_path(path), match)) 63 | list = list.map{ |d| d.chomp('/') } 64 | # return absolute path unless relative flag 65 | if options[:relative] 66 | # the extra '' in File.join adds a '/' to the end of the path 67 | list = list.map{ |f| f.sub(File.join(path, ''), '') } 68 | end 69 | found.concat(list) 70 | end 71 | found 72 | end 73 | 74 | # 75 | # Search data path. 76 | # 77 | def data_path(match, options={}) 78 | return [] if options[:from] 79 | 80 | Dir.glob(File.join(DATA_PATH, match)).uniq 81 | end 82 | 83 | end 84 | 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /lib/finder/find.rb: -------------------------------------------------------------------------------- 1 | require 'rbconfig' 2 | require 'finder/base' 3 | require 'finder/roll' 4 | require 'finder/gem' 5 | require 'finder/site' 6 | 7 | module Finder 8 | 9 | # Find module is the main interface for Finder library. 10 | # 11 | module Find 12 | extend self 13 | 14 | # TODO: expand on extensions 15 | EXTENSIONS = %w{.rb .rbx .so} 16 | 17 | # Find matching paths, searching through Rolled libraries, Gem-installed libraries 18 | # and site locations in `$LOAD_PATH` and `RbConfig::CONFIG['datadir']`. 19 | # 20 | # @param [String] match 21 | # File glob to match against. 22 | # 23 | # @example 24 | # Find.path('lib/foo/*') 25 | # 26 | def path(match, options={}) 27 | found = [] 28 | systems.each do |system| 29 | found.concat system.path(match, options) 30 | end 31 | found.uniq 32 | end 33 | 34 | # Shortcut for #path. 35 | # 36 | # Find['lib/foo/*'] 37 | # 38 | alias_method :[], :path 39 | 40 | # Searching through all systems for matching data paths. 41 | # 42 | # @param [String] match 43 | # File glob to match against. 44 | # 45 | # @example 46 | # Find.data_path('bar/*') 47 | # 48 | def data_path(match, options={}) 49 | found = [] 50 | systems.each do |system| 51 | found.concat system.data_path(match, options) 52 | end 53 | found.uniq 54 | end 55 | 56 | # Searching through all systems for matching load paths. 57 | # 58 | # @param [String] match 59 | # File glob to match against. 60 | # 61 | # @example 62 | # Find.load_path('bar/*') 63 | # 64 | def load_path(match, options={}) 65 | found = [] 66 | systems.each do |system| 67 | found.concat system.load_path(match, options) 68 | end 69 | found.uniq 70 | end 71 | 72 | ## Searching through all systems for matching load paths. 73 | ## 74 | ## @param [String] match 75 | ## File glob to match against. 76 | ## 77 | ## @example 78 | ## Find.require_path('bar/*') 79 | ## 80 | #def require_path(match, options={}) 81 | # found = [] 82 | # systems.each do |system| 83 | # found.concat system.require_path(match, options) 84 | # end 85 | # found.uniq 86 | #end 87 | 88 | # Searching through all systems for matching requirable feature files. 89 | # 90 | # @param [String] match 91 | # File glob to match against. 92 | # 93 | # @example 94 | # Find.feature('ostruct') 95 | # 96 | def feature(match, options={}) 97 | found = [] 98 | systems.each do |system| 99 | found.concat system.feature(match, options) 100 | end 101 | found.uniq 102 | end 103 | 104 | # 105 | # List of supported library management systems. 106 | # 107 | def systems 108 | @systems ||= ( 109 | systems = [] 110 | systems << Roll if defined?(::Library) 111 | systems << Gem if defined?(::Gem) 112 | systems << Site 113 | systems 114 | ) 115 | end 116 | 117 | end 118 | 119 | end 120 | -------------------------------------------------------------------------------- /lib/finder/gem.rb: -------------------------------------------------------------------------------- 1 | module Finder 2 | module Find 3 | 4 | # RubyGems finder methods. 5 | # 6 | module Gem 7 | include Base 8 | 9 | # 10 | # Search gems. 11 | # 12 | # @param [String] match 13 | # The file glob to match. 14 | # 15 | # @param [Hash] options 16 | # Search options. 17 | # 18 | # @option options [String] :from 19 | # Specific gem to search. 20 | # 21 | # @return [Array] List of absolute paths. 22 | # 23 | def path(match, options={}) 24 | specs = specifications(options) 25 | 26 | matches = [] 27 | specs.each do |spec| 28 | list = [] 29 | glob = File.join(spec.full_gem_path, match) 30 | list = Dir[glob] #.map{ |f| f.untaint } 31 | list = list.map{ |d| d.chomp('/') } 32 | matches.concat(list) 33 | # activate the library if activate flag 34 | spec.activate if options[:activate] && !list.empty? 35 | end 36 | matches 37 | end 38 | 39 | # 40 | # Search gem load paths. 41 | # 42 | # @param [String] match 43 | # The file glob to match. 44 | # 45 | # @param [Hash] options 46 | # Search options. 47 | # 48 | # @option options [String] :from 49 | # Specific gem to search. 50 | # 51 | # @option options [true,false] :absolute 52 | # Return absolute paths instead of relative to load path. 53 | # 54 | # @option options [true,false] :activate 55 | # Activate the gems if it has matching files. 56 | # 57 | # @return [Array] List of paths. 58 | # 59 | def load_path(match, options={}) 60 | options = valid_load_options(options) 61 | 62 | specs = specifications(options) 63 | 64 | matches = [] 65 | specs.each do |spec| 66 | list = [] 67 | spec.require_paths.each do |path| 68 | glob = File.join(spec.full_gem_path, path, match) 69 | list = Dir[glob] #.map{ |f| f.untaint } 70 | list = list.map{ |d| d.chomp('/') } 71 | # return relative paths unless absolute flag 72 | if options[:relative] #not options[:absolute] 73 | # the extra '' in File.join adds a '/' to the end of the path 74 | list = list.map{ |f| f.sub(File.join(spec.full_gem_path, path, ''), '') } 75 | end 76 | matches.concat(list) 77 | end 78 | # activate the library if activate flag 79 | spec.activate if options[:activate] && !list.empty? 80 | end 81 | matches 82 | end 83 | 84 | # 85 | # Search gem data paths. 86 | # 87 | # @param [String] match 88 | # The file glob to match. 89 | # 90 | # @param [Hash] options 91 | # Search options. 92 | # 93 | # @return [Array] List of absolute paths. 94 | # 95 | def data_path(match, options={}) 96 | specs = specifications(options) 97 | 98 | matches = [] 99 | specs.each do |spec| 100 | list = [] 101 | glob = File.join(spec.full_gem_path, 'data', match) 102 | list = Dir[glob] #.map{ |f| f.untaint } 103 | list = list.map{ |d| d.chomp('/') } 104 | matches.concat(list) 105 | # activate the library if activate flag 106 | spec.activate if options[:activate] && !list.empty? 107 | end 108 | matches 109 | end 110 | 111 | private 112 | 113 | # 114 | def specifications(options) 115 | name = options[:from] || options[:gem] 116 | if name 117 | criteria = [options[:version]].compact 118 | begin 119 | specs = [::Gem::Specification.find_by_name(name.to_s, *criteria)] 120 | rescue ::Gem::LoadError 121 | specs = [] 122 | end 123 | else 124 | specs = ::Gem::Specification.current_specs 125 | end 126 | return specs 127 | end 128 | 129 | end 130 | 131 | end 132 | end 133 | 134 | 135 | module Gem 136 | 137 | # Gem::Specification is extended to support `current_specs` method. 138 | class Specification 139 | 140 | # Return a list of active specs or latest version of spec if not active. 141 | def self.current_specs 142 | named = Hash.new{|h,k| h[k] = [] } 143 | each{ |spec| named[spec.name] << spec } 144 | list = [] 145 | named.each do |name, vers| 146 | if spec = vers.find{ |s| s.activated? } 147 | list << spec 148 | else 149 | spec = vers.max{ |a,b| a.version <=> b.version } 150 | list << spec 151 | end 152 | end 153 | return list 154 | end 155 | 156 | end 157 | 158 | end 159 | -------------------------------------------------------------------------------- /lib/finder/roll.rb: -------------------------------------------------------------------------------- 1 | module Finder 2 | module Find 3 | 4 | # Finder methods for `Library` system. 5 | # 6 | module Roll 7 | include Base 8 | 9 | # 10 | # Search for current or latest files within a library. 11 | # 12 | # @param [String] match 13 | # The file glob to match. 14 | # 15 | # @param [Hash] options 16 | # Search options. 17 | # 18 | # @return [Array] List of paths. 19 | # 20 | def path(match, options={}) 21 | return [] unless defined?(::Library) 22 | 23 | if from = options[:from] 24 | ledger = {from.to_s => ::Library.ledger[from.to_s]} 25 | else 26 | ledger = ::Library.ledger 27 | end 28 | 29 | criteria = [options[:version]].compact 30 | matches = [] 31 | 32 | ledger.each do |name, lib| 33 | if Array === lib 34 | lib = lib.select do |l| 35 | criteria.all?{ |c| l.version.satisfy?(c) } 36 | end 37 | lib = lib.sort.first 38 | else 39 | next unless criteria.all?{ |c| lib.version.satisfy?(c) } 40 | end 41 | find = File.join(lib.location, match) 42 | list = Dir.glob(find) 43 | list = list.map{ |d| d.chomp('/') } 44 | matches.concat(list) 45 | end 46 | 47 | matches 48 | end 49 | 50 | # 51 | # Search Roll system for current or latest library files. This is useful 52 | # for plugin loading. 53 | # 54 | # This only searches activated libraries or the most recent version 55 | # of any given library. 56 | # 57 | # @param [String] match 58 | # The file glob to match. 59 | # 60 | # @param [Hash] options 61 | # Search options. 62 | # 63 | # @option options [true,false] :absolute 64 | # Return absolute paths instead of relative to load path. 65 | # 66 | # @option options [true,false] :activate 67 | # Activate the library if it has matching files. 68 | # 69 | # @return [Array] List of paths. 70 | # 71 | def load_path(match, options={}) 72 | return [] unless defined?(::Library) 73 | options = valid_load_options(options) 74 | 75 | if from = options[:from] 76 | libs = ::Library.ledger[from.to_s] 77 | if libs 78 | case libs 79 | when ::Array 80 | ledger = libs.empty? ? {} : {from.to_s => libs} 81 | else 82 | ledger = {from.to_s => libs} 83 | end 84 | else 85 | ledger = {} 86 | end 87 | else 88 | ledger = ::Library.ledger 89 | end 90 | 91 | criteria = [options[:version]].compact 92 | matches = [] 93 | 94 | ledger.each do |name, lib| 95 | list = [] 96 | if Array===lib 97 | lib = lib.select do |l| 98 | criteria.all?{ |c| l.version.satisfy?(c) } 99 | end 100 | lib = lib.sort.first 101 | else 102 | next unless criteria.all?{ |c| lib.version.satisfy?(c) } 103 | end 104 | lib.loadpath.each do |path| 105 | find = File.join(lib.location, path, match) 106 | list = Dir.glob(find) 107 | list = list.map{ |d| d.chomp('/') } 108 | # return relative load path unless absolute flag 109 | if options[:relative] 110 | # the extra '' in File.join adds a '/' to the end of the path 111 | list = list.map{ |f| f.sub(File.join(lib.location, path, ''), '') } 112 | end 113 | matches.concat(list) 114 | end 115 | # activate the library if activate flag 116 | lib.activate if options[:activate] && !list.empty? 117 | end 118 | 119 | matches 120 | end 121 | 122 | ## Search rolls for current or latest libraries. 123 | ## 124 | ##def load_path(match, options={}) 125 | # return [] unless defined?(::Library) 126 | # #::Library.search_latest(match) 127 | # ::Library.find_files(match) 128 | #end 129 | 130 | # 131 | # Search project's data paths. 132 | # 133 | def data_path(match, options={}) 134 | return [] unless defined?(::Library) 135 | 136 | if from = options[:from] 137 | ledger = {from.to_s => ::Library.ledger[from.to_s]} 138 | else 139 | ledger = ::Library.ledger 140 | end 141 | 142 | criteria = [options[:version]].compact 143 | matches = [] 144 | 145 | ledger.each do |name, lib| 146 | list = [] 147 | if Array === lib 148 | lib = lib.select do |l| 149 | criteria.all?{ |c| l.version.satisfy?(c) } 150 | end 151 | lib = lib.sort.first 152 | else 153 | next unless criteria.all?{ |c| l.version.satisfy?(c) } 154 | end 155 | find = File.join(lib.location, 'data', match) 156 | list = Dir.glob(find) 157 | list = list.map{ |d| d.chomp('/') } 158 | matches.concat(list) 159 | # activate the library if activate flag 160 | lib.activate if options[:activate] && !list.empty? 161 | end 162 | 163 | matches 164 | end 165 | 166 | end 167 | 168 | end 169 | end 170 | -------------------------------------------------------------------------------- /.gemspec: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'yaml' 4 | require 'pathname' 5 | 6 | module Indexer 7 | 8 | # Convert index data into a gemspec. 9 | # 10 | # Notes: 11 | # * Assumes all executables are in bin/. 12 | # * Does not yet handle default_executable setting. 13 | # * Does not yet handle platform setting. 14 | # * Does not yet handle required_ruby_version. 15 | # * Support for rdoc entries is weak. 16 | # 17 | class GemspecExporter 18 | 19 | # File globs to include in package --unless a manifest file exists. 20 | FILES = ".index .yardopts alt bin data demo ext features lib man spec test try* [A-Z]*.*" unless defined?(FILES) 21 | 22 | # File globs to omit from FILES. 23 | OMIT = "Config.rb" unless defined?(OMIT) 24 | 25 | # Standard file patterns. 26 | PATTERNS = { 27 | :root => '{.index,Gemfile}', 28 | :bin => 'bin/*', 29 | :lib => 'lib/{**/}*', #.rb', 30 | :ext => 'ext/{**/}extconf.rb', 31 | :doc => '*.{txt,rdoc,md,markdown,tt,textile}', 32 | :test => '{test,spec}/{**/}*.rb' 33 | } unless defined?(PATTERNS) 34 | 35 | # For which revision of indexer spec is this converter intended? 36 | REVISION = 2013 unless defined?(REVISION) 37 | 38 | # 39 | def self.gemspec 40 | new.to_gemspec 41 | end 42 | 43 | # 44 | attr :metadata 45 | 46 | # 47 | def initialize(metadata=nil) 48 | @root_check = false 49 | 50 | if metadata 51 | root_dir = metadata.delete(:root) 52 | if root_dir 53 | @root = root_dir 54 | @root_check = true 55 | end 56 | metadata = nil if metadata.empty? 57 | end 58 | 59 | @metadata = metadata || YAML.load_file(root + '.index') 60 | 61 | if @metadata['revision'].to_i != REVISION 62 | warn "This gemspec exporter was not designed for this revision of index metadata." 63 | end 64 | end 65 | 66 | # 67 | def has_root? 68 | root ? true : false 69 | end 70 | 71 | # 72 | def root 73 | return @root if @root || @root_check 74 | @root_check = true 75 | @root = find_root 76 | end 77 | 78 | # 79 | def manifest 80 | return nil unless root 81 | @manifest ||= Dir.glob(root + 'manifest{,.txt}', File::FNM_CASEFOLD).first 82 | end 83 | 84 | # 85 | def scm 86 | return nil unless root 87 | @scm ||= %w{git hg}.find{ |m| (root + ".#{m}").directory? }.to_sym 88 | end 89 | 90 | # 91 | def files 92 | return [] unless root 93 | @files ||= \ 94 | if manifest 95 | File.readlines(manifest). 96 | map{ |line| line.strip }. 97 | reject{ |line| line.empty? || line[0,1] == '#' } 98 | else 99 | list = [] 100 | Dir.chdir(root) do 101 | FILES.split(/\s+/).each do |pattern| 102 | list.concat(glob(pattern)) 103 | end 104 | OMIT.split(/\s+/).each do |pattern| 105 | list = list - glob(pattern) 106 | end 107 | end 108 | list 109 | end.select{ |path| File.file?(path) }.uniq 110 | end 111 | 112 | # 113 | def glob_files(pattern) 114 | return [] unless root 115 | Dir.chdir(root) do 116 | Dir.glob(pattern).select do |path| 117 | File.file?(path) && files.include?(path) 118 | end 119 | end 120 | end 121 | 122 | def patterns 123 | PATTERNS 124 | end 125 | 126 | def executables 127 | @executables ||= \ 128 | glob_files(patterns[:bin]).map do |path| 129 | File.basename(path) 130 | end 131 | end 132 | 133 | def extensions 134 | @extensions ||= \ 135 | glob_files(patterns[:ext]).map do |path| 136 | File.basename(path) 137 | end 138 | end 139 | 140 | def name 141 | metadata['name'] || metadata['title'].downcase.gsub(/\W+/,'_') 142 | end 143 | 144 | def homepage 145 | page = ( 146 | metadata['resources'].find{ |r| r['type'] =~ /^home/i } || 147 | metadata['resources'].find{ |r| r['name'] =~ /^home/i } || 148 | metadata['resources'].find{ |r| r['name'] =~ /^web/i } 149 | ) 150 | page ? page['uri'] : false 151 | end 152 | 153 | def licenses 154 | metadata['copyrights'].map{ |c| c['license'] }.compact 155 | end 156 | 157 | def require_paths 158 | paths = metadata['paths'] || {} 159 | paths['load'] || ['lib'] 160 | end 161 | 162 | # 163 | # Convert to gemnspec. 164 | # 165 | def to_gemspec 166 | if has_root? 167 | Gem::Specification.new do |gemspec| 168 | to_gemspec_data(gemspec) 169 | to_gemspec_paths(gemspec) 170 | end 171 | else 172 | Gem::Specification.new do |gemspec| 173 | to_gemspec_data(gemspec) 174 | to_gemspec_paths(gemspec) 175 | end 176 | end 177 | end 178 | 179 | # 180 | # Convert pure data settings. 181 | # 182 | def to_gemspec_data(gemspec) 183 | gemspec.name = name 184 | gemspec.version = metadata['version'] 185 | gemspec.summary = metadata['summary'] 186 | gemspec.description = metadata['description'] 187 | 188 | metadata['authors'].each do |author| 189 | gemspec.authors << author['name'] 190 | 191 | if author.has_key?('email') 192 | if gemspec.email 193 | gemspec.email << author['email'] 194 | else 195 | gemspec.email = [author['email']] 196 | end 197 | end 198 | end 199 | 200 | gemspec.licenses = licenses 201 | 202 | requirements = metadata['requirements'] || [] 203 | requirements.each do |req| 204 | next if req['optional'] 205 | next if req['external'] 206 | 207 | name = req['name'] 208 | groups = req['groups'] || [] 209 | 210 | version = gemify_version(req['version']) 211 | 212 | if groups.empty? or groups.include?('runtime') 213 | # populate runtime dependencies 214 | if gemspec.respond_to?(:add_runtime_dependency) 215 | gemspec.add_runtime_dependency(name,*version) 216 | else 217 | gemspec.add_dependency(name,*version) 218 | end 219 | else 220 | # populate development dependencies 221 | if gemspec.respond_to?(:add_development_dependency) 222 | gemspec.add_development_dependency(name,*version) 223 | else 224 | gemspec.add_dependency(name,*version) 225 | end 226 | end 227 | end 228 | 229 | # convert external dependencies into gemspec requirements 230 | requirements.each do |req| 231 | next unless req['external'] 232 | gemspec.requirements << ("%s-%s" % req.values_at('name', 'version')) 233 | end 234 | 235 | gemspec.homepage = homepage 236 | gemspec.require_paths = require_paths 237 | gemspec.post_install_message = metadata['install_message'] 238 | end 239 | 240 | # 241 | # Set gemspec settings that require a root directory path. 242 | # 243 | def to_gemspec_paths(gemspec) 244 | gemspec.files = files 245 | gemspec.extensions = extensions 246 | gemspec.executables = executables 247 | 248 | if Gem::VERSION < '1.7.' 249 | gemspec.default_executable = gemspec.executables.first 250 | end 251 | 252 | gemspec.test_files = glob_files(patterns[:test]) 253 | 254 | unless gemspec.files.include?('.document') 255 | gemspec.extra_rdoc_files = glob_files(patterns[:doc]) 256 | end 257 | end 258 | 259 | # 260 | # Return a copy of this file. This is used to generate a local 261 | # .gemspec file that can automatically read the index file. 262 | # 263 | def self.source_code 264 | File.read(__FILE__) 265 | end 266 | 267 | private 268 | 269 | def find_root 270 | root_files = patterns[:root] 271 | if Dir.glob(root_files).first 272 | Pathname.new(Dir.pwd) 273 | elsif Dir.glob("../#{root_files}").first 274 | Pathname.new(Dir.pwd).parent 275 | else 276 | #raise "Can't find root of project containing `#{root_files}'." 277 | warn "Can't find root of project containing `#{root_files}'." 278 | nil 279 | end 280 | end 281 | 282 | def glob(pattern) 283 | if File.directory?(pattern) 284 | Dir.glob(File.join(pattern, '**', '*')) 285 | else 286 | Dir.glob(pattern) 287 | end 288 | end 289 | 290 | def gemify_version(version) 291 | case version 292 | when /^(.*?)\+$/ 293 | ">= #{$1}" 294 | when /^(.*?)\-$/ 295 | "< #{$1}" 296 | when /^(.*?)\~$/ 297 | "~> #{$1}" 298 | else 299 | version 300 | end 301 | end 302 | 303 | end 304 | 305 | end 306 | 307 | Indexer::GemspecExporter.gemspec --------------------------------------------------------------------------------