2017-08-14 13:08:09 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2019-12-05 09:06:14 -05:00
|
|
|
require "pathname"
|
|
|
|
|
2009-06-26 18:36:38 -04:00
|
|
|
module Rails
|
2010-01-23 16:30:17 -05:00
|
|
|
module Paths
|
2011-07-23 06:14:10 -04:00
|
|
|
# This object is an extended hash that behaves as root of the <tt>Rails::Paths</tt> system.
|
2010-10-06 11:18:59 -04:00
|
|
|
# It allows you to collect information about how you want to structure your application
|
2016-12-20 17:19:34 -05:00
|
|
|
# paths through a Hash-like API. It requires you to give a physical path on initialization.
|
2010-10-06 11:18:59 -04:00
|
|
|
#
|
2011-05-25 04:38:51 -04:00
|
|
|
# root = Root.new "/rails"
|
2013-02-19 02:22:37 -05:00
|
|
|
# root.add "app/controllers", eager_load: true
|
2010-10-06 11:18:59 -04:00
|
|
|
#
|
2016-12-20 17:19:34 -05:00
|
|
|
# The above command creates a new root object and adds "app/controllers" as a path.
|
2012-04-27 03:00:30 -04:00
|
|
|
# This means we can get a <tt>Rails::Paths::Path</tt> object back like below:
|
2010-10-06 11:18:59 -04:00
|
|
|
#
|
|
|
|
# path = root["app/controllers"]
|
2013-02-19 02:22:37 -05:00
|
|
|
# path.eager_load? # => true
|
2011-05-04 14:08:21 -04:00
|
|
|
# path.is_a?(Rails::Paths::Path) # => true
|
2010-10-06 11:18:59 -04:00
|
|
|
#
|
2012-03-26 20:25:44 -04:00
|
|
|
# The +Path+ object is simply an enumerable and allows you to easily add extra paths:
|
2010-10-06 11:18:59 -04:00
|
|
|
#
|
2012-03-26 20:25:44 -04:00
|
|
|
# path.is_a?(Enumerable) # => true
|
|
|
|
# path.to_ary.inspect # => ["app/controllers"]
|
2010-10-06 11:18:59 -04:00
|
|
|
#
|
|
|
|
# path << "lib/controllers"
|
2012-03-26 20:25:44 -04:00
|
|
|
# path.to_ary.inspect # => ["app/controllers", "lib/controllers"]
|
2010-10-06 11:18:59 -04:00
|
|
|
#
|
2011-07-23 06:14:10 -04:00
|
|
|
# Notice that when you add a path using +add+, the path object created already
|
|
|
|
# contains the path with the same path value given to +add+. In some situations,
|
2014-01-06 05:47:49 -05:00
|
|
|
# you may not want this behavior, so you can give <tt>:with</tt> as option.
|
2010-10-06 11:18:59 -04:00
|
|
|
#
|
2012-10-14 06:03:39 -04:00
|
|
|
# root.add "config/routes", with: "config/routes.rb"
|
2011-05-04 14:08:21 -04:00
|
|
|
# root["config/routes"].inspect # => ["config/routes.rb"]
|
2010-10-06 11:18:59 -04:00
|
|
|
#
|
2011-07-23 06:14:10 -04:00
|
|
|
# The +add+ method accepts the following options as arguments:
|
2016-09-17 15:36:13 -04:00
|
|
|
# eager_load, autoload, autoload_once, and glob.
|
2010-10-06 11:18:59 -04:00
|
|
|
#
|
2011-07-23 06:14:10 -04:00
|
|
|
# Finally, the +Path+ object also provides a few helpers:
|
2010-10-06 11:18:59 -04:00
|
|
|
#
|
2011-05-25 04:38:51 -04:00
|
|
|
# root = Root.new "/rails"
|
2010-10-06 11:18:59 -04:00
|
|
|
# root.add "app/controllers"
|
|
|
|
#
|
2011-05-04 14:08:21 -04:00
|
|
|
# root["app/controllers"].expanded # => ["/rails/app/controllers"]
|
|
|
|
# root["app/controllers"].existent # => ["/rails/app/controllers"]
|
2010-10-06 11:18:59 -04:00
|
|
|
#
|
2011-07-23 06:14:10 -04:00
|
|
|
# Check the <tt>Rails::Paths::Path</tt> documentation for more information.
|
2012-03-26 20:56:16 -04:00
|
|
|
class Root
|
2009-10-13 20:47:18 -04:00
|
|
|
attr_accessor :path
|
|
|
|
|
2009-06-26 18:36:38 -04:00
|
|
|
def initialize(path)
|
2009-10-13 20:47:18 -04:00
|
|
|
@path = path
|
2012-03-26 20:56:16 -04:00
|
|
|
@root = {}
|
2010-10-06 11:18:59 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def []=(path, value)
|
2012-06-29 10:47:44 -04:00
|
|
|
glob = self[path] ? self[path].glob : nil
|
2012-10-14 06:03:39 -04:00
|
|
|
add(path, with: value, glob: glob)
|
2010-10-06 11:18:59 -04:00
|
|
|
end
|
|
|
|
|
2013-01-08 23:22:18 -05:00
|
|
|
def add(path, options = {})
|
|
|
|
with = Array(options.fetch(:with, path))
|
2013-01-02 10:03:23 -05:00
|
|
|
@root[path] = Path.new(self, path, with, options)
|
2012-03-26 20:56:16 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def [](path)
|
|
|
|
@root[path]
|
|
|
|
end
|
|
|
|
|
|
|
|
def values
|
|
|
|
@root.values
|
|
|
|
end
|
|
|
|
|
|
|
|
def keys
|
|
|
|
@root.keys
|
|
|
|
end
|
|
|
|
|
|
|
|
def values_at(*list)
|
|
|
|
@root.values_at(*list)
|
2009-06-26 20:32:05 -04:00
|
|
|
end
|
|
|
|
|
2010-01-24 03:00:18 -05:00
|
|
|
def all_paths
|
2014-10-27 12:28:53 -04:00
|
|
|
values.tap(&:uniq!)
|
2009-06-26 20:32:05 -04:00
|
|
|
end
|
|
|
|
|
2010-06-27 18:57:47 -04:00
|
|
|
def autoload_once
|
2014-10-27 12:28:53 -04:00
|
|
|
filter_by(&:autoload_once?)
|
2009-06-26 20:32:05 -04:00
|
|
|
end
|
|
|
|
|
2010-01-24 03:00:18 -05:00
|
|
|
def eager_load
|
2014-10-27 12:28:53 -04:00
|
|
|
filter_by(&:eager_load?)
|
2009-06-26 20:32:05 -04:00
|
|
|
end
|
|
|
|
|
2010-06-27 18:57:47 -04:00
|
|
|
def autoload_paths
|
2014-10-27 12:28:53 -04:00
|
|
|
filter_by(&:autoload?)
|
2010-06-27 18:57:47 -04:00
|
|
|
end
|
|
|
|
|
2009-06-26 20:32:05 -04:00
|
|
|
def load_paths
|
2014-10-27 12:28:53 -04:00
|
|
|
filter_by(&:load_path?)
|
2009-06-26 20:32:05 -04:00
|
|
|
end
|
|
|
|
|
2013-10-22 14:00:55 -04:00
|
|
|
private
|
2013-10-22 13:35:32 -04:00
|
|
|
def filter_by(&block)
|
|
|
|
all_paths.find_all(&block).flat_map { |path|
|
|
|
|
paths = path.existent
|
2014-03-03 22:23:29 -05:00
|
|
|
paths - path.children.flat_map { |p| yield(p) ? [] : p.existent }
|
2013-10-22 13:35:32 -04:00
|
|
|
}.uniq
|
2010-01-24 03:00:18 -05:00
|
|
|
end
|
2009-06-26 18:36:38 -04:00
|
|
|
end
|
|
|
|
|
2012-03-26 20:25:44 -04:00
|
|
|
class Path
|
|
|
|
include Enumerable
|
|
|
|
|
2009-06-26 18:36:38 -04:00
|
|
|
attr_accessor :glob
|
|
|
|
|
2012-03-26 18:58:03 -04:00
|
|
|
def initialize(root, current, paths, options = {})
|
2018-11-07 18:12:17 -05:00
|
|
|
@paths = paths
|
|
|
|
@current = current
|
|
|
|
@root = root
|
|
|
|
@glob = options[:glob]
|
|
|
|
@exclude = options[:exclude]
|
2009-07-06 13:04:57 -04:00
|
|
|
|
2011-01-09 13:54:03 -05:00
|
|
|
options[:autoload_once] ? autoload_once! : skip_autoload_once!
|
2013-02-19 02:22:37 -05:00
|
|
|
options[:eager_load] ? eager_load! : skip_eager_load!
|
2011-01-09 13:54:03 -05:00
|
|
|
options[:autoload] ? autoload! : skip_autoload!
|
|
|
|
options[:load_path] ? load_path! : skip_load_path!
|
2009-11-06 20:21:39 -05:00
|
|
|
end
|
|
|
|
|
2015-08-16 08:14:45 -04:00
|
|
|
def absolute_current # :nodoc:
|
2015-08-04 11:53:15 -04:00
|
|
|
File.expand_path(@current, @root.path)
|
|
|
|
end
|
|
|
|
|
2010-10-06 11:18:59 -04:00
|
|
|
def children
|
2013-10-22 13:39:56 -04:00
|
|
|
keys = @root.keys.find_all { |k|
|
|
|
|
k.start_with?(@current) && k != @current
|
|
|
|
}
|
2010-10-06 11:18:59 -04:00
|
|
|
@root.values_at(*keys.sort)
|
2009-06-26 18:36:38 -04:00
|
|
|
end
|
|
|
|
|
2010-10-06 11:18:59 -04:00
|
|
|
def first
|
|
|
|
expanded.first
|
2009-06-26 18:36:38 -04:00
|
|
|
end
|
|
|
|
|
2010-10-06 11:18:59 -04:00
|
|
|
def last
|
|
|
|
expanded.last
|
2009-06-30 16:55:11 -04:00
|
|
|
end
|
|
|
|
|
2013-02-19 02:22:37 -05:00
|
|
|
%w(autoload_once eager_load autoload load_path).each do |m|
|
2010-07-17 03:54:34 -04:00
|
|
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
2013-02-19 02:22:37 -05:00
|
|
|
def #{m}! # def eager_load!
|
|
|
|
@#{m} = true # @eager_load = true
|
2011-05-04 14:12:29 -04:00
|
|
|
end # end
|
|
|
|
#
|
2013-02-19 02:22:37 -05:00
|
|
|
def skip_#{m}! # def skip_eager_load!
|
|
|
|
@#{m} = false # @eager_load = false
|
2011-05-04 14:12:29 -04:00
|
|
|
end # end
|
|
|
|
#
|
2013-02-19 02:22:37 -05:00
|
|
|
def #{m}? # def eager_load?
|
|
|
|
@#{m} # @eager_load
|
2011-05-04 14:12:29 -04:00
|
|
|
end # end
|
2010-07-17 03:54:34 -04:00
|
|
|
RUBY
|
2009-06-26 20:32:05 -04:00
|
|
|
end
|
|
|
|
|
2012-03-26 20:25:44 -04:00
|
|
|
def each(&block)
|
2012-03-31 14:10:27 -04:00
|
|
|
@paths.each(&block)
|
2012-03-26 20:25:44 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def <<(path)
|
|
|
|
@paths << path
|
|
|
|
end
|
|
|
|
alias :push :<<
|
|
|
|
|
|
|
|
def concat(paths)
|
|
|
|
@paths.concat paths
|
|
|
|
end
|
|
|
|
|
2014-11-12 03:27:42 -05:00
|
|
|
def unshift(*paths)
|
|
|
|
@paths.unshift(*paths)
|
2012-03-26 20:25:44 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def to_ary
|
|
|
|
@paths
|
|
|
|
end
|
|
|
|
|
2019-12-05 09:06:14 -05:00
|
|
|
def paths
|
|
|
|
raise "You need to set a path root" unless @root.path
|
|
|
|
|
|
|
|
map do |p|
|
|
|
|
Pathname.new(@root.path).join(p)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-08-16 08:14:45 -04:00
|
|
|
def extensions # :nodoc:
|
2016-08-06 13:15:47 -04:00
|
|
|
$1.split(",") if @glob =~ /\{([\S]+)\}/
|
2015-08-04 11:53:15 -04:00
|
|
|
end
|
|
|
|
|
2010-10-06 11:18:59 -04:00
|
|
|
# Expands all paths against the root and return all unique values.
|
|
|
|
def expanded
|
2009-10-13 20:47:18 -04:00
|
|
|
raise "You need to set a path root" unless @root.path
|
2010-10-06 11:18:59 -04:00
|
|
|
result = []
|
2010-04-05 06:30:59 -04:00
|
|
|
|
2018-11-07 18:12:17 -05:00
|
|
|
each do |path|
|
|
|
|
path = File.expand_path(path, @root.path)
|
2010-10-06 11:18:59 -04:00
|
|
|
|
2012-03-26 19:08:33 -04:00
|
|
|
if @glob && File.directory?(path)
|
2018-11-07 18:12:17 -05:00
|
|
|
result.concat files_in(path)
|
2010-10-06 11:18:59 -04:00
|
|
|
else
|
|
|
|
result << path
|
|
|
|
end
|
2009-06-26 18:36:38 -04:00
|
|
|
end
|
2010-04-05 06:30:59 -04:00
|
|
|
|
2010-01-22 10:24:44 -05:00
|
|
|
result.uniq!
|
|
|
|
result
|
2009-06-26 18:36:38 -04:00
|
|
|
end
|
|
|
|
|
2010-10-06 11:18:59 -04:00
|
|
|
# Returns all expanded paths but only if they exist in the filesystem.
|
|
|
|
def existent
|
2017-03-14 18:16:32 -04:00
|
|
|
expanded.select do |f|
|
|
|
|
does_exist = File.exist?(f)
|
|
|
|
|
|
|
|
if !does_exist && File.symlink?(f)
|
|
|
|
raise "File #{f.inspect} is a symlink that does not point to a valid file"
|
|
|
|
end
|
|
|
|
does_exist
|
|
|
|
end
|
2010-10-06 11:18:59 -04:00
|
|
|
end
|
2011-08-01 20:29:03 -04:00
|
|
|
|
2011-08-01 15:32:17 -04:00
|
|
|
def existent_directories
|
2011-08-01 20:29:03 -04:00
|
|
|
expanded.select { |d| File.directory?(d) }
|
2011-08-01 15:32:17 -04:00
|
|
|
end
|
2010-10-06 11:18:59 -04:00
|
|
|
|
|
|
|
alias to_a expanded
|
2018-11-07 18:12:17 -05:00
|
|
|
|
|
|
|
private
|
|
|
|
def files_in(path)
|
2019-07-21 01:59:00 -04:00
|
|
|
files = Dir.glob(@glob, base: path)
|
|
|
|
files -= @exclude if @exclude
|
|
|
|
files.map! { |file| File.join(path, file) }
|
|
|
|
files.sort
|
2018-11-07 18:12:17 -05:00
|
|
|
end
|
2009-06-26 18:36:38 -04:00
|
|
|
end
|
|
|
|
end
|
2010-10-06 11:50:31 -04:00
|
|
|
end
|