diff --git a/spec/xattr_spec.cr b/spec/xattr_spec.cr index 455358c..87715c6 100644 --- a/spec/xattr_spec.cr +++ b/spec/xattr_spec.cr @@ -22,18 +22,18 @@ describe XAttr do xattr = XAttr.new(path) {% if flag?(:linux) %} - expect_raises(IO::Error, "Please check the target file: No data available") do + expect_raises(File::Error, "Please check the target file: No data available") do xattr["user.foo"] end {% elsif flag?(:darwin) %} - expect_raises(IO::Error, "Please check the target file: Attribute not found") do + expect_raises(File::Error, "Please check the target file: Attribute not found") do xattr["user.foo"] end {% end %} end it "raises IO Error ENOENT if target file is missing" do - expect_raises(IO::Error, "Please check the target file: No such file or directory") do + expect_raises(File::Error, "Please check the target file: No such file or directory") do xattr = XAttr.new("spec/not_there.txt") xattr[key] end @@ -65,12 +65,12 @@ describe XAttr do file = File.touch(path) {% if flag?(:linux) %} - expect_raises(IO::Error, "Please check the target file: No data available") do + expect_raises(File::Error, "Please check the target file: No data available") do xattr = XAttr.new(path, only_create: true, only_replace: true) xattr[key] = "mytag1" end - expect_raises(IO::Error, "Please check the target file: File exists") do + expect_raises(File::Error, "Please check the target file: File exists") do xattr = XAttr.new(path) xattr[key] = "mytag1" @@ -78,7 +78,7 @@ describe XAttr do xattr[key] = "mytag2" end {% elsif flag?(:darwin) %} - expect_raises(IO::Error, "Please check the target file: Invalid argument") do + expect_raises(File::Error, "Please check the target file: Invalid argument") do xattr = XAttr.new(path, only_create: true, only_replace: true) xattr[key] = "mytag1" end @@ -86,7 +86,7 @@ describe XAttr do end it "raise an exception if the target file is missing" do - expect_raises(IO::Error, "Please check the target file: No such file or directory") do + expect_raises(File::Error, "Please check the target file: No such file or directory") do xattr = XAttr.new("spec/test_dir/not_there.txt") xattr[key] = "mytag1" end @@ -98,7 +98,7 @@ describe XAttr do xattr = XAttr.new(path, only_create: true) xattr[key] = "mytag2" - expect_raises(IO::Error, "Please check the target file: File exists") do + expect_raises(File::Error, "Please check the target file: File exists") do xattr[key] = "mytag2" end end @@ -122,11 +122,11 @@ describe XAttr do xattr = XAttr.new(path, only_replace: true) {% if flag?(:linux) %} - expect_raises(IO::Error, "Please check the target file: No data available") do + expect_raises(File::Error, "Please check the target file: No data available") do xattr["user.xdg.nonexisting"] = "mytag1" end {% elsif flag?(:darwin) %} - expect_raises(IO::Error, "Please check the target file: Attribute not found") do + expect_raises(File::Error, "Please check the target file: Attribute not found") do xattr["user.xdg.nonexisting"] = "mytag1" end {% end %} @@ -158,7 +158,7 @@ describe XAttr do context "with no file" do it "raises IO Error" do - expect_raises(IO::Error, "Please check the target file: No such file or directory") do + expect_raises(File::Error, "Please check the target file: No such file or directory") do xattr = XAttr.new("spec/not_there.txt") xattr.keys end @@ -179,8 +179,16 @@ describe XAttr do end it "raise an exception if the target file is missing" do - expect_raises(IO::Error, "Please check the target file: No such file or directory") do + expect_raises(File::NotFoundError, "Please check the target file: No such file or directory") do xattr = XAttr.new("spec/test_dir/not_there.txt") + end + end + + it "raise an exception if the target file is missing (removed while setting up)" do + expect_raises(File::NotFoundError, "Please check the target file: No such file or directory") do + file = File.touch(path) + xattr = XAttr.new(path) + File.delete path xattr.remove(key) end end @@ -190,11 +198,11 @@ describe XAttr do xattr = XAttr.new(path) {% if flag?(:linux) %} - expect_raises(IO::Error, "Please check the target file: No data available") do + expect_raises(File::Error, "Please check the target file: No data available") do xattr.remove("user.foo") end {% elsif flag?(:darwin) %} - expect_raises(IO::Error, "Please check the target file: Attribute not found") do + expect_raises(File::Error, "Please check the target file: Attribute not found") do xattr.remove("user.foo") end {% end %} diff --git a/src/xattr.cr b/src/xattr.cr index 54aa789..7cc1413 100644 --- a/src/xattr.cr +++ b/src/xattr.cr @@ -5,7 +5,7 @@ require "./xattr/**" module XAttr VERSION = {{ `shards version "#{__DIR__}"`.chomp.stringify }} - def self.new(path : String, no_follow = false, only_create = false, only_replace = false) + def self.new(path : String | Path, no_follow = false, only_create = false, only_replace = false) XAttr.new(path, no_follow: no_follow, only_create: only_create, only_replace: only_replace) end end diff --git a/src/xattr/xattr.cr b/src/xattr/xattr.cr index f94d577..feeb73f 100644 --- a/src/xattr/xattr.cr +++ b/src/xattr/xattr.cr @@ -1,46 +1,43 @@ module XAttr class XAttr - def initialize(path : String, no_follow = false, only_create = false, only_replace = false) - @path = path - @no_follow = no_follow - @only_create = only_create - @only_replace = only_replace + def initialize(@path : String | Path, @no_follow = false, @only_create = false, @only_replace = false) + @path = Path.new(@path).expand + raise File::NotFoundError.from_errno("Please check the target file: No such file or directory", file: @path) unless File.exists? @path end def [](key) - size = bindings.get(@path, key, nil, 0, @no_follow) + size = bindings.get(@path.to_s, key, nil, 0, @no_follow) raise_error(size) if size == -1 return unless size > 0 ptr = Slice(LibC::Char).new(size) - res = bindings.get(@path, key, ptr, size, @no_follow) + res = bindings.get(@path.to_s, key, ptr, size, @no_follow) raise_error(res) if res == -1 String.new(ptr) end def []=(key, value) - res = bindings.set(@path, key, value, value.bytesize, @no_follow, @only_create, @only_replace) + res = bindings.set(@path.to_s, key, value, value.bytesize, @no_follow, @only_create, @only_replace) raise_error(res) if res == -1 res end def keys - size = bindings.list(@path, nil, 0, @no_follow) + size = bindings.list(@path.to_s, nil, 0, @no_follow) raise_error(size) if size == -1 return [] of String unless size > 0 ptr = Slice(LibC::Char).new(size) - bindings.list(@path, ptr, size, @no_follow) + bindings.list(@path.to_s, ptr, size, @no_follow) String.new(ptr).split("\000", remove_empty: true).sort end def remove(key) - res = bindings.remove(@path, key, @no_follow) + res = bindings.remove(@path.to_s, key, @no_follow) raise_error(res) if res == -1 - res end @@ -57,7 +54,7 @@ module XAttr end private def raise_error(res) - raise IO::Error.from_errno("Please check the target file") + raise File::Error.from_errno("Please check the target file", file: @path) end private def bindings