bookbindery 1.0.3 → 2.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 +4 -4
- data/{bin → install_bin}/bookbinder +0 -0
- data/lib/bookbinder.rb +2 -9
- data/lib/bookbinder/archive.rb +1 -1
- data/lib/bookbinder/archive_menu_configuration.rb +34 -0
- data/lib/bookbinder/book.rb +17 -17
- data/lib/bookbinder/cli.rb +25 -36
- data/lib/bookbinder/code_example.rb +5 -38
- data/lib/bookbinder/code_example_reader.rb +40 -0
- data/lib/bookbinder/colorizer.rb +14 -0
- data/lib/bookbinder/command_runner.rb +9 -16
- data/lib/bookbinder/command_validator.rb +14 -7
- data/lib/bookbinder/commands/bind.rb +321 -0
- data/lib/bookbinder/commands/build_and_push_tarball.rb +7 -6
- data/lib/bookbinder/commands/chain.rb +11 -0
- data/lib/bookbinder/commands/generate_pdf.rb +4 -3
- data/lib/bookbinder/commands/help.rb +49 -10
- data/lib/bookbinder/commands/naming.rb +9 -1
- data/lib/bookbinder/commands/push_local_to_staging.rb +4 -3
- data/lib/bookbinder/commands/push_to_prod.rb +36 -4
- data/lib/bookbinder/commands/run_publish_ci.rb +21 -24
- data/lib/bookbinder/commands/tag.rb +3 -3
- data/lib/bookbinder/commands/update_local_doc_repos.rb +5 -4
- data/lib/bookbinder/commands/version.rb +11 -8
- data/lib/bookbinder/configuration.rb +8 -3
- data/lib/bookbinder/configuration_fetcher.rb +7 -25
- data/lib/bookbinder/configuration_validator.rb +21 -0
- data/lib/bookbinder/distributor.rb +1 -1
- data/lib/bookbinder/dita_html_to_middleman_formatter.rb +37 -0
- data/lib/bookbinder/dita_section.rb +7 -0
- data/lib/bookbinder/dita_section_gatherer.rb +28 -0
- data/lib/bookbinder/git_accessor.rb +17 -0
- data/lib/bookbinder/git_client.rb +10 -7
- data/lib/bookbinder/git_hub_repository.rb +46 -41
- data/lib/bookbinder/local_dita_preprocessor.rb +27 -0
- data/lib/bookbinder/local_dita_to_html_converter.rb +49 -0
- data/lib/bookbinder/local_file_system_accessor.rb +68 -0
- data/lib/bookbinder/middleman_runner.rb +30 -17
- data/lib/bookbinder/publisher.rb +16 -80
- data/lib/bookbinder/remote_yaml_credential_provider.rb +2 -3
- data/lib/bookbinder/repositories/command_repository.rb +156 -0
- data/lib/bookbinder/repositories/section_repository.rb +31 -0
- data/lib/bookbinder/section.rb +5 -67
- data/lib/bookbinder/shell_out.rb +1 -0
- data/lib/bookbinder/sheller.rb +19 -0
- data/lib/bookbinder/sieve.rb +6 -1
- data/lib/bookbinder/terminal.rb +10 -0
- data/lib/bookbinder/user_message.rb +6 -0
- data/lib/bookbinder/user_message_presenter.rb +21 -0
- data/lib/bookbinder/yaml_loader.rb +18 -7
- data/master_middleman/archive_drop_down_menu.rb +46 -0
- data/master_middleman/bookbinder_helpers.rb +47 -40
- metadata +33 -87
- data/lib/bookbinder/commands/publish.rb +0 -138
- data/lib/bookbinder/usage_messenger.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56679c8bf251f348c3dd66d86317c0c848b35706
|
4
|
+
data.tar.gz: e6a280ed228236c2fa381393d5bdeb5f3710f8e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b28159d61a3847f29100709af210253bc25e90ed5770273d4891ea928a24f643f7537832c36e8e3efe2780b5dfdab773b4dd3c41ab994a3ce4c8cddfcedc9cb9
|
7
|
+
data.tar.gz: 3463e88ed1b0044e735c0e0ffd25c572b4258cc0906985f0b74c6bfca47d1e2269895700f4ca07c694c83c2a4ee25268be1c9dd9be2e5c8284cb286564510097
|
File without changes
|
data/lib/bookbinder.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
-
require 'fog'
|
1
|
+
require 'fog/aws'
|
2
2
|
require 'tmpdir'
|
3
3
|
require 'ansi'
|
4
|
-
require 'faraday'
|
5
|
-
require 'faraday_middleware'
|
6
4
|
require 'octokit'
|
7
|
-
require 'padrino-contrib'
|
8
5
|
require 'middleman-syntax'
|
9
6
|
require 'middleman-core/cli'
|
10
7
|
require 'middleman-core/profiling'
|
@@ -14,10 +11,8 @@ require 'vienna'
|
|
14
11
|
require 'popen4'
|
15
12
|
require 'puma'
|
16
13
|
|
17
|
-
#require_relative 'bookbinder/shell_out'
|
18
14
|
require_relative 'bookbinder/bookbinder_logger'
|
19
15
|
require_relative 'bookbinder/git_client'
|
20
|
-
#require_relative 'bookbinder/repository'
|
21
16
|
require_relative 'bookbinder/section'
|
22
17
|
require_relative 'bookbinder/book'
|
23
18
|
require_relative 'bookbinder/code_example'
|
@@ -43,7 +38,7 @@ require_relative 'bookbinder/distributor'
|
|
43
38
|
|
44
39
|
require_relative 'bookbinder/commands/bookbinder_command'
|
45
40
|
require_relative 'bookbinder/commands/build_and_push_tarball'
|
46
|
-
require_relative 'bookbinder/commands/
|
41
|
+
require_relative 'bookbinder/commands/bind'
|
47
42
|
require_relative 'bookbinder/commands/push_local_to_staging'
|
48
43
|
require_relative 'bookbinder/commands/push_to_prod'
|
49
44
|
require_relative 'bookbinder/commands/run_publish_ci'
|
@@ -51,8 +46,6 @@ require_relative 'bookbinder/commands/update_local_doc_repos'
|
|
51
46
|
require_relative 'bookbinder/commands/tag'
|
52
47
|
require_relative 'bookbinder/commands/generate_pdf'
|
53
48
|
|
54
|
-
require_relative 'bookbinder/usage_messenger'
|
55
|
-
|
56
49
|
require_relative 'bookbinder/cli'
|
57
50
|
|
58
51
|
# Finds the project root for both spec & production
|
data/lib/bookbinder/archive.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Bookbinder
|
2
|
+
class ArchiveMenuConfiguration
|
3
|
+
def initialize(loader: nil, config_filename: nil)
|
4
|
+
@loader = loader
|
5
|
+
@config_filename = config_filename
|
6
|
+
end
|
7
|
+
|
8
|
+
def generate(base_config, sections)
|
9
|
+
base_config.merge(
|
10
|
+
archive_menu: root_config(base_config).merge(section_config(sections))
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_reader :loader, :config_filename
|
17
|
+
|
18
|
+
def root_config(base_config)
|
19
|
+
{ '.' => base_config[:archive_menu] }
|
20
|
+
end
|
21
|
+
|
22
|
+
def section_config(sections)
|
23
|
+
sections.reduce({}) {|config, section|
|
24
|
+
config_path = section.path_to_repository.join(config_filename)
|
25
|
+
archive_config = loader.load_key(config_path, 'archive_menu')
|
26
|
+
if archive_config
|
27
|
+
config.merge(section.directory_name => archive_config)
|
28
|
+
else
|
29
|
+
config
|
30
|
+
end
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/bookbinder/book.rb
CHANGED
@@ -4,7 +4,6 @@ require_relative 'directory_helpers'
|
|
4
4
|
module Bookbinder
|
5
5
|
class Book
|
6
6
|
include DirectoryHelperMethods
|
7
|
-
attr_reader :sections
|
8
7
|
|
9
8
|
def self.from_remote(logger: nil, full_name: nil, destination_dir: nil, ref: nil, git_accessor: Git)
|
10
9
|
book = new(logger: logger, full_name: full_name, target_ref: ref, git_accessor: git_accessor)
|
@@ -12,12 +11,23 @@ module Bookbinder
|
|
12
11
|
book
|
13
12
|
end
|
14
13
|
|
15
|
-
def initialize(logger: nil,
|
16
|
-
|
17
|
-
|
14
|
+
def initialize(logger: nil,
|
15
|
+
full_name: nil,
|
16
|
+
target_ref: nil,
|
17
|
+
github_token: nil,
|
18
|
+
sections: [],
|
19
|
+
git_accessor: Git)
|
20
|
+
@section_vcs_repos = sections.map do |section|
|
21
|
+
GitHubRepository.new(logger: logger,
|
22
|
+
full_name: section['repository']['name'],
|
23
|
+
git_accessor: git_accessor)
|
18
24
|
end
|
19
25
|
|
20
|
-
@repository = GitHubRepository.new(logger: logger,
|
26
|
+
@repository = GitHubRepository.new(logger: logger,
|
27
|
+
full_name: full_name,
|
28
|
+
target_ref: target_ref,
|
29
|
+
github_token: github_token,
|
30
|
+
git_accessor: git_accessor)
|
21
31
|
@git_accessor = git_accessor
|
22
32
|
end
|
23
33
|
|
@@ -33,22 +43,12 @@ module Bookbinder
|
|
33
43
|
@repository.directory
|
34
44
|
end
|
35
45
|
|
36
|
-
def get_modification_date_for(file: nil, full_path: nil)
|
37
|
-
git_directory, file_relative_path = full_path.split(output_dir_name+'/')
|
38
|
-
begin
|
39
|
-
git_base_object = Git.open(git_directory)
|
40
|
-
rescue => e
|
41
|
-
raise "Invalid git repository! #{git_directory} is not a .git directory"
|
42
|
-
end
|
43
|
-
@repository.get_modification_date_for(file: file_relative_path, git: git_base_object)
|
44
|
-
end
|
45
|
-
|
46
46
|
def copy_from_remote(destination_dir)
|
47
|
-
@repository.copy_from_remote(destination_dir
|
47
|
+
@repository.copy_from_remote(destination_dir)
|
48
48
|
end
|
49
49
|
|
50
50
|
def tag_self_and_sections_with(tag)
|
51
|
-
(@
|
51
|
+
(@section_vcs_repos + [@repository]).each { |repo| repo.tag_with tag }
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
data/lib/bookbinder/cli.rb
CHANGED
@@ -1,53 +1,42 @@
|
|
1
|
+
require_relative 'colorizer'
|
1
2
|
require_relative 'command_runner'
|
2
|
-
require_relative 'local_file_system_accessor'
|
3
3
|
require_relative 'command_validator'
|
4
|
-
|
5
|
-
require_relative '
|
6
|
-
require_relative '
|
7
|
-
require_relative '
|
8
|
-
require_relative 'commands/version'
|
9
|
-
require_relative 'commands/help'
|
4
|
+
require_relative 'configuration'
|
5
|
+
require_relative 'repositories/command_repository'
|
6
|
+
require_relative 'terminal'
|
7
|
+
require_relative 'user_message_presenter'
|
10
8
|
|
11
9
|
module Bookbinder
|
12
10
|
class Cli
|
13
|
-
FLAGS = [
|
14
|
-
Commands::Version,
|
15
|
-
Commands::Help
|
16
|
-
]
|
17
|
-
|
18
|
-
COMMANDS = [
|
19
|
-
Commands::BuildAndPushTarball,
|
20
|
-
Commands::GeneratePDF,
|
21
|
-
Commands::Publish,
|
22
|
-
Commands::PushLocalToStaging,
|
23
|
-
Commands::PushToProd,
|
24
|
-
Commands::RunPublishCI,
|
25
|
-
Commands::Tag,
|
26
|
-
Commands::UpdateLocalDocRepos,
|
27
|
-
].freeze
|
28
|
-
|
29
11
|
def run(args)
|
30
12
|
command_name = args[0]
|
31
13
|
command_arguments = args[1..-1]
|
32
14
|
|
33
15
|
logger = BookbinderLogger.new
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
16
|
+
commands = Repositories::CommandRepository.new(logger)
|
17
|
+
|
18
|
+
command_validator = CommandValidator.new(commands, commands.help.usage_message)
|
19
|
+
command_runner = CommandRunner.new(logger, commands)
|
20
|
+
command_name = command_name ? command_name : '--help'
|
21
|
+
|
22
|
+
colorizer = Colorizer.new
|
23
|
+
user_message_presenter = UserMessagePresenter.new(colorizer)
|
24
|
+
terminal = Terminal.new
|
25
|
+
|
26
|
+
user_message = command_validator.validate(command_name)
|
27
|
+
if user_message.escalation_type == EscalationType.error
|
28
|
+
error_message = user_message_presenter.get_error(user_message)
|
29
|
+
terminal.update(error_message)
|
30
|
+
return 1
|
31
|
+
elsif user_message.escalation_type == EscalationType.warn
|
32
|
+
warning_message = user_message_presenter.get_warning(user_message)
|
33
|
+
terminal.update(warning_message)
|
34
|
+
end
|
44
35
|
|
45
36
|
begin
|
46
|
-
command_name ? command_validator.validate!(command_name) : command_name = '--help'
|
47
|
-
|
48
37
|
command_runner.run command_name, command_arguments
|
49
38
|
|
50
|
-
rescue Commands::
|
39
|
+
rescue Commands::Bind::VersionUnsupportedError => e
|
51
40
|
logger.error "config.yml at version '#{e.message}' has an unsupported API."
|
52
41
|
1
|
53
42
|
rescue Configuration::CredentialKeyError => e
|
@@ -1,40 +1,7 @@
|
|
1
|
-
require_relative 'section'
|
2
|
-
|
3
1
|
module Bookbinder
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
10
|
-
|
11
|
-
def get_snippet_and_language_at(marker)
|
12
|
-
unless @repository.copied?
|
13
|
-
@repository.announce_skip
|
14
|
-
return ''
|
15
|
-
end
|
16
|
-
|
17
|
-
prepared_snippet_at(marker)
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def prepared_snippet_at(marker)
|
23
|
-
snippet = ''
|
24
|
-
FileUtils.cd(@repository.copied_to) { snippet = scrape_for(marker) }
|
25
|
-
|
26
|
-
raise InvalidSnippet.new(full_name, marker) if snippet.empty?
|
27
|
-
lines = snippet.split("\n")
|
28
|
-
language_match = lines[0].match(/code_snippet #{Regexp.escape(marker)} start (\w+)/)
|
29
|
-
language = language_match[1] if language_match
|
30
|
-
[lines[1..-2].join("\n"), language]
|
31
|
-
end
|
32
|
-
|
33
|
-
def scrape_for(marker)
|
34
|
-
locale = 'LC_CTYPE=C LANG=C' # Quiets 'sed: RE error: illegal byte sequence'
|
35
|
-
result = `#{locale} find . -exec sed -ne '/code_snippet #{marker} start/,/code_snippet #{marker} end/ p' {} \\; 2> /dev/null`
|
36
|
-
result = "" unless result.lines.last && result.lines.last.match(/code_snippet #{marker} end/)
|
37
|
-
result
|
38
|
-
end
|
39
|
-
end
|
2
|
+
CodeExample = Struct.new(:path_to_repository,
|
3
|
+
:full_name,
|
4
|
+
:copied,
|
5
|
+
:destination_dir,
|
6
|
+
:directory_name)
|
40
7
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative '../../lib/bookbinder/bookbinder_logger'
|
2
|
+
|
3
|
+
module Bookbinder
|
4
|
+
class CodeExampleReader
|
5
|
+
class InvalidSnippet < StandardError
|
6
|
+
def initialize(repo, marker)
|
7
|
+
super "Error with marker #{marker.cyan} #{'in'.red} #{repo.cyan}#{'.'.red}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(logger)
|
12
|
+
@logger = logger
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_snippet_and_language_at(marker, path_to_repository, copied, repo_name)
|
16
|
+
unless copied
|
17
|
+
logger.log ' skipping (not found) '.magenta + repo_name
|
18
|
+
return ''
|
19
|
+
end
|
20
|
+
|
21
|
+
snippet = ''
|
22
|
+
FileUtils.cd(path_to_repository) { locale = 'LC_CTYPE=C LANG=C' # Quiets 'sed: RE error: illegal byte sequence'
|
23
|
+
result = `#{locale} find . -exec sed -ne '/code_snippet #{marker} start/,/code_snippet #{marker} end/ p' {} \\; 2> /dev/null`
|
24
|
+
result = "" unless result.lines.last && result.lines.last.match(/code_snippet #{marker} end/)
|
25
|
+
scrape_for_value = result
|
26
|
+
snippet = scrape_for_value }
|
27
|
+
|
28
|
+
raise InvalidSnippet.new(repo_name, marker) if snippet.empty?
|
29
|
+
lines = snippet.split("\n")
|
30
|
+
language_match = lines[0].match(/code_snippet #{Regexp.escape(marker)} start (\w+)/)
|
31
|
+
language = language_match[1] if language_match
|
32
|
+
[lines[1..-2].join("\n"), language]
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :logger
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'ansi/code'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module Bookbinder
|
5
|
+
|
6
|
+
class Colorizer
|
7
|
+
Colors = OpenStruct.new(red: Proc.new { |msg| ANSI.red {msg} },
|
8
|
+
yellow: Proc.new { |msg| ANSI.yellow {msg} })
|
9
|
+
|
10
|
+
def colorize(string, color)
|
11
|
+
color.call string.to_s
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,32 +1,25 @@
|
|
1
1
|
require_relative 'cli_error'
|
2
|
+
require_relative 'local_dita_to_html_converter'
|
3
|
+
require_relative 'sheller'
|
2
4
|
|
3
5
|
module Bookbinder
|
4
6
|
class CommandRunner
|
5
|
-
def initialize(
|
6
|
-
@configuration_fetcher = configuration_fetcher
|
7
|
-
@usage_message = usage_message
|
7
|
+
def initialize(logger, commands)
|
8
8
|
@logger = logger
|
9
9
|
@commands = commands
|
10
10
|
end
|
11
11
|
|
12
12
|
def run(command_name, command_arguments)
|
13
|
-
command = commands.detect { |known_command| known_command.command_name
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
command.new(logger, @configuration_fetcher).run command_arguments
|
19
|
-
end
|
20
|
-
rescue CliError::InvalidArguments
|
21
|
-
logger.log command.usage
|
22
|
-
1
|
23
|
-
end
|
13
|
+
command = commands.detect { |known_command| known_command.command_for?(command_name) }
|
14
|
+
command.run(command_arguments)
|
15
|
+
rescue CliError::InvalidArguments
|
16
|
+
logger.log command.usage
|
17
|
+
1
|
24
18
|
end
|
25
19
|
|
26
20
|
private
|
27
21
|
|
28
|
-
attr_reader :logger, :
|
29
|
-
|
22
|
+
attr_reader :logger, :commands
|
30
23
|
end
|
31
24
|
end
|
32
25
|
|
@@ -1,24 +1,31 @@
|
|
1
1
|
require_relative 'cli_error'
|
2
|
+
require 'ostruct'
|
3
|
+
require_relative 'user_message'
|
2
4
|
|
3
5
|
module Bookbinder
|
4
6
|
class CommandValidator
|
5
|
-
def initialize(
|
6
|
-
@usage_messenger = usage_messenger
|
7
|
+
def initialize(commands, usage_text)
|
7
8
|
@commands = commands
|
8
9
|
@usage_text = usage_text
|
9
10
|
end
|
10
11
|
|
11
|
-
def validate
|
12
|
-
known_command_names = commands.map(&:command_name)
|
12
|
+
def validate command_name
|
13
13
|
command_type = "#{command_name}".match(/^--/) ? 'flag' : 'command'
|
14
|
-
if
|
15
|
-
|
14
|
+
if commands.none? { |command| command.command_for?(command_name) }
|
15
|
+
UserMessage.new "Unrecognized #{command_type} '#{command_name}'\n" + usage_text, EscalationType.error
|
16
|
+
elsif command = commands.find { |command| (command.respond_to? :deprecated_command_for?) &&
|
17
|
+
(command.deprecated_command_for? command_name) }
|
18
|
+
UserMessage.new "Use of #{command_name} is deprecated. " +
|
19
|
+
"The preferred usage is below: \n#{command.usage}",
|
20
|
+
EscalationType.warn
|
21
|
+
else
|
22
|
+
UserMessage.new "Success", EscalationType.success
|
16
23
|
end
|
17
24
|
end
|
18
25
|
|
19
26
|
private
|
20
27
|
|
21
|
-
attr_reader :
|
28
|
+
attr_reader :commands, :usage_text
|
22
29
|
end
|
23
30
|
end
|
24
31
|
|
@@ -0,0 +1,321 @@
|
|
1
|
+
require_relative '../archive_menu_configuration'
|
2
|
+
require_relative '../book'
|
3
|
+
require_relative '../cli_error'
|
4
|
+
require_relative '../directory_helpers'
|
5
|
+
require_relative '../publisher'
|
6
|
+
require_relative '../section'
|
7
|
+
require_relative '../dita_section'
|
8
|
+
require_relative '../dita_section_gatherer'
|
9
|
+
require_relative 'naming'
|
10
|
+
|
11
|
+
module Bookbinder
|
12
|
+
module Commands
|
13
|
+
class Bind
|
14
|
+
VersionUnsupportedError = Class.new(RuntimeError)
|
15
|
+
|
16
|
+
include Bookbinder::DirectoryHelperMethods
|
17
|
+
include Commands::Naming
|
18
|
+
|
19
|
+
def initialize(logger,
|
20
|
+
config_fetcher,
|
21
|
+
archive_menu_config,
|
22
|
+
version_control_system,
|
23
|
+
file_system_accessor,
|
24
|
+
static_site_generator,
|
25
|
+
sitemap_generator,
|
26
|
+
final_app_directory,
|
27
|
+
server_director,
|
28
|
+
context_dir,
|
29
|
+
dita_preprocessor)
|
30
|
+
@logger = logger
|
31
|
+
@config_fetcher = config_fetcher
|
32
|
+
@archive_menu_config = archive_menu_config
|
33
|
+
@version_control_system = version_control_system
|
34
|
+
@file_system_accessor = file_system_accessor
|
35
|
+
@static_site_generator = static_site_generator
|
36
|
+
@sitemap_generator = sitemap_generator
|
37
|
+
@final_app_directory = final_app_directory
|
38
|
+
@server_director = server_director
|
39
|
+
@context_dir = context_dir
|
40
|
+
@dita_preprocessor = dita_preprocessor
|
41
|
+
end
|
42
|
+
|
43
|
+
def usage
|
44
|
+
["bind <local|github> [--verbose]",
|
45
|
+
"Bind the sections specified in config.yml from <local> or <github> into the final_app directory"]
|
46
|
+
end
|
47
|
+
|
48
|
+
def command_for?(test_command_name)
|
49
|
+
%w(bind publish).include?(test_command_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def deprecated_command_for?(command_name)
|
53
|
+
%w(publish).include?(command_name)
|
54
|
+
end
|
55
|
+
|
56
|
+
def run(cli_arguments)
|
57
|
+
raise CliError::InvalidArguments unless arguments_are_valid?(cli_arguments)
|
58
|
+
@section_repository = Repositories::SectionRepository.new(logger)
|
59
|
+
@gem_root = File.expand_path('../../../../', __FILE__)
|
60
|
+
|
61
|
+
@publisher = Publisher.new(logger, sitemap_generator, static_site_generator, server_director, file_system_accessor)
|
62
|
+
|
63
|
+
location = cli_arguments[0]
|
64
|
+
|
65
|
+
output_paths = output_directory_paths(location)
|
66
|
+
publish_config = publish_config(location)
|
67
|
+
@versions = publish_config.fetch(:versions, [])
|
68
|
+
@book_repo = publish_config[:book_repo]
|
69
|
+
|
70
|
+
master_middleman_dir = output_paths.fetch(:master_middleman_dir)
|
71
|
+
output_dir = output_paths.fetch(:output_dir)
|
72
|
+
|
73
|
+
dita_processing_dir = File.join output_dir, 'dita'
|
74
|
+
dita_section_dir = File.join dita_processing_dir, 'dita_sections'
|
75
|
+
dita_processed_dir = File.join dita_processing_dir, 'html_from_dita'
|
76
|
+
formatted_dir = File.join dita_processing_dir, 'site_generator_ready'
|
77
|
+
|
78
|
+
master_dir = File.join output_dir, 'master_middleman'
|
79
|
+
workspace_dir = File.join master_dir, 'source'
|
80
|
+
prepare_directories(final_app_directory,
|
81
|
+
output_dir,
|
82
|
+
workspace_dir,
|
83
|
+
master_middleman_dir,
|
84
|
+
master_dir,
|
85
|
+
dita_processing_dir,
|
86
|
+
formatted_dir)
|
87
|
+
|
88
|
+
dita_section_config_hash = config.dita_sections || {}
|
89
|
+
dita_sections = dita_section_config_hash.map do |dita_section_config|
|
90
|
+
relative_path_to_dita_map = dita_section_config['ditamap_location']
|
91
|
+
full_name = dita_section_config.fetch('repository', {}).fetch('name')
|
92
|
+
target_ref = dita_section_config.fetch('repository', {})['ref']
|
93
|
+
directory = dita_section_config['directory']
|
94
|
+
|
95
|
+
DitaSection.new(nil, relative_path_to_dita_map, full_name, target_ref, directory)
|
96
|
+
end
|
97
|
+
|
98
|
+
if location == 'github'
|
99
|
+
dita_section_gatherer = DitaSectionGatherer.new(version_control_system, logger)
|
100
|
+
final_dita_sections = dita_section_gatherer.gather(dita_sections, to: dita_section_dir)
|
101
|
+
else
|
102
|
+
final_dita_sections = dita_sections.map do |dita_section|
|
103
|
+
relative_path_to_dita_map = dita_section.ditamap_location
|
104
|
+
full_name = dita_section.full_name
|
105
|
+
target_ref = dita_section.target_ref
|
106
|
+
directory = dita_section.directory
|
107
|
+
|
108
|
+
path_to_local_copy = File.join output_paths[:local_repo_dir], directory
|
109
|
+
|
110
|
+
DitaSection.new(path_to_local_copy, relative_path_to_dita_map, full_name, target_ref, directory)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
dita_preprocessor.preprocess final_dita_sections, dita_processed_dir, formatted_dir, workspace_dir
|
115
|
+
|
116
|
+
sections = gather_sections(workspace_dir, output_paths)
|
117
|
+
|
118
|
+
subnavs = subnavs_by_dir_name(sections)
|
119
|
+
|
120
|
+
success = publisher.publish(
|
121
|
+
subnavs,
|
122
|
+
{verbose: cli_arguments.include?('--verbose')},
|
123
|
+
output_paths,
|
124
|
+
archive_menu_config.generate(publish_config, sections)
|
125
|
+
)
|
126
|
+
|
127
|
+
success ? 0 : 1
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
attr_reader :publisher,
|
133
|
+
:version_control_system,
|
134
|
+
:config_fetcher,
|
135
|
+
:archive_menu_config,
|
136
|
+
:logger,
|
137
|
+
:file_system_accessor,
|
138
|
+
:static_site_generator,
|
139
|
+
:final_app_directory,
|
140
|
+
:sitemap_generator,
|
141
|
+
:server_director,
|
142
|
+
:context_dir,
|
143
|
+
:dita_preprocessor
|
144
|
+
|
145
|
+
def gather_sections(workspace, output_paths)
|
146
|
+
config.sections.map do |attributes|
|
147
|
+
|
148
|
+
local_repo_dir = output_paths[:local_repo_dir]
|
149
|
+
vcs_repo =
|
150
|
+
if local_repo_dir
|
151
|
+
GitHubRepository.
|
152
|
+
build_from_local(logger, attributes, local_repo_dir, version_control_system).
|
153
|
+
tap { |repo| repo.copy_from_local(workspace) }
|
154
|
+
else
|
155
|
+
GitHubRepository.
|
156
|
+
build_from_remote(logger, attributes, nil, version_control_system).
|
157
|
+
tap { |repo| repo.copy_from_remote(workspace) }
|
158
|
+
end
|
159
|
+
|
160
|
+
@section_repository.get_instance(attributes,
|
161
|
+
vcs_repo: vcs_repo,
|
162
|
+
destination_dir: workspace,
|
163
|
+
build: ->(*args) { Section.new(*args) })
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def prepare_directories(final_app,
|
168
|
+
output_dir,
|
169
|
+
middleman_source,
|
170
|
+
master_middleman_dir,
|
171
|
+
middleman_dir,
|
172
|
+
dita_processing_dir,
|
173
|
+
formatted_dir)
|
174
|
+
forget_sections(output_dir)
|
175
|
+
file_system_accessor.remove_directory File.join final_app, '.'
|
176
|
+
file_system_accessor.remove_directory dita_processing_dir
|
177
|
+
file_system_accessor.make_directory output_dir
|
178
|
+
file_system_accessor.make_directory formatted_dir
|
179
|
+
file_system_accessor.make_directory File.join dita_processing_dir, 'dita_sections'
|
180
|
+
file_system_accessor.make_directory File.join final_app, 'public'
|
181
|
+
file_system_accessor.make_directory middleman_source
|
182
|
+
|
183
|
+
copy_directory_from_gem 'template_app', final_app
|
184
|
+
copy_directory_from_gem 'master_middleman', middleman_dir
|
185
|
+
file_system_accessor.copy File.join(master_middleman_dir, '.'), middleman_dir
|
186
|
+
|
187
|
+
copy_version_master_middleman(middleman_source)
|
188
|
+
end
|
189
|
+
|
190
|
+
def forget_sections(middleman_scratch)
|
191
|
+
file_system_accessor.remove_directory File.join middleman_scratch, '.'
|
192
|
+
end
|
193
|
+
|
194
|
+
def copy_directory_from_gem(dir, output_dir)
|
195
|
+
file_system_accessor.copy File.join(@gem_root, "#{dir}/."), output_dir
|
196
|
+
end
|
197
|
+
|
198
|
+
# Copy the index file from each version into the version's directory. Because version
|
199
|
+
# subdirectories are sections, this is the only way they get content from their master
|
200
|
+
# middleman directory.
|
201
|
+
def copy_version_master_middleman(dest_dir)
|
202
|
+
@versions.each do |version|
|
203
|
+
Dir.mktmpdir(version) do |tmpdir|
|
204
|
+
book = Book.from_remote(logger: logger,
|
205
|
+
full_name: @book_repo,
|
206
|
+
destination_dir: tmpdir,
|
207
|
+
ref: version,
|
208
|
+
git_accessor: version_control_system)
|
209
|
+
index_source_dir = File.join(tmpdir, book.directory, 'master_middleman', source_dir_name)
|
210
|
+
index_dest_dir = File.join(dest_dir, version)
|
211
|
+
file_system_accessor.make_directory(index_dest_dir)
|
212
|
+
|
213
|
+
Dir.glob(File.join(index_source_dir, 'index.*')) do |f|
|
214
|
+
file_system_accessor.copy(File.expand_path(f), index_dest_dir)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def output_directory_paths(location)
|
221
|
+
local_repo_dir = (location == 'local') ? File.expand_path('..', context_dir) : nil
|
222
|
+
|
223
|
+
{
|
224
|
+
final_app_dir: final_app_directory,
|
225
|
+
local_repo_dir: local_repo_dir,
|
226
|
+
output_dir: File.join(context_dir, output_dir_name),
|
227
|
+
master_middleman_dir: layout_repo_path(local_repo_dir)
|
228
|
+
}
|
229
|
+
end
|
230
|
+
|
231
|
+
def publish_config(location)
|
232
|
+
arguments = {
|
233
|
+
sections: config.sections,
|
234
|
+
book_repo: config.book_repo,
|
235
|
+
host_for_sitemap: config.public_host,
|
236
|
+
archive_menu: config.archive_menu
|
237
|
+
}
|
238
|
+
|
239
|
+
optional_arguments = {}
|
240
|
+
optional_arguments.merge!(template_variables: config.template_variables) if config.respond_to?(:template_variables)
|
241
|
+
if publishing_to_github? location
|
242
|
+
config.versions.each { |version| arguments[:sections].concat sections_from version }
|
243
|
+
optional_arguments.merge!(versions: config.versions)
|
244
|
+
end
|
245
|
+
|
246
|
+
arguments.merge! optional_arguments
|
247
|
+
end
|
248
|
+
|
249
|
+
def config
|
250
|
+
config_fetcher.fetch_config
|
251
|
+
end
|
252
|
+
|
253
|
+
def sections_from(version)
|
254
|
+
Dir.mktmpdir('book_checkout') do |temp_workspace|
|
255
|
+
book = Book.from_remote(logger: logger,
|
256
|
+
full_name: config.book_repo,
|
257
|
+
destination_dir: temp_workspace,
|
258
|
+
ref: version,
|
259
|
+
git_accessor: version_control_system,
|
260
|
+
)
|
261
|
+
|
262
|
+
book_checkout_value = File.join temp_workspace, book.directory
|
263
|
+
config_file = File.join book_checkout_value, 'config.yml'
|
264
|
+
attrs = YAML.load(File.read(config_file))['sections']
|
265
|
+
raise VersionUnsupportedError.new(version) if attrs.nil?
|
266
|
+
|
267
|
+
attrs.map do |section_hash|
|
268
|
+
section_hash['repository']['ref'] = version
|
269
|
+
section_hash['directory'] = File.join(version, section_hash['directory'])
|
270
|
+
section_hash
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def layout_repo_path(local_repo_dir)
|
276
|
+
if config.has_option?('layout_repo')
|
277
|
+
if local_repo_dir
|
278
|
+
File.join(local_repo_dir, config.layout_repo.split('/').last)
|
279
|
+
else
|
280
|
+
section = {'repository' => {'name' => config.layout_repo}}
|
281
|
+
destination_dir = Dir.mktmpdir
|
282
|
+
repository = GitHubRepository.build_from_remote(logger,
|
283
|
+
section,
|
284
|
+
'master',
|
285
|
+
version_control_system)
|
286
|
+
repository.copy_from_remote(destination_dir)
|
287
|
+
if repository
|
288
|
+
File.join(destination_dir, repository.directory)
|
289
|
+
else
|
290
|
+
raise 'failed to fetch repository'
|
291
|
+
end
|
292
|
+
end
|
293
|
+
else
|
294
|
+
File.absolute_path('master_middleman')
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def arguments_are_valid?(arguments)
|
299
|
+
return false unless arguments.any?
|
300
|
+
verbose = arguments[1] && arguments[1..-1].include?('--verbose')
|
301
|
+
tag_provided = arguments[1] && (arguments[1..-1] - ['--verbose']).any?
|
302
|
+
nothing_special = arguments[1..-1].empty?
|
303
|
+
|
304
|
+
%w(local github).include?(arguments[0]) && (tag_provided || verbose || nothing_special)
|
305
|
+
end
|
306
|
+
|
307
|
+
def publishing_to_github?(publish_location)
|
308
|
+
config.has_option?('versions') && publish_location != 'local'
|
309
|
+
end
|
310
|
+
|
311
|
+
def subnavs_by_dir_name(sections)
|
312
|
+
sections.reduce({}) do |subnavs, section|
|
313
|
+
namespace = section.directory.gsub('/', '_')
|
314
|
+
template = section.subnav_template || 'default'
|
315
|
+
|
316
|
+
subnavs.merge(namespace => template)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|