longleaf 0.1.0 → 0.2.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,14 +1,16 @@
1
1
  require_relative '../models/app_fields'
2
2
  require_relative '../models/service_definition'
3
3
 
4
- # Manager which loads and provides access to Longleaf::ServiceDefinition objects
5
4
  module Longleaf
5
+ # Manager which loads and provides access to Longleaf::ServiceDefinition objects
6
6
  class ServiceDefinitionManager
7
7
  SF ||= Longleaf::ServiceFields
8
8
  AF ||= Longleaf::AppFields
9
9
 
10
+ # Hash containing the set of configured services, represented as {ServiceDefinition} objects
10
11
  attr_reader :services
11
12
 
13
+ # @param config [Hash] hash representation of the application configuration
12
14
  def initialize(config)
13
15
  raise ArgumentError.new("Configuration must be provided") if config.nil? || config.empty?
14
16
 
@@ -18,11 +20,13 @@ module Longleaf
18
20
  @services = Hash.new
19
21
  config[AF::SERVICES].each do |name, properties|
20
22
  work_script = properties.delete(SF::WORK_SCRIPT)
23
+ work_class = properties.delete(SF::WORK_CLASS)
21
24
  frequency = properties.delete(SF::FREQUENCY)
22
25
  delay = properties.delete(SF::DELAY)
23
26
  service = Longleaf::ServiceDefinition.new(
24
27
  name: name,
25
28
  work_script: work_script,
29
+ work_class: work_class,
26
30
  frequency: frequency,
27
31
  delay: delay,
28
32
  properties: properties)
@@ -1,11 +1,11 @@
1
1
  require 'pathname'
2
- require_relative '../models/service_fields'
3
- require_relative '../models/app_fields'
4
- require_relative '../errors'
2
+ require 'longleaf/models/service_fields'
3
+ require 'longleaf/models/app_fields'
4
+ require 'longleaf/errors'
5
5
  require_relative 'configuration_validator'
6
6
 
7
- # Validates application configuration of service definitions
8
7
  module Longleaf
8
+ # Validates application configuration of service definitions
9
9
  class ServiceDefinitionValidator < ConfigurationValidator
10
10
  SF ||= Longleaf::ServiceFields
11
11
  AF ||= Longleaf::AppFields
@@ -1,21 +1,84 @@
1
- # Manager which provides preservation service definitions based on their mappings
1
+ require 'longleaf/helpers/service_date_helper'
2
+ require 'longleaf/services/service_class_cache'
3
+
2
4
  module Longleaf
5
+ # Manager which provides preservation service definitions based on their mappings
3
6
  class ServiceManager
4
-
5
- def initialize(definition_manager:, mapping_manager:)
7
+ # @param definition_manager [ServiceDefinitionManager] the service definition manager
8
+ # @param mapping_manager [ServiceMappingManager] the mapping of services to locations
9
+ # @param app_manager [ApplicationConfigManager] manager for storage locations
10
+ def initialize(definition_manager:, mapping_manager:, app_manager:)
6
11
  raise ArgumentError.new('Service definition manager required') if definition_manager.nil?
7
12
  raise ArgumentError.new('Service mappings manager required') if mapping_manager.nil?
13
+ raise ArgumentError.new('Storage location manager required') if app_manager.nil?
8
14
  @definition_manager = definition_manager
9
15
  @mapping_manager = mapping_manager
16
+ @app_manager = app_manager
17
+ @service_class_cache = ServiceClassCache.new(app_manager)
10
18
  end
11
19
 
12
- # Gets a list of ServiceDefinition objects which match the given criteria
13
- # @param location [String] name of the location to lookup
14
- # @return [Array] a list of ServiceDefinition objects associated with the location,
15
- # or an empty list if no services match the criteria
16
- def list_service_definitions(location: nil)
20
+ # List the names of services which are applicable to the given criteria
21
+ # @param location [String] name of the locations to lookup
22
+ # @param event [String] name of the preservation event taking place
23
+ # @return [Array] a list of service names which match the provided criteria
24
+ def list_services(location: nil, event: nil)
17
25
  service_names = @mapping_manager.list_services(location)
