bookbindery 5.0.1 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 20f7d3bff67f0bf6db5e937eebaa27c123bac001
4
- data.tar.gz: 5f86b7351237c3dafa61f4253bf3cab8d2c40c66
3
+ metadata.gz: c73a7a9a4f263f7730ce38c6e09b98ae457a9571
4
+ data.tar.gz: bbd94c2710ce6052e2ad401525b9e024a584245b
5
5
  SHA512:
6
- metadata.gz: 254c768d3ef65b50837e05c35f3f9fd35014d4dc6b16170e6406aaf1f5399b44d211c40bd999494cda1df0345ec08ee5dadac11d02a6b34b1073993eeb1d6b58
7
- data.tar.gz: 81a255158580983914a0d5fbc90640d7db9f5404e116c67f2e11361f6ed9b92f14cfca8b74677b0b5d3b5e42bcefb47dba9d7d368b82abb2aac7ab25bc778164
6
+ metadata.gz: e6dbef842e82feb7bb9e4ab4dd273cc25bee08d6fb0ce4119f041c304e461ecca957269b2a96b96677e8ab03e8bfb05579654a9b47f1ff4cebe3e82723d76e5a
7
+ data.tar.gz: c6331e3c72ee6a989f26b879d1234f2e9ae1d809b10c50bc6e2e8e633157ee155d6ffa97b7243e1d9f7944b18d532d0ed1eaa517fb7876f3fae6377db8883e2f
@@ -2,7 +2,7 @@ require 'base64'
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'bookbindery'
5
- s.version = '5.0.1'
5
+ s.version = '6.0.0'
6
6
  s.summary = 'Markdown to Rackup application documentation generator'
7
7
  s.description = 'A command line utility to be run in Book repositories to stitch together their constituent Markdown repos into a static-HTML-serving application'
8
8
  s.authors = ['Mike Grafton', 'Lucas Marks', 'Gavin Morgan', 'Nikhil Gajwani', 'Dan Wendorf', 'Brenda Chan', 'Matthew Boedicker', 'Frank Kotsianas', 'Elena Sharma', 'Christa Hartsock']
@@ -15,7 +15,7 @@ module Bookbinder
15
15
  if working_copy.available?
16
16
  process_snippet(marker, working_copy)
17
17
  else
18
- out << " skipping (not found) #{working_copy.full_name}"
18
+ out.puts(" skipping (not found) #{working_copy.full_name}")
19
19
  ''
20
20
  end
21
21
  end
@@ -67,7 +67,8 @@ module Bookbinder
67
67
  def find_text(start_path, pattern)
68
68
  fs.find_files_recursively(start_path).
69
69
  lazy.
