longleaf 0.1.0 → 0.2.0.pre.1

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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +13 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +4 -0
  5. data/.rubocop_todo.yml +755 -0
  6. data/README.md +29 -7
  7. data/lib/longleaf/candidates/file_selector.rb +107 -0
  8. data/lib/longleaf/candidates/service_candidate_filesystem_iterator.rb +99 -0
  9. data/lib/longleaf/candidates/service_candidate_locator.rb +18 -0
  10. data/lib/longleaf/cli.rb +102 -6
  11. data/lib/longleaf/commands/deregister_command.rb +50 -0
  12. data/lib/longleaf/commands/preserve_command.rb +45 -0
  13. data/lib/longleaf/commands/register_command.rb +24 -38
  14. data/lib/longleaf/commands/validate_config_command.rb +6 -2
  15. data/lib/longleaf/commands/validate_metadata_command.rb +49 -0
  16. data/lib/longleaf/errors.rb +19 -0
  17. data/lib/longleaf/events/deregister_event.rb +55 -0
  18. data/lib/longleaf/events/event_names.rb +9 -0
  19. data/lib/longleaf/events/event_status_tracking.rb +59 -0
  20. data/lib/longleaf/events/preserve_event.rb +71 -0
  21. data/lib/longleaf/events/register_event.rb +37 -26
  22. data/lib/longleaf/helpers/digest_helper.rb +50 -0
  23. data/lib/longleaf/helpers/service_date_helper.rb +51 -0
  24. data/lib/longleaf/logging.rb +1 -0
  25. data/lib/longleaf/logging/redirecting_logger.rb +9 -8
  26. data/lib/longleaf/models/app_fields.rb +2 -0
  27. data/lib/longleaf/models/file_record.rb +8 -3
  28. data/lib/longleaf/models/md_fields.rb +1 -0
  29. data/lib/longleaf/models/metadata_record.rb +16 -4
  30. data/lib/longleaf/models/service_definition.rb +4 -3
  31. data/lib/longleaf/models/service_fields.rb +2 -0
  32. data/lib/longleaf/models/service_record.rb +4 -1
  33. data/lib/longleaf/models/storage_location.rb +18 -1
  34. data/lib/longleaf/preservation_services/fixity_check_service.rb +121 -0
  35. data/lib/longleaf/preservation_services/rsync_replication_service.rb +183 -0
  36. data/lib/longleaf/services/application_config_deserializer.rb +4 -6
  37. data/lib/longleaf/services/application_config_manager.rb +4 -2
  38. data/lib/longleaf/services/application_config_validator.rb +1 -1
  39. data/lib/longleaf/services/configuration_validator.rb +1 -0
  40. data/lib/longleaf/services/metadata_deserializer.rb +47 -10
  41. data/lib/longleaf/services/metadata_serializer.rb +42 -6
  42. data/lib/longleaf/services/service_class_cache.rb +112 -0
  43. data/lib/longleaf/services/service_definition_manager.rb +5 -1
  44. data/lib/longleaf/services/service_definition_validator.rb +4 -4
  45. data/lib/longleaf/services/service_manager.rb +72 -9
  46. data/lib/longleaf/services/service_mapping_manager.rb +4 -3
  47. data/lib/longleaf/services/service_mapping_validator.rb +4 -4
  48. data/lib/longleaf/services/storage_location_manager.rb +26 -5
  49. data/lib/longleaf/services/storage_location_validator.rb +1 -1
  50. data/lib/longleaf/services/storage_path_validator.rb +2 -2
  51. data/lib/longleaf/specs/config_builder.rb +9 -5
  52. data/lib/longleaf/specs/custom_matchers.rb +9 -0
  53. data/lib/longleaf/specs/file_helpers.rb +60 -0
  54. data/lib/longleaf/version.rb +1 -1
  55. data/longleaf.gemspec +1 -0
  56. metadata +39 -7
  57. data/lib/longleaf/commands/abstract_command.rb +0 -37
