Skip to content

Commit

Permalink
Rename and rework File::Stat as File::Info (#5584)
Browse files Browse the repository at this point in the history
* Rename and rework File::Stat as File::Info

* fixup! Rename and rework File::Stat as File::Info

* fixup! Rename and rework File::Stat as File::Info
  • Loading branch information
RX14 authored and Serdar Dogruyol committed Apr 14, 2018
1 parent a327907 commit 96bcc34
Show file tree
Hide file tree
Showing 21 changed files with 375 additions and 379 deletions.
161 changes: 91 additions & 70 deletions spec/std/file_spec.cr
Expand Up @@ -224,11 +224,13 @@ describe "File" do

describe "link" do
it "creates a hard link" do
in_path = "#{__DIR__}/data/test_file.txt"
out_path = "#{__DIR__}/data/test_file_link.txt"
begin
File.link("#{__DIR__}/data/test_file.txt", out_path)
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))
ensure
File.delete(out_path) if File.exists?(out_path)
end
Expand All @@ -237,10 +239,12 @@ describe "File" do

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("#{__DIR__}/data/test_file.txt", out_path)
File.symlink(in_path, out_path)
File.symlink?(out_path).should be_true
File.info(in_path).should eq(File.info(out_path))
ensure
File.delete(out_path) if File.exists?(out_path)
end
Expand Down Expand Up @@ -325,7 +329,7 @@ describe "File" do
begin
File.write(path, "")
File.chmod(path, 0o775)
File.stat(path).perm.should eq(0o775)
File.info(path).permissions.should eq(File::Permissions.new(0o775))
ensure
File.delete(path) if File.exists?(path)
end
Expand All @@ -336,20 +340,31 @@ describe "File" do
begin
Dir.mkdir(path, 0o775)
File.chmod(path, 0o664)
File.stat(path).perm.should eq(0o664)
File.info(path).permissions.should eq(File::Permissions.new(0o664))
ensure
Dir.rmdir(path) if Dir.exists?(path)
end
end

it "can take File::Permissions" do
path = "#{__DIR__}/data/chmod.txt"
begin
File.write(path, "")
File.chmod(path, File::Permissions.flags(OwnerAll, GroupAll, OtherExecute, OtherRead))
File.info(path).permissions.should eq(File::Permissions.new(0o775))
ensure
File.delete(path) if File.exists?(path)
end
end

it "follows symlinks" do
path = "#{__DIR__}/data/chmod_destination.txt"
link = "#{__DIR__}/data/chmod.txt"
begin
File.write(path, "")
File.symlink(path, link)
File.chmod(link, 0o775)
File.stat(link).perm.should eq(0o775)
File.info(link).permissions.should eq(File::Permissions.new(0o775))
ensure
File.delete(path) if File.exists?(path)
File.delete(link) if File.symlink?(link)
Expand All @@ -363,83 +378,74 @@ describe "File" do
end
end

it "gets stat for this file" do
stat = File.stat(__FILE__)
stat.blockdev?.should be_false
stat.chardev?.should be_false
stat.directory?.should be_false
stat.file?.should be_true
stat.symlink?.should be_false
stat.socket?.should be_false
it "gets info for this file" do
info = File.info(__FILE__)
info.type.should eq(File::Type::File)
end

it "gets stat for this directory" do
stat = File.stat(__DIR__)
stat.blockdev?.should be_false
stat.chardev?.should be_false
stat.directory?.should be_true
stat.file?.should be_false
stat.symlink?.should be_false
stat.socket?.should be_false
it "gets info for this directory" do
info = File.info(__DIR__)
info.type.should eq(File::Type::Directory)
end

it "gets stat for a character device" do
stat = File.stat("/dev/null")
stat.blockdev?.should be_false
stat.chardev?.should be_true
stat.directory?.should be_false
stat.file?.should be_false
stat.symlink?.should be_false
stat.socket?.should be_false
it "gets info for a character device" do
info = File.info("/dev/null")
info.type.should eq(File::Type::CharacterDevice)
end

it "gets stat for a symlink" do
stat = File.lstat("#{__DIR__}/data/symlink.txt")
stat.blockdev?.should be_false
stat.chardev?.should be_false
stat.directory?.should be_false
stat.file?.should be_false
stat.symlink?.should be_true
stat.socket?.should be_false
it "gets info for a symlink" do
info = File.info("#{__DIR__}/data/symlink.txt", follow_symlinks: false)
info.type.should eq(File::Type::Symlink)
end

it "gets stat for open file" do
it "gets info for open file" do
File.open(__FILE__, "r") do |file|
stat = file.stat
stat.blockdev?.should be_false
stat.chardev?.should be_false
stat.directory?.should be_false
stat.file?.should be_true
stat.symlink?.should be_false
stat.socket?.should be_false
stat.pipe?.should be_false
info = file.info
info.type.should eq(File::Type::File)
end
end

