bookbindery 3.0.1 → 3.1.0

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bookbinder.rb +0 -4
  3. data/lib/bookbinder/archive.rb +12 -5
  4. data/lib/bookbinder/archive_menu_configuration.rb +4 -4
  5. data/lib/bookbinder/commands/bind.rb +29 -97
  6. data/lib/bookbinder/commands/bind/bind_options.rb +50 -0
  7. data/lib/bookbinder/commands/bind/directory_preparer.rb +13 -12
  8. data/lib/bookbinder/commands/build_and_push_tarball.rb +1 -8
  9. data/lib/bookbinder/commands/help.rb +1 -1
  10. data/lib/bookbinder/commands/run_publish_ci.rb +1 -3
  11. data/lib/bookbinder/commands/tag.rb +12 -9
  12. data/lib/bookbinder/commands/update_local_doc_repos.rb +23 -7
  13. data/lib/bookbinder/config/bind_config_factory.rb +5 -7
  14. data/lib/bookbinder/config/remote_bind_configuration.rb +23 -31
  15. data/lib/bookbinder/config/section_config.rb +56 -0
  16. data/lib/bookbinder/configuration.rb +58 -18
  17. data/lib/bookbinder/configuration_fetcher.rb +3 -5
  18. data/lib/bookbinder/configuration_validator.rb +1 -8
  19. data/lib/bookbinder/distributor.rb +1 -1
  20. data/lib/bookbinder/dita_command_creator.rb +60 -16
  21. data/lib/bookbinder/dita_html_to_middleman_formatter.rb +3 -2
  22. data/lib/bookbinder/errors/programmer_mistake.rb +5 -0
  23. data/lib/bookbinder/git_accessor.rb +36 -2
  24. data/lib/bookbinder/ingest/cloner_factory.rb +3 -3
  25. data/lib/bookbinder/ingest/destination_directory.rb +7 -1
  26. data/lib/bookbinder/ingest/{git_hub_repository_cloner.rb → git_cloner.rb} +3 -2
  27. data/lib/bookbinder/ingest/repo_identifier.rb +45 -0
  28. data/lib/bookbinder/local_file_system_accessor.rb +4 -9
  29. data/lib/bookbinder/middleman_runner.rb +5 -6
  30. data/lib/bookbinder/preprocessing/copy_to_site_gen_dir.rb +27 -0
  31. data/lib/bookbinder/preprocessing/dita_preprocessor.rb +103 -0
  32. data/lib/bookbinder/preprocessing/preprocessor.rb +26 -0
  33. data/lib/bookbinder/repositories/command_repository.rb +17 -21
  34. data/lib/bookbinder/repositories/section_repository.rb +24 -16
  35. data/lib/bookbinder/repositories/section_repository_factory.rb +19 -0
  36. data/lib/bookbinder/streams/{switchable_stdout_and_red_stderr.rb → colorized_stream.rb} +0 -17
  37. data/lib/bookbinder/time_fetcher.rb +7 -0
  38. data/lib/bookbinder/validation_checkers/dita_section_checker.rb +2 -2
  39. data/lib/bookbinder/values/output_locations.rb +13 -12
  40. data/lib/bookbinder/values/section.rb +22 -5
  41. data/master_middleman/bookbinder_helpers.rb +4 -11
  42. metadata +59 -75
  43. data/lib/bookbinder/book.rb +0 -59
  44. data/lib/bookbinder/config/local_bind_configuration.rb +0 -23
  45. data/lib/bookbinder/dita_preprocessor.rb +0 -68
  46. data/lib/bookbinder/dita_section_gatherer_factory.rb +0 -23
  47. data/lib/bookbinder/git_client.rb +0 -66
  48. data/lib/bookbinder/git_hub_repository.rb +0 -101
  49. data/lib/bookbinder/local_dita_section_gatherer.rb +0 -32
  50. data/lib/bookbinder/remote_dita_section_gatherer.rb +0 -35
  51. data/lib/bookbinder/validation_checkers/config_version_checker.rb +0 -91
  52. data/lib/bookbinder/values/code_example.rb +0 -7
  53. data/lib/bookbinder/values/dita_section.rb +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 61ee95fb7c8fa4d8f94f82fb98582fd65cb95b00
