moab-versioning 4.2.1 → 4.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +5 -5
  2. data/lib/moab.rb +3 -2
  3. data/lib/moab/bagger.rb +25 -20
  4. data/lib/moab/config.rb +39 -8
  5. data/lib/moab/deposit_bag_validator.rb +22 -17
  6. data/lib/moab/exceptions.rb +10 -8
  7. data/lib/moab/file_group.rb +23 -22
  8. data/lib/moab/file_group_difference.rb +35 -35
  9. data/lib/moab/file_group_difference_subset.rb +5 -5
  10. data/lib/moab/file_instance.rb +4 -3
  11. data/lib/moab/file_instance_difference.rb +5 -5
  12. data/lib/moab/file_inventory.rb +25 -31
  13. data/lib/moab/file_inventory_difference.rb +11 -11
  14. data/lib/moab/file_manifestation.rb +8 -7
  15. data/lib/moab/file_signature.rb +35 -41
  16. data/lib/moab/signature_catalog.rb +19 -21
  17. data/lib/moab/signature_catalog_entry.rb +5 -5
  18. data/lib/moab/stanford.rb +2 -0
  19. data/lib/moab/storage_object.rb +23 -24
  20. data/lib/moab/storage_object_validator.rb +44 -16
  21. data/lib/moab/storage_object_version.rb +45 -40
  22. data/lib/moab/storage_repository.rb +59 -24
  23. data/lib/moab/storage_services.rb +17 -10
  24. data/lib/moab/utc_time.rb +3 -3
  25. data/lib/moab/verification_result.rb +3 -4
  26. data/lib/moab/version_metadata.rb +4 -4
  27. data/lib/moab/version_metadata_entry.rb +6 -6
  28. data/lib/moab/version_metadata_event.rb +1 -1
  29. data/lib/serializer.rb +2 -0
  30. data/lib/serializer/manifest.rb +9 -7
  31. data/lib/serializer/serializable.rb +41 -35
  32. data/lib/stanford/active_fedora_object.rb +1 -1
  33. data/lib/stanford/content_inventory.rb +40 -34
  34. data/lib/stanford/dor_metadata.rb +4 -3
  35. data/lib/stanford/moab_storage_directory.rb +4 -2
  36. data/lib/stanford/storage_object_validator.rb +1 -1
  37. data/lib/stanford/storage_repository.rb +9 -6
  38. data/lib/stanford/storage_services.rb +6 -6
  39. metadata +23 -38
@@ -1,4 +1,4 @@
1
- require 'moab'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Moab
4
4
  # Performs analysis and reports the differences between two matching {FileGroup} objects.
@@ -53,18 +53,18 @@ module Moab
53
53
 
54
54
  # (see Serializable#initialize)
55
55
  def initialize(opts = {})
56
- @subset_hash = Hash.new { |hash, key| hash[key] = FileGroupDifferenceSubset.new(:change => key.to_s) }
56
+ @subset_hash = Hash.new { |hash, key| hash[key] = FileGroupDifferenceSubset.new(change: key.to_s) }
57
57
  super(opts)
58
58
  end
59
59
 
60
60
  # @attribute
61
61
  # @return [String] The name of the file group
62
- attribute :group_id, String, :tag => 'groupId', :key => true
62
+ attribute :group_id, String, tag: 'groupId', key: true
63
63
 
64
64
  # @attribute
65
65
  # @return [Integer] the total number of differences found between the two inventories that were
66
66
  # compared (dynamically calculated)
67
- attribute :difference_count, Integer, :tag => 'differenceCount', :on_save => Proc.new { |i| i.to_s }
67
+ attribute :difference_count, Integer, tag: 'differenceCount', on_save: proc { |i| i.to_s }
68
68
 
69
69
  def difference_count
70
70
  count = 0
@@ -76,49 +76,49 @@ module Moab
76
76
 
77
77
  # @attribute
78
78
  # @return [Integer] How many files were unchanged
79
- attribute :identical, Integer, :on_save => Proc.new { |n| n.to_s }
79
+ attribute :identical, Integer, on_save: proc { |n| n.to_s }
80
80
  def identical
