Skip to content

Commit

Permalink
Add File.same?(path1, path2) with follow_symlinks option (#6161)
Browse files Browse the repository at this point in the history
  • Loading branch information
bcardiff committed Jun 4, 2018
1 parent 94bd7bf commit 4e48495
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 5 deletions.
23 changes: 21 additions & 2 deletions spec/std/file_spec.cr
Expand Up @@ -230,21 +230,40 @@ describe "File" do
File.link(in_path, out_path)
File.exists?(out_path).should be_true
File.symlink?(out_path).should be_false
File.info(in_path).should eq(File.info(out_path))
File.same?(in_path, out_path).should be_true
ensure
File.delete(out_path) if File.exists?(out_path)
end
end
end

describe "same?" do
it "compares following symlinks only if requested" do
file = "#{__DIR__}/data/test_file.txt"
symlink = "#{__DIR__}/data/test_file_symlink.txt"
other = "#{__DIR__}/data/test_file.ini"

begin
File.symlink(file, symlink)

File.same?(file, symlink).should be_false
File.same?(file, symlink, follow_symlinks: true).should be_true
File.same?(file, symlink, follow_symlinks: false).should be_false
File.same?(file, other).should be_false
ensure
File.delete(symlink) if File.exists?(symlink)
end
end
end

describe "symlink" do
it "creates a symbolic link" do
in_path = "#{__DIR__}/data/test_file.txt"
out_path = "#{__DIR__}/data/test_file_symlink.txt"
begin
File.symlink(in_path, out_path)
File.symlink?(out_path).should be_true
File.info(in_path).should eq(File.info(out_path))
File.same?(in_path, out_path, follow_symlinks: true).should be_true
ensure
File.delete(out_path) if File.exists?(out_path)
end
Expand Down
2 changes: 1 addition & 1 deletion src/crystal/system/unix/file_info.cr
Expand Up @@ -54,7 +54,7 @@ struct Crystal::System::FileInfo < ::File::Info
@stat.st_gid.to_u32
end

def ==(other : ::File::Info) : Bool
def same_file?(other : ::File::Info) : Bool
@stat.st_dev == other.@stat.st_dev && @stat.st_ino == other.@stat.st_ino
end
end
6 changes: 6 additions & 0 deletions src/file.cr
Expand Up @@ -82,6 +82,12 @@ class File < IO::FileDescriptor
Crystal::System::File.exists?(path)
end

# Returns `true` if *path1* and *path2* represents the same file.
# The comparison take symlinks in consideration if *follow_symlinks* is `true`.
def self.same?(path1 : String, path2 : String, follow_symlinks = false) : Bool
info(path1, follow_symlinks).same_file? info(path2, follow_symlinks)
end

# Returns the size of *filename* bytes. Raises `Errno` if the file at *path*
# does not exist.
#
Expand Down
4 changes: 2 additions & 2 deletions src/file/info.cr
Expand Up @@ -99,11 +99,11 @@ class File
# The group ID that the file belongs to.
abstract def group : UInt32

# Two `File::Info`s are equal if and only if they are of the same file.
# Returns true if this `Info` and *other* are of the same file.
#
# On unix, this compares device and inode fields, and will compare equal for
# hard linked files.
abstract def ==(other : File::Info)
abstract def same_file?(other : File::Info) : Bool

# Returns true if this `Info` represents a standard file. Shortcut for
# `type.file?`.
Expand Down

0 comments on commit 4e48495

Please sign in to comment.