extattr 0.2 → 0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/gemstub.rb ADDED
@@ -0,0 +1,22 @@
1
+ unless version = File.read("README.md").scan(/^\s*[\*\-]\s*version:{1,2}\s*(.+)/i).flatten[-1]
2
+ raise "バージョン情報が README.md に見つかりません"
3
+ end
4
+
5
+ DOC << "QUICKREF.ja.md"
6
+
7
+ GEMSTUB = Gem::Specification.new do |s|
8
+ s.name = "extattr"
9
+ s.version = version
10
+ s.summary = "extended file attribute manipurator"
11
+ s.description = <<-EOS
12
+ "extattr" is extended file attribute manipurator for Ruby.
13
+ Supported for FreeBSD (extattr), GNU/Linux (xattr) and Microsoft Windows (NTFS Alternative Data Stream (ADS) + NTFS Extended Attributes (EA)).
14
+ EOS
15
+ s.homepage = "https://github.com/dearblue/ruby-extattr"
16
+ s.license = "BSD-2-Clause"
17
+ s.author = "dearblue"
18
+ s.email = "dearblue@users.osdn.me"
19
+
20
+ s.add_development_dependency "rake", "~> 0"
21
+ s.add_development_dependency "test-unit", "~> 0"
22
+ end
data/lib/extattr.rb CHANGED
@@ -1,57 +1,274 @@
1
- #vim: set fileencoding:utf-8
1
+ #!ruby
2
2
 
3
- ver = RbConfig::CONFIG["ruby_version"]
3
+ ver = RUBY_VERSION.slice(/\d+\.\d+/)
4
4
  soname = File.basename(__FILE__, ".rb") << ".so"
5
- lib = File.join(File.dirname(__FILE__), ver, soname)
6
- if File.file?(lib)
7
- require_relative File.join(ver, soname)
8
- else
9
- require_relative soname
5
+ lib = File.join(ver, soname)
6
+ begin
7
+ require_relative lib
8
+ rescue LoadError
9
+ require lib
10
10
  end
11
11
 
12
12
  #
13
- # Add operation methods of extended file attribute to File.
13
+ # Add operation methods of filesystem extended attributes to File.
14
14
  #
15
- # File クラスに拡張属性を操作するメソッドを追加します。
15
+ # === 名前空間の指定について
16
16
  #
17
- # 感嘆符 (『!』) のついたメソッドは、シンボリックリンクに対する操作となります。
17
+ # 拡張属性の名前空間を指定する場合、以下の値が利用できます:
18
18
  #
19
- # メソッドにキーワード引数として <code>namespace:</code> を与えることにより、拡張属性の名前空間を指定することが出来ます。
19
+ # * ExtAttr::USER, ExtAttr::SYSTEM
20
+ # * 文字列又はシンボルで +user+、+system+ (大文字小文字を区別しません)
20
21
  #
21
- # 現在の実装においては <code>EXTATTR_NAMESPACE_USER</code> と <code>EXTATTR_NAMESPACE_SYSTEM</code> のみが利用可能です。
22
+ # これらの値は内部で変換、または処理が分岐されます。
22
23
  #
23
- class File
24
+ # extattr::
25
+ # 整数値に変換されて処理されます。
26
+ #
27
+ # xattr::
28
+ # 拡張属性名に "user." または "system." を追加して処理されます。
29
+ #
30
+ # Windows::
31
+ # ExtAttr::USER の場合は NTFS Alternative Data Stream (ADS) として処理されます。
32
+ #
33
+ # ExtAttr::SYSTEM の場合は NTFS Extended Attribute (EA) として処理されます。
34
+ #
35
+ module ExtAttr
36
+ ExtAttr = self
37
+
38
+ def self.open(path)
39
+ if path.kind_of?(File)
40
+ ea = ExtAttr::Accessor[path, path.to_path]
41
+ block_given? ? yield(ea) : ea
42
+ else
43
+ if block_given?
44
+ ::File.open(path) do |file|
45
+ return yield(ExtAttr::Accessor[file, path])
46
+ end
47
+ else
48
+ ExtAttr::Accessor[::File.open(path), path]
49
+ end
50
+ end
51
+ end
52
+
24
53
  #
25
54
  # call-seq:
