bookbindery 3.1.2 → 4.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: db0253fb2ff70df7454081ccad6222b3cd61ac6e
4
- data.tar.gz: 12281076319eae008bad526b376bba7348007722
3
+ metadata.gz: 4186b0031cc1db33f20038d884a71624f845d175
4
+ data.tar.gz: 439d522cdaba03d005039b45e44b9b3917dab82d
5
5
  SHA512:
6
- metadata.gz: 137791f967ff0fc2df6728d215ce6cd072f9a617e2461a05cc4e55c17affb2fbe932b147b40cd901cf89f891f8b7aa41b2de4ab005f60efa4d3d7de69b0eeb4a
7
- data.tar.gz: 53af686a48cfc52f35b87a825aea6870f1cbe5da92e4e9a7e7b31624e5156e09193b83722fce212c48005a6986c190227371c919db394da92e99fe8d617649d8
6
+ metadata.gz: 384fc6c0bf881e81cc2fd34040af92eae6b83150cbdd14b441d72d84355d2a8ce4dcb0044a892de797eec4f20b3660739fbb99529a0a7b0d57a8295fa827a0a6
7
+ data.tar.gz: 3310d764be0a0d8063e9142ccff2c55046f4378b255a8e5fe63ceb8919a5eb5ddbf10cf8d24584810f5b78678365654a931a2fc66df3f11b9649f54255fbacaf
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require_relative '../lib/bookbinder/cli'
4
- require_relative '../lib/bookbinder/git_accessor'
4
+ require_relative '../lib/bookbinder/ingest/git_accessor'
5
5
 
6
- return_code = Bookbinder::Cli.new(Bookbinder::GitAccessor.new).run ARGV
6
+ return_code = Bookbinder::Cli.new(Bookbinder::Ingest::GitAccessor.new).run ARGV
7
7
  exit return_code.to_i
@@ -11,7 +11,7 @@ module Bookbinder
11
11
  command = commands.detect { |known_command| known_command.command_for?(command_name) }
12
12
  command.run(command_arguments)
13
13
  rescue CliError::InvalidArguments
14
- logger.log command.usage
14
+ logger.log ["bookbinder #{command.usage[0]}", command.usage[1]]
15
15
  1
16
16
  end
17
17
 
@@ -20,7 +20,7 @@ module Bookbinder
20
20
  elsif candidate.deprecated_match
21
21
  UserMessage.new(
22
22
  "Use of #{command_name} is deprecated. " +
23
- "The preferred usage is below: \n#{candidate.deprecated_match.usage}",
23
+ "The preferred usage is below: \nbookbinder #{candidate.deprecated_match.usage[0]}",
24
24
  EscalationType.warn
25
25
  )
26
26
  else
@@ -71,10 +71,12 @@ module Bookbinder
71
71
  ref_override: bind_options.ref_override
72
72
  )
73
73
 
74
- preprocessor.preprocess(sections,
75
- output_locations,
76
- options: options,
77
- output_streams: bind_options.streams)
74
+ preprocessor.preprocess(
75
+ sections,
76
+ output_locations,
77
+ options: options,
78
+ output_streams: bind_options.streams
79
+ )
78
80
 
79
81
  success = publish(
80
82
  sections.map(&:subnav).reduce({}, :merge),
@@ -118,19 +120,18 @@ module Bookbinder
118
120
  subnavs)
119
121
  file_system_accessor.copy output_locations.build_dir, output_locations.public_dir
120
122
 
121
-
122
- result = generate_sitemap(host_for_sitemap)
123
+ raise "Your public host must be a single String." unless host_for_sitemap.is_a?(String)
124
+ result = sitemap_writer.write(
125
+ host_for_sitemap,
126
+ streams,
127
+ publish_config.broken_link_exclusions
128
+ )
123
129
 
124
130
  streams[:success].puts "Bookbinder bound your book into #{output_locations.final_app_dir}"
125
131
 
126
132
  !result.has_broken_links?
127
133
  end
128
134
 
129
- def generate_sitemap(host_for_sitemap)
130
- raise "Your public host must be a single String." unless host_for_sitemap.is_a?(String)
131
- sitemap_writer.write(host_for_sitemap)
132
- end
133
-
134
135
  def generate_local_repo_dir(context_dir, bind_source)
135
136
  File.expand_path('..', context_dir) if bind_source == 'local'
