moab-versioning 4.2.1 → 4.4.2
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 +5 -5
- data/lib/moab.rb +3 -2
- data/lib/moab/bagger.rb +25 -20
- data/lib/moab/config.rb +39 -8
- data/lib/moab/deposit_bag_validator.rb +22 -17
- data/lib/moab/exceptions.rb +10 -8
- data/lib/moab/file_group.rb +23 -22
- data/lib/moab/file_group_difference.rb +35 -35
- data/lib/moab/file_group_difference_subset.rb +5 -5
- data/lib/moab/file_instance.rb +4 -3
- data/lib/moab/file_instance_difference.rb +5 -5
- data/lib/moab/file_inventory.rb +25 -31
- data/lib/moab/file_inventory_difference.rb +11 -11
- data/lib/moab/file_manifestation.rb +8 -7
- data/lib/moab/file_signature.rb +35 -41
- data/lib/moab/signature_catalog.rb +19 -21
- data/lib/moab/signature_catalog_entry.rb +5 -5
- data/lib/moab/stanford.rb +2 -0
- data/lib/moab/storage_object.rb +23 -24
- data/lib/moab/storage_object_validator.rb +44 -16
- data/lib/moab/storage_object_version.rb +45 -40
- data/lib/moab/storage_repository.rb +59 -24
- data/lib/moab/storage_services.rb +17 -10
- data/lib/moab/utc_time.rb +3 -3
- data/lib/moab/verification_result.rb +3 -4
- data/lib/moab/version_metadata.rb +4 -4
- data/lib/moab/version_metadata_entry.rb +6 -6
- data/lib/moab/version_metadata_event.rb +1 -1
- data/lib/serializer.rb +2 -0
- data/lib/serializer/manifest.rb +9 -7
- data/lib/serializer/serializable.rb +41 -35
- data/lib/stanford/active_fedora_object.rb +1 -1
- data/lib/stanford/content_inventory.rb +40 -34
- data/lib/stanford/dor_metadata.rb +4 -3
- data/lib/stanford/moab_storage_directory.rb +4 -2
- data/lib/stanford/storage_object_validator.rb +1 -1
- data/lib/stanford/storage_repository.rb +9 -6
- data/lib/stanford/storage_services.rb +6 -6
- metadata +23 -38
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Moab
|
4
4
|
# Compares two {FileInventory} instances based primarily on file signatures and secondarily on file pathnames.
|
@@ -24,17 +24,17 @@ module Moab
|
|
24
24
|
|
25
25
|
# (see Serializable#initialize)
|
26
26
|
def initialize(opts = {})
|
27
|
-
@group_differences =
|
27
|
+
@group_differences = []
|
28
28
|
super(opts)
|
29
29
|
end
|
30
30
|
|
31
31
|
# @attribute
|
32
32
|
# @return [String] The digital object ID (druid)
|
33
|
-
attribute :digital_object_id, String, :
|
33
|
+
attribute :digital_object_id, String, tag: 'objectId'
|
34
34
|
|
35
35
|
# @attribute
|
36
36
|
# @return [Integer] the number of differences found between the two inventories that were compared (dynamically calculated)
|
37
|
-
attribute :difference_count, Integer, :
|
37
|
+
attribute :difference_count, Integer, tag: 'differenceCount', on_save: proc { |i| i.to_s }
|
38
38
|
|
39
39
|
def difference_count
|
40
40
|
@group_differences.inject(0) { |sum, group| sum + group.difference_count }
|
@@ -50,7 +50,7 @@ module Moab
|
|
50
50
|
|
51
51
|
# @attribute
|
52
52
|
# @return [String] The datetime at which the report was run
|
53
|
-
attribute :report_datetime, String, :
|
53
|
+
attribute :report_datetime, String, tag: 'reportDatetime'
|
54
54
|
|
55
55
|
def report_datetime=(datetime)
|
56
56
|
@report_datetime = Moab::UtcTime.input(datetime)
|
@@ -62,11 +62,11 @@ module Moab
|
|
62
62
|
|
63
63
|
# @attribute
|
64
64
|
# @return [Array<FileGroupDifference>] The set of data groups comprising the version
|
65
|
-
has_many :group_differences, FileGroupDifference, :
|
65
|
+
has_many :group_differences, FileGroupDifference, tag: 'fileGroupDifference'
|
66
66
|
|
67
67
|
# @return [Array<String>] The data fields to include in summary reports
|
68
68
|
def summary_fields
|
69
|
-
%w
|
69
|
+
%w[digital_object_id difference_count basis other report_datetime group_differences]
|
70
70
|
end
|
71
71
|
|
72
72
|
# @param [String] group_id The identifer of the group to be selected
|
@@ -89,8 +89,8 @@ module Moab
|
|
89
89
|
group_ids = basis_inventory.group_ids | other_inventory.group_ids
|
90
90
|
group_ids.each do |group_id|
|
91
91
|
# get a pair of groups to compare, creating a empty group if not present in the inventory
|
92
|
-
basis_group = basis_inventory.group(group_id) || FileGroup.new(:
|
93
|
-
other_group = other_inventory.group(group_id) || FileGroup.new(:
|
92
|
+
basis_group = basis_inventory.group(group_id) || FileGroup.new(group_id: group_id)
|
93
|
+
other_group = other_inventory.group(group_id) || FileGroup.new(group_id: group_id)
|
94
94
|
@group_differences << FileGroupDifference.new.compare_file_groups(basis_group, other_group)
|
95
95
|
end
|
96
96
|
self
|
@@ -110,11 +110,11 @@ module Moab
|
|
110
110
|
# @return [Hash] Serializes the data and then filters it to report only the changes
|
111
111
|
def differences_detail
|
112
112
|
#return self.summary if difference_count == 0
|
113
|
-
inv_diff =
|
113
|
+
inv_diff = to_hash
|
114
114
|
inv_diff["group_differences"].each_value do |group_diff|
|
115
115
|
delete_subsets = []
|
116
116
|
group_diff["subsets"].each do |change_type, subset|
|
117
|
-
delete_subsets << change_type if change_type == "identical"
|
117
|
+
delete_subsets << change_type if (change_type == "identical") || (subset["count"] == 0)
|
118
118
|
end
|
119
119
|
delete_subsets.each do |change_type|
|
120
120
|
group_diff["subsets"].delete(change_type)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Moab
|
4
4
|
# A container for a file signature and all the physical file instances that have that signature
|
@@ -24,13 +24,13 @@ module Moab
|
|
24
24
|
|
25
25
|
# (see Serializable#initialize)
|
26
26
|
def initialize(opts = {})
|
27
|
-
@instances =
|
27
|
+
@instances = []
|
28
28
|
super(opts)
|
29
29
|
end
|
30
30
|
|
31
31
|
# @attribute
|
32
32
|
# @return [FileSignature] The fixity data of the file instance
|
33
|
-
element :signature, FileSignature, :
|
33
|
+
element :signature, FileSignature, tag: 'fileSignature'
|
34
34
|
|
35
35
|
def signature
|
36
36
|
@signature.is_a?(Array) ? @signature[0] : @signature
|
@@ -42,12 +42,12 @@ module Moab
|
|
42
42
|
|
43
43
|
# @attribute
|
44
44
|
# @return [Array<FileInstance>] The location(s) of the file manifestation's file instances
|
45
|
-
has_many :instances, FileInstance, :
|
45
|
+
has_many :instances, FileInstance, tag: 'fileInstance'
|
46
46
|
|
47
47
|
# @api internal
|
48
48
|
# @return [Array<String>] Create an array from all the file paths of the child {FileInstance} objects
|
49
49
|
def paths
|
50
|
-
instances.collect
|
50
|
+
instances.collect(&:path)
|
51
51
|
end
|
52
52
|
|
53
53
|
# @api internal
|
@@ -76,8 +76,9 @@ module Moab
|
|
76
76
|
# @param other [FileManifestation] The {FileManifestation} object to compare with self
|
77
77
|
# @return [Boolean] True if {FileManifestation} objects have same content
|
78
78
|
def ==(other)
|
79
|
-
return false unless
|
80
|
-
|
79
|
+
return false unless other.respond_to?(:signature) && other.respond_to?(:instances) # Cannot equal an incomparable type!
|
80
|
+
|
81
|
+
(signature == other.signature) && (instances == other.instances)
|
81
82
|
end
|
82
83
|
end
|
83
84
|
end
|
data/lib/moab/file_signature.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Moab
|
4
4
|
# The fixity properties of a file, used to determine file content equivalence regardless of filename.
|
@@ -46,19 +46,19 @@ module Moab
|
|
46
46
|
|
47
47
|
# @attribute
|
48
48
|
# @return [Integer] The size of the file in bytes
|
49
|
-
attribute :size, Integer, :
|
49
|
+
attribute :size, Integer, on_save: proc { |n| n.to_s }
|
50
50
|
|
51
51
|
# @attribute
|
52
52
|
# @return [String] The MD5 checksum value of the file
|
53
|
-
attribute :md5, String, :
|
53
|
+
attribute :md5, String, on_save: proc { |n| n.nil? ? "" : n.to_s }
|
54
54
|
|
55
55
|
# @attribute
|
56
56
|
# @return [String] The SHA1 checksum value of the file
|
57
|
-
attribute :sha1, String, :
|
57
|
+
attribute :sha1, String, on_save: proc { |n| n.nil? ? "" : n.to_s }
|
58
58
|
|
59
59
|
# @attribute
|
60
60
|
# @return [String] The SHA256 checksum value of the file
|
61
|
-
attribute :sha256, String, :
|
61
|
+
attribute :sha256, String, on_save: proc { |n| n.nil? ? "" : n.to_s }
|
62
62
|
|
63
63
|
KNOWN_ALGOS = {
|
64
64
|
md5: proc { Digest::MD5.new },
|
@@ -75,7 +75,7 @@ module Moab
|
|
75
75
|
# @param [Array<Symbol>] one or more keys of KNOWN_ALGOS to be computed
|
76
76
|
# @return [Moab::FileSignature] object populated with (requested) checksums
|
77
77
|
def self.from_file(pathname, algos_to_use = active_algos)
|
78
|
-
raise 'Unrecognized algorithm requested' unless algos_to_use.all? { |a| KNOWN_ALGOS.include?(a) }
|
78
|
+
raise(MoabRuntimeError, 'Unrecognized algorithm requested') unless algos_to_use.all? { |a| KNOWN_ALGOS.include?(a) }
|
79
79
|
|
80
80
|
signatures = algos_to_use.map { |k| [k, KNOWN_ALGOS[k].call] }.to_h
|
81
81
|
|
@@ -85,7 +85,7 @@ module Moab
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
new(signatures.
|
88
|
+
new(signatures.transform_values(&:hexdigest).merge(size: pathname.size))
|
89
89
|
end
|
90
90
|
|
91
91
|
# @param type [Symbol,String] The type of checksum
|
@@ -106,12 +106,11 @@ module Moab
|
|
106
106
|
|
107
107
|
# @return [Hash<Symbol,String>] A hash of the checksum data
|
108
108
|
def checksums
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
checksum_hash
|
109
|
+
{
|
110
|
+
md5: md5,
|
111
|
+
sha1: sha1,
|
112
|
+
sha256: sha256
|
113
|
+
}.reject { |_key, value| value.nil? || value.empty? }
|
115
114
|
end
|
116
115
|
|
117
116
|
# @return [Boolean] The signature contains all of the 3 desired checksums
|
@@ -120,24 +119,23 @@ module Moab
|
|
120
119
|
end
|
121
120
|
|
122
121
|
# @api internal
|
123
|
-
# @return [Hash<Symbol
|
122
|
+
# @return [Hash<Symbol => String>] A hash of fixity data from this signataure object
|
124
123
|
def fixity
|
125
|
-
|
126
|
-
fixity_hash[:size] = @size.to_s
|
127
|
-
fixity_hash.merge!(checksums)
|
128
|
-
fixity_hash
|
124
|
+
{ size: size.to_s }.merge(checksums)
|
129
125
|
end
|
130
126
|
|
131
127
|
# @api internal
|
132
128
|
# @param other [FileSignature] The other file signature being compared to this signature
|
133
129
|
# @return [Boolean] Returns true if self and other have comparable fixity data.
|
134
130
|
def eql?(other)
|
135
|
-
return false unless
|
136
|
-
return false if
|
137
|
-
|
131
|
+
return false unless other.respond_to?(:size) && other.respond_to?(:checksums)
|
132
|
+
return false if size.to_i != other.size.to_i
|
133
|
+
|
134
|
+
self_checksums = checksums
|
138
135
|
other_checksums = other.checksums
|
139
136
|
matching_keys = self_checksums.keys & other_checksums.keys
|
140
|
-
return false if matching_keys.
|
137
|
+
return false if matching_keys.empty?
|
138
|
+
|
141
139
|
matching_keys.each do |key|
|
142
140
|
return false if self_checksums[key] != other_checksums[key]
|
143
141
|
end
|
@@ -181,31 +179,27 @@ module Moab
|
|
181
179
|
# @return [FileSignature] The full signature derived from the file, unless the fixity is inconsistent with current values
|
182
180
|
def normalized_signature(pathname)
|
183
181
|
sig_from_file = FileSignature.new.signature_from_file(pathname)
|
184
|
-
if
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
raise "Signature inconsistent between inventory and file for #{pathname}: #{self.diff(sig_from_file).inspect}"
|
190
|
-
end
|
182
|
+
return sig_from_file if eql?(sig_from_file)
|
183
|
+
|
184
|
+
# The full signature from file is consistent with current values, or...
|
185
|
+
# One or more of the fixity values is inconsistent, so raise an exception
|
186
|
+
raise(MoabRuntimeError, "Signature inconsistent between inventory and file for #{pathname}: #{diff(sig_from_file).inspect}")
|
191
187
|
end
|
192
188
|
|
193
189
|
# @return [Hash<Symbol,String>] Key is type (e.g. :sha1), value is checksum names (e.g. ['SHA-1', 'SHA1'])
|
194
|
-
def
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
190
|
+
def self.checksum_names_for_type
|
191
|
+
{
|
192
|
+
md5: ['MD5'],
|
193
|
+
sha1: %w[SHA-1 SHA1],
|
194
|
+
sha256: %w[SHA-256 SHA256]
|
195
|
+
}
|
200
196
|
end
|
201
197
|
|
202
198
|
# @return [Hash<String, Symbol>] Key is checksum name (e.g. MD5), value is checksum type (e.g. :md5)
|
203
|
-
def
|
204
|
-
type_for_name =
|
205
|
-
|
206
|
-
names.each
|
207
|
-
type_for_name[name] = type
|
208
|
-
end
|
199
|
+
def self.checksum_type_for_name
|
200
|
+
type_for_name = {}
|
201
|
+
checksum_names_for_type.each do |type, names|
|
202
|
+
names.each { |name| type_for_name[name] = type }
|
209
203
|
end
|
210
204
|
type_for_name
|
211
205
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Moab
|
4
4
|
# A digital object's Signature Catalog is derived from an filtered aggregation of the file inventories
|
@@ -32,27 +32,27 @@ module Moab
|
|
32
32
|
|
33
33
|
# (see Serializable#initialize)
|
34
34
|
def initialize(opts = {})
|
35
|
-
@entries =
|
36
|
-
@signature_hash =
|
35
|
+
@entries = []
|
36
|
+
@signature_hash = {}
|
37
37
|
super(opts)
|
38
38
|
end
|
39
39
|
|
40
40
|
# @attribute
|
41
41
|
# @return [String] The object ID (druid)
|
42
|
-
attribute :digital_object_id, String, :
|
42
|
+
attribute :digital_object_id, String, tag: 'objectId'
|
43
43
|
|
44
44
|
# @attribute
|
45
45
|
# @return [Integer] The ordinal version number
|
46
|
-
attribute :version_id, Integer, :
|
46
|
+
attribute :version_id, Integer, tag: 'versionId', key: true, on_save: proc { |n| n.to_s }
|
47
47
|
|
48
48
|
# @return [String] The unique identifier concatenating digital object id with version id
|
49
49
|
def composite_key
|
50
|
-
@digital_object_id
|
50
|
+
"#{@digital_object_id}-#{StorageObject.version_dirname(@version_id)}"
|
51
51
|
end
|
52
52
|
|
53
53
|
# @attribute
|
54
54
|
# @return [String] The datetime at which the catalog was updated
|
55
|
-
attribute :catalog_datetime, Time, :
|
55
|
+
attribute :catalog_datetime, Time, tag: 'catalogDatetime'
|
56
56
|
|
57
57
|
def catalog_datetime=(datetime)
|
58
58
|
@catalog_datetime = Moab::UtcTime.input(datetime)
|
@@ -64,7 +64,7 @@ module Moab
|
|
64
64
|
|
65
65
|
# @attribute
|
66
66
|
# @return [Integer] The total number of data files (dynamically calculated)
|
67
|
-
attribute :file_count, Integer, :
|
67
|
+
attribute :file_count, Integer, tag: 'fileCount', on_save: proc { |t| t.to_s }
|
68
68
|
|
69
69
|
def file_count
|
70
70
|
entries.size
|
@@ -72,7 +72,7 @@ module Moab
|
|
72
72
|
|
73
73
|
# @attribute
|
74
74
|
# @return [Integer] The total size (in bytes) of all data files (dynamically calculated)
|
75
|
-
attribute :byte_count, Integer, :
|
75
|
+
attribute :byte_count, Integer, tag: 'byteCount', on_save: proc { |t| t.to_s }
|
76
76
|
|
77
77
|
def byte_count
|
78
78
|
entries.inject(0) { |sum, entry| sum + entry.signature.size.to_i }
|
@@ -80,7 +80,7 @@ module Moab
|
|
80
80
|
|
81
81
|
# @attribute
|
82
82
|
# @return [Integer] The total disk usage (in 1 kB blocks) of all data files (estimating du -k result) (dynamically calculated)
|
83
|
-
attribute :block_count, Integer, :
|
83
|
+
attribute :block_count, Integer, tag: 'blockCount', on_save: proc { |t| t.to_s }
|
84
84
|
|
85
85
|
def block_count
|
86
86
|
block_size = 1024
|
@@ -89,12 +89,12 @@ module Moab
|
|
89
89
|
|
90
90
|
# @return [Array<String>] The data fields to include in summary reports
|
91
91
|
def summary_fields
|
92
|
-
%w
|
92
|
+
%w[digital_object_id version_id catalog_datetime file_count byte_count block_count]
|
93
93
|
end
|
94
94
|
|
95
95
|
# @attribute
|
96
96
|
# @return [Array<SignatureCatalogEntry>] The set of data groups comprising the version
|
97
|
-
has_many :entries, SignatureCatalogEntry, :
|
97
|
+
has_many :entries, SignatureCatalogEntry, tag: 'entry'
|
98
98
|
|
99
99
|
def entries=(entry_array)
|
100
100
|
entry_array.each do |entry|
|
@@ -130,11 +130,11 @@ module Moab
|
|
130
130
|
def normalize_group_signatures(group, group_pathname = nil)
|
131
131
|
unless group_pathname.nil?
|
132
132
|
group_pathname = Pathname(group_pathname)
|
133
|
-
raise "Could not locate #{group_pathname}" unless group_pathname.exist?
|
133
|
+
raise(MoabRuntimeError, "Could not locate #{group_pathname}") unless group_pathname.exist?
|
134
134
|
end
|
135
135
|
group.files.each do |file|
|
136
136
|
unless file.signature.complete?
|
137
|
-
if @signature_hash.
|
137
|
+
if @signature_hash.key?(file.signature)
|
138
138
|
file.signature = @signature_hash.find { |k, _v| k == file.signature }[0]
|
139
139
|
elsif group_pathname
|
140
140
|
file_pathname = group_pathname.join(file.instances[0].path)
|
@@ -153,7 +153,7 @@ module Moab
|
|
153
153
|
def update(version_inventory, data_pathname)
|
154
154
|
version_inventory.groups.each do |group|
|
155
155
|
group.files.each do |file|
|
156
|
-
unless @signature_hash.
|
156
|
+
unless @signature_hash.key?(file.signature)
|
157
157
|
entry = SignatureCatalogEntry.new
|
158
158
|
entry.version_id = version_inventory.version_id
|
159
159
|
entry.group_id = group.group_id
|
@@ -178,16 +178,14 @@ module Moab
|
|
178
178
|
# containing only those files that were added in this version
|
179
179
|
# @example {include:file:spec/features/catalog/version_additions_spec.rb}
|
180
180
|
def version_additions(version_inventory)
|
181
|
-
version_additions = FileInventory.new(:
|
181
|
+
version_additions = FileInventory.new(type: 'additions')
|
182
182
|
version_additions.copy_ids(version_inventory)
|
183
183
|
version_inventory.groups.each do |group|
|
184
|
-
group_addtions = FileGroup.new(:
|
184
|
+
group_addtions = FileGroup.new(group_id: group.group_id)
|
185
185
|
group.files.each do |file|
|
186
|
-
unless @signature_hash.
|
187
|
-
group_addtions.add_file_instance(file.signature, file.instances[0])
|
188
|
-
end
|
186
|
+
group_addtions.add_file_instance(file.signature, file.instances[0]) unless @signature_hash.key?(file.signature)
|
189
187
|
end
|
190
|
-
version_additions.groups << group_addtions
|
188
|
+
version_additions.groups << group_addtions unless group_addtions.files.empty?
|
191
189
|
end
|
192
190
|
version_additions
|
193
191
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Moab
|
4
4
|
# A file-level entry in a digital object's {SignatureCatalog}.
|
@@ -25,19 +25,19 @@ module Moab
|
|
25
25
|
|
26
26
|
# @attribute
|
27
27
|
# @return [Integer] The ordinal version number
|
28
|
-
attribute :version_id, Integer, :
|
28
|
+
attribute :version_id, Integer, tag: 'originalVersion', key: true, on_save: proc { |n| n.to_s }
|
29
29
|
|
30
30
|
# @attribute
|
31
31
|
# @return [String] The name of the file group
|
32
|
-
attribute :group_id, String, :
|
32
|
+
attribute :group_id, String, tag: 'groupId', key: true
|
33
33
|
|
34
34
|
# @attribute
|
35
35
|
# @return [String] The id is the filename path, relative to the file group's base directory
|
36
|
-
attribute :path, String, :
|
36
|
+
attribute :path, String, key: true, tag: 'storagePath'
|
37
37
|
|
38
38
|
# @attribute
|
39
39
|
# @return [FileSignature] The fixity data of the file instance
|
40
|
-
element :signature, FileSignature, :
|
40
|
+
element :signature, FileSignature, tag: 'fileSignature'
|
41
41
|
|
42
42
|
def signature
|
43
43
|
# HappyMapper's parser tries to put an array of signatures in the signature field
|
data/lib/moab/stanford.rb
CHANGED
data/lib/moab/storage_object.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Moab
|
4
4
|
# A class to represent a digital object's repository storage location
|
@@ -84,10 +84,10 @@ module Moab
|
|
84
84
|
# @return [FileInventory] The file inventory of the specified type for this version
|
85
85
|
def versionize_bag(bag_dir, current_version, new_version)
|
86
86
|
new_inventory = FileInventory.new(
|
87
|
-
:
|
88
|
-
:
|
89
|
-
:
|
90
|
-
:
|
87
|
+
type: 'version',
|
88
|
+
digital_object_id: @digital_object_id,
|
89
|
+
version_id: new_version.version_id,
|
90
|
+
inventory_datetime: Time.now
|
91
91
|
)
|
92
92
|
new_inventory.inventory_from_bagit_bag(bag_dir)
|
93
93
|
new_inventory.write_xml_file(bag_dir)
|
@@ -115,6 +115,7 @@ module Moab
|
|
115
115
|
storage_filepath = @object_pathname.join(catalog_filepath)
|
116
116
|
errmsg = "#{catalog_filepath} missing from storage location #{storage_filepath}"
|
117
117
|
raise FileNotFoundException, errmsg unless storage_filepath.exist?
|
118
|
+
|
118
119
|
storage_filepath
|
119
120
|
end
|
120
121
|
|
@@ -122,27 +123,26 @@ module Moab
|
|
122
123
|
# @param version_id [Integer] The version identifier of an object version
|
123
124
|
# @return [String] The directory name of the version, relative to the digital object home directory (e.g v0002)
|
124
125
|
def self.version_dirname(version_id)
|
125
|
-
("v%04d"
|
126
|
+
format("v%04d", version_id)
|
126
127
|
end
|
127
128
|
|
128
129
|
# @return [Array<Integer>] The list of all version ids for this object
|
129
130
|
def version_id_list
|
130
|
-
list =
|
131
|
+
list = []
|
131
132
|
return list unless @object_pathname.exist?
|
133
|
+
|
132
134
|
@object_pathname.children.each do |dirname|
|
133
135
|
vnum = dirname.basename.to_s
|
134
|
-
if vnum =~ /^v(\d+)$/
|
135
|
-
list << vnum[1..-1].to_i
|
136
|
-
end
|
136
|
+
list << vnum[1..].to_i if vnum =~ /^v(\d+)$/
|
137
137
|
end
|
138
138
|
list.sort
|
139
139
|
end
|
140
140
|
|
141
141
|
# @return [Array<StorageObjectVersion>] The list of all versions in this storage object
|
142
142
|
def version_list
|
143
|
-
version_id_list.collect { |id|
|
143
|
+
version_id_list.collect { |id| storage_object_version(id) }
|
144
144
|
end
|
145
|
-
alias
|
145
|
+
alias versions version_list
|
146
146
|
|
147
147
|
# @return [Boolean] true if there are no versions yet in this object
|
148
148
|
def empty?
|
@@ -152,12 +152,12 @@ module Moab
|
|
152
152
|
# @api external
|
153
153
|
# @return [Integer] The identifier of the latest version of this object, or 0 if no versions exist
|
154
154
|
def current_version_id
|
155
|
-
@current_version_id ||=
|
155
|
+
@current_version_id ||= version_id_list.last || 0
|
156
156
|
end
|
157
157
|
|
158
158
|
# @return [StorageObjectVersion] The most recent version in the storage object
|
159
159
|
def current_version
|
160
|
-
|
160
|
+
storage_object_version(current_version_id)
|
161
161
|
end
|
162
162
|
|
163
163
|
# @api internal
|
@@ -165,8 +165,9 @@ module Moab
|
|
165
165
|
# @return [Boolean] Tests whether the new version number is one higher than the current version number
|
166
166
|
def validate_new_inventory(version_inventory)
|
167
167
|
if version_inventory.version_id != (current_version_id + 1)
|
168
|
-
raise "version mismatch - current: #{current_version_id} new: #{version_inventory.version_id}"
|
168
|
+
raise(MoabRuntimeError, "version mismatch - current: #{current_version_id} new: #{version_inventory.version_id}")
|
169
169
|
end
|
170
|
+
|
170
171
|
true
|
171
172
|
end
|
172
173
|
|
@@ -181,7 +182,7 @@ module Moab
|
|
181
182
|
when 1..current
|
182
183
|
StorageObjectVersion.new(self, version_id)
|
183
184
|
else
|
184
|
-
raise "Version ID #{version_id} does not exist"
|
185
|
+
raise(MoabRuntimeError, "Version ID #{version_id} does not exist")
|
185
186
|
end
|
186
187
|
end
|
187
188
|
|
@@ -191,21 +192,19 @@ module Moab
|
|
191
192
|
# * Version 0 is a special case used to generate empty manifests
|
192
193
|
# * Current version + 1 is used for creation of a new version
|
193
194
|
def storage_object_version(version_id)
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
raise "Version ID not specified"
|
198
|
-
end
|
195
|
+
raise(MoabRuntimeError, "Version ID not specified") unless version_id
|
196
|
+
|
197
|
+
StorageObjectVersion.new(self, version_id)
|
199
198
|
end
|
200
199
|
|
201
200
|
# @return [VerificationResult] Return result of storage verification
|
202
201
|
def verify_object_storage
|
203
202
|
result = VerificationResult.new(digital_object_id)
|
204
|
-
|
203
|
+
version_list.each do |version|
|
205
204
|
result.subentities << version.verify_version_storage
|
206
205
|
end
|
207
206
|
result.subentities << current_version.verify_signature_catalog
|
208
|
-
result.verified = result.subentities.all?
|
207
|
+
result.verified = result.subentities.all?(&:verified)
|
209
208
|
result
|
210
209
|
end
|
211
210
|
|
@@ -216,7 +215,7 @@ module Moab
|
|
216
215
|
recovery_object = StorageObject.new(@digital_object_id, recovery_path, false)
|
217
216
|
recovery_object.versions.each do |recovery_version|
|
218
217
|
version_id = recovery_version.version_id
|
219
|
-
storage_version =
|
218
|
+
storage_version = storage_object_version(version_id)
|
220
219
|
# rename/save the original
|
221
220
|
storage_version.deactivate(timestamp)
|
222
221
|
# copy the recovered version into place
|