18
- service_names.collect { |name| @definition_manager.services[name] }
26
+ if !event.nil?
27
+ # Filter service names down by event
28
+ service_names.select{ |name| applicable_for_event?(name, event) }
29
+ else
30
+ service_names
31
+ end
32
+ end
33
+
34
+ # Determines if a service is applicable for a specific preservation event
35
+ # @param service_name [String] name of the service being evaluated
36
+ # @param event [String] name of the event to check against
37
+ # @return [Boolean] true if the service is applicable for the event
38
+ def applicable_for_event?(service_name, event)
39
+ definition = @definition_manager.services[service_name]
40
+ service = @service_class_cache.service_instance(definition)
41
+
42
+ service.is_applicable?(event)
43
+ end
44
+
45
+ # Determine if a service should run for a particular file based on the service's definition and
46
+ # the file's service related metadata.
47
+ # @param service_name [String] name of the service being evaluated
48
+ # @param md_rec [MetadataRecord] metadata record for the file being evaluated
49
+ # @return [Boolean] true if the service should be run.
50
+ def service_needed?(service_name, md_rec)
51
+ # If service not recorded for file, then it is needed
52
+ present_services = md_rec.list_services
53
+ return true unless present_services.include?(service_name)
54
+
55
+ service_rec = md_rec.service(service_name)
56
+
57
+ return true if service_rec.run_needed
58
+ return true if service_rec.timestamp.nil?
59
+
60
+ definition = @definition_manager.services[service_name]
61
+
62
+ # Check if the amount of time defined in frequency has passed since the service timestamp
63
+ frequency = definition.frequency
64
+ unless frequency.nil?
65
+ service_timestamp = service_rec.timestamp
66
+ now = ServiceDateHelper.formatted_timestamp
67
+
68
+ return true if now > ServiceDateHelper.add_to_timestamp(service_timestamp, frequency)
69
+ end
70
+ false
71
+ end
72
+
73
+ # Perform the specified service on the file record, in the context of the specified event
74
+ # @param service_name [String] name of the service
75
+ # @param file_rec [FileRecord] file record to perform service upon
76
+ # @param event_name [String] name of the event service is being performed within.
77
+ def perform_service(service_name, file_rec, event)
78
+ definition = @definition_manager.services[service_name]
79
+
80
+ service = @service_class_cache.service_instance(definition)
81
+ service.perform(file_rec, event)
19
82
  end
20
83
  end
21
84
  end
@@ -1,11 +1,12 @@
1
- require_relative '../models/app_fields'
2
- require_relative '../models/service_definition'
1
+ require 'longleaf/models/app_fields'
2
+ require 'longleaf/models/service_definition'
3
3
 
4
- # Manager which loads and provides access to location to service mappings
5
4
  module Longleaf
5
+ # Manager which loads and provides access to location to service mappings
6
6
  class ServiceMappingManager
7
7
  AF ||= Longleaf::AppFields
8
8
 
9
+ # @param config [Hash] has representation of the application configuration
9
10
  def initialize(config)
10
11
  raise ArgumentError.new("Configuration must be provided") if config.nil? || config.empty?
11
12
 
@@ -1,11 +1,11 @@
1
1
  require 'pathname'
2
- require_relative '../models/service_fields'
3
- require_relative '../models/app_fields'
4
- require_relative '../errors'
2
+ require 'longleaf/models/service_fields'
3
+ require 'longleaf/models/app_fields'
4
+ require 'longleaf/errors'
5
5
  require_relative 'configuration_validator'
6
6
 
7
- # Validates application configuration of service to location mappings
8
7
  module Longleaf
8
+ # Validates application configuration of service to location mappings
9
9
  class ServiceMappingValidator < ConfigurationValidator
10
10
  AF ||= Longleaf::AppFields
11
11
 
@@ -1,13 +1,16 @@
1
- require_relative '../models/app_fields'
2
- require_relative '../models/storage_location'
1
+ require 'longleaf/models/app_fields'
2
+ require 'longleaf/models/storage_location'
3
+ require 'longleaf/errors'
3
4
 
4
- # Manager which loads and provides access to Longleaf::StorageLocation objects
5
5
  module Longleaf
6
+ # Manager which loads and provides access to {StorageLocation} objects
6
7
  class StorageLocationManager
7
8
  AF ||= Longleaf::AppFields
8
9
 
10
+ # Hash mapping storage location names to {StorageLocation} objects
9
11
  attr_reader :locations
10
12
 
13
+ # @param config [Hash] has representation of the application configuration
11
14
  def initialize(config)
12
15
  raise ArgumentError.new("Configuration must be provided") if config&.empty?
13
16
 