70
- map {|path| fs.read(path)}.
70
+ select {|path| fs.file_exist?(path) }.
71
+ map {|path| fs.read(path) }.
71
72
  map {|contents|
72
73
  begin
73
74
  contents.scan(pattern)
@@ -13,7 +13,7 @@ require_relative '../dita_html_to_middleman_formatter'
13
13
  require_relative '../html_document_manipulator'
14
14
  require_relative '../ingest/cloner_factory'
15
15
  require_relative '../ingest/section_repository'
16
- require_relative '../local_file_system_accessor'
16
+ require_relative '../local_filesystem_accessor'
17
17
  require_relative '../middleman_runner'
18
18
  require_relative '../postprocessing/sitemap_writer'
19
19
  require_relative '../preprocessing/dita_preprocessor'
@@ -60,7 +60,7 @@ module Bookbinder
60
60
  def standard_commands
61
61
  @standard_commands ||= [
62
62
  Commands::Generate.new(
63
- local_file_system_accessor,
63
+ local_filesystem_accessor,
64
64
  sheller,
65
65
  Dir.pwd,
66
66
  streams
@@ -71,7 +71,6 @@ module Bookbinder
71
71
  push_local_to_staging,
72
72
  Commands::PushToProd.new(streams, logger, configuration_fetcher, Dir.mktmpdir),
73
73
  Commands::RunPublishCI.new(bind, push_local_to_staging, build_and_push_tarball),
74
- Commands::Tag.new(streams, configuration_fetcher, version_control_system),
75
74
  Commands::UpdateLocalDocRepos.new(
76
75
  streams,
77
76
  configuration_fetcher,
@@ -91,19 +90,19 @@ module Bookbinder
91
90
  OutputLocations.new(final_app_dir: final_app_directory, context_dir: File.absolute_path('.')),
92
91
  configuration_fetcher,
93
92
  Config::ArchiveMenuConfiguration.new(loader: config_loader, config_filename: 'bookbinder.yml'),
94
- local_file_system_accessor,
93
+ local_filesystem_accessor,
95
94
  runner,
96
95
  Postprocessing::SitemapWriter.build(logger, final_app_directory, sitemap_port),
97
96
  Preprocessing::Preprocessor.new(
98
97
  Preprocessing::DitaPreprocessor.new(
99
- DitaHtmlToMiddlemanFormatter.new(local_file_system_accessor, subnav_formatter, html_document_manipulator),
100
- local_file_system_accessor,
98
+ DitaHtmlToMiddlemanFormatter.new(local_filesystem_accessor, subnav_formatter, html_document_manipulator),
99
+ local_filesystem_accessor,
101
100
  DitaCommandCreator.new(ENV['PATH_TO_DITA_OT_LIBRARY']),
102
101
  sheller
103
102
  ),
104
- Preprocessing::LinkToSiteGenDir.new(local_file_system_accessor),
103
+ Preprocessing::LinkToSiteGenDir.new(local_filesystem_accessor),
105
104
  ),
106
- Ingest::ClonerFactory.new(streams, local_file_system_accessor, version_control_system),
105
+ Ingest::ClonerFactory.new(streams, local_filesystem_accessor, version_control_system),
107
106
  Ingest::SectionRepository.new,
108
107
  directory_preparer
109
108
  )
@@ -116,8 +115,8 @@ module Bookbinder
116
115
  output_locations: OutputLocations.new(final_app_dir: final_app_directory, context_dir: File.absolute_path('.')),
117
116
  config_fetcher: configuration_fetcher,
118
117
  config_decorator: Config::ArchiveMenuConfiguration.new(loader: config_loader, config_filename: 'bookbinder.yml'),
119
- file_system_accessor: local_file_system_accessor,
120
- preprocessor: Preprocessing::Preprocessor.new(Preprocessing::LinkToSiteGenDir.new(local_file_system_accessor)),
118
+ file_system_accessor: local_filesystem_accessor,
119
+ preprocessor: Preprocessing::Preprocessor.new(Preprocessing::LinkToSiteGenDir.new(local_filesystem_accessor)),
121
120
  cloner: local_file_system_cloner,
122
121
  section_repository: Ingest::SectionRepository.new,
123
122
  directory_preparer: directory_preparer
@@ -142,7 +141,7 @@ module Bookbinder
142
141
 
143
142
  def configuration_fetcher
144
143
  @configuration_fetcher ||= Config::Fetcher.new(
145
- Config::Validator.new(local_file_system_accessor),
144
+ Config::Validator.new(local_filesystem_accessor),
146
145
  config_loader,
147
146
  Config::RemoteYamlCredentialProvider.new(logger, version_control_system)
148
147
  ).tap do |fetcher|
@@ -155,7 +154,7 @@ module Bookbinder
155
154
  end
156
155
 
157
156
  def directory_preparer
158
- Commands::BindComponents::DirectoryPreparer.new(local_file_system_accessor)
157
+ Commands::BindComponents::DirectoryPreparer.new(local_filesystem_accessor)
159
158
  end
160
159
 
161
160
  def final_app_directory
@@ -170,8 +169,8 @@ module Bookbinder
170
169
  @html_document_manipulator ||= HtmlDocumentManipulator.new
171
170
  end
172
171
 
173
- def local_file_system_accessor
174
- @local_file_system_accessor ||= LocalFileSystemAccessor.new
172
+ def local_filesystem_accessor
173
+ @local_filesystem_accessor ||= LocalFilesystemAccessor.new
175
174
  end
176
175
 
177
176
  def sheller
@@ -183,11 +182,11 @@ module Bookbinder
183
182
  end
184
183
 
185
184
  def runner
186
- MiddlemanRunner.new(local_file_system_accessor, sheller)
185
+ MiddlemanRunner.new(local_filesystem_accessor, sheller)
187
186
  end
188
187
 
189
188
  def local_file_system_cloner
190
- Ingest::LocalFilesystemCloner.new(streams, local_file_system_accessor, File.expand_path('..'))
189
+ Ingest::LocalFilesystemCloner.new(streams, local_filesystem_accessor, File.expand_path('..'))
191
190
  end
192
191
  end
193
192
  end
@@ -1,3 +1,4 @@
1
+ require_relative '../ingest/destination_directory'
1
2
  require_relative '../ingest/repo_identifier'
2
3
  require_relative 'section_config'
3
4
 
@@ -32,18 +33,34 @@ module Bookbinder
32
33
  end
33
34
 
34
35
  def dita_sections(input_config)
35
- (input_config['dita_sections'] || []).map { |dita_section|
36
+ dita_sections = input_config['dita_sections']
37
+ (dita_sections || []).map { |dita_section|
36
38
  dita_section.merge(
37
39
  'preprocessor_config' => {
38
40
  'ditamap_location' => dita_section['ditamap_location'],
39
41
  'ditaval_location' => dita_section['ditaval_location']
40
42
  },
41
- 'subnav_template' => 'dita_subnav'
43
+ 'subnav_template' => dita_subnav_template(dita_sections, dita_section)
42
44
  ).reject { |k, _|
43
45
  %w(ditamap_location ditaval_location).include?(k)
44
46
  }
45
47
  }
46
48
  end
49
+
50
+ def dita_subnav_template(all_sections, current_section)
51
+ subnav_sections = all_sections.select { |section| section['ditamap_location'] }
52
+ if subnav_sections.empty?
53
+ nil
54
+ elsif subnav_sections.one?
55
+ "dita_subnav"
56
+ else
57
+ subnav_section = subnav_sections.include?(current_section) ? current_section : subnav_sections.first
58
+ dest_dir = Ingest::DestinationDirectory.new(
59
+ subnav_section.fetch('repository', {})['name'], subnav_section['directory'])
60
+
61
+ dest_dir ? "dita_subnav_#{dest_dir}" : "dita_subnav"
62
+ end
63
+ end
47
64
  end
48
65
 
49
66
  def initialize(config)
@@ -40,11 +40,7 @@ module Bookbinder
40
40
  end
41
41
 
42
42
  def filter(ditaval_path)
43
- if ditaval_path
44
- { 'args.filter' => ditaval_path }
45
- else
46
- {}
47
- end
43
+ ditaval_path ? { 'args.filter' => ditaval_path } : {}
48
44
  end
49
45
 
50
46
  def base_flags
@@ -59,18 +55,19 @@ module Bookbinder
59
55
 
60
56
  def optional_flags(flags_str)
61
57
  flags = flags_str ? flags_str.split(" ") : []
62
- flags.inject({}) do |h, f|
63
- k,v = f.split('=')
64
- h[k] = v
65
- raise MissingDitaOTFlagValue.new("The DITA-flag '#{k}' that you passed is missing a value. Please pass your DITA option in the format '#{k}=<value>'.") unless v
66
- h
58
+ {}.tap do |h|
59
+ flags.each do |f|
60
+ k,v = f.split('=')
61
+ h[k] = v
62
+ raise MissingDitaOTFlagValue.new("The DITA-flag '#{k}' that you passed is missing a value. Please pass your DITA option in the format '#{k}=<value>'.") unless v
63
+ end
67
64
  end
68
65
  end
69
66
 
70
67
  def format(flags)
71
68
  flags.inject("") do |res, f|
72
69
  k,v = f
73
- res += "-D#{k}='#{stripped_flag_value v}' "
70
+ res + "-D#{k}='#{stripped_flag_value v}' "
74
71
  end
75
72
  end
76
73
 
@@ -1,4 +1,5 @@
1
1
  require 'git'
2
+ require_relative '../directory_helpers'
2
3
  require_relative 'update_failure'
3
4
  require_relative 'update_success'
4
5
 
@@ -7,6 +8,7 @@ module Bookbinder
7
8
  class GitAccessor
8
9
  TagExists = Class.new(RuntimeError)
9
10
  InvalidTagRef = Class.new(RuntimeError)
11
+ include DirectoryHelperMethods
10
12
 
11
13
  def clone(url, name, path: nil, checkout: 'master')
12
14
  cached_clone(url, name, Pathname(path)).tap do |git|
@@ -37,26 +39,12 @@ module Bookbinder
37
39
  end
38
40
  end
39
41
 
40
- def remote_tag(url, tagname, commit_or_object)
41
- Dir.mktmpdir do |dir|
42
- path = Pathname(dir)
43
- git = cached_clone(url, temp_name("tag"), path)
44
- git.config('user.name', 'Bookbinder')
45
- git.config('user.email', 'bookbinder@cloudfoundry.org')
46
- begin
47
- git.add_tag(tagname, "origin/#{commit_or_object}",
48
- message: 'Tagged by Bookbinder')
49
- rescue Git::GitExecuteError => e
50
- case e.message
51
- when /already exists/
52
- raise TagExists
53
- when /as a valid ref/
54
- raise InvalidTagRef
55
- else
56
- raise
57
- end
42
+ def author_date(path)
43
+ Pathname(path).dirname.ascend do |current_dir|
44
+ if current_dir.to_s.include?(source_dir_name) && current_dir.entries.include?(Pathname(".git"))
45
+ git = Git.open(current_dir)
46
+ return git.gblob(path).log.first.author.date
58
47
  end
59
- git.push("origin", "master", tags: true)
60
48
  end
61
49
  end
62
50
 
@@ -19,7 +19,6 @@ module Bookbinder
19
19
  Section.new(
20
20
  working_copy.path,
21
21
  working_copy.full_name,
22
- destination_dir,
23
22
  section_config.desired_directory_name,
24
23
  section_config.subnav_template,
25
24
  section_config.preprocessor_config
@@ -5,7 +5,7 @@ require_relative 'errors/programmer_mistake'
5
5
 
6
6
  module Bookbinder
7
7
 
8
- class LocalFileSystemAccessor
8
+ class LocalFilesystemAccessor
9
9
  def file_exist?(path)
10
10
  File.exist?(path)
11
11
  end
@@ -15,36 +15,31 @@ module Bookbinder
15
15
  end
16
16
 
17
17
  def applicable_to?(section)
18
- section.subnav_template == 'dita_subnav'
18
+ section.subnav_template.include?('dita_subnav') if section.subnav_template
19
19
  end
20
20
 
21
- def preprocess(dita_sections, output_locations, options: nil, output_streams: nil)
22
- dita_sections.select { |dita_section| dita_section.path_to_preprocessor_attribute('ditamap_location') }.each do |dita_section|
23
- command = command_creator.convert_to_html_command(
24
- dita_section,
25
- dita_flags: dita_flags(options),
26
- write_to: output_locations.html_from_preprocessing_dir.join(dita_section.destination_directory)
27
- )
28
- status = sheller.run_command(command, output_streams.to_h)
29
- unless status.success?
30
- raise DitaToHtmlLibraryFailure.new 'The DITA-to-HTML conversion failed. ' +
31
- 'Please check that you have specified the path to your DITA-OT library in the ENV, ' +
32
- 'that your DITA-specific keys/values in config.yml are set, ' +
33
- 'and that your DITA toolkit is correctly configured.'
21
+ def preprocess(dita_sections, output_locations, options: [], output_streams: nil)
22
+ dita_options = dita_flags(options)
23
+ dita_sections.each do |dita_section|
24
+ if dita_section.path_to_preprocessor_attribute('ditamap_location')
25
+ convert_dita_files(dita_section,
26
+ command_creator,
27
+ dita_options,
28
+ output_locations.html_from_preprocessing_dir.join(dita_section.destination_directory),
29
+ sheller,
30
+ output_streams)
31
+
32
+ generate_subnav(dita_section,
33
+ output_locations,
34
+ output_locations.source_for_site_generator.join('subnavs', '_dita_subnav_template.erb'),
35
+ output_locations.subnavs_for_layout_dir)
34
36
  end
35
37
 
36
- generate_subnav(dita_section.destination_directory,
37
- output_locations,
38
- output_locations.source_for_site_generator.join('subnavs', '_dita_subnav_template.erb'),
39
- output_locations.subnavs_for_layout_dir)
40
- end
41
-
42
- dita_sections.each do |dita_section|
43
- html_dir = output_locations.html_from_preprocessing_dir.join(dita_section.destination_directory)
38
+ section_html_dir = output_locations.html_from_preprocessing_dir.join(dita_section.destination_directory)
44
39
  formatted_dir = output_locations.formatted_dir.join(dita_section.destination_directory)
45
40
  source_for_site_gen_dir = output_locations.source_for_site_generator.join(dita_section.destination_directory)
46
41
 
47
- dita_formatter.format_html html_dir, formatted_dir
42
+ dita_formatter.format_html section_html_dir, formatted_dir
48
43
 
49
44
  copy_images(dita_section.path_to_repository, formatted_dir)
50
45
 
@@ -56,26 +51,41 @@ module Bookbinder
56
51
 
57
52
  attr_reader :dita_formatter, :local_fs_accessor, :command_creator, :sheller
58
53
 
59
- def generate_subnav(dita_section_dir, output_locations, dita_subnav_template_path, subnavs_dir)
54
+ def convert_dita_files(section, command_creator, options, section_html_dir, sheller, output_streams)
55
+ command = command_creator.convert_to_html_command(
56
+ section,
57
+ dita_flags: options,
58
+ write_to: section_html_dir
59
+ )
60
+ status = sheller.run_command(command, output_streams.to_h)
61
+ unless status.success?
62
+ raise DitaToHtmlLibraryFailure.new 'The DITA-to-HTML conversion failed. ' +
63
+ 'Please check that you have specified the path to your DITA-OT library in the ENV, ' +
64
+ 'that your DITA-specific keys/values in config.yml are set, ' +
65
+ 'and that your DITA toolkit is correctly configured.'
66
+ end
67
+ end
68
+
69
+ def generate_subnav(dita_section, output_locations, dita_subnav_template_path, subnavs_dir)
60
70
  dita_subnav_template_text = local_fs_accessor.read(dita_subnav_template_path)
61
71
 
62
72
  tocjs_text = local_fs_accessor.read(
63
73
  File.join(
64
- output_locations.html_from_preprocessing_dir.join(dita_section_dir),
74
+ output_locations.html_from_preprocessing_dir.join(dita_section.destination_directory),
65
75
  'index.html')
66
76
  )
67
- json_props_location = File.join('dita-subnav-props.json')
77
+ json_props_location = json_props_location(dita_section.destination_directory)
68
78
  props_file_location = File.join(subnavs_dir, json_props_location)
69
79
 
70
- subnav = dita_formatter.format_subnav(dita_section_dir,
80
+ subnav = dita_formatter.format_subnav(dita_section.destination_directory,
71
81
  dita_subnav_template_text,
72
82
  json_props_location,
73
83
  tocjs_text)
74
84
 
75
- local_fs_accessor.write text: subnav.json_links, to: props_file_location
85
+ local_fs_accessor.write text: subnav.json_links, to: props_file_location
76
86
 
77
- local_fs_accessor.write text: subnav.text,
78
- to: File.join(subnavs_dir, "dita_subnav.erb")
87
+ local_fs_accessor.write text: subnav.text,
88
+ to: File.join(subnavs_dir, "#{dita_section.subnav_template}.erb")
79
89
  end
80
90
 
81
91
  def copy_images(src, dest)
@@ -90,6 +100,10 @@ module Bookbinder
90
100
  end
91
101
  end
92
102
 
103
+ def json_props_location(section_dir)
104
+ (["dita-subnav-props"] + Array(section_dir.to_s)).join("-") + ".json"
105
+ end
106
+
93
107
  def dita_flags(opts)
94
108
  matching_flags = opts.map {|o| o[flag_value_regex("dita-flags"), 1] }
95
109
  matching_flags.compact.first
@@ -4,7 +4,6 @@ require_relative '../ingest/destination_directory'
4
4
  module Bookbinder
5
5
  Section = Struct.new(:path_to_repository,
6
6
  :full_name,
7
- :destination_dir,
8
7
  :desired_directory_name,
9
8
  :subnav_templ,
10
9
  :preprocessor_config) do
@@ -1,7 +1,7 @@
1
1
  require 'bookbinder/code_example_reader'
2
2
  require 'bookbinder/ingest/cloner_factory'
3
3
  require 'bookbinder/ingest/git_accessor'
4
- require 'bookbinder/local_file_system_accessor'
4
+ require 'bookbinder/local_filesystem_accessor'
5
5
  require 'date'
6
6
  require_relative 'archive_drop_down_menu'
7
7
  require_relative 'quicklinks_renderer'
@@ -22,12 +22,12 @@ module Bookbinder
22
22
 
23
23
  def yield_for_code_snippet(from: nil, at: nil)
24
24
  cloner_factory = Ingest::ClonerFactory.new({out: $stdout},
25
- LocalFileSystemAccessor.new,
25
+ LocalFilesystemAccessor.new,
26
26
  Ingest::GitAccessor.new)
27
27
 
28
28
  cloner = cloner_factory.produce(config[:local_repo_dir])
29
29
  code_example_reader = CodeExampleReader.new({out: $stdout},
30
- LocalFileSystemAccessor.new)
30
+ LocalFilesystemAccessor.new)
31
31
  working_copy = cloner.call(source_repo_name: from,
32
32
  source_ref: 'master',
33
33
  destination_parent_dir: config[:workspace])
@@ -53,6 +53,12 @@ module Bookbinder
53
53
  dropdown_links: menu.dropdown_links }
54
54
  end
55
55
 
56
+ def modified_date(format="%B %-d, %Y")
57
+ git_accessor = Ingest::GitAccessor.new
58
+ date = git_accessor.author_date(current_page.source_file) || Time.new(1984,1,1)
59
+ "Page last updated: #{date.strftime(format)}"
60
+ end
61
+
56
62
  def breadcrumbs
57
63
  page_chain = add_ancestors_of(current_page, [])
58
64
  breadcrumbs = page_chain.map do |page|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bookbindery
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.1
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Grafton
@@ -17,7 +17,7 @@ authors:
17
17
  autorequire:
18
18
  bindir: install_bin
19
19
  cert_chain: []
20
- date: 2015-08-27 00:00:00.000000000 Z
20
+ date: 2015-09-08 00:00:00.000000000 Z
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
23
23
  name: fog-aws
@@ -311,7 +311,6 @@ files:
311
311
  - lib/bookbinder/commands/push_from_local.rb
312
312
  - lib/bookbinder/commands/push_to_prod.rb
313
313
  - lib/bookbinder/commands/run_publish_ci.rb
314
- - lib/bookbinder/commands/tag.rb
315
314
  - lib/bookbinder/commands/update_local_doc_repos.rb
316
315
  - lib/bookbinder/commands/version.rb
317
316
  - lib/bookbinder/commands/watch.rb
@@ -358,7 +357,7 @@ files:
358
357
  - lib/bookbinder/ingest/update_failure.rb
359
358
  - lib/bookbinder/ingest/update_success.rb
360
359
  - lib/bookbinder/ingest/working_copy.rb
361
- - lib/bookbinder/local_file_system_accessor.rb
360
+ - lib/bookbinder/local_filesystem_accessor.rb
362
361
  - lib/bookbinder/middleman_runner.rb
363
362
  - lib/bookbinder/postprocessing/sitemap_writer.rb
364
363
  - lib/bookbinder/preprocessing/dita_preprocessor.rb
@@ -1,44 +0,0 @@
1
- require_relative '../errors/cli_error'
2
- require_relative 'naming'
3
-
4
- module Bookbinder
5
- module Commands
6
- class Tag
7
- include Commands::Naming
8
-
9
- def initialize(streams, configuration_fetcher, version_control_system)
10
- @streams = streams
11
- @configuration_fetcher = configuration_fetcher
12
- @version_control_system = version_control_system
13
- end
14
-
15
- def usage
16
- ["tag <git tag>", "Apply the specified <git tag> to your book and all sections of your book"]
17
- end
18
-
19
- def run((tag, *))
20
- raise CliError::InvalidArguments unless tag
21
-
22
- urls(config).each do |url|
23
- version_control_system.remote_tag(url, tag, 'HEAD')
24
- end
25
-
26
- streams[:success].puts 'Success!'
27
- streams[:out].puts "#{config.book_repo} and its sections were tagged with #{tag}"
28
- 0
29
- end
30
-
31
- private
32
-
33
- attr_reader :streams, :configuration_fetcher, :version_control_system
34
-
35
- def urls(config)
36
- [config.book_repo_url] + config.sections.map(&:repo_url).uniq
37
- end
38
-
39
- def config
40
- @config ||= configuration_fetcher.fetch_config
41
- end
42
- end
43
- end
44
- end