26
- # extattr_each(path, namespace: File::EXTATTR_NAMESPACE_USER) -> Enumerator
27
- # extattr_each(path, namespace: File::EXTATTR_NAMESPACE_USER) { |name, data| ... } -> File
28
- # extattr_each!(path, namespace: File::EXTATTR_NAMESPACE_USER) -> Enumerator
29
- # extattr_each!(path, namespace: File::EXTATTR_NAMESPACE_USER) { |name, data| ... } -> File
55
+ # each(path, namespace = ExtAttr::USER) -> Enumerator
56
+ # each(path, namespace = ExtAttr::USER) { |name| ... } -> path
30
57
  #
31
- def self.extattr_each(path, *namespace)
32
- return to_enum(:extattr_each, path, *namespace) unless block_given?
58
+ def self.each(path, namespace = ExtAttr::USER, &block)
59
+ return to_enum(:each, path, namespace) unless block
60
+
61
+ list(path, namespace, &block)
33
62
 
34
- extattr_list(path, *namespace) do |name|
35
- yield(name, extattr_get(path, name, *namespace))
36
- end
37
63
  self
38
64
  end
39
65
 
40
- def self.extattr_each!(path, *namespace)
41
- return to_enum(:extattr_each!, path, *namespace) unless block_given?
66
+ #
67
+ # call-seq:
68
+ # each!(path, namespace = ExtAttr::USER) -> Enumerator
69
+ # each!(path, namespace = ExtAttr::USER) { |name| ... } -> path
70
+ #
71
+ def self.each!(path, namespace = ExtAttr::USER, &block)
72
+ return to_enum(:each!, path, namespace) unless block
73
+
74
+ list!(path, namespace, &block)
42
75
 
43
- extattr_list!(path, *namespace) do |name|
44
- yield(name, extattr_get!(path, name, *namespace))
45
- end
46
76
  self
47
77
  end
48
78
 
49
- def extattr_each(*namespace)
50
- return to_enum(:extattr_each, *namespace) unless block_given?
79
+ #
80
+ # call-seq:
81
+ # each_pair(path, namespace = ExtAttr::USER) -> Enumerator
82
+ # each_pair(path, namespace = ExtAttr::USER) { |name, data| ... } -> path
83
+ #
84
+ def self.each_pair(path, namespace = ExtAttr::USER, &block)
85
+ return to_enum(:each_pair, path, namespace) unless block
86
+
87
+ list(path, namespace) { |name| yield(name, get(path, namespace, name)) }
88
+
89
+ self
90
+ end
91
+
92
+ #
93
+ # call-seq:
94
+ # each_pair!(path, namespace = ExtAttr::USER) -> Enumerator
95
+ # each_pair!(path, namespace = ExtAttr::USER) { |name, data| ... } -> path
96
+ #
97
+ def self.each_pair!(path, namespace = ExtAttr::USER, &block)
98
+ return to_enum(:each_pair!, path, namespace) unless block
99
+
100
+ list!(path, namespace) { |name| yield(name, get!(path, namespace, name)) }
51
101
 
52
- extattr_list(*namespace) do |name|
53
- yield(name, extattr_get(name, *namespace))
54
- end
55
102
  self
56
103
  end
