moab-versioning 4.2.1 → 4.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/moab.rb +1 -1
- data/lib/moab/bagger.rb +15 -15
- data/lib/moab/config.rb +0 -2
- data/lib/moab/deposit_bag_validator.rb +1 -1
- data/lib/moab/file_group.rb +13 -15
- data/lib/moab/file_group_difference.rb +18 -21
- data/lib/moab/file_group_difference_subset.rb +2 -4
- data/lib/moab/file_instance.rb +1 -3
- data/lib/moab/file_instance_difference.rb +3 -5
- data/lib/moab/file_inventory.rb +17 -27
- data/lib/moab/file_inventory_difference.rb +5 -7
- data/lib/moab/file_manifestation.rb +4 -6
- data/lib/moab/file_signature.rb +29 -40
- data/lib/moab/signature_catalog.rb +11 -13
- data/lib/moab/signature_catalog_entry.rb +1 -3
- data/lib/moab/storage_object.rb +12 -19
- data/lib/moab/storage_object_validator.rb +22 -8
- data/lib/moab/storage_object_version.rb +25 -27
- data/lib/moab/storage_repository.rb +6 -13
- data/lib/moab/storage_services.rb +6 -8
- data/lib/moab/utc_time.rb +0 -2
- data/lib/moab/verification_result.rb +0 -2
- data/lib/moab/version_metadata.rb +1 -3
- data/lib/moab/version_metadata_entry.rb +2 -4
- data/lib/moab/version_metadata_event.rb +0 -2
- data/lib/serializer/manifest.rb +5 -5
- data/lib/serializer/serializable.rb +34 -34
- data/lib/stanford/active_fedora_object.rb +0 -2
- data/lib/stanford/content_inventory.rb +22 -20
- data/lib/stanford/dor_metadata.rb +0 -2
- data/lib/stanford/storage_object_validator.rb +0 -2
- data/lib/stanford/storage_repository.rb +1 -2
- data/lib/stanford/storage_services.rb +5 -7
- metadata +3 -3
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'moab'
|
2
|
-
|
3
1
|
module Moab
|
4
2
|
# Compares two {FileInventory} instances based primarily on file signatures and secondarily on file pathnames.
|
5
3
|
# Although the usual use will be to compare the content of 2 different temporal versions of the same object,
|
@@ -24,7 +22,7 @@ module Moab
|
|
24
22
|
|
25
23
|
# (see Serializable#initialize)
|
26
24
|
def initialize(opts = {})
|
27
|
-
@group_differences =
|
25
|
+
@group_differences = []
|
28
26
|
super(opts)
|
29
27
|
end
|
30
28
|
|
@@ -34,7 +32,7 @@ module Moab
|
|
34
32
|
|
35
33
|
# @attribute
|
36
34
|
# @return [Integer] the number of differences found between the two inventories that were compared (dynamically calculated)
|
37
|
-
attribute :difference_count, Integer, :tag => 'differenceCount', :on_save =>
|
35
|
+
attribute :difference_count, Integer, :tag => 'differenceCount', :on_save => proc { |i| i.to_s }
|
38
36
|
|
39
37
|
def difference_count
|
40
38
|
@group_differences.inject(0) { |sum, group| sum + group.difference_count }
|
@@ -66,7 +64,7 @@ module Moab
|
|
66
64
|
|
67
65
|
# @return [Array<String>] The data fields to include in summary reports
|
68
66
|
def summary_fields
|
69
|
-
%w
|
67
|
+
%w[digital_object_id difference_count basis other report_datetime group_differences]
|
70
68
|
end
|
71
69
|
|
72
70
|
# @param [String] group_id The identifer of the group to be selected
|
@@ -110,11 +108,11 @@ module Moab
|
|
110
108
|
# @return [Hash] Serializes the data and then filters it to report only the changes
|
111
109
|
def differences_detail
|
112
110
|
#return self.summary if difference_count == 0
|
113
|
-
inv_diff =
|
111
|
+
inv_diff = to_hash
|
114
112
|
inv_diff["group_differences"].each_value do |group_diff|
|
115
113
|
delete_subsets = []
|
116
114
|
group_diff["subsets"].each do |change_type, subset|
|
117
|
-
delete_subsets << change_type if change_type == "identical"
|
115
|
+
delete_subsets << change_type if (change_type == "identical") || (subset["count"] == 0)
|
118
116
|
end
|
119
117
|
delete_subsets.each do |change_type|
|
120
118
|
group_diff["subsets"].delete(change_type)
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'moab'
|
2
|
-
|
3
1
|
module Moab
|
4
2
|
# A container for a file signature and all the physical file instances that have that signature
|
5
3
|
# This element has one child {FileSignature} element, and one or more {FileInstance} elements
|
@@ -24,7 +22,7 @@ module Moab
|
|
24
22
|
|
25
23
|
# (see Serializable#initialize)
|
26
24
|
def initialize(opts = {})
|
27
|
-
@instances =
|
25
|
+
@instances = []
|
28
26
|
super(opts)
|
29
27
|
end
|
30
28
|
|
@@ -47,7 +45,7 @@ module Moab
|
|
47
45
|
# @api internal
|
48
46
|
# @return [Array<String>] Create an array from all the file paths of the child {FileInstance} objects
|
49
47
|
def paths
|
50
|
-
instances.collect
|
48
|
+
instances.collect(&:path)
|
51
49
|
end
|
52
50
|
|
53
51
|
# @api internal
|
@@ -76,8 +74,8 @@ module Moab
|
|
76
74
|
# @param other [FileManifestation] The {FileManifestation} object to compare with self
|
77
75
|
# @return [Boolean] True if {FileManifestation} objects have same content
|
78
76
|
def ==(other)
|
79
|
-
return false unless
|
80
|
-
(
|
77
|
+
return false unless other.respond_to?(:signature) && other.respond_to?(:instances) # Cannot equal an incomparable type!
|
78
|
+
(signature == other.signature) && (instances == other.instances)
|
81
79
|
end
|
82
80
|
end
|
83
81
|
end
|
data/lib/moab/file_signature.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'moab'
|
2
|
-
|
3
1
|
module Moab
|
4
2
|
# The fixity properties of a file, used to determine file content equivalence regardless of filename.
|
5
3
|
# Placing this data in a class by itself facilitates using file size together with the MD5 and SHA1 checksums
|
@@ -46,19 +44,19 @@ module Moab
|
|
46
44
|
|
47
45
|
# @attribute
|
48
46
|
# @return [Integer] The size of the file in bytes
|
49
|
-
attribute :size, Integer, :on_save =>
|
47
|
+
attribute :size, Integer, :on_save => proc { |n| n.to_s }
|
50
48
|
|
51
49
|
# @attribute
|
52
50
|
# @return [String] The MD5 checksum value of the file
|
53
|
-
attribute :md5, String, :on_save =>
|
51
|
+
attribute :md5, String, :on_save => proc { |n| n.nil? ? "" : n.to_s }
|
54
52
|
|
55
53
|
# @attribute
|
56
54
|
# @return [String] The SHA1 checksum value of the file
|
57
|
-
attribute :sha1, String, :on_save =>
|
55
|
+
attribute :sha1, String, :on_save => proc { |n| n.nil? ? "" : n.to_s }
|
58
56
|
|
59
57
|
# @attribute
|
60
58
|
# @return [String] The SHA256 checksum value of the file
|
61
|
-
attribute :sha256, String, :on_save =>
|
59
|
+
attribute :sha256, String, :on_save => proc { |n| n.nil? ? "" : n.to_s }
|
62
60
|
|
63
61
|
KNOWN_ALGOS = {
|
64
62
|
md5: proc { Digest::MD5.new },
|
@@ -106,12 +104,11 @@ module Moab
|
|
106
104
|
|
107
105
|
# @return [Hash<Symbol,String>] A hash of the checksum data
|
108
106
|
def checksums
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
checksum_hash
|
107
|
+
{
|
108
|
+
md5: md5,
|
109
|
+
sha1: sha1,
|
110
|
+
sha256: sha256
|
111
|
+
}.reject { |_key, value| value.nil? || value.empty? }
|
115
112
|
end
|
116
113
|
|
117
114
|
# @return [Boolean] The signature contains all of the 3 desired checksums
|
@@ -120,24 +117,21 @@ module Moab
|
|
120
117
|
end
|
121
118
|
|
122
119
|
# @api internal
|
123
|
-
# @return [Hash<Symbol
|
120
|
+
# @return [Hash<Symbol => String>] A hash of fixity data from this signataure object
|
124
121
|
def fixity
|
125
|
-
|
126
|
-
fixity_hash[:size] = @size.to_s
|
127
|
-
fixity_hash.merge!(checksums)
|
128
|
-
fixity_hash
|
122
|
+
{ size: size.to_s }.merge(checksums)
|
129
123
|
end
|
130
124
|
|
131
125
|
# @api internal
|
132
126
|
# @param other [FileSignature] The other file signature being compared to this signature
|
133
127
|
# @return [Boolean] Returns true if self and other have comparable fixity data.
|
134
128
|
def eql?(other)
|
135
|
-
return false unless
|
136
|
-
return false if
|
137
|
-
self_checksums =
|
129
|
+
return false unless other.respond_to?(:size) && other.respond_to?(:checksums)
|
130
|
+
return false if size.to_i != other.size.to_i
|
131
|
+
self_checksums = checksums
|
138
132
|
other_checksums = other.checksums
|
139
133
|
matching_keys = self_checksums.keys & other_checksums.keys
|
140
|
-
return false if matching_keys.
|
134
|
+
return false if matching_keys.empty?
|
141
135
|
matching_keys.each do |key|
|
142
136
|
return false if self_checksums[key] != other_checksums[key]
|
143
137
|
end
|
@@ -181,31 +175,26 @@ module Moab
|
|
181
175
|
# @return [FileSignature] The full signature derived from the file, unless the fixity is inconsistent with current values
|
182
176
|
def normalized_signature(pathname)
|
183
177
|
sig_from_file = FileSignature.new.signature_from_file(pathname)
|
184
|
-
if
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
# One or more of the fixity values is inconsistent, so raise an exception
|
189
|
-
raise "Signature inconsistent between inventory and file for #{pathname}: #{self.diff(sig_from_file).inspect}"
|
190
|
-
end
|
178
|
+
return sig_from_file if eql?(sig_from_file)
|
179
|
+
# The full signature from file is consistent with current values, or...
|
180
|
+
# One or more of the fixity values is inconsistent, so raise an exception
|
181
|
+
raise "Signature inconsistent between inventory and file for #{pathname}: #{diff(sig_from_file).inspect}"
|
191
182
|
end
|
192
183
|
|
193
184
|
# @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
|
-
|
185
|
+
def self.checksum_names_for_type
|
186
|
+
{
|
187
|
+
md5: ['MD5'],
|
188
|
+
sha1: ['SHA-1', 'SHA1'],
|
189
|
+
sha256: ['SHA-256', 'SHA256']
|
190
|
+
}
|
200
191
|
end
|
201
192
|
|
202
193
|
# @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
|
194
|
+
def self.checksum_type_for_name
|
195
|
+
type_for_name = {}
|
196
|
+
checksum_names_for_type.each do |type, names|
|
197
|
+
names.each { |name| type_for_name[name] = type }
|
209
198
|
end
|
210
199
|
type_for_name
|
211
200
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'moab'
|
2
|
-
|
3
1
|
module Moab
|
4
2
|
# A digital object's Signature Catalog is derived from an filtered aggregation of the file inventories
|
5
3
|
# of a digital object's set of versions. (see {#update})
|
@@ -32,8 +30,8 @@ module Moab
|
|
32
30
|
|
33
31
|
# (see Serializable#initialize)
|
34
32
|
def initialize(opts = {})
|
35
|
-
@entries =
|
36
|
-
@signature_hash =
|
33
|
+
@entries = []
|
34
|
+
@signature_hash = {}
|
37
35
|
super(opts)
|
38
36
|
end
|
39
37
|
|
@@ -43,7 +41,7 @@ module Moab
|
|
43
41
|
|
44
42
|
# @attribute
|
45
43
|
# @return [Integer] The ordinal version number
|
46
|
-
attribute :version_id, Integer, :tag => 'versionId', :key => true, :on_save =>
|
44
|
+
attribute :version_id, Integer, :tag => 'versionId', :key => true, :on_save => proc { |n| n.to_s }
|
47
45
|
|
48
46
|
# @return [String] The unique identifier concatenating digital object id with version id
|
49
47
|
def composite_key
|
@@ -64,7 +62,7 @@ module Moab
|
|
64
62
|
|
65
63
|
# @attribute
|
66
64
|
# @return [Integer] The total number of data files (dynamically calculated)
|
67
|
-
attribute :file_count, Integer, :tag => 'fileCount', :on_save =>
|
65
|
+
attribute :file_count, Integer, :tag => 'fileCount', :on_save => proc { |t| t.to_s }
|
68
66
|
|
69
67
|
def file_count
|
70
68
|
entries.size
|
@@ -72,7 +70,7 @@ module Moab
|
|
72
70
|
|
73
71
|
# @attribute
|
74
72
|
# @return [Integer] The total size (in bytes) of all data files (dynamically calculated)
|
75
|
-
attribute :byte_count, Integer, :tag => 'byteCount', :on_save =>
|
73
|
+
attribute :byte_count, Integer, :tag => 'byteCount', :on_save => proc { |t| t.to_s }
|
76
74
|
|
77
75
|
def byte_count
|
78
76
|
entries.inject(0) { |sum, entry| sum + entry.signature.size.to_i }
|
@@ -80,7 +78,7 @@ module Moab
|
|
80
78
|
|
81
79
|
# @attribute
|
82
80
|
# @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, :tag => 'blockCount', :on_save =>
|
81
|
+
attribute :block_count, Integer, :tag => 'blockCount', :on_save => proc { |t| t.to_s }
|
84
82
|
|
85
83
|
def block_count
|
86
84
|
block_size = 1024
|
@@ -89,7 +87,7 @@ module Moab
|
|
89
87
|
|
90
88
|
# @return [Array<String>] The data fields to include in summary reports
|
91
89
|
def summary_fields
|
92
|
-
%w
|
90
|
+
%w[digital_object_id version_id catalog_datetime file_count byte_count block_count]
|
93
91
|
end
|
94
92
|
|
95
93
|
# @attribute
|
@@ -134,7 +132,7 @@ module Moab
|
|
134
132
|
end
|
135
133
|
group.files.each do |file|
|
136
134
|
unless file.signature.complete?
|
137
|
-
if @signature_hash.
|
135
|
+
if @signature_hash.key?(file.signature)
|
138
136
|
file.signature = @signature_hash.find { |k, _v| k == file.signature }[0]
|
139
137
|
elsif group_pathname
|
140
138
|
file_pathname = group_pathname.join(file.instances[0].path)
|
@@ -153,7 +151,7 @@ module Moab
|
|
153
151
|
def update(version_inventory, data_pathname)
|
154
152
|
version_inventory.groups.each do |group|
|
155
153
|
group.files.each do |file|
|
156
|
-
unless @signature_hash.
|
154
|
+
unless @signature_hash.key?(file.signature)
|
157
155
|
entry = SignatureCatalogEntry.new
|
158
156
|
entry.version_id = version_inventory.version_id
|
159
157
|
entry.group_id = group.group_id
|
@@ -183,11 +181,11 @@ module Moab
|
|
183
181
|
version_inventory.groups.each do |group|
|
184
182
|
group_addtions = FileGroup.new(:group_id => group.group_id)
|
185
183
|
group.files.each do |file|
|
186
|
-
unless @signature_hash.
|
184
|
+
unless @signature_hash.key?(file.signature)
|
187
185
|
group_addtions.add_file_instance(file.signature, file.instances[0])
|
188
186
|
end
|
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,5 +1,3 @@
|
|
1
|
-
require 'moab'
|
2
|
-
|
3
1
|
module Moab
|
4
2
|
# A file-level entry in a digital object's {SignatureCatalog}.
|
5
3
|
# It has a child {FileSignature} element that identifies the file's contents (the bytestream)
|
@@ -25,7 +23,7 @@ module Moab
|
|
25
23
|
|
26
24
|
# @attribute
|
27
25
|
# @return [Integer] The ordinal version number
|
28
|
-
attribute :version_id, Integer, :tag => 'originalVersion', :key => true, :on_save =>
|
26
|
+
attribute :version_id, Integer, :tag => 'originalVersion', :key => true, :on_save => proc { |n| n.to_s }
|
29
27
|
|
30
28
|
# @attribute
|
31
29
|
# @return [String] The name of the file group
|
data/lib/moab/storage_object.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'moab'
|
2
|
-
|
3
1
|
module Moab
|
4
2
|
# A class to represent a digital object's repository storage location
|
5
3
|
# and methods for
|
@@ -122,27 +120,25 @@ module Moab
|
|
122
120
|
# @param version_id [Integer] The version identifier of an object version
|
123
121
|
# @return [String] The directory name of the version, relative to the digital object home directory (e.g v0002)
|
124
122
|
def self.version_dirname(version_id)
|
125
|
-
("v%04d"
|
123
|
+
format("v%04d", version_id)
|
126
124
|
end
|
127
125
|
|
128
126
|
# @return [Array<Integer>] The list of all version ids for this object
|
129
127
|
def version_id_list
|
130
|
-
list =
|
128
|
+
list = []
|
131
129
|
return list unless @object_pathname.exist?
|
132
130
|
@object_pathname.children.each do |dirname|
|
133
131
|
vnum = dirname.basename.to_s
|
134
|
-
if vnum =~ /^v(\d+)$/
|
135
|
-
list << vnum[1..-1].to_i
|
136
|
-
end
|
132
|
+
list << vnum[1..-1].to_i if vnum =~ /^v(\d+)$/
|
137
133
|
end
|
138
134
|
list.sort
|
139
135
|
end
|
140
136
|
|
141
137
|
# @return [Array<StorageObjectVersion>] The list of all versions in this storage object
|
142
138
|
def version_list
|
143
|
-
version_id_list.collect { |id|
|
139
|
+
version_id_list.collect { |id| storage_object_version(id) }
|
144
140
|
end
|
145
|
-
alias
|
141
|
+
alias versions version_list
|
146
142
|
|
147
143
|
# @return [Boolean] true if there are no versions yet in this object
|
148
144
|
def empty?
|
@@ -152,12 +148,12 @@ module Moab
|
|
152
148
|
# @api external
|
153
149
|
# @return [Integer] The identifier of the latest version of this object, or 0 if no versions exist
|
154
150
|
def current_version_id
|
155
|
-
@current_version_id ||=
|
151
|
+
@current_version_id ||= version_id_list.last || 0
|
156
152
|
end
|
157
153
|
|
158
154
|
# @return [StorageObjectVersion] The most recent version in the storage object
|
159
155
|
def current_version
|
160
|
-
|
156
|
+
storage_object_version(current_version_id)
|
161
157
|
end
|
162
158
|
|
163
159
|
# @api internal
|
@@ -191,21 +187,18 @@ module Moab
|
|
191
187
|
# * Version 0 is a special case used to generate empty manifests
|
192
188
|
# * Current version + 1 is used for creation of a new version
|
193
189
|
def storage_object_version(version_id)
|
194
|
-
|
195
|
-
|
196
|
-
else
|
197
|
-
raise "Version ID not specified"
|
198
|
-
end
|
190
|
+
raise "Version ID not specified" unless version_id
|
191
|
+
StorageObjectVersion.new(self, version_id)
|
199
192
|
end
|
200
193
|
|
201
194
|
# @return [VerificationResult] Return result of storage verification
|
202
195
|
def verify_object_storage
|
203
196
|
result = VerificationResult.new(digital_object_id)
|
204
|
-
|
197
|
+
version_list.each do |version|
|
205
198
|
result.subentities << version.verify_version_storage
|
206
199
|
end
|
207
200
|
result.subentities << current_version.verify_signature_catalog
|
208
|
-
result.verified = result.subentities.all?
|
201
|
+
result.verified = result.subentities.all?(&:verified)
|
209
202
|
result
|
210
203
|
end
|
211
204
|
|
@@ -216,7 +209,7 @@ module Moab
|
|
216
209
|
recovery_object = StorageObject.new(@digital_object_id, recovery_path, false)
|
217
210
|
recovery_object.versions.each do |recovery_version|
|
218
211
|
version_id = recovery_version.version_id
|
219
|
-
storage_version =
|
212
|
+
storage_version = storage_object_version(version_id)
|
220
213
|
# rename/save the original
|
221
214
|
storage_version.deactivate(timestamp)
|
222
215
|
# copy the recovered version into place
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'moab'
|
2
1
|
require 'set'
|
3
2
|
|
4
3
|
module Moab
|
@@ -59,11 +58,11 @@ module Moab
|
|
59
58
|
NO_SIGNATURE_CATALOG => "Version %{addl}: Missing signatureCatalog.xml",
|
60
59
|
NO_MANIFEST_INVENTORY => "Version %{addl}: Missing manifestInventory.xml",
|
61
60
|
NO_FILES_IN_MANIFEST_DIR => "Version %{addl}: No files present in manifest dir",
|
62
|
-
METADATA_SUB_DIRS_DETECTED => "Version %{
|
61
|
+
METADATA_SUB_DIRS_DETECTED => "Version %{version}: metadata directory should only contain files, not directories. Found directory: %{dir}",
|
63
62
|
VERSIONS_NOT_IN_ORDER => "Should contain only sequential version directories. Current directories: %{addl}",
|
64
63
|
NO_FILES_IN_METADATA_DIR => "Version %{addl}: No files present in metadata dir",
|
65
64
|
NO_FILES_IN_CONTENT_DIR => "Version %{addl}: No files present in content dir",
|
66
|
-
CONTENT_SUB_DIRS_DETECTED => "Version %{
|
65
|
+
CONTENT_SUB_DIRS_DETECTED => "Version %{version}: content directory should only contain files, not directories. Found directory: %{dir}",
|
67
66
|
BAD_SUB_DIR_IN_CONTENT_DIR => "Version %{addl}: content directory has forbidden sub-directory name: vnnnn or #{FORBIDDEN_CONTENT_SUB_DIRS}"
|
68
67
|
}.freeze
|
69
68
|
end
|
@@ -139,7 +138,8 @@ module Moab
|
|
139
138
|
errors = []
|
140
139
|
content_dir_path = File.join(version_path, DATA_DIR, CONTENT_DIR)
|
141
140
|
errors << result_hash(NO_FILES_IN_CONTENT_DIR, basename(version_path)) if directory_entries(content_dir_path).empty?
|
142
|
-
|
141
|
+
content_sub_dir = contains_sub_dir?(content_dir_path)
|
142
|
+
errors << result_hash(CONTENT_SUB_DIRS_DETECTED, version: basename(version_path), dir: content_sub_dir) if content_sub_dir && !allow_content_subdirs
|
143
143
|
if allow_content_subdirs && contains_sub_dir?(content_dir_path) && contains_forbidden_content_sub_dir?(content_dir_path)
|
144
144
|
errors << result_hash(BAD_SUB_DIR_IN_CONTENT_DIR, basename(version_path))
|
145
145
|
end
|
@@ -158,7 +158,8 @@ module Moab
|
|
158
158
|
errors = []
|
159
159
|
metadata_dir_path = File.join(version_path, DATA_DIR, METADATA_DIR)
|
160
160
|
errors << result_hash(NO_FILES_IN_METADATA_DIR, basename(version_path)) if directory_entries(metadata_dir_path).empty?
|
161
|
-
|
161
|
+
metadata_sub_dir = contains_sub_dir?(metadata_dir_path)
|
162
|
+
errors << result_hash(METADATA_SUB_DIRS_DETECTED, version: basename(version_path), dir: metadata_sub_dir) if metadata_sub_dir
|
162
163
|
errors
|
163
164
|
end
|
164
165
|
|
@@ -204,12 +205,25 @@ module Moab
|
|
204
205
|
path.split(File::SEPARATOR)[-1]
|
205
206
|
end
|
206
207
|
|
207
|
-
|
208
|
-
|
208
|
+
# @param [Integer] response_code one of the recognized values in error_code_to_messages
|
209
|
+
# @param [Hash<Symbol => String>, String] msg_args Value(s) folded into the error message
|
210
|
+
# @return [Hash<Integer => String>] single key/value Hash
|
211
|
+
# @example Usage
|
212
|
+
# sov.result_hash(10, '/some/dir')
|
213
|
+
# sov.result_hash(10, addl: '/some/dir') # equivalent
|
214
|
+
# sov.result_hash(8, version: '3', dir: '/other/dir')
|
215
|
+
def result_hash(response_code, msg_args = nil)
|
216
|
+
{ response_code => error_code_msg(response_code, msg_args) }
|
209
217
|
end
|
210
218
|
|
211
219
|
def error_code_msg(response_code, addl = nil)
|
212
|
-
|
220
|
+
arg_hash = {}
|
221
|
+
if addl.is_a?(Hash)
|
222
|
+
arg_hash.merge!(addl)
|
223
|
+
else
|
224
|
+
arg_hash[:addl] = addl
|
225
|
+
end
|
226
|
+
self.class.error_code_to_messages[response_code] % arg_hash
|
213
227
|
end
|
214
228
|
|
215
229
|
def check_required_manifest_files(dir, version)
|