@@ -0,0 +1,45 @@
1
+ require 'longleaf/errors'
2
+ require 'longleaf/events/event_status_tracking'
3
+ require 'longleaf/events/preserve_event'
4
+ require 'longleaf/services/application_config_deserializer'
5
+ require 'longleaf/candidates/file_selector'
6
+ require 'longleaf/candidates/service_candidate_locator'
7
+ require 'longleaf/events/event_names'
8
+ require 'longleaf/logging'
9
+
10
+ module Longleaf
11
+ # Command for preserving files
12
+ class PreserveCommand
13
+ include Longleaf::Logging
14
+ include Longleaf::EventStatusTracking
15
+
16
+ def initialize(app_manager)
17
+ @app_manager = app_manager
18
+ end
19
+
20
+ # Execute the preserve command on the given parameters
21
+ # @param file_selector [FileSelector] selector for files to preserve
22
+ # @param force [Boolean] force flag
23
+ # @return [Integer] status code
24
+ def execute(file_selector:, force: false)
25
+ begin
26
+ # Perform preserve events on each of the file paths provided
27
+ candidate_locator = ServiceCandidateLocator.new(@app_manager)
28
+ candidate_it = candidate_locator.candidate_iterator(file_selector, EventNames::PRESERVE, force)
29
+ candidate_it.each do |file_rec|
30
+ f_path = file_rec.path
31
+
32
+ logger.debug("Selected candidate #{file_rec.path} for a preserve event")
33
+ preserve_event = PreserveEvent.new(file_rec: file_rec, force: force, app_manager: @app_manager)
34
+ track_status(preserve_event.perform)
35
+ end
36
+ rescue LongleafError => e
37
+ record_failure(EventNames::PRESERVE, nil, e.message)
38
+ rescue => err
39
+ record_failure(EventNames::PRESERVE, error: err)
40
+ end
41
+
42
+ return_status
43
+ end
44
+ end
45
+ end
@@ -1,56 +1,42 @@
1
1
  require 'longleaf/services/application_config_deserializer'
2
2
  require 'longleaf/events/register_event'
3
3
  require 'longleaf/models/file_record'
4
- require 'longleaf/commands/abstract_command'
4
+ require 'longleaf/events/event_names'
5
+ require 'longleaf/events/event_status_tracking'
5
6
 
6
- # Command for registering files with longleaf
7
7
  module Longleaf
8
- class RegisterCommand < AbstractCommand
8
+ # Command for registering files with longleaf
9
+ class RegisterCommand
10
+ include Longleaf::EventStatusTracking
9
11
 
10
- def initialize(config_path)
11
- @config_path = config_path
12
+ def initialize(app_manager)
13
+ @app_manager = app_manager
12
14
  end
13
15
 
14
16
  # Execute the register command on the given parameters
15
- def execute(file_paths: nil, force: false, checksums: nil)
16
- if file_paths.nil? || file_paths.empty?
17
- record_failure("Must provide one or more file paths to register")
18
- return return_status
19
- end
20
-
17
+ # @param file_selector [FileSelector] selector for files to register
18
+ # @param force [Boolean] force flag
19
+ # @param checksums [Array] array of checksums
20
+ # @return [Integer] status code
21
+ def execute(file_selector:, force: false, checksums: nil)
21
22
  begin
22
- # Retrieve the application configuration
23
- app_manager = Longleaf::ApplicationConfigDeserializer.deserialize(@config_path)
24
-
25
23
  # Perform register events on each of the file paths provided
26
- file_paths.each do |f_path|
27
- begin
28
- storage_location = app_manager.location_manager.get_location_by_path(f_path)
29
- if storage_location.nil?
30
- raise InvalidStoragePathError.new(
31
- "Unable to register '#{f_path}', it does not belong to any registered storage locations.")
32
- end
24
+ loop do
25
+ f_path = file_selector.next_path
26
+ break if f_path.nil?
33
27
 
34
- raise InvalidStoragePathError.new("Unable to register '#{f_path}', file does not exist or is unreachable.") \
35
- unless File.file?(f_path)
28
+ storage_location = @app_manager.location_manager.get_location_by_path(f_path)
29
+
30
+ file_rec = FileRecord.new(f_path, storage_location)
36
31
 