136
137
  end
@@ -19,11 +19,9 @@ module Bookbinder
19
19
  end
20
20
 
21
21
  def streams
22
- {
22
+ base_streams.merge(
23
23
  out: opts.include?('--verbose') ? base_streams[:out] : Sheller::DevNull.new,
24
- success: Streams::ColorizedStream.new(Colorizer::Colors.green, base_streams[:out]),
25
- err: Streams::ColorizedStream.new(Colorizer::Colors.red, base_streams[:err]),
26
- }
24
+ )
27
25
  end
28
26
 
29
27
  private
@@ -65,7 +65,12 @@ module Bookbinder
65
65
  Commands::PushToProd.new(logger, configuration_fetcher),
66
66
  Commands::RunPublishCI.new(bind, push_local_to_staging, build_and_push_tarball),
67
67
  Commands::Tag.new(logger, configuration_fetcher, version_control_system),
68
- Commands::UpdateLocalDocRepos.new(logger, configuration_fetcher, version_control_system, local_file_system_accessor),
68
+ Commands::UpdateLocalDocRepos.new(
69
+ colored_streams,
70
+ configuration_fetcher,
71
+ version_control_system,
72
+ local_file_system_accessor
73
+ ),
69
74
  ]
70
75
  end
71
76
 
@@ -75,7 +80,7 @@ module Bookbinder
75
80
 
76
81
  def bind
77
82
  @bind ||= Commands::Bind.new(
78
- {out: $stdout, err: $stderr},
83
+ colored_streams,
79
84
  OutputLocations.new(final_app_dir: final_app_directory, context_dir: File.absolute_path('.')),
80
85
  Config::BindConfigFactory.new(version_control_system, configuration_fetcher),
81
86
  Config::ArchiveMenuConfiguration.new(loader: config_loader, config_filename: 'bookbinder.yml'),
@@ -112,10 +117,15 @@ module Bookbinder
112
117
  )
113
118
  end
114
119
 
120
+ def colored_streams
121
+ { out: $stdout,
122
+ success: Streams::ColorizedStream.new(Colorizer::Colors.green, $stdout),
123
+ err: Streams::ColorizedStream.new(Colorizer::Colors.red, $stderr) }
124
+ end
125
+
115
126
  def configuration_fetcher
116
127
  @configuration_fetcher ||= Config::Fetcher.new(
117
- logger,
118
- Config::Validator.new(logger, local_file_system_accessor),
128
+ Config::Validator.new(local_file_system_accessor),
119
129
  config_loader,
120
130
  Config::RemoteYamlCredentialProvider.new(logger, version_control_system)
121
131
  ).tap do |fetcher|
@@ -7,8 +7,8 @@ module Bookbinder
7
7
  class UpdateLocalDocRepos
8
8
  include Commands::Naming
9
9
 
10
- def initialize(logger, configuration_fetcher, version_control_system, filesystem)
11
- @logger = logger
10
+ def initialize(streams, configuration_fetcher, version_control_system, filesystem)
11
+ @streams = streams
12
12
  @configuration_fetcher = configuration_fetcher
13
13
  @version_control_system = version_control_system
14
14
  @filesystem = filesystem
@@ -22,19 +22,28 @@ module Bookbinder
22
22
  def run(_)
23
23
  urls = configuration_fetcher.fetch_config.sections.map(&:repo_url)
24
24
  paths(urls).each do |path|
25
- if filesystem.file_exist?(path)
26
- logger.log 'Updating ' + path.cyan
27
- version_control_system.update(path)
28
- else
29
- logger.log ' skipping (not found) '.magenta + path
30
- end
25
+ streams[:out] << "\nUpdating #{path}:"
26
+ report(version_control_system.update(path))
31
27
  end
28
+ streams[:out].puts
32
29
  0
33
30
  end
34
31
 
35
32
  private
36
33
 
37
- attr_reader :logger, :configuration_fetcher, :version_control_system, :filesystem
34
+ attr_reader(:streams,
35
+ :configuration_fetcher,
36
+ :version_control_system,
37
+ :filesystem)
38
+
39
+ def report(result)
40
+ messages = { true => "updated", false => "skipping (#{result.reason})" }
41
+ streams[stream_types[result.success?]] << " #{messages[result.success?]}"
42
+ end
43
+
44
+ def stream_types
45
+ { true => :success, false => :out }
46
+ end
38
47
 