104
+
105
+ class Accessor < Struct.new(:obj, :path)
106
+ BasicStruct = superclass
107
+ VIRT_ENOATTR = (ExtAttr::IMPLEMENT == "windows" ? Errno::ENOENT : Errno::ENOATTR)
108
+
109
+ def [](name, namespace = ExtAttr::USER)
110
+ begin
111
+ ExtAttr.get(obj, namespace, name)
112
+ rescue VIRT_ENOATTR
113
+ nil
114
+ end
115
+ end
116
+
117
+ def []=(name, namespace = ExtAttr::USER, data)
118
+ if data.nil?
119
+ ExtAttr.delete(obj, namespace, name)
120
+ else
121
+ ExtAttr.set(obj, namespace, name, data)
122
+ end
123
+ end
124
+
125
+ def each(namespace: ExtAttr::USER, &block)
126
+ ExtAttr.each(obj, namespace, &block)
127
+ end
128
+
129
+ def each_pair(namespace: ExtAttr::USER, &block)
130
+ ExtAttr.each_pair(obj, namespace, &block)
131
+ end
132
+
133
+ def list(namespace: ExtAttr::USER, &block)
134
+ ExtAttr.list(obj, namespace, &block)
135
+ end
136
+
137
+ def size(name, namespace: ExtAttr::USER)
138
+ ExtAttr.size(obj, namespace, name)
139
+ end
140
+
141
+ def get(name, namespace: ExtAttr::USER)
142
+ ExtAttr.get(obj, namespace, name)
143
+ end
144
+
145
+ def set(name, data, namespace: ExtAttr::USER)
146
+ ExtAttr.set(obj, namespace, name, data)
147
+ end
148
+
149
+ def delete(name, namespace: ExtAttr::USER)
150
+ ExtAttr.delete(obj, namespace, name)
151
+ end
152
+ end
153
+
154
+ refine File do
155
+ def extattr
156
+ ExtAttr::Accessor[self, to_path]
157
+ end
158
+
159
+ #
160
+ # Enumeration file extattr.
161
+ #
162
+ def extattr_each(namespace: ExtAttr::USER, &block)
163
+ ExtAttr.each(self, namespace, &block)
164
+ end
165
+
166
+ #
167
+ # Enumeration file extattr.
168
+ #
169
+ def extattr_each_pair(namespace: ExtAttr::USER, &block)
170
+ ExtAttr.each_pair(self, namespace, &block)
171
+ end
172
+
173
+ #
174
+ # call-seq:
175
+ # extattr_list(namespace: ExtAttr::USER) -> array of strings
176
+ # extattr_list(namespace: ExtAttr::USER) { |name| ... } -> enumerator
177
+ #
178
+ # Get file extattr list.
179
+ #
180
+ def extattr_list(namespace: ExtAttr::USER, &block)
181
+ ExtAttr.list(self, namespace, &block)
182
+ end
183
+
184
+ #
185
+ # Get file extattr data size.
186
+ #
187
+ def extattr_size(name, namespace: ExtAttr::USER)
188
+ ExtAttr.size(self, namespace, name)
189
+ end
190
+
191
+ #
192
+ # Get file extattr data.
193
+ #
194
+ def extattr_get(name, namespace: ExtAttr::USER)
195
+ ExtAttr.get(self, namespace, name)
196
+ end
197
+
198
+ #
199
+ # Set file extattr data.
200
+ #
201
+ def extattr_set(name, value, namespace: ExtAttr::USER)
202
+ ExtAttr.set(self, namespace, name, value)
203
+ end
204
+
205
+ #
206
+ # Delete file extattr.
207
+ #
208
+ def extattr_delete(name, namespace: ExtAttr::USER)
209
+ ExtAttr.delete(self, namespace, name)
210
+ end
211
+ end
212
+
213
+ refine File.singleton_class do
214
+ def extattr(path)
215
+ ExtAttr.open(path)
216
+ end
217
+
218
+ def extattr_each(path, namespace: ExtAttr::USER, &block)
219
+ ExtAttr.each(path, namespace, &block)
220
+ end
221
+
222
+ def extattr_each!(path, namespace: ExtAttr::USER, &block)
223
+ ExtAttr.each!(path, namespace, &block)
224
+ end
225
+
226
+ def extattr_each_pair(path, namespace: ExtAttr::USER, &block)
227
+ ExtAttr.each_pair(path, namespace, &block)
228
+ end
229
+
230
+ def extattr_each_pair!(path, namespace: ExtAttr::USER, &block)
231
+ ExtAttr.each_pair!(path, namespace, &block)
232
+ end
233
+
234
+ def extattr_list(path, namespace: ExtAttr::USER, &block)
235
+ ExtAttr.list(path, namespace, &block)
236
+ end
237
+
238
+ def extattr_list!(path, namespace: ExtAttr::USER, &block)
239
+ ExtAttr.list!(path, namespace, &block)
240
+ end
241
+
242
+ def extattr_get(path, name, namespace: ExtAttr::USER)
243
+ ExtAttr.get(path, namespace, name)
244
+ end
245
+
246
+ def extattr_get!(path, name, namespace: ExtAttr::USER)
247
+ ExtAttr.get(path, namespace, name)
248
+ end
249
+
250
+ def extattr_size(path, name, namespace: ExtAttr::USER)
251
+ ExtAttr.size(path, namespace, name)
252
+ end
253
+
254
+ def extattr_size!(path, name, namespace: ExtAttr::USER)
255
+ ExtAttr.size(path, namespace, name)
256
+ end
257
+
258
+ def extattr_set(path, name, value, namespace: ExtAttr::USER)
259
+ ExtAttr.set(path, namespace, name, value)
260
+ end
261
+
262
+ def extattr_set!(path, name, value, namespace: ExtAttr::USER)
263
+ ExtAttr.set(path, namespace, name, value)
264
+ end
265
+
266
+ def extattr_delete(path, name, namespace: ExtAttr::USER)
267
+ ExtAttr.delete(path, namespace, name)
268
+ end
269
+
270
+ def extattr_delete!(path, name, namespace: ExtAttr::USER)
271
+ ExtAttr.delete(path, namespace, name)
272
+ end
273
+ end
57
274
  end