37
- file_rec = FileRecord.new(f_path, storage_location)
38
-
39
- register_event = RegisterEvent.new(file_rec: file_rec, force: force, app_manager: app_manager,
40
- checksums: checksums)
41
- register_event.perform
42
-
43
- record_success(RegisterEvent::EVENT_NAME, f_path)
44
- rescue RegistrationError => err
45
- record_failure(RegisterEvent::EVENT_NAME, f_path, err.message)
46
- rescue InvalidStoragePathError => err
47
- record_failure(RegisterEvent::EVENT_NAME, f_path, err.message)
48
- end
32
+ register_event = RegisterEvent.new(file_rec: file_rec, force: force, app_manager: @app_manager,
33
+ checksums: checksums)
34
+ track_status(register_event.perform)
49
35
  end
50
- rescue ConfigurationError => err
51
- record_failure("Failed to load application configuration due to the following issue:\n#{err.message}")
36
+ rescue InvalidStoragePathError, StorageLocationUnavailableError => err
37
+ record_failure(EventNames::REGISTER, nil, err.message)
52
38
  rescue => err
53
- record_failure(RegisterEvent::EVENT_NAME, error: err)
39
+ record_failure(EventNames::REGISTER, error: err)
54
40
  end
55
41
 
56
42
  return_status
@@ -1,12 +1,16 @@
1
1
  require 'longleaf/services/application_config_deserializer'
2
- require 'longleaf/commands/abstract_command'
2
+ require 'longleaf/events/event_status_tracking'
3
3
 
4
4
  module Longleaf
5
- class ValidateConfigCommand < AbstractCommand
5
+ # Command for validating an application configuration file
6
+ class ValidateConfigCommand
7
+ include Longleaf::EventStatusTracking
8
+
6
9
  def initialize(config_path)
7
10
  @config_path = config_path
8
11
  end
9
12
 
13
+ # Execute the validate command on the specified configuration yml file
10
14
  def execute
11
15
  begin
12
16
  app_config_manager = Longleaf::ApplicationConfigDeserializer.deserialize(@config_path)
@@ -0,0 +1,49 @@
1
+ require 'longleaf/services/application_config_deserializer'
2
+ require 'longleaf/models/file_record'
3
+ require 'longleaf/events/event_status_tracking'
4
+ require 'longleaf/errors'
5
+
6
+ module Longleaf
7
+ # Command for validating file metadata longleaf
8
+ class ValidateMetadataCommand
9
+ include Longleaf::EventStatusTracking
10
+
11
+ def initialize(app_manager)
12
+ @app_manager = app_manager
13
+ end
14
+
15
+ # Execute the validation command
16
+ # @param file_selector [FileSelector] selector for files to register
17
+ # @return [Integer] status code
18
+ def execute(file_selector:)
19
+ begin
20
+ # Perform metadata validation on each of the file paths provided
21
+ loop do
22
+ f_path = file_selector.next_path
23
+ break if f_path.nil?
24
+
25
+ storage_location = @app_manager.location_manager.get_location_by_path(f_path)
26
+
27
+ begin
28
+ file_rec = FileRecord.new(f_path, storage_location)
29
+ unless file_rec.metadata_present?
30
+ raise MetadataError.new("Cannot validate metadata for #{f_path}, file is not registered.")
31
+ end
32
+
33
+ MetadataDeserializer::deserialize(file_path: file_rec.metadata_path,
34
+ digest_algs: storage_location.metadata_digests)
35
+ record_success("Metadata for file passed validation: #{f_path}")
36
+ rescue LongleafError => err
37
+ record_failure(err.message)
38
+ end
39
+ end
40
+ rescue InvalidStoragePathError, StorageLocationUnavailableError => err
41
+ record_failure(err.message)
42
+ rescue => err
43
+ record_failure("Encountered error while validating metadata files", error: err)
44
+ end
45
+
46
+ return_status
47
+ end
48
+ end
49
+ end
@@ -1,15 +1,34 @@
1
1
  module Longleaf
2
+ # General Longleaf error
2
3
  class LongleafError < StandardError; end
3
4
 
5
+ # Invalid application configuration error
4
6
  class ConfigurationError < LongleafError; end
5
7
 
8
+ # Invalid storage path error
6
9
  class InvalidStoragePathError < LongleafError; end
7
10
 
11
+ # Metadata does not meet requirements error
8
12
  class MetadataError < LongleafError; end
9
13
 
14
+ # Unavailable storage location error
10
15
  class StorageLocationUnavailableError < LongleafError; end
11
16
 
17
+ # Error related to executing a preservation event
12
18
  class EventError < LongleafError; end
13
19
 