39
48
  def paths(urls)
40
49
  urls.map {|url| File.absolute_path("../#{Ingest::DestinationDirectory.new(url)}")}
@@ -12,11 +12,9 @@ module Bookbinder
12
12
 
13
13
  def check(config)
14
14
  partial_location = './master_middleman/source/archive_menus/_default.erb'
15
- if config.has_key?("archive_menu") && config["archive_menu"].nil?
16
- ArchiveMenuNotDefinedError.new 'Did you mean to provide an archive menu value to display? If you use the archive_menu key, you must provide at least one value.'
17
- elsif archive_items(config).include?(nil)
15
+ if config.archive_menu && config.archive_menu.include?(nil)
18
16
  EmptyArchiveItemsError.new 'Did you forget to add a value to the archive_menu?'
19
- elsif config.has_key?("archive_menu") && !file_system_accessor.file_exist?(partial_location)
17
+ elsif config.archive_menu && !file_system_accessor.file_exist?(partial_location)
20
18
  MissingArchiveMenuPartialError.new "You must provide a template partial named at #{partial_location}"
21
19
  end
22
20
  end
@@ -25,10 +23,6 @@ module Bookbinder
25
23
 
26
24
  attr_reader :file_system_accessor
27
25
 
28
- def archive_items(config)
29
- config.fetch('archive_menu', [])
30
- end
31
-
32
26
  end
33
27
  end
34
28
  end
@@ -5,18 +5,25 @@ module Bookbinder
5
5
  DitamapLocationError = Class.new(RuntimeError)
6
6
 
7
7
  def check(config)
8
- dita_sections = config['dita_sections'].to_a
9
-
10
- sum = 0
11
- dita_sections.each do |section|
12
- if section['ditamap_location']
13
- sum += 1
14
- end
8
+ if none_with_pred?(dita_sections(config)) { |s|
9
+ s.preprocessor_config['ditamap_location']
10
+ }
11
+ DitamapLocationError.new(
12
+ "You must have at least one 'ditamap_location' key in dita_sections."
13
+ )
15
14
  end
15
+ end
16
16
 
17
- if !dita_sections.empty? && (sum < 1)
18
- DitamapLocationError.new "You must have at least one 'ditamap_location' key in dita_sections."
19
- end
17
+ private
18
+
19
+ def none_with_pred?(coll, &block)
20
+ coll.any? && coll.none?(&block)
21
+ end
22
+
23
+ def dita_sections(config)
24
+ config.sections.select {|s|
25
+ s.preprocessor_config.has_key?('ditamap_location')
26
+ }
20
27
  end
21
28
  end
22
29
  end
@@ -1,3 +1,5 @@
1
+ require_relative '../../ingest/destination_directory'
2
+
1
3
  module Bookbinder
2
4
  module Config
3
5
  module Checkers
@@ -13,8 +15,10 @@ module Bookbinder
13
15
  private
14
16
 
15
17
  def duplicate_section_names?(config)
16
- sections = config['sections'].to_a + config['dita_sections'].to_a
17
- directory_names = sections.map {|section| section['directory']}
18
+ directory_names = config.sections.map {|section|
19
+ Ingest::DestinationDirectory.new(section.repo_name,
20
+ section.desired_directory_name)
21
+ }
18
22
  directory_names.length != directory_names.uniq.length
19
23
  end
20
24
 
@@ -5,14 +5,11 @@ module Bookbinder
5
5
  MissingRepositoryNameError = Class.new(RuntimeError)
6
6
 
7
7
  def check(config)
8
- all_sections = config['sections'].to_a + config['dita_sections'].to_a
9
- failures = all_sections.map do |section|
10
- if !section['repository'] || !section['repository']['name']
11
- true
12
- end
8
+ failures = config.sections.reject do |section|
9
+ section.repo_name
13
10
  end
14
11
 
15
- if failures.compact.empty?
12
+ if failures.empty?
16
13
  nil
17
14
  else
18
15
  MissingRepositoryNameError.new error_message
@@ -5,42 +5,22 @@ module Bookbinder
5
5
  module Checkers
6
6
  class RequiredKeysChecker
7
7
  MissingRequiredKeyError = Class.new(RuntimeError)
8
- SectionAbsenceError = Class.new(RuntimeError)
9
8
 