@@ -0,0 +1,75 @@
1
+ #!ruby
2
+
3
+ require "test/unit"
4
+ require "fileutils"
5
+ require "tmpdir"
6
+
7
+ include FileUtils
8
+
9
+ require "extattr"
10
+
11
+ using ExtAttr
12
+
13
+ class ExtAttr::Test < Test::Unit::TestCase
14
+ WORKDIR = Dir.mktmpdir(["", ".ruby-extattr.test-work"])
15
+ FILEPATH1 = File.join(WORKDIR, "file1")
16
+ FILEPATH2 = File.join(WORKDIR, "file2")
17
+
18
+ def self.startup
19
+ @@file = File.open(FILEPATH1, "a")
20
+ end
21
+
22
+ def self.shutdown
23
+ @@file.close
24
+ @@file = nil
25
+ Dir.chdir "/" rescue nil
26
+ rmtree WORKDIR, secure: true, verbose: true #, noop: true
27
+ end
28
+
29
+ def test_fd_extattr
30
+ extdata = "abcdefg"
31
+
32
+ assert_equal([], @@file.extattr_list)
33
+ assert_nil(@@file.extattr_set("ext1", extdata))
34
+ assert_equal(["ext1"], @@file.extattr_list())
35
+ assert_equal("ext1", `lsextattr -qq user #{@@file.to_path}`.chomp) if RUBY_PLATFORM =~ /freebsd/
36
+ assert_equal(extdata, @@file.extattr_get("ext1"))
37
+ assert_equal(extdata, `getextattr -qq user ext1 #{@@file.to_path}`) if RUBY_PLATFORM =~ /freebsd/
38
+ assert_nil(@@file.extattr_delete("ext1"))
39
+ assert_equal([], @@file.extattr_list())
40
+ end
41
+
42
+ def test_extattr
43
+ extdata = "abcdefg"
44
+ File.open(FILEPATH2, "ab") {}
45
+
46
+ assert_equal([], File.extattr_list(FILEPATH2))
47
+ assert_nil(File.extattr_set(FILEPATH2, "ext1", extdata))
48
+ assert_equal(["ext1"], File.extattr_list(FILEPATH2))
49
+ assert_equal(extdata, File.extattr_get(FILEPATH2, "ext1"))
50
+ assert_nil(File.extattr_delete(FILEPATH2, "ext1"))
51
+ assert_equal([], File.extattr_list(FILEPATH2))
52
+ end
53
+
54
+ def test_ractor_extattr
55
+ # Skip this test on Ruby < 3.0
56
+ return true unless defined?(Ractor)
57
+
58
+ # Ractor is still experimental in Ruby 3.0.x — suppress warning for this test.
59
+ old_warning_status = Warning[:experimental]
60
+ Warning[:experimental] = false
61
+
62
+ extdata = "abcdefg"
63
+ File.open(FILEPATH2, "ab") {}
64
+
65
+ assert_equal([], File.extattr_list(FILEPATH2))
66
+ assert_nil(File.extattr_set(FILEPATH2, "ext1", extdata))
67
+
68
+ assert_equal(["ext1"], Ractor.new(FILEPATH2) { |path| File.extattr_list(path) }.take)
69
+ assert_equal(extdata, Ractor.new(FILEPATH2) { |path| File.extattr_get(path, "ext1") }.take)
70
+
71
+ assert_nil(File.extattr_delete(FILEPATH2, "ext1"))
72
+ assert_equal([], File.extattr_list(FILEPATH2))
73
+ Warning[:experimental] = old_warning_status
74
+ end
75
+ end
metadata CHANGED
@@ -1,53 +1,64 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: extattr
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: '0.4'
5
5
  platform: ruby
6
6
  authors:
7
7
  - dearblue
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-16 00:00:00.000000000 Z
11
+ date: 2021-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rspec
14
+ name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.14'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.14'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: test-unit
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '0'
41
41
  description: |
