Created
May 26, 2018 21:07
-
-
Save bbg/018f4f5423befa19a7c05d1433bc4c47 to your computer and use it in GitHub Desktop.
Some Crystal File add-ons
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module FileX | |
def self.mount?(path) | |
begin | |
stat_path = File.lstat(path) | |
rescue Errno | |
# It doesn't exist so not a mount point | |
return false | |
end | |
# A symlink can never be a mount point | |
if (stat_path.mode & LibC::S_IFMT) == LibC::S_IFLNK | |
return false | |
end | |
parent = File.real_path(File.join(path, "..")) | |
begin | |
stat_parent = File.lstat(parent) | |
rescue Errno | |
return false | |
end | |
# Parent path on a different device to path | |
if stat_path.dev != stat_parent.dev | |
return true | |
end | |
# Parent path is the same i-node as path | |
if stat_path.ino == stat_parent.ino | |
return true | |
end | |
return false | |
end | |
# Given a list of path names, returns the longest common leading component | |
def self.common_prefix(paths : Array(Array(String))) : Array(String) | |
if paths.empty? | |
return [] of String | |
end | |
path_min = paths.min | |
path_max = paths.max | |
path_min.each_with_index do |path, index| | |
if path != path_max[index] | |
return path_min[0, index] | |
end | |
end | |
return path_min | |
end | |
# Return a relative version of a path | |
def self.relative_path(path : String, start : Nil | String = nil) | |
current_dir = "." | |
parent_dir = ".." | |
start = current_dir unless start | |
# Ensure both paths are absolute | |
unless path.starts_with?(File::SEPARATOR) | |
path = File.join(Dir.current, path) | |
end | |
path = File.expand_path(path) | |
unless start.starts_with?(File::SEPARATOR) | |
start = File.join(Dir.current, start) | |
end | |
start = File.expand_path(start) | |
# Break up paths into their parts (ensuring no empty parts) | |
path_parts = path.split(File::SEPARATOR).reject { |p| p.empty? } | |
start_parts = start.split(File::SEPARATOR).reject { |p| p.empty? } | |
# Work out how much of the file path is shared by start and path | |
index = common_prefix([start_parts, path_parts]).size | |
relative_parts = [parent_dir] * (start_parts.size - index) + path_parts[index..-1] | |
if relative_parts.empty? | |
return current_dir | |
end | |
return File.join(relative_parts) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment