Class: Build::Files::Path

Inherits:
Object
  • Object
show all
Defined in:
lib/build/files/path.rb,
lib/build/files/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.



63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/build/files/path.rb', line 63

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

#rootObject (readonly)

Returns the value of attribute root.



90
91
92
# File 'lib/build/files/path.rb', line 90

def root
  @root
end

Class Method Details

.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



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

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)
	
	# 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

#+(extension) ⇒ Object



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

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

#==(other) ⇒ Object



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

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

#componentsObject



77
78
79
# File 'lib/build/files/path.rb', line 77

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

#directory?Boolean

Returns:

  • (Boolean)


29
30
31
# File 'lib/build/files/filesystem.rb', line 29

def directory?
	File.directory? self
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


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

def eql?(other)
	@full_path.eql?(other.to_s)
end

#exist?Boolean

Returns:

  • (Boolean)


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

def exist?
	File.exist? self
end

#for_appendingObject



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

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

#for_readingObject



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

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

#for_writingObject



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

def for_writing
	[@full_path, File::CREAT|File::TRUNC|File::WRONLY]
end

#hashObject



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

def hash
	@full_path.hash
end

#inspectObject



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

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

#mtimeObject



33
34
35
# File 'lib/build/files/filesystem.rb', line 33

def mtime
	File.mtime self
end

#partsObject



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

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

#rebase(root) ⇒ Object



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

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
	basename, _, filename = self.relative_path.rpartition(File::SEPARATOR)
	
	return basename, filename
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



134
135
136
# File 'lib/build/files/path.rb', line 134

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:



82
83
84
85
86
87
88
# File 'lib/build/files/path.rb', line 82

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

#to_pathObject



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

def to_path
	@full_path
end

#to_sObject



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

def to_s
	@full_path
end

#to_strObject



92
93
94
# File 'lib/build/files/path.rb', line 92

def to_str
	@full_path
end

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



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

def with(root: @root, extension: nil)
	self.class.new(File.join(root, extension ? relative_path + extension : relative_path), root)
end