bookbindery 3.1.2 → 4.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: 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