bookbindery 5.0.1 → 6.0.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.
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