4
- data.tar.gz: 402dbbe4d95e314482d09803c85d2560f424bde5
3
+ metadata.gz: 76b73998f089e3dd934d8eb163cddfd19f66be5e
4
+ data.tar.gz: 98e8dc00c79fad5bd569f4532adde577588afe7a
5
5
  SHA512:
6
- metadata.gz: 657c1ab7338a891a60f59b3f3a01d683f65cac80a528907ee9918d55ef45202615684a57069c72525a65bbf6a310bb4183fecaabde6c2bfa73743ef9daeaa2b1
7
- data.tar.gz: 725747cd9531772d3df4fe41af349bc165bc13fbc8db64c886debfc7f0866d720c730a72ee977ff3759d0f046e3f20dd18267ebe19fe5d47aed302b0f84532ef
6
+ metadata.gz: 932df3bf015a4f130ecbfde27454d173fbdfb58ea187527f60871de14d7066ff797e0c91c01573cf4da8473149a466618021c2cda517a18e3f9275a80d8faae1
7
+ data.tar.gz: 8e481e936fbf7f12f16d4f735d58f6b28f4db037fe42a9393bfa2315f9725f3eaaaa3a965ecaada1e1023c61c84d1ba8820710ef7460f557f9a662df6d25f072
@@ -1,7 +1,6 @@
1
1
  require 'fog/aws'
2
2
  require 'tmpdir'
3
3
  require 'ansi'
4
- require 'octokit'
5
4
  require 'middleman-syntax'
6
5
  require 'middleman-core/cli'
7
6
  require 'middleman-core/profiling'
@@ -11,10 +10,7 @@ require 'vienna'
11
10
  require 'puma'
12
11
 
13
12
  require_relative 'bookbinder/deprecated_logger'
14
- require_relative 'bookbinder/git_client'
15
13
  require_relative 'bookbinder/values/section'
16
- require_relative 'bookbinder/book'
17
- require_relative 'bookbinder/values/code_example'
18
14
  require_relative 'bookbinder/remote_yaml_credential_provider'
19
15
  require_relative 'bookbinder/configuration'
20
16
  require_relative 'bookbinder/configuration_fetcher'
@@ -2,20 +2,22 @@ require 'fog/aws'
2
2
  require 'tmpdir'
3
3
  require_relative 'artifact_namer'
4
4
  require_relative 'deprecated_logger'
5
+ require_relative 'time_fetcher'
5
6
 
6
7
  module Bookbinder
7
8
  class Archive
8
9
  class FileDoesNotExist < StandardError; end
9
10
  class NoNamespaceGiven < StandardError; end
10
11
 
11
- def initialize(logger: nil, key: '', secret: '')
12
+ def initialize(logger: nil, time_fetcher: TimeFetcher.new, key: '', secret: '')
12
13
  @logger = logger
14
+ @time_fetcher = time_fetcher
13
15
  @aws_key = key
14
16
  @aws_secret_key = secret
15
17
  end
16
18
 
17
19
  def create_and_upload_tarball(build_number: nil, app_dir: 'final_app', bucket: '', namespace: nil)
18
- raise 'You must provide a build_number to push an identifiable build.' unless build_number
20
+ build_number ||= time_fetcher.current_time
19
21
  raise 'You must provide a namespace to push an identifiable build.' unless namespace
20
22
 
21
23
  tarball_filename, tarball_path = create_tarball(app_dir, build_number, namespace)
@@ -48,8 +50,14 @@ module Bookbinder
48
50
  @logger.log "Green build ##{build_number.to_s.green} has been downloaded from S3 and untarred into #{download_dir.to_s.cyan}"
49
51
  end
50
52
 
53
+ def tarball_name_regex(namespace)
54
+ /^#{namespace}-(\d+_?\d*)\.tgz/
55
+ end
56
+
51
57
  private
52
58
 
59
+ attr_reader :time_fetcher
60
+
53
61
  def find_or_create_directory(name)
54
62
  connection.directories.create(key: name)
55
63
  rescue Excon::Errors::Conflict
@@ -69,15 +77,14 @@ module Bookbinder
69
77
 
70
78
  all_files_with_namespace = all_files.map do |file|
71
79
  filename = file.key