@@ -15,14 +18,18 @@ module Longleaf
15
18
  config[AF::LOCATIONS].each do |name, properties|
16
19
  path = properties[AF::LOCATION_PATH]
17
20
  md_path = properties[AF::METADATA_PATH]
18
- location = Longleaf::StorageLocation.new(name: name, path: path, metadata_path: md_path)
21
+ md_digests = properties[AF::METADATA_DIGESTS]
22
+ location = Longleaf::StorageLocation.new(name: name,
23
+ path: path,
24
+ metadata_path: md_path,
25
+ metadata_digests: md_digests)
19
26
 
20
27
  @locations[name] = location
21
28
  end
22
29
  @locations.freeze
23
30
  end
24
31
 
25
- # Get the StorageLocation object which should contain the given path
32
+ # Get the {StorageLocation} object which should contain the given path
26
33
  # @return [Longleaf::StorageLocation] location containing the given path
27
34
  # or nil if the path is not contained by a registered location.
28
35
  def get_location_by_path(path)
@@ -33,5 +40,19 @@ module Longleaf
33
40
 
34
41
  nil
35
42
  end
43
+
44
+ # Raises a {StorageLocationUnavailableError} if the given path is not in a known storage location,
45
+ # or if it is not within the expected location if provided
46
+ # @param path [String] file path
47
+ # @param expected_loc [String] name of the storage location which path should be contained by
48
+ # @raise [StorageLocationUnavailableError] if the path is not in a known/expected storage location
49
+ def verify_path_in_location(path, expected_loc = nil)
50
+ location = get_location_by_path(path)
51
+ if location.nil?
52
+ raise StorageLocationUnavailableError.new("Path #{path} is not from a known storage location.")
53
+ elsif !expected_loc.nil? && expected_loc != location.name
54
+ raise StorageLocationUnavailableError.new("Path #{path} is not contained by storage location #{expected_loc}.")
55
+ end
56
+ end
36
57
  end
37
58
  end
@@ -5,8 +5,8 @@ require 'longleaf/errors'
5
5
  require_relative 'configuration_validator'
6
6
  require 'longleaf/services/storage_path_validator'
7
7
 
8
- # Validates application configuration of storage locations
9
8
  module Longleaf
9
+ # Validates application configuration of storage locations
10
10
  class StorageLocationValidator < ConfigurationValidator
11
11
  AF ||= Longleaf::AppFields
12
12
 
@@ -1,11 +1,11 @@
1
1
  require 'longleaf/errors'
2
2
 
3
- # Validator for storage paths
4
3
  module Longleaf
4
+ # Validator for storage paths
5
5
  class StoragePathValidator
6
6
  # Checks that the given path is a syntactically valid storage path
7
7
  # @param path [String] file storage path to validate
8
- # @raises [InvalidStoragePathError]
8
+ # @raise [InvalidStoragePathError]
9
9
  def self.validate(path)
10
10
  raise InvalidStoragePathError.new("Path must not be empty") if path.to_s.strip.empty?
11
11
  raise InvalidStoragePathError.new("Path must be absolute") unless Pathname.new(path).absolute?
@@ -1,9 +1,9 @@
1
- require_relative '../models/app_fields'
2
- require_relative '../models/service_fields'
1
+ require 'longleaf/models/app_fields'
2
+ require 'longleaf/models/service_fields'
3
3
  require 'yaml'
4
4
 
5
- # Test helper for constructing application configuration hashes
6
5
  module Longleaf
6
+ # Test helper for constructing application configuration hashes
7
7
  class ConfigBuilder
8
8
  AF ||= Longleaf::AppFields
9
9
  SF ||= Longleaf::ServiceFields
@@ -27,13 +27,14 @@ module Longleaf
27
27
  # @param path [String] value for the 'path' field
28
28
  # @param md_path [String] value for the 'metadata_path' field
29
29
  # @return this builder
30
- def with_location(name:, path: '/file/path/', md_path: '/metadata/path/')
30
+ def with_location(name:, path: '/file/path/', md_path: '/metadata/path/', md_digests: nil)
31
31
  @config[AF::LOCATIONS] = Hash.new unless @config.key?(AF::LOCATIONS)
32
32
 
33
33
  location = {}
34
34
  @config[AF::LOCATIONS][name] = location
35
35
  location[AF::LOCATION_PATH] = path unless path.nil?
36
36
  location[AF::METADATA_PATH] = md_path unless md_path.nil?