20
+ # Error while attempting to perform a registration event
14
21
  class RegistrationError < EventError; end
22
+
23
+ # Error while attempting to perform a deregistration event
24
+ class DeregistrationError < EventError; end
25
+
26
+ # Error while performing a preservation service
27
+ class PreservationServiceError < LongleafError; end
28
+
29
+ # Fixity check failure error
30
+ class ChecksumMismatchError < PreservationServiceError; end
31
+
32
+ # Error indicating an unknown or invalid digest algorithm was specified
33
+ class InvalidDigestAlgorithmError < LongleafError; end
15
34
  end
@@ -0,0 +1,55 @@
1
+ require 'longleaf/errors'
2
+ require 'longleaf/events/event_names'
3
+ require 'longleaf/events/event_status_tracking'
4
+ require 'longleaf/services/metadata_serializer'
5
+
6
+ module Longleaf
7
+ # Event to deregister a file from longleaf
8
+ class DeregisterEvent
9
+ include Longleaf::EventStatusTracking
10
+
11
+ # @param file_rec [FileRecord] file record
12
+ # @param app_manager [ApplicationConfigManager] the application configuration
13
+ # @param force [boolean] if true, then already deregistered files will be deregistered again
14
+ def initialize(file_rec:, app_manager:, force: false)
15
+ raise ArgumentError.new('Must provide a file_rec parameter') if file_rec.nil?
16
+ raise ArgumentError.new('Parameter file_rec must be a FileRecord') \
17
+ unless file_rec.is_a?(FileRecord)
18
+ raise ArgumentError.new('Must provide an ApplicationConfigManager') if app_manager.nil?
19
+ raise ArgumentError.new('Parameter app_manager must be an ApplicationConfigManager') \
20
+ unless app_manager.is_a?(ApplicationConfigManager)
21
+
22
+ @app_manager = app_manager
23
+ @file_rec = file_rec
24
+ @force = force
25
+ end
26
+
27
+ # Perform a deregistration event on the given file record
28
+ # @raise DeregistrationError if a file cannot be deregistered
29
+ def perform
30
+ begin
31
+ md_rec = @file_rec.metadata_record
32
+
33
+ # Only need to deregister a deregistered file if the force flag is provided
34
+ if md_rec.deregistered? && !@force
35
+ raise DeregistrationError.new("Unable to deregister '#{@file_rec.path}', it is already deregistered.")
36
+ end
37
+
38
+ md_rec.deregistered = Time.now.utc.iso8601
39
+
40
+ # persist the metadata out to file
41
+ MetadataSerializer::write(metadata: md_rec,
42
+ file_path: @file_rec.metadata_path,
43
+ digest_algs: @file_rec.storage_location.metadata_digests)
44
+
45
+ record_success(EventNames::DEREGISTER, @file_rec.path)
46
+ rescue DeregistrationError => err
47
+ record_failure(EventNames::DEREGISTER, @file_rec.path, err.message)
48
+ rescue InvalidStoragePathError => err
49
+ record_failure(EventNames::DEREGISTER, @file_rec.path, err.message)
50
+ end
51
+
52
+ return_status
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,9 @@
1
+ module Longleaf
2
+ # Constants for preservation event names
3
+ class EventNames
4
+ REGISTER = 'register'
5
+ PRESERVE = 'preserve'
6
+ CLEANUP = 'cleanup'
7
+ DEREGISTER = 'deregister'
8
+ end
9
+ end
@@ -0,0 +1,59 @@
1
+ require 'longleaf/logging'
2
+
3
+ module Longleaf
4
+ # Helper methods for tracking and recording the overall outcome of a preservation event.
5
+ module EventStatusTracking
6
+ include Longleaf::Logging
7
+
8
+ # Record a successful operation to the output and the overall status of this event.
9
+ # @param args [Array] arguments to pass to logger
10
+ def record_success(*args)
11
+ logger.success(*args)
12
+ track_success
13
+ end
14
+
15
+ # Update the status of this action with a success outcome.
16
+ def track_success
17
+ if @return_status.nil? || @return_status == 0
18
+ @return_status = 0
19
+ else
20
+ @return_status = 2
21
+ end
22
+ end
23
+
24
+ # Record a failed operation to the output and the overall status of this event.
25
+ # @param args [Array] arguments to pass to logger
26
+ def record_failure(*args)
27
+ logger.failure(*args)
28
+ track_failure
29
+ end
30
+
31
+ # Update the status of this action with a failure outcome.
32
+ def track_failure
33
+ if @return_status.nil? || @return_status == 1
34
+ @return_status = 1
35
+ else
36
+ @return_status = 2
37
+ end
38
+ end
39
+
40
+ # Update the status of this action with the provided outcome status number.
41
+ # @param status [Integer] outcome status
42
+ def track_status(status)
43
+ if status == 2
44
+ @return_status = 2
45
+ elsif status == 0
46
+ track_success
47
+ elsif status == 1
48
+ track_failure
49
+ end
50
+ end
51
+
52
+ # @return [Integer] the return status for this event, where 0 indicates success,
53
+ # 1 indicates failure, and 2 indicates partial failure
54
+ def return_status
55
+ @return_status = 0 if @return_status.nil?
56
+ @return_status
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,71 @@
1
+ require 'longleaf/services/service_manager'
2
+ require 'longleaf/events/event_names'
3
+ require 'longleaf/events/event_status_tracking'
4
+ require 'longleaf/logging'
5
+
6
+ module Longleaf
7
+ # Verify event for a single file
8
+ class PreserveEvent
9
+ include Longleaf::Logging
10
+ include Longleaf::EventStatusTracking
11
+
12
+ # @param file_rec [FileRecord] file record
13
+ # @param app_manager [ApplicationConfigManager] the application configuration
14
+ # @param force [boolean] if true, then services run regardless of whether they are flagged as needed
15
+ def initialize(file_rec:, app_manager:, force: false)
16
+ raise ArgumentError.new('Must provide a file_rec parameter') if file_rec.nil?
17
+ raise ArgumentError.new('Must provide an ApplicationConfigManager') if app_manager.nil?
18
+
19
+ @app_manager = app_manager
20
+ @file_rec = file_rec
21
+ @force = force
22
+ end
23
+
24
+ # Perform a preserve event on the given file, updating its metadata record if any services were executed.
25
+ def perform
26
+ storage_loc = @file_rec.storage_location
27
+ service_manager = @app_manager.service_manager
28
+ md_rec = @file_rec.metadata_record
29
+ f_path = @file_rec.path
30
+
31
+ logger.info("Performing preserve event on #{@file_rec.path}")
32
+
33
+ service_performed = false
34
+ begin
35
+ # get the list of services applicable to this location and event
36
+ service_manager.list_services(location: storage_loc.name, event: EventNames::PRESERVE).each do |service_name|
37
+ # Skip over this service if it does not need to be run, unless force flag active
38
+ unless @force || service_manager.service_needed?(service_name, md_rec)
39
+ logger.debug("Service #{service_name} not needed for file '#{@file_rec.path}', skipping")
40
+ next
41
+ end
42
+
43
+ begin
44
+ logger.info("Performing preserve service #{service_name} for #{@file_rec.path}")
45
+ # execute the service
46
+ service_manager.perform_service(service_name, @file_rec, EventNames::PRESERVE)
47
+
48
+ # record the outcome
49
+ @file_rec.metadata_record.update_service_as_performed(service_name)
50
+ service_performed = true
51
+ record_success(EventNames::PRESERVE, f_path, nil, service_name)
52
+ rescue PreservationServiceError => e
53
+ record_failure(EventNames::PRESERVE, f_path, e.message, service_name)
54
+ rescue StandardError => e
55
+ record_failure(EventNames::PRESERVE, f_path, nil, service_name, error: e)
56
+ return return_status
57
+ end
58
+ end
59
+ ensure
60
+ # persist the metadata out to file if any services were executed
61
+ if service_performed
62
+ MetadataSerializer::write(metadata: @file_rec.metadata_record,
63
+ file_path: @file_rec.metadata_path,
64
+ digest_algs: storage_loc.metadata_digests)
65
+ end
66
+ end
67
+
68
+ return_status
69
+ end
70
+ end
71
+ end
@@ -1,13 +1,15 @@
1
1
  require 'longleaf/errors'
