Class: Pod::Sandbox::PathList
- Inherits:
-
Object
- Object
- Pod::Sandbox::PathList
- Defined in:
- lib/cocoapods/sandbox/path_list.rb
Overview
A PathList once it has generated the list of the paths this is updated only if explicitly requested by calling #read_file_system
The PathList class is designed to perform multiple glob matches against a given directory. Basically, it generates a list of all the children paths and matches the globs patterns against them, resulting in just one access to the file system.
Instance Attribute Summary collapse
-
#root ⇒ Pathname
readonly
The root of the list whose files and directories are used to perform the matching operations.
Globbing collapse
-
#glob(patterns, options = {}) ⇒ Array<Pathname>
Similar to #glob but returns the absolute paths.
-
#relative_glob(patterns, options = {}) ⇒ Array<Pathname>
The list of relative paths that are case insensitively matched by a given pattern.
Private helpers collapse
-
#dir_glob_equivalent_patterns(pattern) ⇒ Array<String>
private
The expansion provides support for:.
-
#directory?(sub_path) ⇒ Boolean
private
Wether a path is a directory.
-
#escape_path_for_glob(path) ⇒ Pathname
private
Escapes the glob metacharacters from a given path so it can used in Dir#glob and similar methods.
Instance Method Summary collapse
-
#dirs ⇒ Array<String>
The list of absolute the path of all the directories contained in #root.
-
#files ⇒ Array<String>
The list of absolute the path of all the files contained in #root.
-
#initialize(root) ⇒ PathList
constructor
Initialize a new instance.
-
#read_file_system ⇒ void
Reads the file system and populates the files and paths lists.
Constructor Details
Instance Attribute Details
#root ⇒ Pathname (readonly)
Returns The root of the list whose files and directories are used to perform the matching operations.
19 20 21 |
# File 'lib/cocoapods/sandbox/path_list.rb', line 19 def root @root end |
Instance Method Details
#dir_glob_equivalent_patterns(pattern) ⇒ Array<String> (private)
The expansion provides support for:
Literals
dir_glob_equivalent_patterns('file1,file2.h,m') => ["file1.h", "file1.m", "file2.h", "file2.m"]
Matching the direct children of a directory with
**
dir_glob_equivalent_patterns('Classes//file.m') => ["Classes//file.m", "Classes/file.m"]
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/cocoapods/sandbox/path_list.rb', line 197 def dir_glob_equivalent_patterns(pattern) pattern = pattern.gsub('/**/', '{/**/,/}') values_by_set = {} pattern.scan(/\{[^}]*\}/) do |set| values = set.gsub(/[{}]/, '').split(',') values_by_set[set] = values end if values_by_set.empty? [pattern] else patterns = [pattern] values_by_set.each do |set, values| patterns = patterns.flat_map do |old_pattern| values.map do |value| old_pattern.gsub(set, value) end end end patterns end end |
#directory?(sub_path) ⇒ Boolean (private)
Returns Wether a path is a directory. The result of this method computed without accessing the file system and is case insensitive.
173 174 175 176 |
# File 'lib/cocoapods/sandbox/path_list.rb', line 173 def directory?(sub_path) sub_path = sub_path.to_s.downcase.sub(/\/$/, '') dirs.any? { |dir| dir.downcase == sub_path } end |
#dirs ⇒ Array<String>
Returns The list of absolute the path of all the directories contained in #root.
42 43 44 45 |
# File 'lib/cocoapods/sandbox/path_list.rb', line 42 def dirs read_file_system unless @dirs @dirs end |
#escape_path_for_glob(path) ⇒ Pathname (private)
See CocoaPods/CocoaPods#862.
Escapes the glob metacharacters from a given path so it can used in Dir#glob and similar methods.
230 231 232 233 234 235 236 237 |
# File 'lib/cocoapods/sandbox/path_list.rb', line 230 def escape_path_for_glob(path) result = path.to_s characters_to_escape = ['[', ']', '{', '}', '?', '*'] characters_to_escape.each do |character| result.gsub!(character, "\\#{character}") end Pathname.new(result) end |
#files ⇒ Array<String>
Returns The list of absolute the path of all the files contained in #root.
34 35 36 37 |
# File 'lib/cocoapods/sandbox/path_list.rb', line 34 def files read_file_system unless @files @files end |
#glob(patterns, options = {}) ⇒ Array<Pathname>
Similar to #glob but returns the absolute paths.
93 94 95 96 |
# File 'lib/cocoapods/sandbox/path_list.rb', line 93 def glob(patterns, = {}) cache_key = .merge(:patterns => patterns) @glob_cache[cache_key] ||= relative_glob(patterns, ).map { |p| root.join(p) } end |
#read_file_system ⇒ void
This method returns an undefined value.
Returns Reads the file system and populates the files and paths lists.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/cocoapods/sandbox/path_list.rb', line 50 def read_file_system unless root.exist? raise Informative, "Attempt to read non existent folder `#{root}`." end dirs = [] files = [] root_length = root.cleanpath.to_s.length + File::SEPARATOR.length escaped_root = escape_path_for_glob(root) Dir.glob(escaped_root + '**/*', File::FNM_DOTMATCH).each do |f| directory = File.directory?(f) # Ignore `.` and `..` directories next if directory && f =~ /\.\.?$/ f = f.slice(root_length, f.length - root_length) next if f.nil? (directory ? dirs : files) << f end dirs.sort_by!(&:upcase) files.sort_by!(&:upcase) @dirs = dirs @files = files @glob_cache = {} end |
#relative_glob(patterns, options = {}) ⇒ Array<Pathname>
The list of relative paths that are case insensitively matched by a given pattern. This method emulates Dir#glob with the File::FNM_CASEFOLD option.
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/cocoapods/sandbox/path_list.rb', line 119 def relative_glob(patterns, = {}) return [] if patterns.empty? dir_pattern = [:dir_pattern] exclude_patterns = [:exclude_patterns] include_dirs = [:include_dirs] if include_dirs full_list = files + dirs else full_list = files end patterns_array = Array(patterns) exact_matches = (full_list & patterns_array).to_set unless patterns_array.empty? list = patterns_array.flat_map do |pattern| if exact_matches.include?(pattern) pattern else if directory?(pattern) && dir_pattern pattern += '/' unless pattern.end_with?('/') pattern += dir_pattern end = dir_glob_equivalent_patterns(pattern) full_list.select do |path| .any? do |p| File.fnmatch(p, path, File::FNM_CASEFOLD | File::FNM_PATHNAME) end end end end end list = list.map { |path| Pathname.new(path) } if exclude_patterns = { :dir_pattern => '**/*', :include_dirs => include_dirs } list -= relative_glob(exclude_patterns, ) end list end |