81
81
  subset_hash[:identical].count
82
82
  end
83
83
 
84
84
  # @attribute
85
85
  # @return [Integer] How many duplicate copies of files were added
86
- attribute :copyadded, Integer, :on_save => Proc.new { |n| n.to_s }
86
+ attribute :copyadded, Integer, on_save: proc { |n| n.to_s }
87
87
  def copyadded
88
88
  subset_hash[:copyadded].count
89
89
  end
90
90
 
91
91
  # @attribute
92
92
  # @return [Integer] How many duplicate copies of files were deleted
93
- attribute :copydeleted, Integer, :on_save => Proc.new { |n| n.to_s }
93
+ attribute :copydeleted, Integer, on_save: proc { |n| n.to_s }
94
94
  def copydeleted
95
95
  subset_hash[:copydeleted].count
96
96
  end
97
97
 
98
98
  # @attribute
99
99
  # @return [Integer] How many files were renamed
100
- attribute :renamed, Integer, :on_save => Proc.new { |n| n.to_s }
100
+ attribute :renamed, Integer, on_save: proc { |n| n.to_s }
101
101
  def renamed
102
102
  subset_hash[:renamed].count
103
103
  end
104
104
 
105
105
  # @attribute
106
106
  # @return [Integer] How many files were modified
107
- attribute :modified, Integer, :on_save => Proc.new { |n| n.to_s }
107
+ attribute :modified, Integer, on_save: proc { |n| n.to_s }
108
108
  def modified
109
109
  subset_hash[:modified].count
110
110
  end
111
111
 
112
112
  # @attribute
113
113
  # @return [Integer] How many files were added
114
- attribute :added, Integer, :on_save => Proc.new { |n| n.to_s }
114
+ attribute :added, Integer, on_save: proc { |n| n.to_s }
115
115
  def added
116
116
  subset_hash[:added].count
117
117
  end
118
118
 
119
119
  # @attribute
120
120
  # @return [Integer] How many files were deleted
121
- attribute :deleted, Integer, :on_save => Proc.new { |n| n.to_s }
121
+ attribute :deleted, Integer, on_save: proc { |n| n.to_s }
122
122
  def deleted
123
123
  subset_hash[:deleted].count
124
124
  end
@@ -126,35 +126,35 @@ module Moab
126
126
  # @attribute
127
127
  # @return [Array<FileGroupDifferenceSubset>] A set of Arrays (one for each change type),
128
128
  # each of which contains an collection of file-level differences having that change type.
129
- has_many :subsets, FileGroupDifferenceSubset, :tag => 'subset'
129
+ has_many :subsets, FileGroupDifferenceSubset, tag: 'subset'
130
130
 
131
131
  def subsets
132
132
  subset_hash.values
133
133
  end
134
134
 
135
135
  def subsets=(array)
136
- if array
137
- array.each { |subset| subset_hash[subset.change.to_sym] = subset }
138
- end
136
+ return unless array
137
+
138
+ array.each { |subset| subset_hash[subset.change.to_sym] = subset }
139
139
  end
140
140
 
141
141
  # @return [Array<String>] The data fields to include in summary reports
142
142
  def summary_fields
143
- %w{group_id difference_count identical copyadded copydeleted renamed modified deleted added}
143
+ %w[group_id difference_count identical copyadded copydeleted renamed modified deleted added]
144
144
  end
145
145
 
146
146
  # @api internal
147
147
  # @return [FileGroupDifference] Clone just this element for inclusion in a versionMetadata structure
148
- def summary()
148
+ def summary
149
149
  FileGroupDifference.new(
150
- :group_id => group_id,
151
- :identical => identical,
152
- :copyadded => copyadded,
153
- :copydeleted => copydeleted,
154
- :renamed => renamed,
155
- :modified => modified,
156
- :added => added,
157
- :deleted => deleted
150
+ group_id: group_id,
151
+ identical: identical,
152
+ copyadded: copyadded,
153
+ copydeleted: copydeleted,
154
+ renamed: renamed,
155
+ modified: modified,
156
+ added: added,
157
+ deleted: deleted
158
158
  )
159
159
  end
