bookbindery 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/bookbinder +6 -0
- data/lib/bookbinder.rb +59 -0
- data/lib/bookbinder/app_fetcher.rb +40 -0
- data/lib/bookbinder/archive.rb +95 -0
- data/lib/bookbinder/artifact_namer.rb +22 -0
- data/lib/bookbinder/blue_green_app.rb +27 -0
- data/lib/bookbinder/book.rb +54 -0
- data/lib/bookbinder/bookbinder_logger.rb +33 -0
- data/lib/bookbinder/cf_command_runner.rb +114 -0
- data/lib/bookbinder/cf_routes.rb +19 -0
- data/lib/bookbinder/cli.rb +68 -0
- data/lib/bookbinder/cli_error.rb +6 -0
- data/lib/bookbinder/code_example.rb +40 -0
- data/lib/bookbinder/command_runner.rb +32 -0
- data/lib/bookbinder/command_validator.rb +24 -0
- data/lib/bookbinder/commands/bookbinder_command.rb +18 -0
- data/lib/bookbinder/commands/build_and_push_tarball.rb +31 -0
- data/lib/bookbinder/commands/generate_pdf.rb +140 -0
- data/lib/bookbinder/commands/help.rb +31 -0
- data/lib/bookbinder/commands/naming.rb +9 -0
- data/lib/bookbinder/commands/publish.rb +138 -0
- data/lib/bookbinder/commands/push_local_to_staging.rb +35 -0
- data/lib/bookbinder/commands/push_to_prod.rb +35 -0
- data/lib/bookbinder/commands/run_publish_ci.rb +42 -0
- data/lib/bookbinder/commands/tag.rb +31 -0
- data/lib/bookbinder/commands/update_local_doc_repos.rb +27 -0
- data/lib/bookbinder/commands/version.rb +25 -0
- data/lib/bookbinder/configuration.rb +163 -0
- data/lib/bookbinder/configuration_fetcher.rb +55 -0
- data/lib/bookbinder/configuration_validator.rb +162 -0
- data/lib/bookbinder/css_link_checker.rb +64 -0
- data/lib/bookbinder/directory_helpers.rb +15 -0
- data/lib/bookbinder/distributor.rb +69 -0
- data/lib/bookbinder/git_client.rb +63 -0
- data/lib/bookbinder/git_hub_repository.rb +151 -0
- data/lib/bookbinder/local_file_system_accessor.rb +9 -0
- data/lib/bookbinder/middleman_runner.rb +86 -0
- data/lib/bookbinder/pdf_generator.rb +73 -0
- data/lib/bookbinder/publisher.rb +125 -0
- data/lib/bookbinder/pusher.rb +34 -0
- data/lib/bookbinder/remote_yaml_credential_provider.rb +21 -0
- data/lib/bookbinder/section.rb +78 -0
- data/lib/bookbinder/server_director.rb +53 -0
- data/lib/bookbinder/shell_out.rb +19 -0
- data/lib/bookbinder/sieve.rb +62 -0
- data/lib/bookbinder/sitemap_generator.rb +19 -0
- data/lib/bookbinder/spider.rb +91 -0
- data/lib/bookbinder/stabilimentum.rb +59 -0
- data/lib/bookbinder/usage_messenger.rb +33 -0
- data/lib/bookbinder/yaml_loader.rb +22 -0
- data/master_middleman/bookbinder_helpers.rb +133 -0
- data/master_middleman/config.rb +23 -0
- data/master_middleman/quicklinks_renderer.rb +78 -0
- data/master_middleman/submodule_aware_assets.rb +45 -0
- data/template_app/Gemfile +7 -0
- data/template_app/Gemfile.lock +20 -0
- data/template_app/app.rb +3 -0
- data/template_app/config.ru +9 -0
- data/template_app/lib/rack_static.rb +19 -0
- data/template_app/lib/vienna_application.rb +26 -0
- metadata +462 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
module Bookbinder
|
2
|
+
class CfRoutes
|
3
|
+
def initialize(raw_routes)
|
4
|
+
@raw_routes = raw_routes
|
5
|
+
end
|
6
|
+
|
7
|
+
def apps_by_host_and_domain
|
8
|
+
@apps_by_host_and_domain ||= Hash[
|
9
|
+
raw_routes.lines[3..-1].
|
10
|
+
map { |line| line.split(/\s+/, 3) }.
|
11
|
+
map { |item| [item[0..1], item[2].split(',').map(&:strip)] }
|
12
|
+
]
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
attr_reader :raw_routes
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require_relative 'command_runner'
|
2
|
+
require_relative 'local_file_system_accessor'
|
3
|
+
require_relative 'command_validator'
|
4
|
+
|
5
|
+
require_relative 'commands/build_and_push_tarball'
|
6
|
+
require_relative 'commands/generate_pdf'
|
7
|
+
require_relative 'commands/publish'
|
8
|
+
require_relative 'commands/version'
|
9
|
+
require_relative 'commands/help'
|
10
|
+
|
11
|
+
module Bookbinder
|
12
|
+
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
|
+
def run(args)
|
30
|
+
command_name = args[0]
|
31
|
+
command_arguments = args[1..-1]
|
32
|
+
|
33
|
+
logger = BookbinderLogger.new
|
34
|
+
yaml_loader = YAMLLoader.new
|
35
|
+
local_file_system_accessor = LocalFileSystemAccessor.new
|
36
|
+
configuration_validator = ConfigurationValidator.new(logger, local_file_system_accessor)
|
37
|
+
configuration_fetcher = ConfigurationFetcher.new(logger, configuration_validator, yaml_loader)
|
38
|
+
configuration_fetcher.set_config_file_path './config.yml'
|
39
|
+
usage_messenger = UsageMessenger.new
|
40
|
+
usage_message = usage_messenger.construct_for(COMMANDS, FLAGS)
|
41
|
+
command_validator = CommandValidator.new usage_messenger, COMMANDS + FLAGS, usage_message
|
42
|
+
|
43
|
+
command_runner = CommandRunner.new(configuration_fetcher, usage_message, logger, COMMANDS + FLAGS)
|
44
|
+
|
45
|
+
begin
|
46
|
+
command_name ? command_validator.validate!(command_name) : command_name = '--help'
|
47
|
+
|
48
|
+
command_runner.run command_name, command_arguments
|
49
|
+
|
50
|
+
rescue Commands::Publish::VersionUnsupportedError => e
|
51
|
+
logger.error "config.yml at version '#{e.message}' has an unsupported API."
|
52
|
+
1
|
53
|
+
rescue Configuration::CredentialKeyError => e
|
54
|
+
logger.error "#{e.message}, in credentials.yml"
|
55
|
+
1
|
56
|
+
rescue KeyError => e
|
57
|
+
logger.error "#{e.message} from your configuration."
|
58
|
+
1
|
59
|
+
rescue CliError::UnknownCommand => e
|
60
|
+
logger.log e.message
|
61
|
+
1
|
62
|
+
rescue RuntimeError => e
|
63
|
+
logger.error e.message
|
64
|
+
1
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative 'section'
|
2
|
+
|
3
|
+
module Bookbinder
|
4
|
+
class CodeExample < Section
|
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 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
|
40
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative 'cli_error'
|
2
|
+
|
3
|
+
module Bookbinder
|
4
|
+
class CommandRunner
|
5
|
+
def initialize(configuration_fetcher, usage_message, logger, commands)
|
6
|
+
@configuration_fetcher = configuration_fetcher
|
7
|
+
@usage_message = usage_message
|
8
|
+
@logger = logger
|
9
|
+
@commands = commands
|
10
|
+
end
|
11
|
+
|
12
|
+
def run(command_name, command_arguments)
|
13
|
+
command = commands.detect { |known_command| known_command.command_name == command_name }
|
14
|
+
begin
|
15
|
+
if command_name == '--help'
|
16
|
+
command.new(logger, usage_message).run command_arguments
|
17
|
+
else
|
18
|
+
command.new(logger, @configuration_fetcher).run command_arguments
|
19
|
+
end
|
20
|
+
rescue CliError::InvalidArguments
|
21
|
+
logger.log command.usage
|
22
|
+
1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :logger, :usage_message, :commands
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative 'cli_error'
|
2
|
+
|
3
|
+
module Bookbinder
|
4
|
+
class CommandValidator
|
5
|
+
def initialize(usage_messenger, commands, usage_text)
|
6
|
+
@usage_messenger = usage_messenger
|
7
|
+
@commands = commands
|
8
|
+
@usage_text = usage_text
|
9
|
+
end
|
10
|
+
|
11
|
+
def validate! command_name
|
12
|
+
known_command_names = commands.map(&:command_name)
|
13
|
+
command_type = "#{command_name}".match(/^--/) ? 'flag' : 'command'
|
14
|
+
if !known_command_names.include?(command_name)
|
15
|
+
raise CliError::UnknownCommand.new "Unrecognized #{command_type} '#{command_name}'\n" + usage_text
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :usage_messenger, :commands, :usage_text
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Bookbinder
|
2
|
+
module Commands
|
3
|
+
class BookbinderCommand
|
4
|
+
def initialize(logger, configuration_fetcher)
|
5
|
+
@logger = logger
|
6
|
+
@configuration_fetcher = configuration_fetcher
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def config
|
12
|
+
@config ||= configuration_fetcher.fetch_config
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :configuration_fetcher
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative 'naming'
|
2
|
+
require_relative 'bookbinder_command'
|
3
|
+
require_relative '../archive'
|
4
|
+
|
5
|
+
module Bookbinder
|
6
|
+
module Commands
|
7
|
+
class BuildAndPushTarball < BookbinderCommand
|
8
|
+
extend Commands::Naming
|
9
|
+
|
10
|
+
class MissingBuildNumber < StandardError
|
11
|
+
def initialize
|
12
|
+
super 'You must set $BUILD_NUMBER to push an identifiable build.'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.usage
|
17
|
+
"build_and_push_tarball \t \t \t Create a tarball from the final_app directory and push to the S3 bucket specified in your credentials.yml"
|
18
|
+
end
|
19
|
+
|
20
|
+
def run(_)
|
21
|
+
raise MissingBuildNumber unless ENV['BUILD_NUMBER']
|
22
|
+
config = configuration_fetcher.fetch_config
|
23
|
+
aws_credentials = config.aws_credentials
|
24
|
+
repository = Archive.new(logger: @logger, key: aws_credentials.access_key, secret: aws_credentials.secret_key)
|
25
|
+
repository.create_and_upload_tarball(build_number: ENV['BUILD_NUMBER'], bucket: aws_credentials.green_builds_bucket,
|
26
|
+
namespace: GitHubRepository.new(logger: @logger, full_name: config.book_repo).short_name)
|
27
|
+
0
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require_relative '../pdf_generator'
|
2
|
+
require_relative '../server_director'
|
3
|
+
require_relative 'bookbinder_command'
|
4
|
+
require_relative 'naming'
|
5
|
+
|
6
|
+
module Bookbinder
|
7
|
+
module Commands
|
8
|
+
class GeneratePDF < BookbinderCommand
|
9
|
+
extend Commands::Naming
|
10
|
+
|
11
|
+
class AppNotPublished < StandardError
|
12
|
+
def initialize(msg='You must publish locally before you generate a PDF.')
|
13
|
+
super(msg)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class PDFConfigMissing < StandardError
|
18
|
+
def initialize(file)
|
19
|
+
super("PDF config file '#{file}' does not exist.")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class PDFOptionMissing < StandardError
|
24
|
+
def initialize(msg='No PDF options provided in config.yml')
|
25
|
+
super(msg)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class IncompletePDFConfig < StandardError
|
30
|
+
def initialize(file:nil, key:nil)
|
31
|
+
super("#{file} is missing required key '#{key}'")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.usage
|
36
|
+
"generate_pdf [<file_name>.yml] \t \t Generate a PDF from the files specified in <file_name.yml>"
|
37
|
+
end
|
38
|
+
|
39
|
+
def run(params)
|
40
|
+
raise AppNotPublished unless Dir.exists?('final_app')
|
41
|
+
|
42
|
+
@pdf_config_file = find_pdf_config_file(params)
|
43
|
+
|
44
|
+
ServerDirector.new(@logger, directory: 'final_app').use_server { |port| capture_pages_into_pdf_at(port) }
|
45
|
+
0
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_pdf_config_file(params)
|
49
|
+
if params.first
|
50
|
+
pdf_config_file = File.expand_path(params.first)
|
51
|
+
raise PDFConfigMissing, File.basename(pdf_config_file) unless File.exists?(pdf_config_file)
|
52
|
+
pdf_config_file
|
53
|
+
else
|
54
|
+
@logger.warn "Declaring PDF options in config.yml is deprecated.\nDeclare them in a PDF config file, instead, and target that file when you re-invoke bookbinder.\ne.g. bookbinder generate_pdf theGoodParts.yml"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def capture_pages_into_pdf_at(port)
|
61
|
+
local_host = "localhost:#{port}"
|
62
|
+
header = pdf_options.fetch('header') { raise IncompletePDFConfig, {file: @pdf_config_file, key: :header} }
|
63
|
+
|
64
|
+
output_filename = get_output_file_name
|
65
|
+
urls_to_capture = get_urls_to_capture(local_host)
|
66
|
+
|
67
|
+
PdfGenerator.new(@logger).generate(urls_to_capture, output_filename, "http://#{local_host}/#{header}", pdf_options['copyright_notice'])
|
68
|
+
end
|
69
|
+
|
70
|
+
def pdf_options
|
71
|
+
@pdf_options ||= @pdf_config_file ? YAML.load(File.read(@pdf_config_file)) : main_config_pdf_options
|
72
|
+
end
|
73
|
+
|
74
|
+
def main_config_pdf_options
|
75
|
+
raise PDFOptionMissing unless config.has_option?('pdf')
|
76
|
+
{
|
77
|
+
'filename' => config.pdf.fetch('filename'),
|
78
|
+
'header' => config.pdf.fetch('header')
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_output_file_name
|
83
|
+
if @pdf_config_file
|
84
|
+
File.basename(@pdf_config_file).gsub(/yml/, 'pdf')
|
85
|
+
else
|
86
|
+
pdf_options.fetch('filename')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_urls_to_capture(local_host)
|
91
|
+
if @pdf_config_file
|
92
|
+
pages = pdf_options.fetch('pages')
|
93
|
+
return expand_urls(pages, local_host) if any_include_wildcard?(pages)
|
94
|
+
pages.map { |l| "http://#{local_host}/#{l}" }
|
95
|
+
else
|
96
|
+
sitemap_links(local_host)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def any_include_wildcard?(pages)
|
101
|
+
pages.each do |page|
|
102
|
+
return true if page.include?('*')
|
103
|
+
end
|
104
|
+
false
|
105
|
+
end
|
106
|
+
|
107
|
+
def expand_urls(pages, local_host)
|
108
|
+
final_pages = []
|
109
|
+
pages.each do |page|
|
110
|
+
if page.include?('*')
|
111
|
+
matching_pages = find_matching_files_in_directory(page, local_host)
|
112
|
+
final_pages += matching_pages
|
113
|
+
else
|
114
|
+
final_pages << "http://#{local_host}/#{page}"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
final_pages
|
118
|
+
end
|
119
|
+
|
120
|
+
def find_matching_files_in_directory(wildcard_page, local_host)
|
121
|
+
wildcard_path = wildcard_page.gsub('*','')
|
122
|
+
possible_links = sitemap_links(local_host)
|
123
|
+
possible_links.select { |link| URI(link).path.match(/^\/#{Regexp.escape(wildcard_path)}/)}
|
124
|
+
end
|
125
|
+
|
126
|
+
def sitemap_links(local_host)
|
127
|
+
raw_links = Nokogiri::XML(sitemap).css('loc').map &:inner_html
|
128
|
+
deployed_host = URI(raw_links[0]).host
|
129
|
+
|
130
|
+
deployed_host ?
|
131
|
+
raw_links.map { |l| l.gsub(/#{Regexp.escape(deployed_host)}/, local_host) } :
|
132
|
+
raw_links.map { |l| "http://#{local_host}/#{l}" }
|
133
|
+
end
|
134
|
+
|
135
|
+
def sitemap
|
136
|
+
File.read File.join('public', 'sitemap.xml')
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Bookbinder
|
2
|
+
module Commands
|
3
|
+
class Help
|
4
|
+
def initialize(logger, usage_message)
|
5
|
+
@logger = logger
|
6
|
+
@usage_message = usage_message
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_s
|
10
|
+
'help'
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.command_name
|
14
|
+
'--help'
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.usage
|
18
|
+
"--help \t \t \t \t \t Print this message"
|
19
|
+
end
|
20
|
+
|
21
|
+
def run(*)
|
22
|
+
logger.log(usage_message)
|
23
|
+
0
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :logger, :usage_message
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require_relative '../book'
|
2
|
+
require_relative '../cli_error'
|
3
|
+
require_relative '../configuration'
|
4
|
+
require_relative '../directory_helpers'
|
5
|
+
require_relative '../middleman_runner'
|
6
|
+
require_relative '../publisher'
|
7
|
+
require_relative '../spider'
|
8
|
+
require_relative 'bookbinder_command'
|
9
|
+
require_relative 'naming'
|
10
|
+
|
11
|
+
module Bookbinder
|
12
|
+
module Commands
|
13
|
+
class Publish < BookbinderCommand
|
14
|
+
VersionUnsupportedError = Class.new(StandardError)
|
15
|
+
|
16
|
+
include Bookbinder::DirectoryHelperMethods
|
17
|
+
extend Commands::Naming
|
18
|
+
|
19
|
+
def self.usage
|
20
|
+
"publish <local|github> [--verbose] \t Bind the sections specified in config.yml from <local> or <github> into the final_app directory"
|
21
|
+
end
|
22
|
+
|
23
|
+
def run(cli_arguments, git_accessor=Git)
|
24
|
+
raise CliError::InvalidArguments unless arguments_are_valid?(cli_arguments)
|
25
|
+
@git_accessor = git_accessor
|
26
|
+
|
27
|
+
final_app_dir = File.absolute_path('final_app')
|
28
|
+
bind_book(cli_arguments, final_app_dir)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def bind_book(cli_arguments, final_app_dir)
|
34
|
+
generate_site_etc(cli_arguments, final_app_dir)
|
35
|
+
end
|
36
|
+
|
37
|
+
def generate_site_etc(cli_args, final_app_dir, target_tag=nil)
|
38
|
+
# TODO: general solution to turn all string keys to symbols
|
39
|
+
verbosity = cli_args.include?('--verbose')
|
40
|
+
location = cli_args[0]
|
41
|
+
|
42
|
+
cli_options = { verbose: verbosity, target_tag: target_tag }
|
43
|
+
output_paths = output_directory_paths(location, final_app_dir)
|
44
|
+
publish_config = publish_config(location)
|
45
|
+
spider = Spider.new(@logger, app_dir: final_app_dir)
|
46
|
+
static_site_generator = MiddlemanRunner.new(@logger)
|
47
|
+
|
48
|
+
success = Publisher.new(@logger, spider, static_site_generator).publish(cli_options, output_paths, publish_config, @git_accessor)
|
49
|
+
success ? 0 : 1
|
50
|
+
end
|
51
|
+
|
52
|
+
def output_directory_paths(location, final_app_dir)
|
53
|
+
local_repo_dir = (location == 'local') ? File.absolute_path('..') : nil
|
54
|
+
|
55
|
+
{
|
56
|
+
final_app_dir: final_app_dir,
|
57
|
+
local_repo_dir: local_repo_dir,
|
58
|
+
output_dir: File.absolute_path(output_dir_name),
|
59
|
+
master_middleman_dir: layout_repo_path(local_repo_dir)
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
def publish_config(location)
|
64
|
+
arguments = {
|
65
|
+
sections: config.sections,
|
66
|
+
book_repo: config.book_repo,
|
67
|
+
host_for_sitemap: config.public_host,
|
68
|
+
archive_menu: config.archive_menu
|
69
|
+
}
|
70
|
+
|
71
|
+
optional_arguments = {}
|
72
|
+
optional_arguments.merge!(template_variables: config.template_variables) if config.respond_to?(:template_variables)
|
73
|
+
if publishing_to_github? location
|
74
|
+
config.versions.each { |version| arguments[:sections].concat sections_from version, @git_accessor }
|
75
|
+
optional_arguments.merge!(versions: config.versions)
|
76
|
+
end
|
77
|
+
|
78
|
+
arguments.merge! optional_arguments
|
79
|
+
end
|
80
|
+
|
81
|
+
def sections_from(version, git_accessor)
|
82
|
+
config_file = File.join book_checkout(version, git_accessor), 'config.yml'
|
83
|
+
attrs = YAML.load(File.read(config_file))['sections']
|
84
|
+
raise VersionUnsupportedError.new(version) if attrs.nil?
|
85
|
+
|
86
|
+
attrs.map do |section_hash|
|
87
|
+
section_hash['repository']['ref'] = version
|
88
|
+
section_hash['directory'] = File.join(version, section_hash['directory'])
|
89
|
+
section_hash
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def book_checkout(ref, git_accessor=Git)
|
94
|
+
temp_workspace = Dir.mktmpdir('book_checkout')
|
95
|
+
book = Book.from_remote(logger: @logger,
|
96
|
+
full_name: config.book_repo,
|
97
|
+
destination_dir: temp_workspace,
|
98
|
+
ref: ref,
|
99
|
+
git_accessor: git_accessor,
|
100
|
+
)
|
101
|
+
|
102
|
+
File.join temp_workspace, book.directory
|
103
|
+
end
|
104
|
+
|
105
|
+
def layout_repo_path(local_repo_dir)
|
106
|
+
if config.has_option?('layout_repo')
|
107
|
+
if local_repo_dir
|
108
|
+
File.join(local_repo_dir, config.layout_repo.split('/').last)
|
109
|
+
else
|
110
|
+
section = {'repository' => {'name' => config.layout_repo}}
|
111
|
+
destination_dir = Dir.mktmpdir
|
112
|
+
repository = GitHubRepository.build_from_remote(@logger, section, destination_dir, 'master', @git_accessor)
|
113
|
+
if repository
|
114
|
+
File.join(destination_dir, repository.directory)
|
115
|
+
else
|
116
|
+
raise 'failed to fetch repository'
|
117
|
+
end
|
118
|
+
end
|
119
|
+
else
|
120
|
+
File.absolute_path('master_middleman')
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def arguments_are_valid?(arguments)
|
125
|
+
return false unless arguments.any?
|
126
|
+
verbose = arguments[1] && arguments[1..-1].include?('--verbose')
|
127
|
+
tag_provided = arguments[1] && (arguments[1..-1] - ['--verbose']).any?
|
128
|
+
nothing_special = arguments[1..-1].empty?
|
129
|
+
|
130
|
+
%w(local github).include?(arguments[0]) && (tag_provided || verbose || nothing_special)
|
131
|
+
end
|
132
|
+
|
133
|
+
def publishing_to_github?(publish_location)
|
134
|
+
config.has_option?('versions') && publish_location != 'local'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|