Class: Build::Files::Path

Inherits:
Object
  • Object
show all
Defined in:
lib/build/files/path.rb,
lib/build/files/glob.rb,
lib/build/files/path/filesystem.rb

Overview

Represents a file path with an absolute root and a relative offset:

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

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.



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/build/files/path.rb', line 67

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_pathObject (readonly)

Returns the value of attribute full_path.



98
99
100
# File 'lib/build/files/path.rb', line 98

def full_path
  @full_path
end

#rootObject (readonly)

Returns the value of attribute root.



97
98
99
# File 'lib/build/files/path.rb', line 97

def root
  @root
end

Class Method Details

.[](path) ⇒ Object



62
63
64
# File 'lib/build/files/path.rb', line 62

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.



31
32
33
34
35
36
37
# File 'lib/build/files/path.rb', line 31

def self.components(path)
	if Path === path
		path.components
	else
		path.split(File::SEPARATOR)
	end
end

.join(root, relative_path) ⇒ Object



142
143
144
# File 'lib/build/files/path.rb', line 142

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.



26
27
28
# File 'lib/build/files/path.rb', line 26

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



53
54
55
56
57
58
59
60
# File 'lib/build/files/path.rb', line 53

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:



40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/build/files/path.rb', line 40

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

Instance Method Details

#+(path) ⇒ Object



122
123
124
# File 'lib/build/files/path.rb', line 122

def +(path)
	self.class.new(File.join(@full_path, path), @root)
end

#/(path) ⇒ Object

Define a new root with a sub-path:



127
128
129
# File 'lib/build/files/path.rb', line 127

def /(path)
	self.class.new(File.join(self, path), self)
end

#==(other) ⇒ Object



174
175
176
# File 'lib/build/files/path.rb', line 174

def ==(other)
	self.to_s == other.to_s
end

#append(extension) ⇒ Object



118
119
120
# File 'lib/build/files/path.rb', line 118

def append(extension)
	self.class.new(@full_path + extension, @root)
end

#basenameObject



84
85
86
# File 'lib/build/files/path.rb', line 84

def basename
	self.components.last
end

#componentsObject



80
81
82
# File 'lib/build/files/path.rb', line 80

def components
	@components ||= @full_path.split(File::SEPARATOR)
end

#createObject Also known as: mkpath



60
61
62
# File 'lib/build/files/path/filesystem.rb', line 60

def create
	FileUtils.mkpath self
end

#deleteObject Also known as: rmpath



66
67
68
# File 'lib/build/files/path/filesystem.rb', line 66

def delete
	FileUtils.rm_rf self
end

#directory?Boolean



50
51
52
# File 'lib/build/files/path/filesystem.rb', line 50

def directory?
	File.directory? self
end

#eql?(other) ⇒ Boolean



170
171
172
# File 'lib/build/files/path.rb', line 170

def eql?(other)
	self.class.eql?(other.class) and @root.eql?(other.root) and @full_path.eql?(other.full_path)
end

#exist?Boolean



46
47
48
# File 'lib/build/files/path/filesystem.rb', line 46

def exist?
	File.exist? self
end

#for_appendingObject



186
187
188
# File 'lib/build/files/path.rb', line 186

def for_appending
	[@full_path, File::CREAT|File::APPEND|File::WRONLY]
end

#for_readingObject



178
179
180
# File 'lib/build/files/path.rb', line 178

def for_reading
	[@full_path, File::RDONLY]
end

#for_writingObject



182
183
184
# File 'lib/build/files/path.rb', line 182

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

#hashObject



166
167
168
# File 'lib/build/files/path.rb', line 166

def hash
	[@root, @full_path].hash
end

#inspectObject



162
163
164
# File 'lib/build/files/path.rb', line 162

def inspect
	"#{@root.inspect}/#{relative_path.inspect}"
end

#lengthObject



100
101
102
# File 'lib/build/files/path.rb', line 100

def length
	@full_path.length
end

#modified_timeObject Also known as: mtime



54
55
56
# File 'lib/build/files/path/filesystem.rb', line 54

def modified_time
	File.mtime self
end

#open(mode, &block) ⇒ Object



26
27
28
# File 'lib/build/files/path/filesystem.rb', line 26

def open(mode, &block)
	File.open(self, mode, &block)
end

#partsObject



104
105
106
# File 'lib/build/files/path.rb', line 104

def parts
	@parts ||= @full_path.split(File::SEPARATOR)
end

#read(mode = File::RDONLY) ⇒ Object



30
31
32
33
34
# File 'lib/build/files/path/filesystem.rb', line 30

def read(mode = File::RDONLY)
	open(mode) do |file|
		file.read
	end
end

#rebase(root) ⇒ Object



131
132
133
# File 'lib/build/files/path.rb', line 131

def rebase(root)
	self.class.new(File.join(root, relative_path), root)
end

#relative_partsObject



112
113
114
115
116
# File 'lib/build/files/path.rb', line 112

def relative_parts
	dirname, _, basename = self.relative_path.rpartition(File::SEPARATOR)
	
	return dirname, basename
end

#relative_pathObject



108
109
110
# File 'lib/build/files/path.rb', line 108

def relative_path
	@relative_path ||= Path.relative_path(@root.to_s, @full_path)
end

#shortest_path(root) ⇒ Object



146
147
148
# File 'lib/build/files/path.rb', line 146

def shortest_path(root)
	self.class.shortest_path(self, root)
end

#to_absolute(root) ⇒ Object

Ensure the path has an absolute root if it doesn’t already:



89
90
91
92
93
94
95
# File 'lib/build/files/path.rb', line 89

def to_absolute(root)
	if @root == "."
		self.rebase(root)
	else
		self
	end
end

#to_pathObject



154
155
156
# File 'lib/build/files/path.rb', line 154

def to_path
	@full_path
end

#to_sObject



158
159
160
# File 'lib/build/files/path.rb', line 158

def to_s
	@full_path
end

#to_strObject



150
151
152
# File 'lib/build/files/path.rb', line 150

def to_str
	@full_path
end

#touchObject



42
43
44
# File 'lib/build/files/path/filesystem.rb', line 42

def touch
	FileUtils.touch self
end

#with(root: @root, extension: nil) ⇒ Object



135
136
137
138
139
140
# File 'lib/build/files/path.rb', line 135

def with(root: @root, extension: nil)
	# self.relative_path should be a string so using + to add an extension should be fine.
	relative_path = extension ? self.relative_path + extension : self.relative_path
	
	self.class.new(File.join(root, relative_path), root, relative_path)
end

#write(buffer, mode = File::CREAT|File::TRUNC|File::WRONLY) ⇒ Object



36
37
38
39
40
# File 'lib/build/files/path/filesystem.rb', line 36

def write(buffer, mode = File::CREAT|File::TRUNC|File::WRONLY)
	open(mode) do |file|
		file.write(buffer)
	end
end