37
+ location[AF::METADATA_DIGESTS] = md_digests unless md_digests.nil?
37
38
  self
38
39
  end
39
40
 
@@ -48,15 +49,18 @@ module Longleaf
48
49
  # Add a 'service' to the config
49
50
  # @param name [String] name of the service
50
51
  # @param work_script [String] value for the 'work_script' field
52
+ # @param work_class [String] value for the 'work_class' field
51
53
  # @param frequency [String] value for the 'frequency' field
52
54
  # @param delay [String] value for the 'delay' field
53
55
  # @param properties [Hash] hash of additional properties to include in the service
54
56
  # @return this builder
55
- def with_service(name:, work_script: 'some_pres_service.rb', frequency: nil, delay: nil, properties: nil)
57
+ def with_service(name:, work_script: 'some_pres_service.rb', work_class: nil,
58
+ frequency: nil, delay: nil, properties: nil)
56
59
  @config[AF::SERVICES] = Hash.new unless @config.key?(AF::SERVICES)
57
60
 
58
61
  service = {}
59
62
  service[SF::WORK_SCRIPT] = work_script
63
+ service[SF::WORK_CLASS] = work_class
60
64
  service[SF::FREQUENCY] = frequency unless frequency.nil?
61
65
  service[SF::DELAY] = delay unless delay.nil?
62
66
  service = service.merge(properties) unless properties.nil?
@@ -0,0 +1,9 @@
1
+ module Longleaf
2
+ # Match if the parameter is a {FileRecord} with the expected path
3
+ RSpec::Matchers.define :be_file_record_for do |expected|
4
+ match do |actual|
5
+ return false if actual.nil? || !actual.is_a?(Longleaf::FileRecord)
6
+ actual.path == expected
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,60 @@
1
+ require 'tempfile'
2
+ require 'tmpdir'
3
+
4
+ module Longleaf
5
+ # Test helper methods for creating test files
6
+ module FileHelpers
7
+ def make_test_dir(parent: nil, name: 'dir')
8
+ FileHelpers.make_test_dir(parent: parent, name: name)
9
+ end
10
+
11
+ def self.make_test_dir(parent: nil, name: 'dir')
12
+ if parent.nil?
13
+ Dir.mktmpdir(name)
14
+ else
15
+ path = File.join(parent, name)
16
+ Dir.mkdir(path)
17
+ path
18
+ end
19
+ end
20
+
21
+ def create_test_file(dir: nil, name: 'test_file', content: 'content')
22
+ FileHelpers.create_test_file(dir: dir, name: name, content: content)
23
+ end
24
+
25
+ def self.create_test_file(dir: nil, name: 'test_file', content: 'content')
26
+ if dir.nil?
27
+ file = Tempfile.create(name)
28
+ file << content
29
+ file.close
30
+ return file.path
31
+ else
32
+ path = File.join(dir, name)
33
+ File.open(path, 'w') { |f| f.write(content) }
34
+ path
35
+ end
36
+ end
37
+
38
+ def create_work_class(lib_dir, class_name, file_name, module_name = nil, is_applicable: true, perform: "")
39
+ FileHelpers.create_work_class(lib_dir, class_name, file_name, module_name, is_applicable: is_applicable,
40
+ perform: perform)
41
+ end
42
+
43
+ def self.create_work_class(lib_dir, class_name, file_name, module_name = nil, is_applicable: true, perform: "")
44
+ class_contents = %Q(
45
+ class #{class_name}
46
+ def initialize(service_def, app_manager)
47
+ end
48
+ def perform(file_rec, event)
49
+ #{perform}
50
+ end
51
+ def is_applicable?(event)
52
+ #{is_applicable}
53
+ end
54
+ end
55
+ )
56
+ class_contents = "module #{module_name}\n#{class_contents}\nend" unless module_name.nil?
57
+ create_test_file(dir: lib_dir, name: file_name, content: class_contents)
58
+ end
59
+ end
60
+ end
@@ -1,3 +1,3 @@
1
1
  module Longleaf
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0.pre.1"
3
3
  end
data/longleaf.gemspec CHANGED
@@ -31,4 +31,5 @@ Gem::Specification.new do |spec|
31
31
  spec.add_development_dependency "rspec", "~> 3.6.0"
32
32
  spec.add_development_dependency "factory_bot", "~> 4.0"
33
33
  spec.add_development_dependency "aruba", "~> 0.14.0"
