ascii_binder 0.1.9 → 0.1.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +16 -0
- data/ascii_binder.gemspec +5 -3
- data/bin/asciibinder +53 -44
- data/features/command_help.feature +8 -0
- data/features/command_version.feature +8 -0
- data/features/repo_build.feature +34 -0
- data/features/repo_clean.feature +20 -0
- data/features/repo_clone.feature +22 -0
- data/features/repo_create.feature +13 -0
- data/features/repo_package.feature +15 -0
- data/features/step_definitions/steps.rb +182 -0
- data/features/support/_clone_distro_map.yml +14 -0
- data/features/support/_invalid_distro_map.yml +14 -0
- data/features/support/env.rb +468 -0
- data/features/support/test_distro/.gitignore +9 -0
- data/features/support/test_distro/_distro_map.yml +29 -0
- data/features/support/test_distro/_images/asciibinder-logo-horizontal.png +0 -0
- data/features/support/test_distro/_images/asciibinder_web_logo.svg +125 -0
- data/features/support/test_distro/_images/book_pages_bg.jpg +0 -0
- data/features/support/test_distro/_images/favicon.ico +0 -0
- data/features/support/test_distro/_images/favicon32x32.png +0 -0
- data/features/support/test_distro/_javascripts/.gitkeep +0 -0
- data/features/support/test_distro/_stylesheets/asciibinder.css +568 -0
- data/features/support/test_distro/_templates/_css.html.erb +3 -0
- data/features/support/test_distro/_templates/_nav.html.erb +31 -0
- data/features/support/test_distro/_templates/page.html.erb +92 -0
- data/features/support/test_distro/_topic_map.yml +36 -0
- data/features/support/test_distro/index-main.html +10 -0
- data/features/support/test_distro/index-test.html +10 -0
- data/features/support/test_distro/main_only_topic_group/index.adoc +17 -0
- data/features/support/test_distro/test_only_topic_group/index.adoc +17 -0
- data/features/support/test_distro/welcome/index.adoc +17 -0
- data/features/support/test_distro/welcome/subtopics/index.adoc +17 -0
- data/features/support/test_distro/welcome/subtopics/main_only_topic.adoc +17 -0
- data/features/support/test_distro/welcome/subtopics/test_only_topic.adoc +17 -0
- data/features/support/test_distro/welcome/subtopics/wildcard_all.adoc +17 -0
- data/lib/ascii_binder.rb +4 -2
- data/lib/ascii_binder/distro.rb +111 -0
- data/lib/ascii_binder/distro_branch.rb +93 -0
- data/lib/ascii_binder/distro_map.rb +67 -0
- data/lib/ascii_binder/engine.rb +581 -0
- data/lib/ascii_binder/helpers.rb +42 -856
- data/lib/ascii_binder/site.rb +52 -0
- data/lib/ascii_binder/site_info.rb +22 -0
- data/lib/ascii_binder/site_map.rb +24 -0
- data/lib/ascii_binder/topic_entity.rb +255 -0
- data/lib/ascii_binder/topic_map.rb +61 -0
- data/lib/ascii_binder/version.rb +1 -1
- data/templates/_templates/page.html.erb +1 -1
- metadata +118 -14
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'ascii_binder/distro'
|
2
|
+
require 'trollop'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module AsciiBinder
|
6
|
+
class DistroMap
|
7
|
+
def initialize(distro_map_filepath)
|
8
|
+
@distro_yaml = YAML.load_file(distro_map_filepath)
|
9
|
+
@distro_map = {}
|
10
|
+
@distro_yaml.each do |distro_key,distro_config|
|
11
|
+
if @distro_map.has_key?(distro_key)
|
12
|
+
Trollop::die "Error parsing '#{distro_map_filepath}': distro key '#{distro_key}' is used more than once."
|
13
|
+
end
|
14
|
+
distro = AsciiBinder::Distro.new(distro_map_filepath,distro_key,distro_config)
|
15
|
+
@distro_map[distro_key] = distro
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_distro(distro_key)
|
20
|
+
unless @distro_map.has_key?(distro_key)
|
21
|
+
Trollop::die "Distro key '#{distro_key}' does not exist"
|
22
|
+
end
|
23
|
+
@distro_map[distro_key]
|
24
|
+
end
|
25
|
+
|
26
|
+
def include_distro_key?(distro_key)
|
27
|
+
@distro_map.has_key?(distro_key)
|
28
|
+
end
|
29
|
+
|
30
|
+
def distro_keys
|
31
|
+
@distro_map.keys
|
32
|
+
end
|
33
|
+
|
34
|
+
def distros
|
35
|
+
@distro_map.values
|
36
|
+
end
|
37
|
+
|
38
|
+
def distro_branches(distro_key='')
|
39
|
+
if distro_key == ''
|
40
|
+
branch_list = []
|
41
|
+
distros.each do |distro|
|
42
|
+
branch_list.concat(distro.branch_ids)
|
43
|
+
end
|
44
|
+
return branch_list.uniq
|
45
|
+
else
|
46
|
+
return get_distro(distro_key).branch_ids
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def is_valid?
|
51
|
+
@distro_map.values.each do |distro|
|
52
|
+
next if distro.is_valid?
|
53
|
+
return false
|
54
|
+
end
|
55
|
+
return true
|
56
|
+
end
|
57
|
+
|
58
|
+
def errors
|
59
|
+
errors = []
|
60
|
+
@distro_map.values.each do |distro|
|
61
|
+
next if distro.is_valid?
|
62
|
+
errors << distro.errors
|
63
|
+
end
|
64
|
+
return errors
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,581 @@
|
|
1
|
+
require 'ascii_binder/distro_branch'
|
2
|
+
require 'ascii_binder/distro_map'
|
3
|
+
require 'ascii_binder/helpers'
|
4
|
+
require 'ascii_binder/site_map'
|
5
|
+
require 'ascii_binder/template_renderer'
|
6
|
+
require 'ascii_binder/topic_map'
|
7
|
+
require 'asciidoctor'
|
8
|
+
require 'asciidoctor/cli'
|
9
|
+
require 'asciidoctor-diagram'
|
10
|
+
require 'fileutils'
|
11
|
+
require 'find'
|
12
|
+
require 'git'
|
13
|
+
require 'logger'
|
14
|
+
require 'pandoc-ruby'
|
15
|
+
require 'pathname'
|
16
|
+
require 'sitemap_generator'
|
17
|
+
require 'trollop'
|
18
|
+
require 'yaml'
|
19
|
+
|
20
|
+
include AsciiBinder::Helpers
|
21
|
+
|
22
|
+
module AsciiBinder
|
23
|
+
module Engine
|
24
|
+
|
25
|
+
def build_date
|
26
|
+
Time.now.utc
|
27
|
+
end
|
28
|
+
|
29
|
+
def notice(hey,message,newline = false)
|
30
|
+
# TODO: (maybe) redirect everything to stderr
|
31
|
+
if newline
|
32
|
+
puts "\n"
|
33
|
+
end
|
34
|
+
puts "#{hey}: #{message}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def warning(message,newline = false)
|
38
|
+
notice("WARNING",message,newline)
|
39
|
+
end
|
40
|
+
|
41
|
+
def nl_warning(message)
|
42
|
+
warning(message,true)
|
43
|
+
end
|
44
|
+
|
45
|
+
def git
|
46
|
+
@git ||= Git.open(git_root_dir)
|
47
|
+
end
|
48
|
+
|
49
|
+
def git_checkout branch_name
|
50
|
+
target_branch = git.branches.local.select{ |b| b.name == branch_name }[0]
|
51
|
+
if not target_branch.nil? and not target_branch.current
|
52
|
+
target_branch.checkout
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def git_stash_all
|
57
|
+
# See if there are any changes in need of stashing
|
58
|
+
@stash_needed = `cd #{git_root_dir} && git status --porcelain` !~ /^\s*$/
|
59
|
+
if @stash_needed
|
60
|
+
puts "\nNOTICE: Stashing uncommited changes and files in working branch."
|
61
|
+
`cd #{docs_root_dir} && git stash -u`
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def git_apply_and_drop
|
66
|
+
return unless @stash_needed
|
67
|
+
puts "\nNOTE: Re-applying uncommitted changes and files to working branch."
|
68
|
+
if system("cd #{docs_root_dir} && git stash pop")
|
69
|
+
puts "NOTE: Stash application successful."
|
70
|
+
else
|
71
|
+
puts "ERROR: Could not apply stashed code. Run `git stash apply` manually."
|
72
|
+
end
|
73
|
+
@stash_needed = false
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns the local git branches; current branch is always first
|
77
|
+
def local_branches
|
78
|
+
@local_branches ||= begin
|
79
|
+
branches = []
|
80
|
+
if not git.branches.local.empty?
|
81
|
+
branches << git.branches.local.select{ |b| b.current }[0].name
|
82
|
+
branches << git.branches.local.select{ |b| not b.current }.map{ |b| b.name }
|
83
|
+
end
|
84
|
+
branches.flatten
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def working_branch
|
89
|
+
@working_branch ||= local_branches[0]
|
90
|
+
end
|
91
|
+
|
92
|
+
def dir_empty?(dir)
|
93
|
+
Dir.entries(dir).select{ |f| not f.start_with?('.') }.empty?
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
# Protip: Don't cache these! The topic map needs to be reread every time we change branches.
|
98
|
+
def topic_map_file
|
99
|
+
topic_file = TOPIC_MAP_FILENAME
|
100
|
+
unless File.exist?(File.join(docs_root_dir,topic_file))
|
101
|
+
# The new filename '_topic_map.yml' couldn't be found;
|
102
|
+
# switch to the old one and warn the user.
|
103
|
+
topic_file = BUILD_FILENAME
|
104
|
+
unless File.exist?(File.join(docs_root_dir,topic_file))
|
105
|
+
# Critical error - no topic map file at all.
|
106
|
+
Trollop::die "Could not find any topic map file ('#{TOPIC_MAP_FILENAME}' or '#{BUILD_FILENAME}') at #{docs_root_dir} in branch '#{git.branch}'"
|
107
|
+
end
|
108
|
+
warning "'#{BUILD_FILENAME}' is a deprecated filename. Rename this to '#{TOPIC_MAP_FILENAME}'."
|
109
|
+
end
|
110
|
+
topic_file
|
111
|
+
end
|
112
|
+
|
113
|
+
def topic_map
|
114
|
+
topic_map = AsciiBinder::TopicMap.new(topic_map_file,distro_map.distro_keys)
|
115
|
+
unless topic_map.is_valid?
|
116
|
+
errors = topic_map.errors
|
117
|
+
Trollop::die "The topic map file at '#{topic_map_file}' contains the following errors:\n- " + errors.join("\n- ") + "\n"
|
118
|
+
end
|
119
|
+
return topic_map
|
120
|
+
end
|
121
|
+
|
122
|
+
def create_new_repo
|
123
|
+
gem_template_dir = File.join(gem_root_dir,"templates")
|
124
|
+
|
125
|
+
# Create the new repo dir
|
126
|
+
FileUtils.mkdir_p(docs_root_dir)
|
127
|
+
|
128
|
+
# Copy the basic repo content into the new repo dir
|
129
|
+
Find.find(gem_template_dir).each do |path|
|
130
|
+
next if path == gem_template_dir
|
131
|
+
src_path = Pathname.new(path)
|
132
|
+
tgt_path = src_path.sub(gem_template_dir,docs_root_dir)
|
133
|
+
if src_path.directory?
|
134
|
+
FileUtils.mkdir_p(tgt_path.to_s)
|
135
|
+
else
|
136
|
+
FileUtils.cp src_path.to_s, tgt_path.to_s
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Initialize the git repo
|
141
|
+
Git.init(docs_root_dir)
|
142
|
+
end
|
143
|
+
|
144
|
+
def find_topic_files
|
145
|
+
file_list = []
|
146
|
+
Find.find(docs_root_dir).each do |path|
|
147
|
+
# Only consider .adoc files and ignore README, and anything in
|
148
|
+
# directories whose names begin with 'old' or '_' (underscore)
|
149
|
+
next if path.nil? or not path =~ /.*\.adoc/ or path =~ /README/ or path =~ /\/old\// or path =~ /\/_/
|
150
|
+
src_path = Pathname.new(path).sub(docs_root_dir,'').to_s
|
151
|
+
next if src_path.split('/').length < 3
|
152
|
+
file_list << src_path
|
153
|
+
end
|
154
|
+
file_list.map{ |path|
|
155
|
+
parts = path.split('/').slice(1..-1);
|
156
|
+
parts.slice(0..-2).join('/') + '/' + parts[-1].split('.')[0]
|
157
|
+
}
|
158
|
+
end
|
159
|
+
|
160
|
+
def remove_found_topic_files(branch,branch_topic_map,branch_topic_files)
|
161
|
+
nonexistent_topics = []
|
162
|
+
branch_topic_map.filepaths.each do |topic_map_filepath|
|
163
|
+
result = branch_topic_files.delete(topic_map_filepath)
|
164
|
+
if result.nil?
|
165
|
+
nonexistent_topics << topic_map_filepath
|
166
|
+
end
|
167
|
+
end
|
168
|
+
if nonexistent_topics.length > 0
|
169
|
+
nl_warning "The #{topic_map_file} file on branch '#{branch}' references nonexistent topics:\n" + nonexistent_topics.map{ |topic| "- #{topic}" }.join("\n")
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def distro_map
|
174
|
+
@distro_map ||= begin
|
175
|
+
distro_map_file = File.join(docs_root_dir, DISTRO_MAP_FILENAME)
|
176
|
+
distro_map = AsciiBinder::DistroMap.new(distro_map_file)
|
177
|
+
unless distro_map.is_valid?
|
178
|
+
errors = distro_map.errors
|
179
|
+
Trollop::die "The distro map file at '#{distro_map_file}' contains the following errors:\n- " + errors.join("\n- ") + "\n"
|
180
|
+
end
|
181
|
+
distro_map
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def site_map
|
186
|
+
@site_map ||= AsciiBinder::SiteMap.new(distro_map)
|
187
|
+
end
|
188
|
+
|
189
|
+
def branch_group_branches
|
190
|
+
@branch_group_branches ||= begin
|
191
|
+
group_branches = Hash.new
|
192
|
+
group_branches[:working_only] = [local_branches[0]]
|
193
|
+
group_branches[:publish] = distro_map.distro_branches
|
194
|
+
site_map.sites.each do |site|
|
195
|
+
group_branches["publish_#{site.id}".to_sym] = site.branches
|
196
|
+
end
|
197
|
+
group_branches[:all] = local_branches
|
198
|
+
group_branches
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def page(args)
|
203
|
+
# TODO: This process of rebuilding the entire nav for every page will not scale well.
|
204
|
+
# As the doc set increases, we will need to think about refactoring this.
|
205
|
+
args[:breadcrumb_root], args[:breadcrumb_group], args[:breadcrumb_subgroup], args[:breadcrumb_topic] = extract_breadcrumbs(args)
|
206
|
+
|
207
|
+
args[:breadcrumb_subgroup_block] = ''
|
208
|
+
args[:subtopic_shim] = ''
|
209
|
+
if args[:breadcrumb_subgroup]
|
210
|
+
args[:breadcrumb_subgroup_block] = "<li class=\"hidden-xs active\">#{args[:breadcrumb_subgroup]}</li>"
|
211
|
+
args[:subtopic_shim] = '../'
|
212
|
+
end
|
213
|
+
|
214
|
+
template_path = File.expand_path("#{docs_root_dir}/_templates/page.html.erb")
|
215
|
+
template_renderer.render(template_path, args)
|
216
|
+
end
|
217
|
+
|
218
|
+
def extract_breadcrumbs(args)
|
219
|
+
breadcrumb_root = breadcrumb_group = breadcrumb_subgroup = breadcrumb_topic = nil
|
220
|
+
|
221
|
+
root_group = args[:navigation].first
|
222
|
+
selected_group = args[:navigation].detect { |group| group[:id] == args[:group_id] }
|
223
|
+
selected_subgroup = selected_group[:topics].detect { |subgroup| subgroup[:id] == args[:subgroup_id] }
|
224
|
+
current_is_subtopic = selected_subgroup ? true : false
|
225
|
+
|
226
|
+
if root_group
|
227
|
+
root_topic = root_group[:topics].first
|
228
|
+
breadcrumb_root = linkify_breadcrumb(root_topic[:path], "#{args[:distro]} #{args[:version]}", current_is_subtopic) if root_topic
|
229
|
+
end
|
230
|
+
|
231
|
+
if selected_group
|
232
|
+
group_topic = selected_group[:topics].first
|
233
|
+
breadcrumb_group = linkify_breadcrumb(group_topic[:path], selected_group[:name], current_is_subtopic) if group_topic
|
234
|
+
|
235
|
+
if selected_subgroup
|
236
|
+
subgroup_topic = selected_subgroup[:topics].first
|
237
|
+
breadcrumb_subgroup = linkify_breadcrumb(subgroup_topic[:path], selected_subgroup[:name], current_is_subtopic) if subgroup_topic
|
238
|
+
|
239
|
+
selected_topic = selected_subgroup[:topics].detect { |topic| topic[:id] == args[:topic_id] }
|
240
|
+
breadcrumb_topic = linkify_breadcrumb(nil, selected_topic[:name], current_is_subtopic) if selected_topic
|
241
|
+
else
|
242
|
+
selected_topic = selected_group[:topics].detect { |topic| topic[:id] == args[:topic_id] }
|
243
|
+
breadcrumb_topic = linkify_breadcrumb(nil, selected_topic[:name], current_is_subtopic) if selected_topic
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
return breadcrumb_root, breadcrumb_group, breadcrumb_subgroup, breadcrumb_topic
|
248
|
+
end
|
249
|
+
|
250
|
+
def linkify_breadcrumb(href, text, extra_level)
|
251
|
+
addl_level = extra_level ? '../' : ''
|
252
|
+
href ? "<a href=\"#{addl_level}#{href}\">#{text}</a>" : text
|
253
|
+
end
|
254
|
+
|
255
|
+
def asciidoctor_page_attrs(more_attrs=[])
|
256
|
+
[
|
257
|
+
'source-highlighter=coderay',
|
258
|
+
'coderay-css=style',
|
259
|
+
'linkcss!',
|
260
|
+
'icons=font',
|
261
|
+
'idprefix=',
|
262
|
+
'idseparator=-',
|
263
|
+
'sectanchors',
|
264
|
+
'data-uri',
|
265
|
+
].concat(more_attrs)
|
266
|
+
end
|
267
|
+
|
268
|
+
def generate_docs(branch_group,build_distro,single_page)
|
269
|
+
# First, test to see if the docs repo has any commits. If the user has just
|
270
|
+
# run `asciibinder create`, there will be no commits to work from, yet.
|
271
|
+
if local_branches.empty?
|
272
|
+
raise "Before you can build the docs, you need at least one commit in your docs repo."
|
273
|
+
end
|
274
|
+
|
275
|
+
# Make a filepath in list form from the single_page argument
|
276
|
+
single_page_path = []
|
277
|
+
if not single_page.nil?
|
278
|
+
single_page_path = single_page.split(':')[0].split('/')
|
279
|
+
single_page_path << single_page.split(':')[1]
|
280
|
+
puts "Rebuilding '#{single_page_path.join('/')}' on branch '#{working_branch}'."
|
281
|
+
end
|
282
|
+
|
283
|
+
if not build_distro == ''
|
284
|
+
if not distro_map.include_distro_key?(build_distro)
|
285
|
+
exit
|
286
|
+
else
|
287
|
+
puts "Building only the #{distro_map.get_distro(build_distro).name} distribution."
|
288
|
+
end
|
289
|
+
elsif single_page.nil?
|
290
|
+
puts "Building all distributions."
|
291
|
+
end
|
292
|
+
|
293
|
+
# Notify the user of missing local branches
|
294
|
+
missing_branches = []
|
295
|
+
distro_map.distro_branches(build_distro).sort.each do |dbranch|
|
296
|
+
next if local_branches.include?(dbranch)
|
297
|
+
missing_branches << dbranch
|
298
|
+
end
|
299
|
+
if missing_branches.length > 0 and single_page.nil?
|
300
|
+
puts "\nNOTE: The following branches do not exist in your local git repo:"
|
301
|
+
missing_branches.each do |mbranch|
|
302
|
+
puts "- #{mbranch}"
|
303
|
+
end
|
304
|
+
puts "The build will proceed but these branches will not be generated."
|
305
|
+
end
|
306
|
+
|
307
|
+
# Generate all distros for all branches in the indicated branch group
|
308
|
+
branch_group_branches[branch_group].each do |local_branch|
|
309
|
+
# Skip known missing branches; this will only come up for the :publish branch group
|
310
|
+
next if missing_branches.include?(local_branch)
|
311
|
+
|
312
|
+
# Single-page regen only occurs for the working branch
|
313
|
+
if not local_branch == working_branch
|
314
|
+
if single_page.nil?
|
315
|
+
# Checkout the branch
|
316
|
+
puts "\nCHANGING TO BRANCH '#{local_branch}'"
|
317
|
+
git_checkout(local_branch)
|
318
|
+
else
|
319
|
+
next
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
# Note the image files checked in to this branch.
|
324
|
+
branch_image_files = Find.find(docs_root_dir).select{ |path| not path.nil? and (path =~ /.*\.png$/ or path =~ /.*\.png\.cache$/) }
|
325
|
+
|
326
|
+
first_branch = single_page.nil?
|
327
|
+
|
328
|
+
if local_branch =~ /^\(detached from .*\)/
|
329
|
+
local_branch = 'detached'
|
330
|
+
end
|
331
|
+
|
332
|
+
# The branch_orphan_files list starts with the set of all
|
333
|
+
# .adoc files found in the repo, and will be whittled
|
334
|
+
# down from there.
|
335
|
+
branch_orphan_files = find_topic_files
|
336
|
+
branch_topic_map = topic_map
|
337
|
+
remove_found_topic_files(local_branch,branch_topic_map,branch_orphan_files)
|
338
|
+
|
339
|
+
if branch_orphan_files.length > 0 and single_page.nil?
|
340
|
+
nl_warning "Branch '#{local_branch}' includes the following .adoc files that are not referenced in the #{topic_map_file} file:\n" + branch_orphan_files.map{ |file| "- #{file}" }.join("\n")
|
341
|
+
end
|
342
|
+
|
343
|
+
# Run all distros.
|
344
|
+
distro_map.distros.each do |distro|
|
345
|
+
if not build_distro == ''
|
346
|
+
# Only building a single distro; build for all indicated branches, skip the others.
|
347
|
+
next unless build_distro == distro.id
|
348
|
+
else
|
349
|
+
current_distro_branches = distro_map.distro_branches(distro.id)
|
350
|
+
|
351
|
+
# In publish mode we only build "valid" distro-branch combos from the distro map
|
352
|
+
if branch_group.to_s.start_with?("publish") and not current_distro_branches.include?(local_branch)
|
353
|
+
next
|
354
|
+
end
|
355
|
+
|
356
|
+
# In "build all" mode we build every distro on the working branch plus the publish distro-branch combos
|
357
|
+
if branch_group == :all and not local_branch == working_branch and not current_distro_branches.include?(local_branch)
|
358
|
+
next
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
# Get the current distro / branch object
|
363
|
+
branch_config = AsciiBinder::DistroBranch.new('',{ "name" => "Branch Build", "dir" => local_branch },distro)
|
364
|
+
dev_branch = true
|
365
|
+
if distro.branch_ids.include?(local_branch)
|
366
|
+
branch_config = distro.branch(local_branch)
|
367
|
+
dev_branch = false
|
368
|
+
end
|
369
|
+
|
370
|
+
if first_branch
|
371
|
+
puts "\nBuilding #{distro.name} for branch '#{local_branch}'"
|
372
|
+
first_branch = false
|
373
|
+
end
|
374
|
+
|
375
|
+
# Copy files into the preview area.
|
376
|
+
[[stylesheet_dir, '*css', branch_config.branch_stylesheet_dir],
|
377
|
+
[javascript_dir, '*js', branch_config.branch_javascript_dir],
|
378
|
+
[image_dir, '*', branch_config.branch_image_dir]].each do |dgroup|
|
379
|
+
src_dir = dgroup[0]
|
380
|
+
glob = dgroup[1]
|
381
|
+
tgt_dir = dgroup[2]
|
382
|
+
if Dir.exist?(src_dir) and not dir_empty?(src_dir)
|
383
|
+
FileUtils.mkdir_p tgt_dir
|
384
|
+
FileUtils.cp_r Dir.glob(File.join(src_dir,glob)), tgt_dir
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
# Build the navigation structure for this branch / distro
|
389
|
+
navigation = branch_topic_map.nav_tree(distro.id)
|
390
|
+
|
391
|
+
# Build the topic files for this branch & distro
|
392
|
+
process_topic_entity_list(branch_config,single_page_path,navigation,branch_topic_map.list)
|
393
|
+
end
|
394
|
+
|
395
|
+
# In single-page context, we're done.
|
396
|
+
if not single_page.nil?
|
397
|
+
#exit 200
|
398
|
+
return
|
399
|
+
end
|
400
|
+
|
401
|
+
# Remove DITAA-generated images
|
402
|
+
ditaa_image_files = Find.find(docs_root_dir).select{ |path| not path.nil? and not (path =~ /_preview/ or path =~ /_package/) and (path =~ /.*\.png$/ or path =~ /.*\.png\.cache$/) and not branch_image_files.include?(path) }
|
403
|
+
if not ditaa_image_files.empty?
|
404
|
+
puts "\nRemoving ditaa-generated files from repo before changing branches."
|
405
|
+
ditaa_image_files.each do |dfile|
|
406
|
+
File.unlink(dfile)
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
if local_branch == working_branch
|
411
|
+
# We're moving away from the working branch, so save off changed files
|
412
|
+
git_stash_all
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
# Return to the original branch
|
417
|
+
git_checkout(working_branch)
|
418
|
+
|
419
|
+
# If necessary, restore temporarily stashed files
|
420
|
+
git_apply_and_drop
|
421
|
+
|
422
|
+
puts "\nAll builds completed."
|
423
|
+
end
|
424
|
+
|
425
|
+
def process_topic_entity_list(branch_config,single_page_path,navigation,topic_entity_list,preview_path='')
|
426
|
+
# When called from a topic group entity, create the preview dir for that group
|
427
|
+
Dir.mkdir(preview_path) unless preview_path == '' or File.exists?(preview_path)
|
428
|
+
|
429
|
+
topic_entity_list.each do |topic_entity|
|
430
|
+
# If this topic entity or any potential subentities are outside of the distro or single-page params, skip it.
|
431
|
+
next unless topic_entity.include?(branch_config.distro.id,single_page_path)
|
432
|
+
|
433
|
+
if topic_entity.is_group?
|
434
|
+
preview_path = topic_entity.preview_path(branch_config.distro.id,branch_config.dir)
|
435
|
+
process_topic_entity_list(branch_config,single_page_path,navigation,topic_entity.subitems,preview_path)
|
436
|
+
elsif topic_entity.is_topic?
|
437
|
+
if single_page_path.length == 0
|
438
|
+
puts " - #{topic_entity.repo_path}"
|
439
|
+
end
|
440
|
+
configure_and_generate_page(topic_entity,branch_config,navigation)
|
441
|
+
end
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
def configure_and_generate_page(topic,branch_config,navigation)
|
446
|
+
distro = branch_config.distro
|
447
|
+
topic_adoc = File.open(topic.source_path,'r').read
|
448
|
+
|
449
|
+
page_attrs = asciidoctor_page_attrs([
|
450
|
+
"imagesdir=#{File.join(topic.parent.source_path,'images')}",
|
451
|
+
branch_config.distro.id,
|
452
|
+
"product-title=#{branch_config.distro_name}",
|
453
|
+
"product-version=#{branch_config.name}",
|
454
|
+
"product-author=#{branch_config.distro_author}"
|
455
|
+
])
|
456
|
+
|
457
|
+
doc = Asciidoctor.load topic_adoc, :header_footer => false, :safe => :unsafe, :attributes => page_attrs
|
458
|
+
article_title = doc.doctitle || topic.name
|
459
|
+
|
460
|
+
topic_html = doc.render
|
461
|
+
dir_depth = ''
|
462
|
+
if branch_config.dir.split('/').length > 1
|
463
|
+
dir_depth = '../' * (branch_config.dir.split('/').length - 1)
|
464
|
+
end
|
465
|
+
|
466
|
+
# This is logic bridges newer arbitrary-depth-tolerant code to
|
467
|
+
# older depth-limited code. Truly removing depth limitations will
|
468
|
+
# require changes to page templates in user docs repos.
|
469
|
+
breadcrumb = topic.breadcrumb
|
470
|
+
group_title = breadcrumb[0][:name]
|
471
|
+
group_id = breadcrumb[0][:id]
|
472
|
+
topic_title = breadcrumb[-1][:name]
|
473
|
+
topic_id = breadcrumb[-1][:id]
|
474
|
+
subgroup_title = nil
|
475
|
+
subgroup_id = nil
|
476
|
+
if breadcrumb.length == 3
|
477
|
+
subgroup_title = breadcrumb[1][:name]
|
478
|
+
subgroup_id = breadcrumb[1][:id]
|
479
|
+
dir_depth = '../' + dir_depth
|
480
|
+
end
|
481
|
+
|
482
|
+
preview_path = topic.preview_path(distro.id,branch_config.dir)
|
483
|
+
|
484
|
+
page_args = {
|
485
|
+
:distro_key => distro.id,
|
486
|
+
:distro => branch_config.distro_name,
|
487
|
+
:site_name => distro.site.name,
|
488
|
+
:site_url => distro.site.url,
|
489
|
+
:topic_url => preview_path,
|
490
|
+
:version => branch_config.name,
|
491
|
+
:group_title => group_title,
|
492
|
+
:subgroup_title => subgroup_title,
|
493
|
+
:topic_title => topic_title,
|
494
|
+
:article_title => article_title,
|
495
|
+
:content => topic_html,
|
496
|
+
:navigation => navigation,
|
497
|
+
:group_id => group_id,
|
498
|
+
:subgroup_id => subgroup_id,
|
499
|
+
:topic_id => topic_id,
|
500
|
+
:css_path => "../../#{dir_depth}#{branch_config.dir}/#{STYLESHEET_DIRNAME}/",
|
501
|
+
:javascripts_path => "../../#{dir_depth}#{branch_config.dir}/#{JAVASCRIPT_DIRNAME}/",
|
502
|
+
:images_path => "../../#{dir_depth}#{branch_config.dir}/#{IMAGE_DIRNAME}/",
|
503
|
+
:site_home_path => "../../#{dir_depth}index.html",
|
504
|
+
:template_path => template_dir,
|
505
|
+
}
|
506
|
+
full_file_text = page(page_args)
|
507
|
+
File.write(preview_path,full_file_text)
|
508
|
+
end
|
509
|
+
|
510
|
+
# package_docs
|
511
|
+
# This method generates the docs and then organizes them the way they will be arranged
|
512
|
+
# for the production websites.
|
513
|
+
def package_docs(package_site)
|
514
|
+
site_map.sites.each do |site|
|
515
|
+
next if not package_site == '' and not package_site == site.id
|
516
|
+
site.distros.each do |distro_id,branches|
|
517
|
+
branches.each do |branch|
|
518
|
+
src_dir = File.join(preview_dir,distro_id,branch.dir)
|
519
|
+
tgt_tdir = branch.dir.split('/')
|
520
|
+
tgt_tdir.pop
|
521
|
+
tgt_dir = ''
|
522
|
+
if tgt_tdir.length > 0
|
523
|
+
tgt_dir = File.join(package_dir,site.id,tgt_tdir.join('/'))
|
524
|
+
else
|
525
|
+
tgt_dir = File.join(package_dir,site.id)
|
526
|
+
end
|
527
|
+
next if not File.directory?(src_dir)
|
528
|
+
FileUtils.mkdir_p(tgt_dir)
|
529
|
+
FileUtils.cp_r(src_dir,tgt_dir)
|
530
|
+
end
|
531
|
+
site_dir = File.join(package_dir,site.id)
|
532
|
+
if File.directory?(site_dir)
|
533
|
+
puts "\nPackaging #{distro_id} for #{site.id} site."
|
534
|
+
|
535
|
+
# Any files in the root of the docs repo with names ending in:
|
536
|
+
# *-#{site}.html
|
537
|
+
# will get copied into the root dir of the packaged site with
|
538
|
+
# the site name stripped out.
|
539
|
+
#
|
540
|
+
# Example: for site name 'commercial', the files:
|
541
|
+
# * index-commercial.html would end up as #{site_root}/index.html
|
542
|
+
# * search-commercial.html would end up as #{site_root}/search.html
|
543
|
+
# * index-community.html would be ignored
|
544
|
+
site_files = Dir.glob(File.join(docs_root_dir, '*-' + site.id + '.html'))
|
545
|
+
unless site_files.empty?
|
546
|
+
site_files.each do |fpath|
|
547
|
+
target_basename = File.basename(fpath).gsub(/-#{site.id}\.html$/, '.html')
|
548
|
+
FileUtils.cp(fpath,File.join(package_dir,site.id,target_basename))
|
549
|
+
end
|
550
|
+
else
|
551
|
+
FileUtils.cp(File.join(preview_dir,distro_id,'index.html'),File.join(package_dir,site.id,'index.html'))
|
552
|
+
end
|
553
|
+
['_images','_stylesheets'].each do |support_dir|
|
554
|
+
FileUtils.cp_r(File.join(docs_root_dir,support_dir),File.join(package_dir,site.id,support_dir))
|
555
|
+
end
|
556
|
+
|
557
|
+
# Now build a sitemap
|
558
|
+
site_dir_path = Pathname.new(site_dir)
|
559
|
+
SitemapGenerator::Sitemap.create(
|
560
|
+
:default_host => site.url,
|
561
|
+
:public_path => site_dir_path,
|
562
|
+
:compress => false,
|
563
|
+
:filename => File.join(site_dir,'sitemap')
|
564
|
+
) do
|
565
|
+
file_list = Find.find(site_dir).select{ |path| not path.nil? and path =~ /.*\.html$/ }.map{ |path| '/' + Pathname.new(path).relative_path_from(site_dir_path).to_s }
|
566
|
+
file_list.each do |file|
|
567
|
+
add(file, :changefreq => 'daily')
|
568
|
+
end
|
569
|
+
end
|
570
|
+
end
|
571
|
+
end
|
572
|
+
end
|
573
|
+
end
|
574
|
+
|
575
|
+
def clean_up
|
576
|
+
if not system("rm -rf #{docs_root_dir}/_preview/* #{docs_root_dir}/_package/*")
|
577
|
+
puts "Nothing to clean."
|
578
|
+
end
|
579
|
+
end
|
580
|
+
end
|
581
|
+
end
|