72
- matches = /^#{namespace}-([\d]+)\.tgz/.match(filename)
73
- file if matches
80
+ file if filename[tarball_name_regex(namespace)]
74
81
  end.compact
75
82
 
76
83
  return nil if all_files_with_namespace.empty?
77
84
  most_recent_file = all_files_with_namespace.sort_by { |file| file.last_modified }.last
78
85
 
79
86
  most_recent_filename = most_recent_file.key
80
- most_recent_build_number = /^#{namespace}-([\d]+)\.tgz/.match(most_recent_filename)[1]
87
+ most_recent_filename[tarball_name_regex(namespace), 1]
81
88
  end
82
89
 
83
90
  def connection
@@ -7,8 +7,8 @@ module Bookbinder
7
7
 
8
8
  def generate(base_config, sections)
9
9
  base_config.merge(
10
- archive_menu: root_config(base_config).merge(section_config(sections))
11
- )
10
+ Configuration.parse(
11
+ 'archive_menu' => root_config(base_config).merge(section_config(sections))))
12
12
  end
13
13
 
14
14
  private
@@ -16,7 +16,7 @@ module Bookbinder
16
16
  attr_reader :loader, :config_filename
17
17
 
18
18
  def root_config(base_config)
19
- { '.' => base_config[:archive_menu] }
19
+ { '.' => base_config.archive_menu }
20
20
  end
21
21
 
22
22
  def section_config(sections)
@@ -24,7 +24,7 @@ module Bookbinder
24
24
  config_path = section.path_to_repository.join(config_filename)
25
25
  archive_config = loader.load_key(config_path, 'archive_menu')
26
26
  if archive_config
27
- config.merge(section.directory_name => archive_config)
27
+ config.merge(section.desired_directory_name => archive_config)
28
28
  else
29
29
  config
30
30
  end
@@ -1,13 +1,10 @@
1
1
  require 'middleman-syntax'
2
2
 
3
3
  require_relative '../archive_menu_configuration'
4
- require_relative '../book'
5
- require_relative '../dita_section_gatherer_factory'
6
4
  require_relative '../errors/cli_error'
7
- require_relative '../streams/switchable_stdout_and_red_stderr'
8
- require_relative '../values/dita_section'
9
5
  require_relative '../values/output_locations'
10
6
  require_relative '../values/section'
7
+ require_relative 'bind/bind_options'
11
8
  require_relative 'naming'
12
9
 
13
10
  module Bookbinder
@@ -15,10 +12,7 @@ module Bookbinder
15
12
  class Bind
16
13
  include Commands::Naming
17
14
 
18
- DitaToHtmlLibraryFailure = Class.new(RuntimeError)
19
-
20
15
  def initialize(logger,
21
- config_fetcher,
22
16
  config_factory,
23
17
  archive_menu_config,
24
18
  version_control_system,
@@ -27,15 +21,11 @@ module Bookbinder
27
21
  sitemap_writer,
28
22
  final_app_directory,
29
23
  context_dir,
30
- dita_preprocessor,
24
+ preprocessor,
31
25
  cloner_factory,
32
- dita_section_gatherer_factory,
33
- section_repository,
34
- command_creator,
35
- sheller,
26
+ section_repository_factory,
36
27
  directory_preparer)
37
28
  @logger = logger
38
- @config_fetcher = config_fetcher
39
29
  @config_factory = config_factory
40
30
  @archive_menu_config = archive_menu_config
41
31
  @version_control_system = version_control_system
@@ -44,18 +34,15 @@ module Bookbinder
44
34
  @sitemap_writer = sitemap_writer
45
35
  @final_app_directory = final_app_directory
46
36
  @context_dir = context_dir
47
- @dita_preprocessor = dita_preprocessor
37
+ @preprocessor = preprocessor
48
38
  @cloner_factory = cloner_factory
49
- @dita_section_gatherer_factory = dita_section_gatherer_factory
50
- @section_repository = section_repository
51
- @command_creator = command_creator
52
- @sheller = sheller
39
+ @section_repository_factory = section_repository_factory
53
40
  @directory_preparer = directory_preparer
54
41
  end
55
42
 
56
43
  def usage