2
+ require 'longleaf/events/event_names'
3
+ require 'longleaf/events/event_status_tracking'
2
4
  require 'longleaf/models/metadata_record'
3
5
  require 'longleaf/services/metadata_deserializer'
4
6
  require 'longleaf/services/metadata_serializer'
5
7
  require 'time'
6
8
 
7
- # Event to register a file with longleaf
8
9
  module Longleaf
10
+ # Event to register a file with longleaf
9
11
  class RegisterEvent
10
- EVENT_NAME = 'register'
12
+ include Longleaf::EventStatusTracking
11
13
 
12
14
  # @param file_rec [FileRecord] file record
13
15
  # @param app_manager [ApplicationConfigManager] the application configuration
@@ -27,31 +29,42 @@ module Longleaf
27
29
  end
28
30
 
29
31
  # Perform a registration event on the given file
30
- # @raises RegistrationError if a file cannot be registered
32
+ # @raise RegistrationError if a file cannot be registered
31
33
  def perform
32
- metadata_exists = File.file?(@file_rec.metadata_path)
33
- # If the file's metadata exists, only need to register it if the force flag is provided
34
- if metadata_exists && !@force
35
- raise RegistrationError.new("Unable to register '#{@file_rec.path}', it is already registered.")
36
- end
34
+ begin
35
+ # Only need to re-register file if the force flag is provided
36
+ if @file_rec.metadata_present? && !@force
37
+ raise RegistrationError.new("Unable to register '#{@file_rec.path}', it is already registered.")
38
+ end
37
39
 