160
160
 
@@ -231,7 +231,7 @@ module Moab
231
231
  other_paths = other_signature_hash[signature].paths
232
232
  matching_paths = basis_paths & other_paths
233
233
  matching_paths.each do |path|
234
- fid = FileInstanceDifference.new(:change => 'identical')
234
+ fid = FileInstanceDifference.new(change: 'identical')
235
235
  fid.basis_path = path
236
236
  fid.other_path = "same"
237
237
  fid.signatures << signature
@@ -257,7 +257,7 @@ module Moab
257
257
  other_only_paths = other_paths - basis_paths
258
258
  maxsize = [basis_only_paths.size, other_only_paths.size].max
259
259
  (0..maxsize - 1).each do |n|
260
- fid = FileInstanceDifference.new()
260
+ fid = FileInstanceDifference.new
261
261
  fid.basis_path = basis_only_paths[n]
262
262
  fid.other_path = other_only_paths[n]
263
263
  fid.signatures << signature
@@ -284,7 +284,7 @@ module Moab
284
284
  # Container for reporting the set of file-level differences of type 'modified'
285
285
  def tabulate_modified_files(basis_path_hash, other_path_hash)
286
286
  matching_keys(basis_path_hash, other_path_hash).each do |path|
287
- fid = FileInstanceDifference.new(:change => 'modified')
287
+ fid = FileInstanceDifference.new(change: 'modified')
288
288
  fid.basis_path = path
289
289
  fid.other_path = "same"
290
290
  fid.signatures << basis_path_hash[path]
@@ -303,7 +303,7 @@ module Moab
303
303
  # Container for reporting the set of file-level differences of type 'added'
304
304
  def tabulate_added_files(basis_path_hash, other_path_hash)
305
305
  other_only_keys(basis_path_hash, other_path_hash).each do |path|
306
- fid = FileInstanceDifference.new(:change => 'added')
306
+ fid = FileInstanceDifference.new(change: 'added')
307
307
  fid.basis_path = ""
308
308
  fid.other_path = path
309
309
  fid.signatures << other_path_hash[path]
@@ -321,7 +321,7 @@ module Moab
321
321
  # Container for reporting the set of file-level differences of type 'deleted'
322
322
  def tabulate_deleted_files(basis_path_hash, other_path_hash)
323
323
  basis_only_keys(basis_path_hash, other_path_hash).each do |path|
324
- fid = FileInstanceDifference.new(:change => 'deleted')
324
+ fid = FileInstanceDifference.new(change: 'deleted')
325
325
  fid.basis_path = path
326
326
  fid.other_path = ""
327
327
  fid.signatures << basis_path_hash[path]
@@ -331,20 +331,20 @@ module Moab
331
331
  end
332
332
 
333
333
  # @return [Hash<Symbol,Array>] Sets of filenames grouped by change type for use in performing file or metadata operations
334
- def file_deltas()
334
+ def file_deltas
335
335
  # The hash to be returned
336
336
  deltas = Hash.new { |hash, key| hash[key] = [] }
337
337
  # case where other_path is empty or 'same'. (create array of strings)
338
- [:identical, :modified, :deleted, :copydeleted].each do |change|
339
- deltas[change].concat(subset_hash[change].files.collect { |file| file.basis_path })
338
+ %i[identical modified deleted copydeleted].each do |change|
339
+ deltas[change].concat(subset_hash[change].files.collect(&:basis_path))
340
340
  end
341
341
  # case where basis_path and other_path are both present. (create array of arrays)
342
- [:copyadded, :renamed].each do |change|
342
+ %i[copyadded renamed].each do |change|
343
343
  deltas[change].concat(subset_hash[change].files.collect { |file| [file.basis_path, file.other_path] })
344
344
  end
345
345
  # case where basis_path is empty. (create array of strings)
346
346
  [:added].each do |change|
347
- deltas[change].concat(subset_hash[change].files.collect { |file| file.other_path })
347
+ deltas[change].concat(subset_hash[change].files.collect(&:other_path))
348
348
  end
349
349
  deltas
350
350
  end
