Class: Root
- Inherits:
-
Object
- Object
- Root
- Includes:
- Configurable, Utils
- Defined in:
- lib/root.rb,
lib/root/gems.rb,
lib/root/utils.rb,
lib/root/intern.rb,
lib/root/minimap.rb,
lib/root/constant.rb,
lib/root/manifest.rb,
lib/root/versions.rb,
lib/root/string_ext.rb,
lib/root/constant_manifest.rb
Overview
Root allows you to define a root directory and alias relative paths, so that you can conceptualize what filepaths you need without predefining the full filepaths. Root also simplifies operations on filepaths.
# define a root directory with aliased relative paths
r = Root.new '/root_dir', :input => 'in', :output => 'out'
# work with aliases
r[:input] # => '/root_dir/in'
r[:output] # => '/root_dir/out'
r['implicit'] # => '/root_dir/implicit'
# expanded paths are returned unchanged
r[File.('expanded')] # => File.expand_path('expanded')
# work with filepaths
fp = r.filepath(:input, 'path/to/file.txt') # => '/root_dir/in/path/to/file.txt'
r.relative_filepath(:input, fp) # => 'path/to/file.txt'
r.translate(fp, :input, :output) # => '/root_dir/out/path/to/file.txt'
# version filepaths
r.version('path/to/config.yml', 1.0) # => 'path/to/config-1.0.yml'
r.increment('path/to/config-1.0.yml', 0.1) # => 'path/to/config-1.1.yml'
r.deversion('path/to/config-1.1.yml') # => ['path/to/config.yml', "1.1"]
# absolute paths can also be aliased
r[:abs, true] = "/absolute/path"
r.filepath(:abs, "to", "file.txt") # => '/absolute/path/to/file.txt'
By default, Roots are initialized to the present working directory (Dir.pwd).
–
Implementation Notes
Internally Root expands and stores all aliased paths in the ‘paths’ hash. Expanding paths ensures they remain constant even when the present working directory (Dir.pwd) changes.
Root keeps a separate ‘relative_paths’ hash mapping aliases to their relative paths. This hash allow reassignment if and when the root directory changes. By contrast, there is no separate data structure storing the absolute paths. An absolute path thus has an alias in ‘paths’ but not ‘relative_paths’, whereas relative paths have aliases in both.
These features may be important to note when subclassing Root:
-
root and all filepaths in ‘paths’ are expanded
-
relative paths are stored in ‘relative_paths’
-
absolute paths are present in ‘paths’ but not in ‘relative_paths’
Defined Under Namespace
Modules: Gems, Minimap, StringExt, Utils, Versions Classes: Constant, ConstantManifest, Manifest
Constant Summary collapse
- INTERN_MODULES =
An array of already-declared intern modules, keyed by method_name.
{}
Constants included from Utils
Instance Attribute Summary collapse
-
#path_root ⇒ Object
readonly
The filesystem root, inferred from self.root (ex ‘/’ on *nix or something like ‘C:/’ on Windows).
-
#paths ⇒ Object
readonly
A hash of (alias, expanded path) pairs for expanded relative and absolute paths.
Class Method Summary collapse
-
.Intern(method_name) ⇒ Object
Generates an Intern module for the specified method_name.
Instance Method Summary collapse
-
#[](als) ⇒ Object
Returns the expanded path for the specified alias.
-
#[]=(als, path, absolute = false) ⇒ Object
Sets an alias for the path relative to the root directory.
-
#absolute_paths ⇒ Object
Returns the absolute paths registered with self.
-
#absolute_paths=(paths) ⇒ Object
Sets the absolute paths to those provided.
-
#chdir(als, mkdir = false, &block) ⇒ Object
Changes pwd to the specified directory using Root.chdir.
-
#filepath(als, *paths) ⇒ Object
Resolves the specified alias, joins the paths together, and expands the resulting filepath.
-
#glob(als, *patterns) ⇒ Object
Lists all files along the aliased path matching the input patterns.
-
#initialize(root = Dir.pwd, relative_paths = {}, absolute_paths = {}) ⇒ Root
constructor
Creates a new Root with the given root directory, aliased relative paths and absolute paths.
-
#prepare(als, *paths, &block) ⇒ Object
Constructs a path from the inputs (using filepath) and prepares it using Root.prepare.
-
#relative_filepath(als, path) ⇒ Object
Retrieves the filepath relative to the path of the specified alias.
-
#relative_paths=(paths) ⇒ Object
Sets the relative_paths to those provided.
-
#root=(path) ⇒ Object
Sets the root directory.
-
#subpath(als, *paths) ⇒ Object
Same as filepath but raises an error if the result is not a subpath of the aliased directory.
-
#translate(path, source_als, target_als) ⇒ Object
Generates a filepath translated from the aliased source dir to the aliased target dir.
-
#vglob(als, path, *vpatterns) ⇒ Object
Lists all versions of path in the aliased dir matching the version patterns.
Methods included from Utils
chdir, dirname_or_array, empty?, exchange, expanded?, glob, just_one?, min_join, minimal_match?, minimize, non_version_extname, path_root_type, prepare, relative_filepath, sglob, split, translate, trivial?, vglob
Methods included from Versions
#compare_versions, #deversion, #increment, #version, #vniq
Constructor Details
#initialize(root = Dir.pwd, relative_paths = {}, absolute_paths = {}) ⇒ Root
Creates a new Root with the given root directory, aliased relative paths and absolute paths. By default root is the present working directory and no aliased relative or absolute paths are specified.
79 80 81 82 |
# File 'lib/root.rb', line 79 def initialize(root=Dir.pwd, relative_paths={}, absolute_paths={}) assign_paths(root, relative_paths, absolute_paths) @config = DelegateHash.new(self.class.configurations, {}, self) end |
Instance Attribute Details
#path_root ⇒ Object (readonly)
The filesystem root, inferred from self.root (ex ‘/’ on *nix or something like ‘C:/’ on Windows).
74 75 76 |
# File 'lib/root.rb', line 74 def path_root @path_root end |
#paths ⇒ Object (readonly)
A hash of (alias, expanded path) pairs for expanded relative and absolute paths.
70 71 72 |
# File 'lib/root.rb', line 70 def paths @paths end |
Class Method Details
.Intern(method_name) ⇒ Object
Generates an Intern module for the specified method_name.
An Intern module:
-
adds an accessor for <method_name>_block
-
overrides <method_name> to call the block
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/root/intern.rb', line 9 def self.Intern(method_name) mod = INTERN_MODULES[method_name.to_sym] return mod unless mod == nil mod = INTERN_MODULES[method_name.to_sym] = Module.new mod.module_eval %Q{ attr_accessor :#{method_name}_block def #{method_name}(*inputs) raise "no #{method_name} block set" unless #{method_name}_block inputs.unshift(self) arity = #{method_name}_block.arity n = inputs.length unless n == arity || (arity < 0 && (-1-n) <= arity) raise ArgumentError.new("wrong number of arguments (\#{n} for \#{arity})") end #{method_name}_block.call(*inputs) end } mod end |
Instance Method Details
#[](als) ⇒ Object
Returns the expanded path for the specified alias. If the alias has not been set, then the path is inferred to be ‘root/als’. Expanded paths are returned directly.
r = Root.new '/root_dir', :dir => 'path/to/dir'
r[:dir] # => '/root_dir/path/to/dir'
r.path_root # => '/'
r['relative/path'] # => '/root_dir/relative/path'
r['/expanded/path'] # => '/expanded/path'
179 180 181 182 183 184 185 |
# File 'lib/root.rb', line 179 def [](als) path = self.paths[als] return path unless path == nil als = als.to_s (als) ? als : File.(File.join(root, als)) end |
#[]=(als, path, absolute = false) ⇒ Object
Sets an alias for the path relative to the root directory. The aliases ‘root’ and :root cannot be set with this method (use root= instead). Absolute filepaths can be set using the second syntax.
r = Root.new '/root_dir'
r[:dir] = 'path/to/dir'
r[:dir] # => '/root_dir/path/to/dir'
r[:abs, true] = '/abs/path/to/dir'
r[:abs] # => '/abs/path/to/dir'
– Implementation Note:
The syntax for setting an absolute filepath requires an odd use []=.
In fact the method recieves the arguments (:dir, true, ‘/abs/path/to/dir’) rather than (:dir, ‘/abs/path/to/dir’, true), meaning that internally path and absolute are switched when setting an absolute filepath.
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/root.rb', line 145 def []=(als, path, absolute=false) raise ArgumentError, "the alias #{als.inspect} is reserved" if als.to_s == 'root' # switch the paths if absolute was provided unless absolute == false switch = path path = absolute absolute = switch end case when path.nil? @relative_paths.delete(als) @paths.delete(als) when absolute @relative_paths.delete(als) @paths[als] = File.(path) else @relative_paths[als] = path @paths[als] = File.(File.join(root, path)) end end |
#absolute_paths ⇒ Object
Returns the absolute paths registered with self.
116 117 118 119 120 121 122 123 124 |
# File 'lib/root.rb', line 116 def absolute_paths abs_paths = {} paths.each do |als, path| unless relative_paths.include?(als) || als.to_s == 'root' abs_paths[als] = path end end abs_paths end |
#absolute_paths=(paths) ⇒ Object
Sets the absolute paths to those provided. ‘root’ and :root are reserved aliases and cannot be set using this method (use root= instead).
r = Root.new
r['abs'] # => File.join(r.root, 'abs')
r.absolute_paths = {'abs' => '/path/to/dir'}
r['abs'] # => '/path/to/dir'
110 111 112 113 |
# File 'lib/root.rb', line 110 def absolute_paths=(paths) paths = Validation::HASH[paths] assign_paths(root, relative_paths, paths) end |
#chdir(als, mkdir = false, &block) ⇒ Object
Changes pwd to the specified directory using Root.chdir.
241 242 243 |
# File 'lib/root.rb', line 241 def chdir(als, mkdir=false, &block) super(self[als], mkdir, &block) end |
#filepath(als, *paths) ⇒ Object
Resolves the specified alias, joins the paths together, and expands the resulting filepath.
189 190 191 |
# File 'lib/root.rb', line 189 def filepath(als, *paths) File.(File.join(self[als], *paths)) end |
#glob(als, *patterns) ⇒ Object
Lists all files along the aliased path matching the input patterns. Patterns should join with the aliased path make valid globs for Dir.glob. If no patterns are specified, glob returns all paths matching ‘als/**/*’.
227 228 229 230 231 |
# File 'lib/root.rb', line 227 def glob(als, *patterns) patterns << "**/*" if patterns.empty? patterns.collect! {|pattern| filepath(als, pattern)} super(*patterns) end |
#prepare(als, *paths, &block) ⇒ Object
Constructs a path from the inputs (using filepath) and prepares it using Root.prepare. Returns the path.
247 248 249 |
# File 'lib/root.rb', line 247 def prepare(als, *paths, &block) super(filepath(als, *paths), &block) end |
#relative_filepath(als, path) ⇒ Object
Retrieves the filepath relative to the path of the specified alias.
194 195 196 |
# File 'lib/root.rb', line 194 def relative_filepath(als, path) super(self[als], path) end |
#relative_paths=(paths) ⇒ Object
Sets the relative_paths to those provided. ‘root’ and :root are reserved aliases and cannot be set using this method (use root= instead).
r = Root.new
r['alt'] # => File.join(r.root, 'alt')
r.relative_paths = {'alt' => 'dir'}
r['alt'] # => File.join(r.root, 'dir')
97 98 99 100 |
# File 'lib/root.rb', line 97 def relative_paths=(paths) paths = Validation::HASH[paths] assign_paths(root, paths, absolute_paths) end |
#root=(path) ⇒ Object
Sets the root directory. All paths are reassigned accordingly.
85 86 87 |
# File 'lib/root.rb', line 85 def root=(path) assign_paths(path, relative_paths, absolute_paths) end |
#subpath(als, *paths) ⇒ Object
Same as filepath but raises an error if the result is not a subpath of the aliased directory.
200 201 202 203 204 205 206 207 208 209 |
# File 'lib/root.rb', line 200 def subpath(als, *paths) dir = self[als] path = filepath(als, *paths) if path.rindex(dir, 0) != 0 raise "not a subpath: #{path} (#{dir})" end path end |
#translate(path, source_als, target_als) ⇒ Object
Generates a filepath translated from the aliased source dir to the aliased target dir. Raises an error if the filepath is not relative to the source dir.
r = Root.new '/root_dir'
path = r.filepath(:in, 'path/to/file.txt') # => '/root_dir/in/path/to/file.txt'
r.translate(path, :in, :out) # => '/root_dir/out/path/to/file.txt'
219 220 221 |
# File 'lib/root.rb', line 219 def translate(path, source_als, target_als) super(path, self[source_als], self[target_als]) end |
#vglob(als, path, *vpatterns) ⇒ Object
Lists all versions of path in the aliased dir matching the version patterns. If no patterns are specified, then all versions of path will be returned.
236 237 238 |
# File 'lib/root.rb', line 236 def vglob(als, path, *vpatterns) super(filepath(als, path), *vpatterns) end |