42
- extattr is extended file attribute operation library for ruby.
43
- Supported for FreeBSD (extattr), GNU/Linux (xattr) and Microsoft Windows (NTFS ADS + Extended Attributes).
44
- email: dearblue@users.sourceforge.jp
42
+ "extattr" is extended file attribute manipurator for Ruby.
43
+ Supported for FreeBSD (extattr), GNU/Linux (xattr) and Microsoft Windows (NTFS Alternative Data Stream (ADS) + NTFS Extended Attributes (EA)).
44
+ email: dearblue@users.osdn.me
45
45
  executables: []
46
46
  extensions:
47
47
  - ext/extconf.rb
48
- extra_rdoc_files: []
48
+ extra_rdoc_files:
49
+ - HISTORY.ja.md
50
+ - LICENSE.md
51
+ - QUICKREF.ja.md
52
+ - README.md
53
+ - ext/extattr-extattr.h
54
+ - ext/extattr-windows.h
55
+ - ext/extattr-xattr.h
56
+ - ext/extattr.c
57
+ - lib/extattr.rb
49
58
  files:
59
+ - HISTORY.ja.md
50
60
  - LICENSE.md
61
+ - QUICKREF.ja.md
51
62
  - README.md
52
63
  - Rakefile
53
64
  - ext/extattr-extattr.h
@@ -55,17 +66,18 @@ files:
55
66
  - ext/extattr-xattr.h
56
67
  - ext/extattr.c
57
68
  - ext/extconf.rb
69
+ - gemstub.rb
58
70
  - lib/extattr.rb
59
- - spec/extattr_spec.rb
60
- homepage: http://sourceforge.jp/projects/rutsubo/
71
+ - test/test_extattr.rb
72
+ homepage: https://github.com/dearblue/ruby-extattr
61
73
  licenses:
62
- - 2-clause BSD License
74
+ - BSD-2-Clause
63
75
  metadata: {}
64
- post_install_message:
76
+ post_install_message:
65
77
  rdoc_options:
66
78
  - "--charset"
67
79
  - UTF-8
68
- - "--main"
80
+ - "-m"
69
81
  - README.md
70
82
  require_paths:
71
83
  - lib
@@ -73,17 +85,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
73
85
  requirements:
74
86
  - - ">="
75
87
  - !ruby/object:Gem::Version
76
- version: 1.9.3
88
+ version: '0'
77
89
  required_rubygems_version: !ruby/object:Gem::Requirement
78
90
  requirements:
79
91
  - - ">="
80
92
  - !ruby/object:Gem::Version
81
93
  version: '0'
82
94
  requirements: []
83
- rubyforge_project:
84
- rubygems_version: 2.2.2
85
- signing_key:
95
+ rubygems_version: 3.2.14
96
+ signing_key:
86
97
  specification_version: 4
87
- summary: extended attribute operation library for ruby
98
+ summary: extended file attribute manipurator
88
99
  test_files: []
89
- has_rdoc:
data/spec/extattr_spec.rb DELETED
@@ -1,62 +0,0 @@
1
- #vim: set fileencoding:utf-8
2
-
3
- require "tmpdir"
4
- basedir = File.join(Dir.tmpdir, "ruby-extattr.test-work")
5
- Dir.mkdir basedir unless File.directory? basedir
6
- filepath = File.join(basedir, "file1")
7
-
8
- require "extattr"
9
-
10
- extdata = "abcdefg"
11
-
12
- Dir.chdir basedir do
13
- describe "file" do
14
- file = nil
15
- before(:all) do
16
- file = File.open(filepath, "a")
17
- end
18
-
19
- it ".extattr_list" do
20
- file.extattr_list.should eq([])
21
- end
22
-
23
- after(:all) do
24
- file.close
25
- file = nil
26
- end
27
- end
28
-
29
- describe File do
30
- before(:all) do
31
- File.open(filepath, "a") {}
32
- end
33
-
34
- it ".extattr_list" do
35
- File.extattr_list(filepath).should eq([])
36
- end
37
-
38
- it ".extattr_set" do
39
- File.extattr_set(filepath, "ext1", extdata).should nil
40
- end
41
-
42
- it ".extattr_list ((2))" do
43
- File.extattr_list(filepath).should eq(["ext1"])
44
- end
45
-
46
- it ".extattr_get" do
47
- File.extattr_get(filepath, "ext1").should eq(extdata)
48
- end
49
-
50
- it ".extattr_delete" do
51
- File.extattr_delete(filepath, "ext1").should nil
52
- end
53
-
54
- it ".extattr_list ((3))" do
55
- File.extattr_list(filepath).should eq([])
56
- end
57
-
58
- after(:all) do
59
- File.unlink filepath
60
- end
61
- end
62
- end