it "gets stat for pipe" do
it "gets info for pipe" do
IO.pipe do |r, w|
r.stat.pipe?.should be_true
w.stat.pipe?.should be_true
r.info.type.should eq(File::Type::Pipe)
w.info.type.should eq(File::Type::Pipe)
end
end

it "gets stat for non-existent file and raises" do
it "gets info for non-existent file and raises" do
expect_raises Errno do
File.stat("non-existent")
File.info("non-existent")
end
end

it "gets stat mtime for new file" do
it "gets info mtime for new file" do
tmp = Tempfile.new "tmp"
begin
(tmp.stat.atime - Time.utc_now).total_seconds.should be < 5
(tmp.stat.ctime - Time.utc_now).total_seconds.should be < 5
(tmp.stat.mtime - Time.utc_now).total_seconds.should be < 5
tmp.info.modification_time.should be_close(Time.now, 5.seconds)
File.info(tmp.path).modification_time.should be_close(Time.now, 5.seconds)
ensure
tmp.delete
end
end

describe "File::Info" do
it "tests equal for the same file" do
File.info(__FILE__).should eq(File.info(__FILE__))
end

it "tests equal for the same directory" do
File.info(__DIR__).should eq(File.info(__DIR__))
end

it "tests unequal for different files" do
File.info(__FILE__).should_not eq(File.info("#{__DIR__}/data/test_file.txt"))
end

it "tests unequal for file and directory" do
File.info(__DIR__).should_not eq(File.info("#{__DIR__}/data/test_file.txt"))
end
end

describe "size" do
it { File.size("#{__DIR__}/data/test_file.txt").should eq(240) }
it do
Expand Down Expand Up @@ -713,11 +719,20 @@ describe "File" do
end
end

it "opens with perm" do
it "opens with perm (int)" do
filename = "#{__DIR__}/data/temp_write.txt"
perm = 0o600
File.open(filename, "w", perm) do |file|
file.stat.perm.should eq(perm)
file.info.permissions.should eq(File::Permissions.new(perm))
end
File.delete filename
end

it "opens with perm (File::Permissions)" do
filename = "#{__DIR__}/data/temp_write.txt"
perm = File::Permissions.flags(OwnerRead, OwnerWrite)
File.open(filename, "w", perm) do |file|
file.info.permissions.should eq(perm)
end
File.delete filename
end
Expand Down Expand Up @@ -920,12 +935,12 @@ describe "File" do
File.rename("baz", "foo\0bar")
end

it_raises_on_null_byte "stat" do
File.stat("foo\0bar")
it_raises_on_null_byte "info" do
File.info("foo\0bar")
end

it_raises_on_null_byte "lstat" do
File.lstat("foo\0bar")
it_raises_on_null_byte "info?" do
File.info?("foo\0bar")
end

it_raises_on_null_byte "exists?" do
Expand Down Expand Up @@ -1071,9 +1086,8 @@ describe "File" do

File.utime(atime, mtime, filename)

stat = File.stat(filename)
stat.atime.should eq(atime)
stat.mtime.should eq(mtime)
info = File.info(filename)
info.modification_time.should eq(mtime)

File.delete filename
end
Expand Down Expand Up @@ -1106,9 +1120,8 @@ describe "File" do
begin
File.touch(filename, time)

stat = File.stat(filename)
stat.atime.should eq(time)
stat.mtime.should eq(time)
info = File.info(filename)
info.modification_time.should eq(time)
ensure
File.delete filename
end
Expand All @@ -1120,9 +1133,8 @@ describe "File" do
begin
File.touch(filename)

stat = File.stat(filename)
stat.atime.should be_close(time, 1.second)
stat.mtime.should be_close(time, 1.second)
info = File.info(filename)
info.modification_time.should be_close(time, 1.second)
ensure
File.delete filename
end
Expand Down Expand Up @@ -1254,4 +1266,13 @@ describe "File" do
File.match?("ab{{c,d}ef,}", "abdef").should be_true
end
end

describe File::Permissions do
it "does to_s" do
perm = File::Permissions.flags(OwnerAll, GroupRead, GroupWrite, OtherRead)
perm.to_s.should eq("rwxrw-r-- (0o764)")
perm.inspect.should eq("rwxrw-r-- (0o764)")
perm.pretty_inspect.should eq("rwxrw-r-- (0o764)")
end
end
end
17 changes: 17 additions & 0 deletions spec/std/file_utils_spec.cr
Expand Up @@ -136,6 +136,23 @@ describe "FileUtils" do
end
end

