From c3e4503581ef35e87c706f2942aca19006a506db Mon Sep 17 00:00:00 2001 From: iain barnett Date: Wed, 7 Jul 2021 02:00:44 +0900 Subject: [PATCH 1/2] Should handle paths too. --- src/xattr.cr | 2 +- src/xattr/xattr.cr | 19 ++++++++----------- 2 files changed, 9 insertions(+), 12 deletions(-) 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..2e6cf7d 100644 --- a/src/xattr/xattr.cr +++ b/src/xattr/xattr.cr @@ -1,44 +1,41 @@ 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 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 From 016290e54bf20d62cbdfe4e5fc0c125a2df02af0 Mon Sep 17 00:00:00 2001 From: iain barnett Date: Wed, 7 Jul 2021 02:33:22 +0900 Subject: [PATCH 2/2] More precision with the errors. refactor: Use File::Error instead of IO::Error to be more precise and provide more debug info. --- spec/xattr_spec.cr | 36 ++++++++++++++++++++++-------------- src/xattr/xattr.cr | 4 ++-- 2 files changed, 24 insertions(+), 16 deletions(-) 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/xattr.cr b/src/xattr/xattr.cr index 2e6cf7d..feeb73f 100644 --- a/src/xattr/xattr.cr +++ b/src/xattr/xattr.cr @@ -2,6 +2,7 @@ module XAttr class XAttr 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) @@ -37,7 +38,6 @@ module XAttr def remove(key) res = bindings.remove(@path.to_s, key, @no_follow) raise_error(res) if res == -1 - res end @@ -54,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