57
- ["bind <local|github> [--verbose]",
58
- "Bind the sections specified in config.yml from <local> or <github> into the final_app directory"]
44
+ ["bind <local|remote> [--verbose] [--dita-flags='<dita-option>=<value>']",
45
+ "Bind the sections specified in config.yml from <local> or <remote> into the final_app directory"]
59
46
  end
60
47
 
61
48
  def command_for?(test_command_name)
@@ -67,59 +54,40 @@ module Bookbinder
67
54
  end
68
55
 
69
56
  def run(cli_arguments)
70
- bind_source, *options = cli_arguments
71
- validate(bind_source, options)
57
+ bind_options = BindComponents::BindOptions.new(cli_arguments)
58
+ bind_options.validate!
72
59
 
60
+ bind_source, *options = cli_arguments
73
61
  bind_config = config_factory.produce(bind_source)
74
- output_streams = Streams::SwitchableStdoutAndRedStderr.new(options)
75
62
 
76
63
  output_locations = OutputLocations.new(
77
64
  context_dir: context_dir,
78
65
  final_app_dir: final_app_directory,
79
- layout_repo_dir: layout_repo_path(generate_local_repo_dir(context_dir, bind_source)),
66
+ layout_repo_dir: layout_repo_path(bind_config, generate_local_repo_dir(context_dir, bind_source)),
80
67
  local_repo_dir: generate_local_repo_dir(context_dir, bind_source)
81
68
  )
69
+ cloner = cloner_factory.produce(output_locations.local_repo_dir)
70
+ section_repository = section_repository_factory.produce(cloner)
82
71
 
83
72
  directory_preparer.prepare_directories(
73
+ bind_config,
84
74
  File.expand_path('../../../../', __FILE__),
85
- bind_config.fetch(:versions, []),
86
- output_locations,
87
- bind_config[:book_repo]
75
+ output_locations
88
76
  )
89
77
 