it "copies permissions" do
src_path = File.join(__DIR__, "data/new_test_file.txt")
out_path = File.join(__DIR__, "data/test_file_cp.txt")
begin
File.write(src_path, "foo")
File.chmod(src_path, 0o700)

FileUtils.cp(src_path, out_path)

File.info(out_path).permissions.should eq(File::Permissions.new(0o700))
FileUtils.cmp(src_path, out_path).should be_true
ensure
File.delete(src_path) if File.exists?(out_path)
File.delete(out_path) if File.exists?(out_path)
end
end

it "raises an error if the directory doesn't exists" do
expect_raises(ArgumentError, "No such directory : not_existing_dir") do
FileUtils.cp({File.join(__DIR__, "data/test_file.text")}, "not_existing_dir")
Expand Down
12 changes: 6 additions & 6 deletions spec/std/http/server/handlers/static_file_handler_spec.cr
Expand Up @@ -24,26 +24,26 @@ describe HTTP::StaticFileHandler do
context "with header If-Modified-Since" do
it "should return 304 Not Modified if file mtime is equal" do
headers = HTTP::Headers.new
headers["If-Modified-Since"] = HTTP.rfc1123_date(File.stat("#{__DIR__}/static/test.txt").mtime)
headers["If-Modified-Since"] = HTTP.rfc1123_date(File.info("#{__DIR__}/static/test.txt").modification_time)
response = handle HTTP::Request.new("GET", "/test.txt", headers), ignore_body: true
response.status_code.should eq(304)
response.headers["Last-Modified"].should eq(HTTP.rfc1123_date(File.stat("#{__DIR__}/static/test.txt").mtime))
response.headers["Last-Modified"].should eq(HTTP.rfc1123_date(File.info("#{__DIR__}/static/test.txt").modification_time))
end

it "should return 304 Not Modified if file mtime is older" do
headers = HTTP::Headers.new
headers["If-Modified-Since"] = HTTP.rfc1123_date(File.stat("#{__DIR__}/static/test.txt").mtime + 1.hour)
headers["If-Modified-Since"] = HTTP.rfc1123_date(File.info("#{__DIR__}/static/test.txt").modification_time + 1.hour)
response = handle HTTP::Request.new("GET", "/test.txt", headers), ignore_body: true
response.status_code.should eq(304)
response.headers["Last-Modified"].should eq(HTTP.rfc1123_date(File.stat("#{__DIR__}/static/test.txt").mtime))
response.headers["Last-Modified"].should eq(HTTP.rfc1123_date(File.info("#{__DIR__}/static/test.txt").modification_time))
end

it "should serve file if file mtime is younger" do
headers = HTTP::Headers.new
headers["If-Modified-Since"] = HTTP.rfc1123_date(File.stat("#{__DIR__}/static/test.txt").mtime - 1.hour)
headers["If-Modified-Since"] = HTTP.rfc1123_date(File.info("#{__DIR__}/static/test.txt").modification_time - 1.hour)
response = handle HTTP::Request.new("GET", "/test.txt")
response.status_code.should eq(200)
response.headers["Last-Modified"].should eq(HTTP.rfc1123_date(File.stat("#{__DIR__}/static/test.txt").mtime))
response.headers["Last-Modified"].should eq(HTTP.rfc1123_date(File.info("#{__DIR__}/static/test.txt").modification_time))
response.body.should eq(File.read("#{__DIR__}/static/test.txt"))
end
end
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/crystal/codegen/cache_dir.cr
Expand Up @@ -107,7 +107,7 @@ module Crystal
private def cleanup_dirs(entries)
entries
.select { |dir| Dir.exists?(dir) }
.sort_by! { |dir| File.stat(dir).mtime rescue Time.epoch(0) }
.sort_by! { |dir| File.info?(dir).try(&.modification_time) || Time.epoch(0) }
.reverse!
.skip(10)
.each { |name| `rm -rf "#{name}"` rescue nil }
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/crystal/macros/macros.cr
Expand Up @@ -158,7 +158,7 @@ class Crystal::Program
# Together with their timestamp
# (this is the list of all effective files that were required)
requires_with_timestamps = result.program.requires.map do |required_file|
epoch = File.stat(required_file).mtime.epoch
epoch = File.info(required_file).modification_time.epoch
RequireWithTimestamp.new(required_file, epoch)
end

Expand Down Expand Up @@ -203,7 +203,7 @@ class Crystal::Program
end

new_requires_with_timestamps = required_files.map do |required_file|
epoch = File.stat(required_file).mtime.epoch
epoch = File.info(required_file).modification_time.epoch
RequireWithTimestamp.new(required_file, epoch)
end

Expand Down
1 change: 1 addition & 0 deletions src/crystal/system/file_info.cr
@@ -0,0 +1 @@
require "./unix/file_info"

0 comments on commit 96bcc34

Please sign in to comment.