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/paths.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
Convert a path-like object to a Path instance.
-
.components(path) ⇒ Object
Returns a list of components for a path, either represented as a Path instance or a String.
-
.current ⇒ Object
Get the current working directory as a path.
-
.expand(path, root = Dir.getwd) ⇒ Object
Expand a path within a given root.
-
.join(root, relative_path) ⇒ Object
Join a root and relative path to create a new Path.
-
.prefix_length(a, b) ⇒ Object
Returns the length of the prefix which is shared by two strings.
-
.relative_path(root, full_path) ⇒ Object
Compute the relative path from root to full path.
-
.root(path) ⇒ Object
Get the root directory of a path.
-
.shortest_path(path, root) ⇒ Object
Compute the shortest relative path from root to path.
-
.split(path) ⇒ Object
Split a path into directory, filename, and extension components.
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
Compare this path with another for sorting.
-
#append(extension) ⇒ Object
Append an extension to the path.
-
#basename ⇒ Object
Get the basename of the path.
-
#components ⇒ Object
(also: #parts)
Get the path components as an array.
-
#copy(destination) ⇒ Object
Copy the path to a destination.
-
#directory? ⇒ Boolean
Checks if the path refers to a directory.
-
#eql?(other) ⇒ Boolean
Check equality with another path.
-
#exist? ⇒ Boolean
Checks if the file exists in the local file system.
-
#file? ⇒ Boolean
Check if the path refers to a regular file.
-
#for_appending ⇒ Object
Get file opening arguments for appending.
-
#for_reading ⇒ Object
Get file opening arguments for reading.
-
#for_writing ⇒ Object
Get file opening arguments for writing.
-
#glob(pattern) ⇒ Object
Create a glob pattern matcher for files under this path.
-
#hash ⇒ Object
Compute the hash value for this path.
-
#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
Generate a string representation for debugging.
-
#length ⇒ Object
(also: #size)
Get the length of the full path.
-
#list(*relative_paths) ⇒ Object
Create a paths list from relative paths under this path.
-
#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.
-
#parent ⇒ Object
Get the parent directory path.
-
#read(mode = File::RDONLY) ⇒ Object
Read the entire contents of the file.
-
#readable? ⇒ Boolean
Check if the file is readable.
-
#rebase(root) ⇒ Object
Rebase the path to a new root directory.
-
#relative_parts ⇒ Object
Split the relative path into directory and basename components.
-
#relative_path ⇒ Object
Get the relative path from the root.
-
#rm ⇒ Object
(also: #delete)
Recursively delete the given path and all contents.
-
#shortest_path(root) ⇒ Object
Compute the shortest path from this path to a root.
-
#start_with?(*args) ⇒ Boolean
Check if the path starts with the given prefix.
-
#stat ⇒ Object
Get file statistics.
-
#symlink? ⇒ Boolean
Check if the path is a symbolic link.
-
#to_path ⇒ Object
Convert the path to a path string.
-
#to_s ⇒ Object
Convert the path to a string representation.
-
#to_str ⇒ Object
Convert the path to a string.
-
#touch ⇒ Object
Touch the file, changing it’s last modified time.
-
#with(root: @root, extension: nil, basename: false) ⇒ Object
Create a modified path with new root, extension, or basename.
-
#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.
96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/build/files/path.rb', line 96 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 end |
Instance Attribute Details
#full_path ⇒ Object (readonly)
Returns the value of attribute full_path.
110 111 112 |
# File 'lib/build/files/path.rb', line 110 def full_path @full_path end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
109 110 111 |
# File 'lib/build/files/path.rb', line 109 def root @root end |
Class Method Details
.[](path) ⇒ Object
Convert a path-like object to a Path instance.
91 92 93 |
# File 'lib/build/files/path.rb', line 91 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.
33 34 35 36 37 38 39 |
# File 'lib/build/files/path.rb', line 33 def self.components(path) if Path === path path.components else path.split(File::SEPARATOR) end end |
.current ⇒ Object
Get the current working directory as a path.
12 13 14 |
# File 'lib/build/files/path.rb', line 12 def self.current self.new(::Dir.pwd) end |
.expand(path, root = Dir.getwd) ⇒ Object
Expand a path within a given root.
239 240 241 242 243 244 245 |
# File 'lib/build/files/path.rb', line 239 def self.(path, root = Dir.getwd) if path.start_with?(File::SEPARATOR) self.new(path) else self.join(root, path) end end |
.join(root, relative_path) ⇒ Object
Join a root and relative path to create a new Path.
234 235 236 |
# File 'lib/build/files/path.rb', line 234 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.
28 29 30 |
# File 'lib/build/files/path.rb', line 28 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
Compute the relative path from root to full path.
79 80 81 82 83 84 85 86 |
# File 'lib/build/files/path.rb', line 79 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 |
.root(path) ⇒ Object
Get the root directory of a path.
44 45 46 47 48 49 50 |
# File 'lib/build/files/path.rb', line 44 def self.root(path) if Path === path path.root else File.dirname(path) end end |
.shortest_path(path, root) ⇒ Object
Compute the shortest relative path from root to path.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/build/files/path.rb', line 56 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 components = [".."] * up + path_components[i..-1] if components.empty? return "." else return File.join(components) end end |
.split(path) ⇒ Object
Split a path into directory, filename, and extension components.
19 20 21 22 23 24 25 |
# File 'lib/build/files/path.rb', line 19 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.
181 182 183 184 185 186 187 |
# File 'lib/build/files/path.rb', line 181 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.
191 192 193 194 195 196 197 |
# File 'lib/build/files/path.rb', line 191 def /(path) if path self.class.new(File.join(self, path), self) else self.class.new(self, self) end end |
#<=>(other) ⇒ Object
Compare this path with another for sorting.
297 298 299 |
# File 'lib/build/files/path.rb', line 297 def <=>(other) self.to_s <=> other.to_s end |
#append(extension) ⇒ Object
Append an extension to the path.
175 176 177 |
# File 'lib/build/files/path.rb', line 175 def append(extension) self.class.new(@full_path + extension, @root) end |
#basename ⇒ Object
Get the basename of the path.
128 129 130 |
# File 'lib/build/files/path.rb', line 128 def basename self.parts.last end |
#components ⇒ Object Also known as: parts
Get the path components as an array.
122 123 124 |
# File 'lib/build/files/path.rb', line 122 def components @components ||= @full_path.split(File::SEPARATOR).freeze end |
#copy(destination) ⇒ Object
Copy the path to a destination.
35 36 37 38 39 40 41 |
# File 'lib/build/files/system.rb', line 35 def copy(destination) if directory? destination.create else FileUtils.cp(self.to_s, destination.to_s) end end |
#directory? ⇒ Boolean
Checks if the path refers to a directory.
60 61 62 |
# File 'lib/build/files/system.rb', line 60 def directory? File.directory?(self.to_s) end |
#eql?(other) ⇒ Boolean
Check equality with another path.
288 289 290 |
# File 'lib/build/files/path.rb', line 288 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.
55 56 57 |
# File 'lib/build/files/system.rb', line 55 def exist? File.exist?(self.to_s) end |
#file? ⇒ Boolean
Check if the path refers to a regular file.
66 67 68 |
# File 'lib/build/files/system.rb', line 66 def file? File.file?(self.to_s) end |
#for_appending ⇒ Object
Get file opening arguments for appending.
322 323 324 |
# File 'lib/build/files/path.rb', line 322 def for_appending [@full_path, File::CREAT|File::APPEND|File::WRONLY] end |
#for_reading ⇒ Object
Get file opening arguments for reading.
310 311 312 |
# File 'lib/build/files/path.rb', line 310 def for_reading [@full_path, File::RDONLY] end |
#for_writing ⇒ Object
Get file opening arguments for writing.
316 317 318 |
# File 'lib/build/files/path.rb', line 316 def for_writing [@full_path, File::CREAT|File::TRUNC|File::WRONLY] end |
#glob(pattern) ⇒ Object
Create a glob pattern matcher for files under this path.
14 15 16 |
# File 'lib/build/files/glob.rb', line 14 def glob(pattern) Glob.new(self, pattern) end |
#hash ⇒ Object
Compute the hash value for this path.
281 282 283 |
# File 'lib/build/files/path.rb', line 281 def hash [@root, @full_path].hash end |
#inspect ⇒ Object
Generate a string representation for debugging.
275 276 277 |
# File 'lib/build/files/path.rb', line 275 def inspect "#{@root.inspect}/#{relative_path.inspect}" end |
#length ⇒ Object Also known as: size
Get the length of the full path.
114 115 116 |
# File 'lib/build/files/path.rb', line 114 def length @full_path.length end |
#list(*relative_paths) ⇒ Object
Create a paths list from relative paths under this path.
84 85 86 |
# File 'lib/build/files/paths.rb', line 84 def list(*relative_paths) Paths.directory(self, relative_paths) end |
#match(pattern, flags = 0) ⇒ Object
Match a path with a given pattern, using ‘File#fnmatch`.
302 303 304 305 306 |
# File 'lib/build/files/path.rb', line 302 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.
88 89 90 |
# File 'lib/build/files/system.rb', line 88 def mkpath FileUtils.mkpath(self.to_s) end |
#modified_time ⇒ Object
The time the file was last modified.
83 84 85 |
# File 'lib/build/files/system.rb', line 83 def modified_time File.mtime(self.to_s) end |
#open(mode, &block) ⇒ Object
Open a file with the specified mode.
15 16 17 |
# File 'lib/build/files/system.rb', line 15 def open(mode, &block) File.open(self.to_s, mode, &block) end |
#parent ⇒ Object
Get the parent directory path.
134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/build/files/path.rb', line 134 def parent root = @root full_path = File.dirname(@full_path) while root.size > full_path.size root = Path.root(root) end if root.size == full_path.size root = Path.root(root) end self.class.new(full_path, root) end |
#read(mode = File::RDONLY) ⇒ Object
Read the entire contents of the file.
20 21 22 23 24 |
# File 'lib/build/files/system.rb', line 20 def read(mode = File::RDONLY) open(mode) do |file| file.read end end |
#readable? ⇒ Boolean
Check if the file is readable.
78 79 80 |
# File 'lib/build/files/system.rb', line 78 def readable? File.readable?(self.to_s) end |
#rebase(root) ⇒ Object
Rebase the path to a new root directory.
202 203 204 |
# File 'lib/build/files/path.rb', line 202 def rebase(root) self.class.new(File.join(root, relative_path), root) end |
#relative_parts ⇒ Object
Split the relative path into directory and basename components.
166 167 168 169 170 |
# File 'lib/build/files/path.rb', line 166 def relative_parts dirname, _, basename = self.relative_path.rpartition(File::SEPARATOR) return dirname, basename end |
#relative_path ⇒ Object
Get the relative path from the root.
160 161 162 |
# File 'lib/build/files/path.rb', line 160 def relative_path @relative_path ||= Path.relative_path(@root.to_s, @full_path.to_s).freeze end |
#rm ⇒ Object Also known as: delete
Recursively delete the given path and all contents.
95 96 97 |
# File 'lib/build/files/system.rb', line 95 def rm FileUtils.rm_rf(self.to_s) end |
#shortest_path(root) ⇒ Object
Compute the shortest path from this path to a root.
250 251 252 |
# File 'lib/build/files/path.rb', line 250 def shortest_path(root) self.class.shortest_path(self, root) end |
#start_with?(*args) ⇒ Boolean
Check if the path starts with the given prefix.
152 153 154 |
# File 'lib/build/files/path.rb', line 152 def start_with?(*args) @full_path.start_with?(*args) end |
#stat ⇒ Object
Get file statistics.
50 51 52 |
# File 'lib/build/files/system.rb', line 50 def stat File.stat(self.to_s) end |
#symlink? ⇒ Boolean
Check if the path is a symbolic link.
72 73 74 |
# File 'lib/build/files/system.rb', line 72 def symlink? File.symlink?(self.to_s) end |
#to_path ⇒ Object
Convert the path to a path string.
262 263 264 |
# File 'lib/build/files/path.rb', line 262 def to_path @full_path end |
#to_s ⇒ Object
Convert the path to a string representation.
268 269 270 271 |
# File 'lib/build/files/path.rb', line 268 def to_s # It's not guaranteed to be string. @full_path.to_s end |
#to_str ⇒ Object
Convert the path to a string.
256 257 258 |
# File 'lib/build/files/path.rb', line 256 def to_str @full_path.to_str end |
#touch ⇒ Object
Touch the file, changing it’s last modified time.
44 45 46 |
# File 'lib/build/files/system.rb', line 44 def touch FileUtils.touch(self.to_s) end |
#with(root: @root, extension: nil, basename: false) ⇒ Object
Create a modified path with new root, extension, or basename.
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/build/files/path.rb', line 211 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.
27 28 29 30 31 |
# File 'lib/build/files/system.rb', line 27 def write(buffer, mode = File::CREAT|File::TRUNC|File::WRONLY) open(mode) do |file| file.write(buffer) end end |