pstore 0.2.1 → 0.3.0
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.
- checksums.yaml +4 -4
- data/.github/release.yml +4 -0
- data/.github/workflows/push_gem.yml +3 -3
- data/.github/workflows/test.yml +1 -1
- data/lib/pstore.rb +52 -31
- data/pstore.gemspec +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: be4c744cb12983612ebef3ae585d25571252869cfef51a8799a0c3328be339c8
|
|
4
|
+
data.tar.gz: 9527c38bdea78cfee23874de9ecfdfee3ce9beefb541bd6e26abfa3ba55e3a3c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7fa202004bbd5761b8a457fda173f69d2b0574d1b995ef3e2800c2881213719fb6e9cacd4d0cccfb29b0864c28f149a0520b4102f0172ecfccf7ae277367d023
|
|
7
|
+
data.tar.gz: b2724f28ea0ede1bac0675f77bc00665771b88b6e946da3dfd00ab0e946adef9589a350bcce05732c4568b867714b98fc7133810083a5af60ee62fdd67936efc
|
data/.github/release.yml
ADDED
|
@@ -23,11 +23,11 @@ jobs:
|
|
|
23
23
|
|
|
24
24
|
steps:
|
|
25
25
|
- name: Harden Runner
|
|
26
|
-
uses: step-security/harden-runner@
|
|
26
|
+
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
|
27
27
|
with:
|
|
28
28
|
egress-policy: audit
|
|
29
29
|
|
|
30
|
-
- uses: actions/checkout@
|
|
30
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
31
31
|
|
|
32
32
|
- name: Set up Ruby
|
|
33
33
|
uses: ruby/setup-ruby@d5126b9b3579e429dd52e51e68624dda2e05be25 # v1.267.0
|
|
@@ -36,7 +36,7 @@ jobs:
|
|
|
36
36
|
ruby-version: ruby
|
|
37
37
|
|
|
38
38
|
- name: Publish to RubyGems
|
|
39
|
-
uses: rubygems/release-gem@
|
|
39
|
+
uses: rubygems/release-gem@7f9650160c1a4e7989fdc9855807bdbd421d8b6b # v1.4.1
|
|
40
40
|
|
|
41
41
|
- name: Create GitHub release
|
|
42
42
|
run: |
|
data/.github/workflows/test.yml
CHANGED
data/lib/pstore.rb
CHANGED
|
@@ -327,12 +327,13 @@ require "digest"
|
|
|
327
327
|
#
|
|
328
328
|
class PStore
|
|
329
329
|
# :stopdoc:
|
|
330
|
-
VERSION = "0.
|
|
330
|
+
VERSION = "0.3.0"
|
|
331
331
|
|
|
332
|
-
RDWR_ACCESS =
|
|
333
|
-
RD_ACCESS =
|
|
334
|
-
WR_ACCESS =
|
|
335
|
-
|
|
332
|
+
RDWR_ACCESS = IO::RDWR | IO::CREAT | IO::BINARY
|
|
333
|
+
RD_ACCESS = IO::RDONLY | IO::BINARY
|
|
334
|
+
WR_ACCESS = IO::WRONLY | IO::CREAT | IO::TRUNC | IO::BINARY
|
|
335
|
+
NOFOLLOW = IO.const_defined?(:NOFOLLOW) ? IO::NOFOLLOW : 0
|
|
336
|
+
private_constant :RDWR_ACCESS, :RD_ACCESS, :WR_ACCESS, :NOFOLLOW
|
|
336
337
|
# :startdoc:
|
|
337
338
|
|
|
338
339
|
# The error type thrown by all PStore methods.
|
|
@@ -367,12 +368,26 @@ class PStore
|
|
|
367
368
|
#
|
|
368
369
|
# A \PStore object is
|
|
369
370
|
# {reentrant}[https://en.wikipedia.org/wiki/Reentrancy_(computing)].
|
|
370
|
-
# If argument +thread_safe+ is given as +true+,
|
|
371
|
+
# If argument or keyword argument +thread_safe+ is given as +true+,
|
|
371
372
|
# the object is also thread-safe (at the cost of a small performance penalty):
|
|
372
373
|
#
|
|
373
374
|
# store = PStore.new(path, true)
|
|
375
|
+
# store = PStore.new(path, thread_safe: true)
|
|
374
376
|
#
|
|
375
|
-
|
|
377
|
+
# If keyword argument +ultra_safe+ is given as +true+, the object is
|
|
378
|
+
# set to +ultra_safe+ mode.
|
|
379
|
+
#
|
|
380
|
+
# store = PStore.new(path, ultra_safe: true)
|
|
381
|
+
#
|
|
382
|
+
# If keyword argument +follow_symlink+ is given as +false+, the store file
|
|
383
|
+
# itself must not be a symbolic link. This option has no effect on platforms
|
|
384
|
+
# that do not support IO::NOFOLLOW. Symbolic links in parent directories are
|
|
385
|
+
# not affected.
|
|
386
|
+
#
|
|
387
|
+
# store = PStore.new(path, follow_symlink: false)
|
|
388
|
+
#
|
|
389
|
+
def initialize(file, _thread_safe = false, thread_safe: _thread_safe,
|
|
390
|
+
ultra_safe: false, follow_symlink: true)
|
|
376
391
|
dir = File::dirname(file)
|
|
377
392
|
unless File::directory? dir
|
|
378
393
|
raise PStore::Error, format("directory %s does not exist", dir)
|
|
@@ -380,16 +395,17 @@ class PStore
|
|
|
380
395
|
if File::exist? file and not File::readable? file
|
|
381
396
|
raise PStore::Error, format("file %s not readable", file)
|
|
382
397
|
end
|
|
383
|
-
@filename = file
|
|
398
|
+
@filename = File.path(file)
|
|
384
399
|
@abort = false
|
|
385
|
-
@ultra_safe =
|
|
400
|
+
@ultra_safe = ultra_safe
|
|
386
401
|
@thread_safe = thread_safe
|
|
402
|
+
@nofollow = follow_symlink ? 0 : NOFOLLOW
|
|
387
403
|
@lock = Thread::Mutex.new
|
|
388
404
|
end
|
|
389
405
|
|
|
390
406
|
# Raises PStore::Error if the calling code is not in a PStore#transaction.
|
|
391
407
|
def in_transaction
|
|
392
|
-
raise PStore::Error, "not in transaction" unless @lock.
|
|
408
|
+
raise PStore::Error, "not in transaction" unless @lock.owned?
|
|
393
409
|
end
|
|
394
410
|
#
|
|
395
411
|
# Raises PStore::Error if the calling code is not in a PStore#transaction or
|
|
@@ -439,7 +455,7 @@ class PStore
|
|
|
439
455
|
def fetch(key, default=PStore::Error)
|
|
440
456
|
in_transaction
|
|
441
457
|
unless @table.key? key
|
|
442
|
-
if
|
|
458
|
+
if PStore::Error.equal?(default)
|
|
443
459
|
raise PStore::Error, format("undefined key '%s'", key)
|
|
444
460
|
else
|
|
445
461
|
return default
|
|
@@ -527,7 +543,7 @@ class PStore
|
|
|
527
543
|
def commit
|
|
528
544
|
in_transaction
|
|
529
545
|
@abort = false
|
|
530
|
-
throw
|
|
546
|
+
throw self
|
|
531
547
|
end
|
|
532
548
|
|
|
533
549
|
# Exits the current transaction block, discarding any changes
|
|
@@ -538,7 +554,7 @@ class PStore
|
|
|
538
554
|
def abort
|
|
539
555
|
in_transaction
|
|
540
556
|
@abort = true
|
|
541
|
-
throw
|
|
557
|
+
throw self
|
|
542
558
|
end
|
|
543
559
|
|
|
544
560
|
# Opens a transaction block for the store.
|
|
@@ -570,7 +586,7 @@ class PStore
|
|
|
570
586
|
begin
|
|
571
587
|
@table, checksum, original_data_size = load_data(file, read_only)
|
|
572
588
|
|
|
573
|
-
catch(
|
|
589
|
+
catch(self) do
|
|
574
590
|
value = yield(self)
|
|
575
591
|
end
|
|
576
592
|
|
|
@@ -583,7 +599,7 @@ class PStore
|
|
|
583
599
|
else
|
|
584
600
|
# This can only occur if read_only == true.
|
|
585
601
|
@table = {}
|
|
586
|
-
catch(
|
|
602
|
+
catch(self) do
|
|
587
603
|
value = yield(self)
|
|
588
604
|
end
|
|
589
605
|
end
|
|
@@ -621,23 +637,26 @@ class PStore
|
|
|
621
637
|
# All exceptions are propagated.
|
|
622
638
|
#
|
|
623
639
|
def open_and_lock_file(filename, read_only)
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
640
|
+
filename = File.path(filename)
|
|
641
|
+
loop do
|
|
642
|
+
if read_only
|
|
627
643
|
begin
|
|
628
|
-
file.
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
file.close
|
|
632
|
-
raise
|
|
644
|
+
file = File.new(filename, mode: RD_ACCESS | @nofollow, encoding: Encoding::ASCII_8BIT)
|
|
645
|
+
rescue Errno::ENOENT
|
|
646
|
+
return nil
|
|
633
647
|
end
|
|
634
|
-
|
|
635
|
-
|
|
648
|
+
else
|
|
649
|
+
file = File.new(filename, mode: RDWR_ACCESS | @nofollow, encoding: Encoding::ASCII_8BIT)
|
|
650
|
+
end
|
|
651
|
+
current = false
|
|
652
|
+
begin
|
|
653
|
+
file.flock(read_only ? File::LOCK_SH : File::LOCK_EX)
|
|
654
|
+
# An atomic save may have replaced the file while this lock was pending.
|
|
655
|
+
current = File.identical?(file, filename)
|
|
656
|
+
return file if current
|
|
657
|
+
ensure
|
|
658
|
+
file.close unless current
|
|
636
659
|
end
|
|
637
|
-
else
|
|
638
|
-
file = File.new(filename, **RDWR_ACCESS)
|
|
639
|
-
file.flock(File::LOCK_EX)
|
|
640
|
-
return file
|
|
641
660
|
end
|
|
642
661
|
end
|
|
643
662
|
|
|
@@ -651,6 +670,7 @@ class PStore
|
|
|
651
670
|
table = load(file)
|
|
652
671
|
raise Error, "PStore file seems to be corrupted." unless table.is_a?(Hash)
|
|
653
672
|
rescue EOFError
|
|
673
|
+
raise unless file.size == 0
|
|
654
674
|
# This seems to be a newly-created file.
|
|
655
675
|
table = {}
|
|
656
676
|
end
|
|
@@ -694,13 +714,14 @@ class PStore
|
|
|
694
714
|
|
|
695
715
|
def save_data_with_atomic_file_rename_strategy(data, file)
|
|
696
716
|
temp_filename = "#{@filename}.tmp.#{Process.pid}.#{rand 1000000}"
|
|
697
|
-
temp_file = File.new(temp_filename,
|
|
717
|
+
temp_file = File.new(temp_filename, mode: WR_ACCESS | @nofollow, encoding: Encoding::ASCII_8BIT, perm: 0o000)
|
|
698
718
|
begin
|
|
699
719
|
temp_file.flock(File::LOCK_EX)
|
|
700
720
|
temp_file.write(data)
|
|
701
721
|
temp_file.flush
|
|
722
|
+
temp_file.chmod(file.stat.mode)
|
|
702
723
|
File.rename(temp_filename, @filename)
|
|
703
|
-
rescue
|
|
724
|
+
rescue Exception
|
|
704
725
|
File.unlink(temp_file) rescue nil
|
|
705
726
|
raise
|
|
706
727
|
ensure
|
data/pstore.gemspec
CHANGED
|
@@ -17,6 +17,7 @@ Gem::Specification.new do |spec|
|
|
|
17
17
|
spec.description = spec.summary
|
|
18
18
|
spec.homepage = "https://github.com/ruby/pstore"
|
|
19
19
|
spec.licenses = ["Ruby", "BSD-2-Clause"]
|
|
20
|
+
spec.required_ruby_version = ">= 2.4"
|
|
20
21
|
|
|
21
22
|
spec.metadata["homepage_uri"] = spec.homepage
|
|
22
23
|
spec.metadata["source_code_uri"] = "https://github.com/ruby/pstore"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pstore
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yukihiro Matsumoto
|
|
@@ -18,6 +18,7 @@ extra_rdoc_files: []
|
|
|
18
18
|
files:
|
|
19
19
|
- ".document"
|
|
20
20
|
- ".github/dependabot.yml"
|
|
21
|
+
- ".github/release.yml"
|
|
21
22
|
- ".github/workflows/push_gem.yml"
|
|
22
23
|
- ".github/workflows/test.yml"
|
|
23
24
|
- ".gitignore"
|
|
@@ -44,7 +45,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
44
45
|
requirements:
|
|
45
46
|
- - ">="
|
|
46
47
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
48
|
+
version: '2.4'
|
|
48
49
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
49
50
|
requirements:
|
|
50
51
|
- - ">="
|