10
9
  def check(config)
11
10
  missing_keys = []
12
11
 
13
- Config::Configuration::CONFIG_REQUIRED_KEYS.map do |required_key|
14
- config_keys = config.keys
15
- unless config_keys.include?(required_key)
12
+ Config::Configuration::CONFIG_REQUIRED_KEYS.each do |required_key|
13
+ begin
14
+ config.public_send(required_key)
15
+ rescue KeyError
16
16
  missing_keys.push(required_key)
17
17
  end
18
18
  end
19
19
 
20
20
  if missing_keys.length > 0
21
21
  MissingRequiredKeyError.new("Your config.yml is missing required key(s). Required keys are #{missing_keys.join(", ")}.")
22
- elsif !config['sections'] && !config['dita_sections']
23
- SectionAbsenceError.new error_message
24
22
  end
25
23
  end
26
-
27
- private
28
-
29
- def error_message
30
- <<-ERROR
31
- Cannot locate your sections.
32
- Must specify at least one of 'sections' and/or 'dita_sections' in config.yml:
33
-
34
- sections:
35
- - repository:
36
- name: 'your-org/your-repo'
37
-
38
- dita_sections:
39
- - repository:
40
- name: 'dita-org/dita-repo'
41
- ditamap_location: 'example.ditamap'
42
- ERROR
43
- end
44
24
  end
45
25
  end
46
26
  end
@@ -65,6 +65,10 @@ module Bookbinder
65
65
  end
66
66
  end
67
67
 
68
+ def broken_link_exclusions
69
+ config.fetch(:broken_link_exclusions, /(?!.*)/)
70
+ end
71
+
68
72
  def template_variables
69
73
  config.fetch(:template_variables, {})
70
74
  end
@@ -6,9 +6,8 @@ require_relative 'yaml_loader'
6
6
  module Bookbinder
7
7
  module Config
8
8
  class Fetcher
9
- def initialize(logger, configuration_validator, loader, credentials_provider)
9
+ def initialize(configuration_validator, loader, credentials_provider)
10
10
  @loader = loader
11
- @logger = logger
12
11
  @configuration_validator = configuration_validator
13
12
  @credentials_provider = credentials_provider
14
13
  end
@@ -36,7 +35,7 @@ module Bookbinder
36
35
 
37
36
  private
38
37
 