38
- # create metadata record
39
- md_rec = MetadataRecord.new(registered: Time.now.utc.iso8601)
40
- @file_rec.metadata_record = md_rec
40
+ # create metadata record
41
+ md_rec = MetadataRecord.new(registered: Time.now.utc.iso8601)
42
+ @file_rec.metadata_record = md_rec
41
43
 
42
- # retain significant details from former record
43
- if metadata_exists
44
- retain_existing_properties
45
- end
44
+ # retain significant details from former record
45
+ if @file_rec.metadata_present?
46
+ retain_existing_properties
47
+ end
46
48
 
47
- populate_file_properties
49
+ populate_file_properties
48
50
 
49
- md_rec.checksums.merge!(@checksums) unless @checksums.nil?
51
+ md_rec.checksums.merge!(@checksums) unless @checksums.nil?
50
52
 
51
- populate_services
53
+ populate_services
52
54
 
53
- # persist the metadata out to file
54
- MetadataSerializer::write(metadata: md_rec, file_path: @file_rec.metadata_path)
55
+ # persist the metadata out to file
56
+ MetadataSerializer::write(metadata: md_rec,
57
+ file_path: @file_rec.metadata_path,
58
+ digest_algs: @file_rec.storage_location.metadata_digests)
59
+
60
+ record_success(EventNames::REGISTER, @file_rec.path)
61
+ rescue RegistrationError => err
62
+ record_failure(EventNames::REGISTER, @file_rec.path, err.message)
63
+ rescue InvalidStoragePathError => err
64
+ record_failure(EventNames::REGISTER, @file_rec.path, err.message)
65
+ end
66
+
67
+ return_status
55
68
  end
56
69
 
57
70
  private
@@ -67,20 +80,18 @@ module Longleaf
67
80
  md_rec = @file_rec.metadata_record
68
81
 
69
82
  service_manager = @app_manager.service_manager
70
- definitions = service_manager.list_service_definitions(location: @file_rec.storage_location.name)
83
+ service_names = service_manager.list_services(location: @file_rec.storage_location.name)
71
84
 
72
85
  # Add service section
73
- definitions.each do |serv_def|
74
- serv_name = serv_def.name
75
- md_rec.add_service(serv_name)
76
- end
86
+ service_names.each { |serv_name| md_rec.add_service(serv_name) }
77
87
  end
78
88
 
79
89
  # Copy a subset of properties from an existing metadata record to the new record
80
90
  def retain_existing_properties
81
91
  md_rec = @file_rec.metadata_record
82
92
 
83
- old_md = MetadataDeserializer.deserialize(file_path: @file_rec.metadata_path)
93
+ old_md = MetadataDeserializer.deserialize(file_path: @file_rec.metadata_path,
94
+ digest_algs: @file_rec.storage_location.metadata_digests)
84
95
  # Copy custom properties
85
96
  old_md.properties.each { |name, value| md_rec.properties[name] = value }
86
97
  # Copy stale-replicas flag per service