34
+ spec.add_development_dependency "bixby", ">= 2.0.0.pre.beta1"
34
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: longleaf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - bbpennel
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-10-17 00:00:00.000000000 Z
11
+ date: 2019-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: 0.14.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: bixby
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 2.0.0.pre.beta1
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 2.0.0.pre.beta1
111
125
  description: Provides a framework for performing preservation services over sets of
112
126
  files.
113
127
  email:
@@ -117,8 +131,11 @@ executables:
117
131
  extensions: []
118
132
  extra_rdoc_files: []
119
133
  files:
134
+ - ".editorconfig"
120
135
  - ".gitignore"
121
136
  - ".rspec"
137
+ - ".rubocop.yml"
138
+ - ".rubocop_todo.yml"
122
139
  - ".travis.yml"
123
140
  - Gemfile
124
141
  - LICENSE.txt
@@ -128,12 +145,23 @@ files:
128
145
  - bin/setup
129
146
  - exe/longleaf
130
147
  - lib/longleaf.rb
148
+ - lib/longleaf/candidates/file_selector.rb
149
+ - lib/longleaf/candidates/service_candidate_filesystem_iterator.rb
150
+ - lib/longleaf/candidates/service_candidate_locator.rb
131
151
  - lib/longleaf/cli.rb
132
- - lib/longleaf/commands/abstract_command.rb
152
+ - lib/longleaf/commands/deregister_command.rb
153
+ - lib/longleaf/commands/preserve_command.rb
133
154
  - lib/longleaf/commands/register_command.rb
134
155
  - lib/longleaf/commands/validate_config_command.rb
156
+ - lib/longleaf/commands/validate_metadata_command.rb
135
157
  - lib/longleaf/errors.rb
158
+ - lib/longleaf/events/deregister_event.rb
159
+ - lib/longleaf/events/event_names.rb
160
+ - lib/longleaf/events/event_status_tracking.rb
161
+ - lib/longleaf/events/preserve_event.rb
136
162
  - lib/longleaf/events/register_event.rb
163
+ - lib/longleaf/helpers/digest_helper.rb
164
+ - lib/longleaf/helpers/service_date_helper.rb
137
165
  - lib/longleaf/logging.rb
138
166
  - lib/longleaf/logging/redirecting_logger.rb
139
167
  - lib/longleaf/models/app_fields.rb
@@ -144,12 +172,15 @@ files:
144
172
  - lib/longleaf/models/service_fields.rb
145
173
  - lib/longleaf/models/service_record.rb
146
174
  - lib/longleaf/models/storage_location.rb
175
+ - lib/longleaf/preservation_services/fixity_check_service.rb
176
+ - lib/longleaf/preservation_services/rsync_replication_service.rb
147
177
  - lib/longleaf/services/application_config_deserializer.rb
148
178
  - lib/longleaf/services/application_config_manager.rb
149
179
  - lib/longleaf/services/application_config_validator.rb
150
180
  - lib/longleaf/services/configuration_validator.rb
151
181
  - lib/longleaf/services/metadata_deserializer.rb
152
182
  - lib/longleaf/services/metadata_serializer.rb
183
+ - lib/longleaf/services/service_class_cache.rb
153
184
  - lib/longleaf/services/service_definition_manager.rb
154
185
  - lib/longleaf/services/service_definition_validator.rb
155
186
  - lib/longleaf/services/service_manager.rb
@@ -159,6 +190,8 @@ files:
159
190
  - lib/longleaf/services/storage_location_validator.rb
160
191
  - lib/longleaf/services/storage_path_validator.rb
161
192
  - lib/longleaf/specs/config_builder.rb
193
+ - lib/longleaf/specs/custom_matchers.rb
194
+ - lib/longleaf/specs/file_helpers.rb
162
195
  - lib/longleaf/version.rb
163
196
  - longleaf.gemspec
164
197
  homepage: https://github.com/UNC-Libraries/
@@ -176,12 +209,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
176
209
  version: '0'
177
210
  required_rubygems_version: !ruby/object:Gem::Requirement
178
211
  requirements:
179
- - - ">="
212
+ - - ">"
180
213
  - !ruby/object:Gem::Version
181
- version: '0'
214
+ version: 1.3.1
182
215
  requirements: []
183
- rubyforge_project:
184
- rubygems_version: 2.7.6
216
+ rubygems_version: 3.0.2
185
217
  signing_key:
186
218
  specification_version: 4
187
219
  summary: Longleaf preservation services tool