@@ -1,4 +1,4 @@
1
- require 'moab'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Moab
4
4
  # A container for reporting a set of file-level differences of the type specified by the change attribute
@@ -20,17 +20,17 @@ module Moab
20
20
 
21
21
  # (see Serializable#initialize)
22
22
  def initialize(opts = {})
23
- @files = Array.new
23
+ @files = []
24
24
  super(opts)
25
25
  end
26
26
 
27
27
  # @attribute
28
28
  # @return [String] The type of change (identical|renamed|modified|deleted|added)
29
- attribute :change, String, :key => true
29
+ attribute :change, String, key: true
30
30
 
31
31
  # @attribute
32
32
  # @return [Integer] How many files were changed
33
- attribute :count, Integer, :on_save => Proc.new { |n| n.to_s }
33
+ attribute :count, Integer, on_save: proc { |n| n.to_s }
34
34
 
35
35
  def count
36
36
  files.size
@@ -38,6 +38,6 @@ module Moab
38
38
 
39
39
  # @attribute
40
40
  # @return [Array<FileInstanceDifference>] The set of file instances having this type of change
41
- has_many :files, FileInstanceDifference, :tag => 'file'
41
+ has_many :files, FileInstanceDifference, tag: 'file'
42
42
  end
43
43
  end
@@ -1,4 +1,4 @@
1
- require 'moab'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Moab
4
4
  # The file path and last modification date properties of a file
@@ -25,7 +25,7 @@ module Moab
25
25
 
26
26
  # @attribute
27
27
  # @return [String] The id is the filename path, relative to the file group's base directory
28
- attribute :path, String, :key => true
28
+ attribute :path, String, key: true
29
29
 
30
30
  # @attribute
31
31
  # @return [String] gsub(/\n/,' ')
@@ -54,7 +54,8 @@ module Moab
54
54
  # @return [Boolean] Returns true if self and other have the same path.
55
55
  def eql?(other)
56
56
  return false unless other.respond_to?(:path) # Cannot equal an incomparable type!
57
- self.path == other.path
57
+
58
+ path == other.path
58
59
  end
59
60
 
60
61
  # @api internal
@@ -1,4 +1,4 @@
1
- require 'moab'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Moab
4
4
  # A container for recording difference information at the file level
@@ -28,7 +28,7 @@ module Moab
28
28
 
29
29
  # (see Serializable#initialize)
30
30
  def initialize(opts = {})
31
- @signatures = Array.new
31
+ @signatures = []
32
32
  super(opts)
33
33
  end
34
34
 
@@ -38,14 +38,14 @@ module Moab
38
38
 
39
39
  # @attribute
40
40
  # @return [String] The file's path in the basis inventory (usually for an old version)
41
- attribute :basis_path, String, :tag => 'basisPath', :on_save => Proc.new { |s| s.to_s }
41
+ attribute :basis_path, String, tag: 'basisPath', on_save: proc { |s| s.to_s }
42
42
 
43
43
  # @attribute
44
44
  # @return [String] The file's path in the other inventory (usually for an new version) compared against the basis
45
- attribute :other_path, String, :tag => 'otherPath', :on_save => Proc.new { |s| s.to_s }
45
+ attribute :other_path, String, tag: 'otherPath', on_save: proc { |s| s.to_s }
46
46
 
47
47
  # @attribute
48
48
  # @return [Array<FileSignature>] The fixity data of the file manifestation(s) (plural if change was a content modification)
49
- has_many :signatures, FileSignature, :tag => 'fileSignature'
49
+ has_many :signatures, FileSignature, tag: 'fileSignature'
50
50
  end
51
51
  end
@@ -1,4 +1,4 @@
1
- require 'moab'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Moab
4
4
  # A structured container for recording information about a collection of related files.
@@ -35,7 +35,7 @@ module Moab
35
35
 
36
36
  # (see Serializable#initialize)
37
37
  def initialize(opts = {})
38
- @groups = Array.new
38
+ @groups = []
39
39
  @inventory_datetime = Time.now
40
40
  super(opts)
41
41
  end
@@ -46,20 +46,20 @@ module Moab
46
46
 
47
47
  # @attribute
