Module: Mutineer::ProjectPath
- Defined in:
- lib/mutineer/project_path.rb
Overview
Realpath-based path normalization against a project root. Shared by the
coverage cache (map keys) and mutant ids (the path hashed into each id), so
lib/x.rb, ./lib/x.rb, an absolute path and a path through a symlinked
root all resolve to the same key. Realpaths on both sides also absorb the
macOS /var vs /private/var alias.
Class Method Summary collapse
-
.absolute(path, root) ⇒ String
Expands
pathagainstroot, resolved to its real path when it exists. -
.relative(path, root) ⇒ String
Path of
pathrelative to the real project root. -
.root_real(root) ⇒ String
Canonical project root (
/varvs/private/var).
Instance Method Summary collapse
-
#absolute(path, root) ⇒ String
private
Expands
pathagainstroot, resolved to its real path when it exists. -
#relative(path, root) ⇒ String
private
Path of
pathrelative to the real project root. -
#root_real(root) ⇒ String
private
Canonical project root (
/varvs/private/var).
Class Method Details
.absolute(path, root) ⇒ String
Expands path against root, resolved to its real path when it exists.
32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/mutineer/project_path.rb', line 32 def absolute(path, root) # Join, don't expand: File.expand_path collapses `..` textually, before any # symlink is followed, so `link/../x.rb` would name the wrong file. The file # system resolves `..` physically in File.realpath. # A leading `~` names the home directory (as File.expand_path reads it), so # expand it rather than joining it under the root. raw = if File.absolute_path?(path) then path elsif path.start_with?("~") then File.(path) else File.join(File.(root), path) end File.exist?(raw) ? File.realpath(raw) : File.(raw) end |
.relative(path, root) ⇒ String
Path of path relative to the real project root. A path outside the root
comes back as its absolute real path.
18 19 20 21 22 23 24 25 |
# File 'lib/mutineer/project_path.rb', line 18 def relative(path, root) abs = absolute(path, root) real_root = root_real(root) prefix = real_root.end_with?("/") ? real_root : "#{real_root}/" return abs unless abs.start_with?(prefix) abs.delete_prefix(prefix) end |
.root_real(root) ⇒ String
Canonical project root (/var vs /private/var). Any file system error
(missing, unreadable, a symlink loop) falls back to the expanded path, so
a caller such as the CLI's run-root warning never crashes on it.
51 52 53 54 55 |
# File 'lib/mutineer/project_path.rb', line 51 def root_real(root) File.realpath(File.(root)) rescue SystemCallError File.(root) end |
Instance Method Details
#absolute(path, root) ⇒ String (private)
Expands path against root, resolved to its real path when it exists.
32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/mutineer/project_path.rb', line 32 def absolute(path, root) # Join, don't expand: File.expand_path collapses `..` textually, before any # symlink is followed, so `link/../x.rb` would name the wrong file. The file # system resolves `..` physically in File.realpath. # A leading `~` names the home directory (as File.expand_path reads it), so # expand it rather than joining it under the root. raw = if File.absolute_path?(path) then path elsif path.start_with?("~") then File.(path) else File.join(File.(root), path) end File.exist?(raw) ? File.realpath(raw) : File.(raw) end |
#relative(path, root) ⇒ String (private)
Path of path relative to the real project root. A path outside the root
comes back as its absolute real path.
18 19 20 21 22 23 24 25 |
# File 'lib/mutineer/project_path.rb', line 18 def relative(path, root) abs = absolute(path, root) real_root = root_real(root) prefix = real_root.end_with?("/") ? real_root : "#{real_root}/" return abs unless abs.start_with?(prefix) abs.delete_prefix(prefix) end |
#root_real(root) ⇒ String (private)
Canonical project root (/var vs /private/var). Any file system error
(missing, unreadable, a symlink loop) falls back to the expanded path, so
a caller such as the CLI's run-root warning never crashes on it.
51 52 53 54 55 |
# File 'lib/mutineer/project_path.rb', line 51 def root_real(root) File.realpath(File.(root)) rescue SystemCallError File.(root) end |