Class: Build::Files::Path
- Inherits:
-
Object
- Object
- Build::Files::Path
- Includes:
- Comparable
- Defined in:
- lib/build/files/path.rb,
lib/build/files/glob.rb,
lib/build/files/system.rb
Overview
Represents a file path with an absolute root and a relative offset:
Instance Attribute Summary collapse
-
#full_path ⇒ Object
readonly
Returns the value of attribute full_path.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
Class Method Summary collapse
- .[](path) ⇒ Object
-
.components(path) ⇒ Object
Returns a list of components for a path, either represented as a Path instance or a String.
-
.expand(subpath, root = Dir.getwd) ⇒ Object
Expand a subpath within a given root, similar to ‘File.expand_path`.
- .join(root, relative_path) ⇒ Object
-
.prefix_length(a, b) ⇒ Object
Returns the length of the prefix which is shared by two strings.
- .relative_path(root, full_path) ⇒ Object
-
.shortest_path(path, root) ⇒ Object
Return the shortest relative path to get to path from root.
- .split(path) ⇒ Object
Instance Method Summary collapse
-
#+(path) ⇒ Object
Add a path component to the current path.
-
#/(path) ⇒ Object
Use the current path to define a new root, with an optional sub-path.
- #<=>(other) ⇒ Object
- #append(extension) ⇒ Object
- #basename ⇒ Object
- #components ⇒ Object (also: #parts)
-
#directory? ⇒ Boolean
Checks if the path refers to a directory.
- #eql?(other) ⇒ Boolean
-
#exist? ⇒ Boolean
Checks if the file exists in the local file system.
- #file? ⇒ Boolean
- #for_appending ⇒ Object
- #for_reading ⇒ Object
- #for_writing ⇒ Object
- #glob(pattern) ⇒ Object
- #hash ⇒ Object
-
#initialize(full_path, root = nil, relative_path = nil) ⇒ Path
constructor
Both paths must be full absolute paths, and path must have root as an prefix.
- #inspect ⇒ Object
- #length ⇒ Object
-
#match(pattern, flags = 0) ⇒ Object
Match a path with a given pattern, using ‘File#fnmatch`.
-
#mkpath ⇒ Object
(also: #create)
Recursively create a directory hierarchy for the given path.
-
#modified_time ⇒ Object
The time the file was last modified.
-
#open(mode, &block) ⇒ Object
Open a file with the specified mode.
-
#read(mode = File::RDONLY) ⇒ Object
Read the entire contents of the file.
- #readable? ⇒ Boolean
- #rebase(root) ⇒ Object
- #relative_parts ⇒ Object
- #relative_path ⇒ Object
-
#rm ⇒ Object
(also: #delete)
Recursively delete the given path and all contents.
- #shortest_path(root) ⇒ Object
- #start_with?(*args) ⇒ Boolean
- #stat ⇒ Object
- #symlink? ⇒ Boolean
- #to_path ⇒ Object
- #to_s ⇒ Object
- #to_str ⇒ Object
-
#touch ⇒ Object
Touch the file, changing it’s last modified time.
- #with(root: @root, extension: nil, basename: false) ⇒ Object
-
#write(buffer, mode = File::CREAT|File::TRUNC|File::WRONLY) ⇒ Object
Write a buffer to the file, creating it if it doesn’t exist.
Constructor Details
#initialize(full_path, root = nil, relative_path = nil) ⇒ Path
Both paths must be full absolute paths, and path must have root as an prefix.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/build/files/path.rb', line 75 def initialize(full_path, root = nil, relative_path = nil) # This is the object identity: @full_path = full_path if root @root = root @relative_path = relative_path else # Effectively dirname and basename: @root, _, @relative_path = full_path.rpartition(File::SEPARATOR) end # This improves the cost of hash/eql? slightly but the root cannot be deconstructed if it was an instance of Path. # @root = @root.to_s end |
Instance Attribute Details
#full_path ⇒ Object (readonly)
Returns the value of attribute full_path.
92 93 94 |
# File 'lib/build/files/path.rb', line 92 def full_path @full_path end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
91 92 93 |
# File 'lib/build/files/path.rb', line 91 def root @root end |
Class Method Details
.[](path) ⇒ Object
70 71 72 |
# File 'lib/build/files/path.rb', line 70 def self.[] path self === path ? path : self.new(path.to_s) end |
.components(path) ⇒ Object
Returns a list of components for a path, either represented as a Path instance or a String.
39 40 41 42 43 44 45 |
# File 'lib/build/files/path.rb', line 39 def self.components(path) if Path === path path.components else path.split(File::SEPARATOR) end end |
.expand(subpath, root = Dir.getwd) ⇒ Object
Expand a subpath within a given root, similar to ‘File.expand_path`
174 175 176 177 178 179 180 |
# File 'lib/build/files/path.rb', line 174 def self.(subpath, root = Dir.getwd) if subpath.start_with? File::SEPARATOR self.new(subpath) else self.join(root, subpath) end end |
.join(root, relative_path) ⇒ Object
169 170 171 |
# File 'lib/build/files/path.rb', line 169 def self.join(root, relative_path) self.new(File.join(root, relative_path), root) end |
.prefix_length(a, b) ⇒ Object
Returns the length of the prefix which is shared by two strings.
34 35 36 |
# File 'lib/build/files/path.rb', line 34 def self.prefix_length(a, b) [a.size, b.size].min.times{|i| return i if a[i] != b[i]} end |
.relative_path(root, full_path) ⇒ Object
61 62 63 64 65 66 67 68 |
# File 'lib/build/files/path.rb', line 61 def self.relative_path(root, full_path) relative_offset = root.length # Deal with the case where the root may or may not end with the path separator: relative_offset += 1 unless root.end_with?(File::SEPARATOR) return full_path.slice(relative_offset..-1) end |
.shortest_path(path, root) ⇒ Object
Return the shortest relative path to get to path from root. Root should be a directory with which you are computing the relative path.
48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/build/files/path.rb', line 48 def self.shortest_path(path, root) path_components = Path.components(path) root_components = Path.components(root) # Find the common prefix: i = prefix_length(path_components, root_components) || 0 # The difference between the root path and the required path, taking into account the common prefix: up = root_components.size - i return File.join([".."] * up + path_components[i..-1]) end |
.split(path) ⇒ Object
25 26 27 28 29 30 31 |
# File 'lib/build/files/path.rb', line 25 def self.split(path) # Effectively dirname and basename: dirname, separator, filename = path.rpartition(File::SEPARATOR) filename, dot, extension = filename.rpartition('.') return dirname + separator, filename, dot + extension end |
Instance Method Details
#+(path) ⇒ Object
Add a path component to the current path.
128 129 130 131 132 133 134 |
# File 'lib/build/files/path.rb', line 128 def +(path) if path self.class.new(File.join(@full_path, path), @root) else self end end |
#/(path) ⇒ Object
Use the current path to define a new root, with an optional sub-path.
138 139 140 141 142 143 144 |
# File 'lib/build/files/path.rb', line 138 def /(path) if path self.class.new(File.join(self, path), self) else self.class.new(self, self) end end |
#<=>(other) ⇒ Object
212 213 214 |
# File 'lib/build/files/path.rb', line 212 def <=>(other) self.to_s <=> other.to_s end |
#append(extension) ⇒ Object
122 123 124 |
# File 'lib/build/files/path.rb', line 122 def append(extension) self.class.new(@full_path + extension, @root) end |
#basename ⇒ Object
102 103 104 |
# File 'lib/build/files/path.rb', line 102 def basename self.parts.last end |
#components ⇒ Object Also known as: parts
98 99 100 |
# File 'lib/build/files/path.rb', line 98 def components @components ||= @full_path.split(File::SEPARATOR).freeze end |
#directory? ⇒ Boolean
Checks if the path refers to a directory.
63 64 65 |
# File 'lib/build/files/system.rb', line 63 def directory? File.directory? self end |
#eql?(other) ⇒ Boolean
206 207 208 |
# File 'lib/build/files/path.rb', line 206 def eql?(other) self.class.eql?(other.class) and @root.eql?(other.root) and @full_path.eql?(other.full_path) end |
#exist? ⇒ Boolean
Checks if the file exists in the local file system.
58 59 60 |
# File 'lib/build/files/system.rb', line 58 def exist? File.exist? self end |
#file? ⇒ Boolean
67 68 69 |
# File 'lib/build/files/system.rb', line 67 def file? File.file? self end |
#for_appending ⇒ Object
231 232 233 |
# File 'lib/build/files/path.rb', line 231 def for_appending [@full_path, File::CREAT|File::APPEND|File::WRONLY] end |
#for_reading ⇒ Object
223 224 225 |
# File 'lib/build/files/path.rb', line 223 def for_reading [@full_path, File::RDONLY] end |
#for_writing ⇒ Object
227 228 229 |
# File 'lib/build/files/path.rb', line 227 def for_writing [@full_path, File::CREAT|File::TRUNC|File::WRONLY] end |
#glob(pattern) ⇒ Object
26 27 28 |
# File 'lib/build/files/glob.rb', line 26 def glob(pattern) Glob.new(self, pattern) end |
#hash ⇒ Object
202 203 204 |
# File 'lib/build/files/path.rb', line 202 def hash [@root, @full_path].hash end |
#inspect ⇒ Object
198 199 200 |
# File 'lib/build/files/path.rb', line 198 def inspect "#{@root.inspect}/#{relative_path.inspect}" end |
#length ⇒ Object
94 95 96 |
# File 'lib/build/files/path.rb', line 94 def length @full_path.length end |
#match(pattern, flags = 0) ⇒ Object
Match a path with a given pattern, using ‘File#fnmatch`.
217 218 219 220 221 |
# File 'lib/build/files/path.rb', line 217 def match(pattern, flags = 0) path = pattern.start_with?('/') ? full_path : relative_path return File.fnmatch(pattern, path, flags) end |
#mkpath ⇒ Object Also known as: create
Recursively create a directory hierarchy for the given path.
85 86 87 |
# File 'lib/build/files/system.rb', line 85 def mkpath FileUtils.mkpath self end |
#modified_time ⇒ Object
The time the file was last modified.
80 81 82 |
# File 'lib/build/files/system.rb', line 80 def modified_time File.mtime self end |
#open(mode, &block) ⇒ Object
Open a file with the specified mode.
30 31 32 |
# File 'lib/build/files/system.rb', line 30 def open(mode, &block) File.open(self, mode, &block) end |
#read(mode = File::RDONLY) ⇒ Object
Read the entire contents of the file.
35 36 37 38 39 |
# File 'lib/build/files/system.rb', line 35 def read(mode = File::RDONLY) open(mode) do |file| file.read end end |
#readable? ⇒ Boolean
75 76 77 |
# File 'lib/build/files/system.rb', line 75 def readable? File.readable? self end |
#rebase(root) ⇒ Object
146 147 148 |
# File 'lib/build/files/path.rb', line 146 def rebase(root) self.class.new(File.join(root, relative_path), root) end |
#relative_parts ⇒ Object
116 117 118 119 120 |
# File 'lib/build/files/path.rb', line 116 def relative_parts dirname, _, basename = self.relative_path.rpartition(File::SEPARATOR) return dirname, basename end |
#relative_path ⇒ Object
112 113 114 |
# File 'lib/build/files/path.rb', line 112 def relative_path @relative_path ||= Path.relative_path(@root.to_s, @full_path).freeze end |
#rm ⇒ Object Also known as: delete
Recursively delete the given path and all contents.
92 93 94 |
# File 'lib/build/files/system.rb', line 92 def rm FileUtils.rm_rf self end |
#shortest_path(root) ⇒ Object
182 183 184 |
# File 'lib/build/files/path.rb', line 182 def shortest_path(root) self.class.shortest_path(self, root) end |
#start_with?(*args) ⇒ Boolean
106 107 108 |
# File 'lib/build/files/path.rb', line 106 def start_with?(*args) @full_path.start_with?(*args) end |
#stat ⇒ Object
53 54 55 |
# File 'lib/build/files/system.rb', line 53 def stat File.stat self end |
#symlink? ⇒ Boolean
71 72 73 |
# File 'lib/build/files/system.rb', line 71 def symlink? File.symlink? self end |
#to_path ⇒ Object
190 191 192 |
# File 'lib/build/files/path.rb', line 190 def to_path @full_path end |
#to_s ⇒ Object
194 195 196 |
# File 'lib/build/files/path.rb', line 194 def to_s @full_path end |
#to_str ⇒ Object
186 187 188 |
# File 'lib/build/files/path.rb', line 186 def to_str @full_path end |
#touch ⇒ Object
Touch the file, changing it’s last modified time.
49 50 51 |
# File 'lib/build/files/system.rb', line 49 def touch FileUtils.touch self end |
#with(root: @root, extension: nil, basename: false) ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/build/files/path.rb', line 150 def with(root: @root, extension: nil, basename: false) relative_path = self.relative_path if basename dirname, filename, _ = self.class.split(relative_path) # Replace the filename if the basename is supplied: filename = basename if basename.is_a? String relative_path = dirname + filename end if extension relative_path = relative_path + extension end self.class.new(File.join(root, relative_path), root, relative_path) end |
#write(buffer, mode = File::CREAT|File::TRUNC|File::WRONLY) ⇒ Object
Write a buffer to the file, creating it if it doesn’t exist.
42 43 44 45 46 |
# File 'lib/build/files/system.rb', line 42 def write(buffer, mode = File::CREAT|File::TRUNC|File::WRONLY) open(mode) do |file| file.write(buffer) end end |