48
48
  # @return [String] The digital object identifier (druid)
49
- attribute :digital_object_id, String, :tag => 'objectId'
49
+ attribute :digital_object_id, String, tag: 'objectId'
50
50
 
51
51
  # @attribute
52
52
  # @return [Integer] The ordinal version number
53
- attribute :version_id, Integer, :tag => 'versionId', :key => true, :on_save => Proc.new { |n| n.to_s }
53
+ attribute :version_id, Integer, tag: 'versionId', key: true, on_save: proc { |n| n.to_s }
54
54
 
55
55
  # @return [String] The unique identifier concatenating digital object id with version id
56
56
  def composite_key
57
- digital_object_id + '-' + StorageObject.version_dirname(version_id)
57
+ "#{digital_object_id}-#{StorageObject.version_dirname(version_id)}"
58
58
  end
59
59
 
60
60
  # @attribute
61
61
  # @return [String] The datetime at which the inventory was created
62
- attribute :inventory_datetime, String, :tag => 'inventoryDatetime'
62
+ attribute :inventory_datetime, String, tag: 'inventoryDatetime'
63
63
 
64
64
  def inventory_datetime=(datetime)
65
65
  @inventory_datetime = Moab::UtcTime.input(datetime)
@@ -71,7 +71,7 @@ module Moab
71
71
 
72
72
  # @attribute
73
73
  # @return [Integer] The total number of data files in the inventory (dynamically calculated)
74
- attribute :file_count, Integer, :tag => 'fileCount', :on_save => Proc.new { |t| t.to_s }
74
+ attribute :file_count, Integer, tag: 'fileCount', on_save: proc { |t| t.to_s }
75
75
 
76
76
  def file_count
77
77
  groups.inject(0) { |sum, group| sum + group.file_count }
@@ -79,7 +79,7 @@ module Moab
79
79
 
80
80
  # @attribute
81
81
  # @return [Integer] The total size (in bytes) in all files of all files in the inventory (dynamically calculated)
82
- attribute :byte_count, Integer, :tag => 'byteCount', :on_save => Proc.new { |t| t.to_s }
82
+ attribute :byte_count, Integer, tag: 'byteCount', on_save: proc { |t| t.to_s }
83
83
 
84
84
  def byte_count
85
85
  groups.inject(0) { |sum, group| sum + group.byte_count }
@@ -87,7 +87,7 @@ module Moab
87
87
 
88
88
  # @attribute
89
89
  # @return [Integer] The total disk usage (in 1 kB blocks) of all data files (estimating du -k result) (dynamically calculated)
90
- attribute :block_count, Integer, :tag => 'blockCount', :on_save => Proc.new { |t| t.to_s }
90
+ attribute :block_count, Integer, tag: 'blockCount', on_save: proc { |t| t.to_s }
91
91
 
92
92
  def block_count
93
93
  groups.inject(0) { |sum, group| sum + group.block_count }
@@ -95,18 +95,18 @@ module Moab
95
95
 
96
96
  # @attribute
97
97
  # @return [Array<FileGroup>] The set of data groups comprising the version
98
- has_many :groups, FileGroup, :tag => 'fileGroup'
98
+ has_many :groups, FileGroup, tag: 'fileGroup'
99
99
 
100
100
  # @return [Array<FileGroup] The set of data groups that contain files
101
101
  def non_empty_groups
102
- groups.select { |group| !group.files.empty? }
102
+ groups.reject { |group| group.files.empty? }
103
103
  end
104
104
 
105
105
  # @param non_empty [Boolean] if true, return group_id's only for groups having files
106
106
  # @return [Array<String>] group identifiers contained in this file inventory
107
107
  def group_ids(non_empty = nil)
108
- my_groups = non_empty ? self.non_empty_groups : groups
109
- my_groups.map { |g| g.group_id }
108
+ my_groups = non_empty ? non_empty_groups : groups
109
+ my_groups.map(&:group_id)
110
110
  end
111
111
 
112
112
  # @param [String] group_id The identifer of the group to be selected
@@ -119,12 +119,12 @@ module Moab
119
119
  # @return [Boolean] true if the group is missing or empty
