Module: Pathological
- Defined in:
- lib/pathological/base.rb
Defined Under Namespace
Classes: NoPathfileException, PathologicalException
Constant Summary collapse
- PATHFILE_NAME =
"Pathfile"
Class Method Summary collapse
-
.add_paths!(load_path = $LOAD_PATH, paths = nil) ⇒ Object
Add paths to the load path.
- .bundlerize_mode ⇒ Object
-
.copy_outside_paths!(destination, options = {}) ⇒ Object
Copies directories in pathfile to a destination, such that the destination has no references to directories outside of the destination in the load path.
-
.debug_mode ⇒ Object
Convenience functions for the various modes in which Pathological may run.
- .excluderoot_mode ⇒ Object
-
.find_load_paths(pathfile = nil) ⇒ Array<String>
For some pathfile, parse it and find all the load paths that it references.
-
.find_pathfile(directory = nil) ⇒ String?
Find the pathfile by searching up from a starting directory.
- .noexceptions_mode ⇒ Object
- .parentdir_mode ⇒ Object
-
.requiring_filename ⇒ String
Searches the call stack for the file that required pathological.
-
.reset! ⇒ Object
Reset all Pathological options (useful if you want to require a different Pathfile).
Class Method Details
.add_paths!(load_path = $LOAD_PATH, paths = nil) ⇒ Object
Add paths to the load path.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/pathological/base.rb', line 13 def self.add_paths!(load_path = $LOAD_PATH, paths = nil) begin paths ||= find_load_paths rescue NoPathfileException STDERR.puts "Warning: using Pathological, but no Pathfile was found." return end paths.each do |path| if load_path.include? path debug "Skipping <#{path}>, which is already in the load path." else debug "Adding <#{path}> to load path." load_path << path @@loaded_paths << path end end end |
.bundlerize_mode ⇒ Object
136 137 138 139 140 141 142 143 144 |
# File 'lib/pathological/base.rb', line 136 def self.bundlerize_mode pathfile = self.find_pathfile raise NoPathfileException unless pathfile bundle_gemfile = File.join(File.dirname(pathfile), "Gemfile") unless File.file? bundle_gemfile raise PathologicalException, "No Gemfile found in #{File.dirname(pathfile)}." end ENV["BUNDLE_GEMFILE"] = bundle_gemfile end |
.copy_outside_paths!(destination, options = {}) ⇒ Object
Copies directories in pathfile to a destination, such that the destination has no references to directories outside of the destination in the load path.
Hierarchy of destination directory:
destination/
Pathfile # new paths
dependency_directory/
dependency1 # Copied from original location
This is very useful for deployment, for example.
TODO(ev): Break this function up into a set of more functional primitives
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/pathological/base.rb', line 96 def self.copy_outside_paths!(destination, = {}) = { :dependency_directory => "pathological_dependencies" }.merge() saved_exclude_root = @@exclude_root begin self.excluderoot_mode pathfile = self.find_pathfile([:pathfile_search_path]) # Nothing to do if there's no Pathfile return unless pathfile && File.file?(pathfile) foreign_paths = self.find_load_paths(pathfile).uniq return if foreign_paths.empty? path_root = File.join(destination, [:dependency_directory]) FileUtils.mkdir_p path_root # Copy in each path and save the relative paths to write to the rewritten Pathfile. We copy each unique # path into the folder not as the basename, but as the longest suffix of the path necessary to make it # unique. (Otherwise this won't work if you have two entries with the same basename in the Pathfile, # such as "foo/lib" and "bar/lib".) common_prefix = find_longest_common_prefix(foreign_paths) new_pathfile_paths = foreign_paths.map do |foreign_path| path_short_name = foreign_path.gsub(/^#{common_prefix}/, "") symlinked_name = File.join(path_root, path_short_name) FileUtils.mkdir_p File.split(symlinked_name)[0] debug "About to move #{foreign_path} to #{symlinked_name}..." copy_directory(foreign_path, symlinked_name) File.join([:dependency_directory], path_short_name) end # Overwrite the Pathfile with the new relative paths. File.open(File.join(destination, "Pathfile"), "w") do |file| new_pathfile_paths.each { |path| file.puts path } end ensure @@exclude_root = saved_exclude_root end end |
.debug_mode ⇒ Object
Convenience functions for the various modes in which Pathological may run.
135 |
# File 'lib/pathological/base.rb', line 135 def self.debug_mode; @@debug = true; end |
.excluderoot_mode ⇒ Object
147 |
# File 'lib/pathological/base.rb', line 147 def self.excluderoot_mode; @@exclude_root = true; end |
.find_load_paths(pathfile = nil) ⇒ Array<String>
For some pathfile, parse it and find all the load paths that it references.
35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/pathological/base.rb', line 35 def self.find_load_paths(pathfile = nil) pathfile ||= find_pathfile raise NoPathfileException unless pathfile begin pathfile_handle = File.open(pathfile) rescue Errno::ENOENT raise NoPathfileException rescue raise PathologicalException, "There was an error opening the pathfile <#{pathfile}>." end parse_pathfile(pathfile_handle) end |
.find_pathfile(directory = nil) ⇒ String?
Find the pathfile by searching up from a starting directory. Symlinks are expanded out.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/pathological/base.rb', line 52 def self.find_pathfile(directory = nil) # If we're in IRB, use the working directory as the root of the search path for the Pathfile. if $0 != __FILE__ && $0 == "irb" directory = Dir.pwd debug "In IRB -- using the cwd (#{directory}) as the search root for Pathfile." end return nil if directory && !File.directory?(directory) # Find the full, absolute path of this directory, resolving symlinks. If no directory was given, use the # directory where the file requiring pathological resides. full_path = real_path(directory || requiring_filename) current_path = directory ? full_path : File.dirname(full_path) loop do debug "Searching <#{current_path}> for Pathfile." pathfile = File.join(current_path, PATHFILE_NAME) if File.file? pathfile debug "Pathfile found: <#{pathfile}>." return pathfile end new_path = File.dirname current_path if new_path == current_path debug "Reached filesystem root, but no Pathfile found." return nil end current_path = new_path end end |
.noexceptions_mode ⇒ Object
146 |
# File 'lib/pathological/base.rb', line 146 def self.noexceptions_mode; @@no_exceptions = true; end |
.parentdir_mode ⇒ Object
145 |
# File 'lib/pathological/base.rb', line 145 def self.parentdir_mode; @@add_parents = true; end |
.requiring_filename ⇒ String
Searches the call stack for the file that required pathological. If no file can be found, falls back to the currently executing file ($0). This handles the case where the app was launched by another executable (rake, thin, etc.)
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/pathological/base.rb', line 243 def self.requiring_filename # Match paths like .../gems/pathological-0.2.2.1/lib/pathological/base.rb and also # .../gems/pathological-0.2.2.1/lib/pathological.rb pathological_file_pattern = %r{/pathological(/[^/]+|)\.rb} requiring_file = Kernel.caller.find do |stack_line| trimed_ruby_version = RUBY_VERSION[0..3].to_f rescue 1.9 if trimed_ruby_version >= 1.9 # In Ruby >=1.9, top-level files will have the string "top (required)" included in the stack listing. stack_line.include?("top (required)") && stack_line !~ pathological_file_pattern else # In Ruby <=1.8, top-level files are listed with their relative path and without a line number. stack_line !~ /:\d+:in/ && stack_line !~ pathological_file_pattern end end requiring_file ? requiring_file.match(/(.+):\d+/)[1] : $0 rescue $0 end |
.reset! ⇒ Object
Reset all Pathological options (useful if you want to require a different Pathfile)
150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/pathological/base.rb', line 150 def self.reset! # Debug mode -- print out information about load paths @@debug = false # Parentdir mode -- add unique parents of specified directories. @@add_parents = false # Noexceptions mode -- don't raise exceptions if the Pathfile contains bad paths @@no_exceptions = false # Excluderoot mode -- don't add the project root (where the Pathfile lives) to the load path @@exclude_root = false @@loaded_paths ||= [] @@loaded_paths.each { |path| $LOAD_PATH.delete path } @@loaded_paths = [] end |