39
- attr_reader(:loader, :logger, :configuration_validator, :config, :config_file_path,
38
+ attr_reader(:loader, :configuration_validator, :config, :config_file_path,
40
39
  :credentials_provider)
41
40
 
42
41
  def read_config_file
@@ -51,10 +50,10 @@ module Bookbinder
51
50
  def validate(config_hash)
52
51
  raise 'Your config.yml appears to be empty. Please check and try again.' unless config_hash
53
52
 
54
- errors = configuration_validator.exceptions(config_hash)
55
- raise errors.first if errors.any?
56
-
57
- Configuration.parse(config_hash)
53
+ Configuration.parse(config_hash).tap do |config|
54
+ errors = configuration_validator.exceptions(config)
55
+ raise errors.first if errors.any?
56
+ end
58
57
  end
59
58
  end
60
59
  end
@@ -28,7 +28,7 @@ module Bookbinder
28
28
  end
29
29
 
30
30
  def preprocessor_config
31
- config['preprocessor_config']
31
+ config.fetch('preprocessor_config', {})
32
32
  end
33
33
 
34
34
  def ==(other)
@@ -46,7 +46,7 @@ module Bookbinder
46
46
  private
47
47
 
48
48
  def repo
49
- config['repository']
49
+ config.fetch('repository', {})
50
50
  end
51
51
 
52
52
  attr_reader :config
@@ -7,12 +7,11 @@ require_relative 'checkers/dita_section_checker'
7
7
  module Bookbinder
8
8
  module Config
9
9
  class Validator
10
- def initialize(logger, file_system_accessor)
11
- @logger = logger
10
+ def initialize(file_system_accessor)
12
11
  @file_system_accessor = file_system_accessor
13
12
  end
14
13
 
15
- def exceptions(config_hash)
14
+ def exceptions(config)
16
15
  exceptions = [
17
16
  Checkers::RequiredKeysChecker.new,
18
17
  Checkers::DuplicateSectionNameChecker.new,
@@ -20,7 +19,7 @@ module Bookbinder
20
19
  Checkers::DitaSectionChecker.new,
21
20
  Checkers::ArchiveMenuChecker.new(@file_system_accessor)
22
21
  ].map do |checker|
23
- checker.check(config_hash)
22
+ checker.check(config)
24
23
  end
25
24
 
26
25
  exceptions.compact
@@ -0,0 +1,84 @@
1
+ require 'git'
2
+ require_relative 'update_failure'
3
+ require_relative 'update_success'
4
+
5
+ module Bookbinder
6
+ module Ingest
7
+ class GitAccessor
8
+ TagExists = Class.new(RuntimeError)
9
+ InvalidTagRef = Class.new(RuntimeError)
10
+
11
+ def initialize
12
+ @cache = {}
13
+ end
14
+
15
+ def clone(url, name, path: nil, checkout: 'master')
16
+ cached_clone(url, name, path).tap do |git|
17
+ git.checkout(checkout)
18
+ end
19
+ end
20
+
21
+ def update(cloned_path)
22
+ Git.open(cloned_path).pull
23
+ Ingest::UpdateSuccess.new
24
+ rescue ArgumentError, Git::GitExecuteError => e
25
+ case e.message
26
+ when /overwritten by merge/
27
+ Ingest::UpdateFailure.new('merge error')
28
+ when /path does not exist/
29
+ Ingest::UpdateFailure.new('not found')
30
+ else
31
+ raise
32
+ end
33
+ end
34
+
35
+ def read_file(filename, from_repo: nil, checkout: 'master')
36
+ Dir.mktmpdir do |dir|
37
+ path = Pathname(dir)
38
+ git = _clone(from_repo, temp_name("read-file"), path)
39
+ git.checkout(checkout)
40
+ path.join(temp_name("read-file"), filename).read
41
+ end
42
+ end
43
+
44
+ def remote_tag(url, tagname, commit_or_object)
45
+ Dir.mktmpdir do |dir|
46
+ path = Pathname(dir)
47
+ git = _clone(url, temp_name("tag"), path)
48
+ git.config('user.name', 'Bookbinder')
49
+ git.config('user.email', 'bookbinder@cloudfoundry.org')
50
+ begin
51
+ git.add_tag(tagname, "origin/#{commit_or_object}",
52
+ message: 'Tagged by Bookbinder')
53
+ rescue Git::GitExecuteError => e
54
+ case e.message
55
+ when /already exists/
56
+ raise TagExists
57
+ when /as a valid ref/
58
+ raise InvalidTagRef
59
+ else
60
+ raise
61
+ end
62
+ end
63
+ git.push("origin", "master", tags: true)
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ attr_reader :cache
70
+
71
+ def temp_name(purpose)
72
+ "bookbinder-git-accessor-#{purpose}"
73
+ end
74
+
75
+ def cached_clone(url, name, path)
76
+ cache[[url, name, path]] ||= _clone(url, name, path)
77
+ end
78
+
79
+ def _clone(url, name, path)
80
+ Git.clone(url, name, path: path)
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,15 @@
1
+ module Bookbinder
2
+ module Ingest
3
+ class UpdateFailure
4
+ attr_reader :reason
5
+
6
+ def initialize(reason)
7
+ @reason = reason
8
+ end
9
+
10
+ def success?
11
+ false
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,12 @@
1
+ module Bookbinder
2
+ module Ingest
3
+ class UpdateSuccess
4
+ def reason
5
+ end
6
+
7
+ def success?
8
+ true
9
+ end
10
+ end
11
+ end
12
+ end
@@ -6,8 +6,8 @@ module Bookbinder
6
6
  class SitemapWriter
7
7
  def self.build(logger, final_app_directory, port)
8
8
  new(
9
- Spider.new(logger, app_dir: final_app_directory),
10
- ServerDirector.new(logger, directory: final_app_directory, port: port)
9
+ Spider.new(app_dir: final_app_directory),
10
+ ServerDirector.new(directory: final_app_directory, port: port)
11
11
  )
12
12
  end
13
13
 
@@ -16,9 +16,14 @@ module Bookbinder
16
16
  @server_director = server_director
17
17
  end
18
18
 
19
- def write(host_for_sitemap)
19
+ def write(host_for_sitemap, streams, broken_link_exclusions)
20
20
  server_director.use_server { |port|
21
- spider.generate_sitemap(host_for_sitemap, port)
21
+ spider.generate_sitemap(
22
+ host_for_sitemap,
23
+ port,
24
+ streams,
25
+ broken_link_exclusions: broken_link_exclusions
26
+ )
22
27
  }.tap do |sitemap|
23
28
  File.write(sitemap.to_path, sitemap.to_xml)
24
29
  end
@@ -4,8 +4,7 @@ require 'vienna'
4
4
 
5
5
  module Bookbinder
6
6
  class ServerDirector
7
- def initialize(logger, directory: nil, port: 41722)
8
- @logger = logger
7
+ def initialize(directory: nil, port: 41722)
9
8
  @directory = directory
10
9
  @port = port
11
10
  end
@@ -15,7 +15,7 @@ module Bookbinder
15
15
  end
16
16
 
17
17
  def has_broken_links?
18
- @broken_links.any? { |link| !link.include?('#') }
18
+ @broken_links.any?
19
19
  end
20
20
 
21
21
  def to_xml
@@ -27,46 +27,46 @@ module Bookbinder
27
27
  end
28
28
  end
29
29
 
30
- def initialize(logger, app_dir: nil)
31
- @logger = logger
30
+ def self.prepend_location(location, url)
31
+ "#{URI(location).path} => #{url}"
32
+ end
33
+
34
+ def initialize(app_dir: nil)
32
35
  @app_dir = app_dir || raise('Spiders must be initialized with an app directory.')
33
- @broken_links = []
34
36
  end
35
37
 
36
- def generate_sitemap(target_host, port)
38
+ def generate_sitemap(target_host, port, streams,
39
+ broken_link_exclusions: /(?!.*)/)
37
40
  temp_host = "localhost:#{port}"
38
41
 
39
42
  sieve = Sieve.new domain: "http://#{temp_host}"
40
43
  links = crawl_from "http://#{temp_host}/index.html", sieve
41
44
  broken_links, working_links = links
42
-
43
- announce_broken_links broken_links
44
-
45
45
  sitemap_links = substitute_hostname(temp_host, target_host, working_links)
46
- Result.new(broken_links, SitemapGenerator.new.generate(sitemap_links), @app_dir)
47
- end
48
-
49
- def self.prepend_location(location, url)
50
- "#{URI(location).path} => #{url}"
46
+ public_broken_links = broken_links.reject {|l| l.match(broken_link_exclusions)}
47
+ announce_broken_links(public_broken_links, streams)
48
+ Result.new(
49
+ public_broken_links,
50
+ SitemapGenerator.new.generate(sitemap_links), app_dir
51
+ )
51
52
  end
52
53
 
53
54
  private
54
55
 
55
- def announce_broken_links(broken_links)
56
- if broken_links.any?
57
- @logger.error "\nFound #{broken_links.count} broken links!"
58
-
59
- broken_links.each do |link|
60
- if link.include?('#')
61
- @logger.warn(link)
62
- else
63
- @logger.notify(link)
64
- end
65
- end
56
+ attr_reader :app_dir
66
57
 
67
- @logger.error "\nFound #{broken_links.count} broken links!"
58
+ def announce_broken_links(broken_links, streams)
59
+ if broken_links.none?
60
+ streams[:out].puts "\nNo broken links!"
68
61
  else
69
- @logger.success "\nNo broken links!"
62
+ streams[:err].puts(<<-MESSAGE)
63
+
64
+ Found #{broken_links.count} broken links!
65
+
66
+ #{broken_links.sort.join("\n")}
67
+
68
+ Found #{broken_links.count} broken links!
69
+ MESSAGE
70
70
  end
71
71
  end
72
72
 
@@ -13,6 +13,10 @@ module Bookbinder
13
13
  stream.puts(colorizer.colorize(line, color))
14
14
  end
15
15
 
16
+ def <<(text)
17
+ stream << colorizer.colorize(text, color)
18
+ end
19
+
16
20
  private
17
21
 
18
22
  attr_reader :color, :colorizer, :stream
@@ -70,14 +70,10 @@ module Bookbinder
70
70
  private
71
71
 
72
72
  def subnav_template_name
73
- if current_page.data.index_subnav
74
- current_page.data.index_subnav
75
- else
76
- template_key = decreasingly_specific_namespaces.detect { |ns|
77
- config[:subnav_templates].has_key?(ns)
78
- }
79
- config[:subnav_templates][template_key] || 'default'
80
- end
73
+ template_key = decreasingly_specific_namespaces.detect { |ns|
74
+ config[:subnav_templates].has_key?(ns)
75
+ }
76
+ config[:subnav_templates][template_key] || 'default'
81
77
  end
82
78
 
83
79
  def decreasingly_specific_namespaces
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: 3.1.2
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Grafton
@@ -15,7 +15,7 @@ authors:
15
15
  autorequire:
16
16
  bindir: install_bin
17
17
  cert_chain: []
18
- date: 2015-06-09 00:00:00.000000000 Z
18
+ date: 2015-06-24 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: fog-aws
@@ -311,16 +311,18 @@ files:
311
311
  - lib/bookbinder/dita_html_to_middleman_formatter.rb
312
312
  - lib/bookbinder/errors/cli_error.rb
313
313
  - lib/bookbinder/errors/programmer_mistake.rb
314
- - lib/bookbinder/git_accessor.rb
315
314
  - lib/bookbinder/html_document_manipulator.rb
316
315
  - lib/bookbinder/ingest/cloner_factory.rb
317
316
  - lib/bookbinder/ingest/destination_directory.rb
317
+ - lib/bookbinder/ingest/git_accessor.rb
318
318
  - lib/bookbinder/ingest/git_cloner.rb
319
319
  - lib/bookbinder/ingest/local_filesystem_cloner.rb
320
320
  - lib/bookbinder/ingest/missing_working_copy.rb
321
321
  - lib/bookbinder/ingest/repo_identifier.rb
322
322
  - lib/bookbinder/ingest/section_repository.rb
323
323
  - lib/bookbinder/ingest/section_repository_factory.rb
324
+ - lib/bookbinder/ingest/update_failure.rb
325
+ - lib/bookbinder/ingest/update_success.rb
324
326
  - lib/bookbinder/ingest/working_copy.rb
325
327
  - lib/bookbinder/local_file_system_accessor.rb
326
328
  - lib/bookbinder/middleman_runner.rb
@@ -1,70 +0,0 @@
1
- require 'git'
2
-
3
- module Bookbinder
4
- class GitAccessor
5
- TagExists = Class.new(RuntimeError)
6
- InvalidTagRef = Class.new(RuntimeError)
7
-
8
- def initialize
9
- @cache = {}
10
- end
11
-
12
- def clone(url, name, path: nil, checkout: 'master')
13
- cached_clone(url, name, path).tap do |git|
14
- git.checkout(checkout)
15
- end
16
- end
17
-
18
- def update(cloned_path)
19
- Git.open(cloned_path).pull
20
- end
21
-
22
- def read_file(filename, from_repo: nil, checkout: 'master')
23
- Dir.mktmpdir do |dir|
24
- path = Pathname(dir)
25
- git = _clone(from_repo, temp_name("read-file"), path)
26
- git.checkout(checkout)
27
- path.join(temp_name("read-file"), filename).read
28
- end
29
- end
30
-
31
- def remote_tag(url, tagname, commit_or_object)
32
- Dir.mktmpdir do |dir|
33
- path = Pathname(dir)
34
- git = _clone(url, temp_name("tag"), path)
35
- git.config('user.name', 'Bookbinder')
36
- git.config('user.email', 'bookbinder@cloudfoundry.org')
37
- begin
38
- git.add_tag(tagname, "origin/#{commit_or_object}",
39
- message: 'Tagged by Bookbinder')
40
- rescue Git::GitExecuteError => e
41
- case e.message
42
- when /already exists/
43
- raise TagExists
44
- when /as a valid ref/
45
- raise InvalidTagRef
46
- else
47
- raise
48
- end
49
- end
50
- git.push("origin", "master", tags: true)
51
- end
52
- end
53
-
54
- private
55
-
56
- attr_reader :cache
57
-
58
- def temp_name(purpose)
59
- "bookbinder-git-accessor-#{purpose}"
60
- end
61
-
62
- def cached_clone(url, name, path)
63
- cache[[url, name, path]] ||= _clone(url, name, path)
64
- end
65
-
66
- def _clone(url, name, path)
67
- Git.clone(url, name, path: path)
68
- end
69
- end
70
- end