120
120
  def group_empty?(group_id)
121
121
  group = self.group(group_id)
122
- group.nil? or group.files.empty?
122
+ group.nil? || group.files.empty?
123
123
  end
124
124
 
125
125
  # @return [Array<String>] The data fields to include in summary reports
126
126
  def summary_fields
127
- %w{type digital_object_id version_id inventory_datetime file_count byte_count block_count groups}
127
+ %w[type digital_object_id version_id inventory_datetime file_count byte_count block_count groups]
128
128
  end
129
129
 
130
130
  # @param [String] group_id The identifer of the group to be selected
@@ -134,9 +134,11 @@ module Moab
134
134
  file_group = group(group_id)
135
135
  errmsg = "group #{group_id} not found for #{digital_object_id} - #{version_id}"
136
136
  raise FileNotFoundException, errmsg if file_group.nil?
137
+
137
138
  file_signature = file_group.path_hash[file_id]
138
139
  errmsg = "#{group_id} file #{file_id} not found for #{digital_object_id} - #{version_id}"
139
140
  raise FileNotFoundException, errmsg if file_signature.nil?
141
+
140
142
  file_signature
141
143
  end
142
144
 
@@ -161,17 +163,9 @@ module Moab
161
163
  def data_source
162
164
  data_source = (groups.collect { |g| g.data_source.to_s }).join('|')
163
165
  if data_source.start_with?('contentMetadata')
164
- if version_id
165
- "v#{version_id}-#{data_source}"
166
- else
167
- "new-#{data_source}"
168
- end
166
+ version_id ? "v#{version_id}-#{data_source}" : "new-#{data_source}"
169
167
  else
170
- if version_id
171
- "v#{version_id}"
172
- else
173
- data_source
174
- end
168
+ version_id ? "v#{version_id}" : data_source
175
169
  end
176
170
  end
177
171
 
@@ -185,7 +179,7 @@ module Moab
185
179
  if group_id
186
180
  groups << FileGroup.new(group_id: group_id).group_from_directory(data_dir)
187
181
  else
188
- ['content', 'metadata'].each do |gid|
182
+ %w[content metadata].each do |gid|
189
183
  groups << FileGroup.new(group_id: gid).group_from_directory(Pathname(data_dir).join(gid))
190
184
  end
191
185
  end
@@ -200,7 +194,7 @@ module Moab
200
194
  signatures_from_bag = signatures_from_bagit_manifests(bag_pathname)
201
195
  bag_data_subdirs = bag_pathname.join('data').children
202
196
  bag_data_subdirs.each do |subdir|
203
- groups << FileGroup.new(:group_id => subdir.basename.to_s).group_from_bagit_subdir(subdir, signatures_from_bag)
197
+ groups << FileGroup.new(group_id: subdir.basename.to_s).group_from_bagit_subdir(subdir, signatures_from_bag)
204
198
  end
205
199
  self
206
200
  end
@@ -208,7 +202,7 @@ module Moab
208
202
  # @param bag_pathname [Pathname] The location of the BagIt bag to be inventoried
209
203
  # @return [Hash<Pathname,FileSignature>] The fixity data present in the bag's manifest files
210
204
  def signatures_from_bagit_manifests(bag_pathname)
211
- manifest_pathname = Hash.new
205
+ manifest_pathname = {}
212
206
  DEFAULT_CHECKSUM_TYPES.each do |type|
213
207
  manifest_pathname[type] = bag_pathname.join("manifest-#{type}.txt")
214
208
  end
@@ -235,14 +229,14 @@ module Moab
235
229
  def human_size
236
230
  count = 0
237
231
  size = byte_count
238
- while size >= 1024 and count < 4
232
+ while (size >= 1024) && (count < 4)
239
233
  size /= 1024.0
240
234
  count += 1
241
235
  end
242
236
  if count == 0
243
- sprintf("%d B", size)
237
+ format("%d B", size)
244
238
  else
245
- sprintf("%.2f %s", size, %w[B KB MB GB TB][count])
239
+ format("%.2f %s", size, %w[B KB MB GB TB][count])
246
240
  end
247
241
  end
248
242