90
- dita_gatherer = dita_section_gatherer_factory.produce(bind_source, output_locations)
91
- gathered_dita_sections = dita_gatherer.gather(config.dita_sections)
92
-
93
- dita_preprocessor.preprocess(gathered_dita_sections,
94
- output_locations.subnavs_for_layout_dir,
95
- output_locations.dita_subnav_template_path) do |dita_section|
96
- command = command_creator.convert_to_html_command(
97
- dita_section,
98
- write_to: dita_section.html_from_dita_section_dir
99
- )
100
- status = sheller.run_command(command, output_streams.to_h)
101
- unless status.success?
102
- raise DitaToHtmlLibraryFailure.new 'The DITA-to-HTML conversion failed. ' +
103
- 'Please check that you have specified the path to your DITA-OT library in the ENV, ' +
104
- 'that your DITA-specific keys/values in config.yml are set, ' +
105
- 'and that your DITA toolkit is correctly configured.'
106
- end
107
- end
108
-
109
- cloner = cloner_factory.produce(
110
- bind_source,
111
- output_locations.local_repo_dir
112
- )
113
- sections = gather_sections(
114
- output_locations.source_for_site_generator,
115
- cloner,
116
- ('master' if options.include?('--ignore-section-refs'))
78
+ sections = section_repository.fetch(
79
+ configured_sections: bind_config.sections,
80
+ destination_dir: output_locations.cloned_preprocessing_dir,
81
+ ref_override: bind_options.ref_override
117
82
  )
118
83
 
119
- subnavs = (sections + gathered_dita_sections).map(&:subnav).reduce(&:merge)
84
+ preprocessor.preprocess(sections,
85
+ output_locations,
86
+ options: options,
87
+ output_streams: bind_options.streams)
120
88
 
121
89
  success = publish(
122
- subnavs,
90
+ sections.map(&:subnav).reduce(&:merge),
123
91
  {verbose: options.include?('--verbose')},
124
92
  output_locations,
125
93
  archive_menu_config.generate(bind_config, sections),
@@ -132,7 +100,6 @@ module Bookbinder
132
100
  private
133
101
 
134
102
  attr_reader :version_control_system,
135
- :config_fetcher,
136
103
  :config_factory,
137
104
  :archive_menu_config,
138
105
  :logger,
@@ -141,18 +108,15 @@ module Bookbinder
141
108
  :final_app_directory,
142
109
  :sitemap_writer,
143
110
  :context_dir,
144
- :dita_preprocessor,
111
+ :preprocessor,
145
112
  :cloner_factory,
146
- :dita_section_gatherer_factory,
147
- :section_repository,
148
- :command_creator,
149
- :sheller,
113
+ :section_repository_factory,
150
114
  :directory_preparer
151
115
 
152
116
  def publish(subnavs, cli_options, output_locations, publish_config, cloner)
153
117
  FileUtils.cp 'redirects.rb', output_locations.final_app_dir if File.exists?('redirects.rb')
154
118
 
155
- host_for_sitemap = publish_config.fetch(:host_for_sitemap)
119
+ host_for_sitemap = publish_config.public_host
156
120
 
157
121
  static_site_generator.run(output_locations,
158
122
  publish_config,
@@ -178,34 +142,11 @@ module Bookbinder
178
142
  File.expand_path('..', context_dir) if bind_source == 'local'
179
143
  end
180
144
 
181
- def gather_sections(workspace, cloner, ref_override)
182
- config.sections.map do |section_config|
183
- target_ref = ref_override ||
184
- section_config.fetch('repository', {})['ref'] ||
185
- 'master'
186
- repo_name = section_config.fetch('repository').fetch('name')
187
- directory = section_config['directory']
188
- working_copy = cloner.call(source_repo_name: repo_name,
189
- source_ref: target_ref,
190
- destination_parent_dir: workspace,
191
- destination_dir_name: directory)
192
- @section_repository.get_instance(
193
- section_config,
194
- working_copy: working_copy,
195
- destination_dir: workspace
196
- ) { |*args| Section.new(*args) }
197
- end
198
- end
199
-
200
- def config
201
- config_fetcher.fetch_config
202
- end
203
-
204
- def layout_repo_path(local_repo_dir)
145
+ def layout_repo_path(config, local_repo_dir)
205
146
  if local_repo_dir && config.has_option?('layout_repo')
206
147
  File.join(local_repo_dir, config.layout_repo.split('/').last)
207
148
  elsif config.has_option?('layout_repo')
208
- cloner = cloner_factory.produce('github', nil)
149
+ cloner = cloner_factory.produce(nil)
209
150
  working_copy = cloner.call(source_repo_name: config.layout_repo,
210
151
  destination_parent_dir: Dir.mktmpdir)
211
152
  working_copy.path
@@ -213,15 +154,6 @@ module Bookbinder
213
154
  File.absolute_path('master_middleman')
214
155
  end
215
156
  end
216
-
217
- def validate(bind_source, options)
218
- raise CliError::InvalidArguments unless arguments_are_valid?(bind_source, options)
219
- end
220
-
221
- def arguments_are_valid?(bind_source, options)
222
- valid_options = %w(--verbose --ignore-section-refs).to_set
223
- %w(local github).include?(bind_source) && options.to_set.subset?(valid_options)
224
- end
225
157
  end
226
158
  end
227
159
  end
@@ -0,0 +1,50 @@
1
+ require_relative '../../sheller'
2
+ require_relative '../../streams/colorized_stream'
3
+
4
+ module Bookbinder
5
+ module Commands
6
+ module BindComponents
7
+ class BindOptions
8
+ def initialize(opts)
9
+ @opts = opts
10
+ end
11
+
12
+ def validate!
13
+ raise CliError::InvalidArguments unless arguments_are_valid?
14
+ end
15
+
16
+ def ref_override
17
+ 'master' if opts.include?('--ignore-section-refs')
18
+ end
19
+
20
+ def streams
21
+ {
22
+ out: opts.include?('--verbose') ? $stdout : Sheller::DevNull.new,
23
+ err: Streams::ColorizedStream.new(Colorizer::Colors.red, $stderr)
24
+ }
25
+ end
26
+
27
+ private
28
+
29
+ attr_accessor :opts
30
+
31
+ def arguments_are_valid?
32
+ valid_options = %w(--verbose --ignore-section-refs --dita-flags).to_set
33
+ %w(local remote github).include?(bind_source) && flag_names.to_set.subset?(valid_options)
34
+ end
35
+
36
+ def flag_names
37
+ options.map {|o| o.split('=').first}
38
+ end
39
+
40
+ def bind_source
41
+ opts.first
42
+ end
43
+
44
+ def options
45
+ opts[1..-1]
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1,4 +1,5 @@
1
1
  require_relative '../../directory_helpers'
2
+ require_relative '../../ingest/destination_directory'
2
3
 
3
4
  module Bookbinder
4
5
  module Commands
@@ -12,17 +13,17 @@ module Bookbinder
12
13
  @version_control_system = version_control_system
13
14
  end
14
15
 
15
- def prepare_directories(gem_root, versions, locations, book_repo)
16
+ def prepare_directories(config, gem_root, locations)
16
17
  forget_sections(locations.output_dir)
17
18
  file_system_accessor.remove_directory(File.join(locations.final_app_dir, '.'))
18
- file_system_accessor.remove_directory(locations.dita_home_dir)
19
+ file_system_accessor.remove_directory(locations.preprocessing_home_dir)
19
20
 
20
21
  copy_directory_from_gem(gem_root, 'template_app', locations.final_app_dir)
21
22
  copy_directory_from_gem(gem_root, 'master_middleman', locations.site_generator_home)
22
23
  file_system_accessor.copy(File.join(locations.layout_repo_dir, '.'), locations.site_generator_home)
23
24
 
24
- versions.each do |version|
25
- copy_index_file_from_version_to_master_middleman(version, locations.source_for_site_generator, book_repo)
25
+ config.versions.each do |version|
26
+ copy_index_file_from_version_to_master_middleman(version, locations.source_for_site_generator, config.book_repo_url)
26
27
  end
27
28
  end
28
29
 
@@ -30,18 +31,18 @@ module Bookbinder
30
31
 
31
32
  attr_reader :logger, :file_system_accessor, :version_control_system
32
33
 
33
- def copy_index_file_from_version_to_master_middleman(version, dest_dir, book_repo)
34
+ def copy_index_file_from_version_to_master_middleman(version, dest_dir, url)
35
+ clone_dir_name = Ingest::DestinationDirectory.new(url)
34
36
  Dir.mktmpdir(version) do |tmpdir|
35
- book = Book.from_remote(logger: logger,
36
- full_name: book_repo,
37
- destination_dir: tmpdir,
38
- ref: version,
39
- git_accessor: version_control_system)
40
- index_source_dir = File.join(tmpdir, book.directory, 'master_middleman', source_dir_name)
37
+ version_control_system.clone(url,
38
+ clone_dir_name,
39
+ path: tmpdir,
40
+ checkout: version)
41
+ index_source_dir = Pathname(tmpdir).join(clone_dir_name, 'master_middleman', source_dir_name)
41
42
  index_dest_dir = File.join(dest_dir, version)
42
43
  file_system_accessor.make_directory(index_dest_dir)
43
44
 
44
- Dir.glob(File.join(index_source_dir, 'index.*')) do |f|
45
+ Dir.glob(index_source_dir.join('index.*')) do |f|
45
46
  file_system_accessor.copy(File.expand_path(f), index_dest_dir)
46
47
  end
47
48
  end
@@ -8,24 +8,17 @@ module Bookbinder
8
8
  class BuildAndPushTarball < BookbinderCommand
9
9
  include Commands::Naming
10
10
 
11
- class MissingBuildNumber < StandardError
12
- def initialize
13
- super 'You must set $BUILD_NUMBER to push an identifiable build.'
14
- end
15
- end
16
-
17
11
  def usage
18
12
  [command_name,
19
13
  "Create a tarball from the final_app directory and push to the S3 bucket specified in your credentials.yml"]
20
14
  end
21
15
 
22
16
  def run(_)
23
- raise MissingBuildNumber unless ENV['BUILD_NUMBER']
24
17
  config = configuration_fetcher.fetch_config
25
18
  aws_credentials = configuration_fetcher.fetch_credentials[:aws]
26
19
  archive = Archive.new(logger: @logger, key: aws_credentials.access_key, secret: aws_credentials.secret_key)
27
20
  archive.create_and_upload_tarball(build_number: ENV['BUILD_NUMBER'], bucket: aws_credentials.green_builds_bucket,
28
- namespace: Ingest::DestinationDirectory.new(config.book_repo, nil))
21
+ namespace: Ingest::DestinationDirectory.new(config.book_repo))
29
22
  0
30
23
  end
31
24
  end