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