ascii_binder_gabriel_rh 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +56 -0
  3. data/Dockerfile +19 -0
  4. data/Gemfile +3 -0
  5. data/Guardfile +3 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.adoc +21 -0
  8. data/README.md +1 -0
  9. data/Rakefile +1 -0
  10. data/ascii_binder_gabriel_rh.gemspec +41 -0
  11. data/bin/ascii_binder_gabriel_rh +1 -0
  12. data/bin/asciibinder_gabriel_rh +350 -0
  13. data/features/command_help.feature +8 -0
  14. data/features/command_version.feature +8 -0
  15. data/features/repo_build.feature +39 -0
  16. data/features/repo_clean.feature +20 -0
  17. data/features/repo_clone.feature +22 -0
  18. data/features/repo_create.feature +13 -0
  19. data/features/repo_package.feature +15 -0
  20. data/features/step_definitions/steps.rb +189 -0
  21. data/features/support/_clone_distro_map.yml +14 -0
  22. data/features/support/_invalid_alias_topic_map.yml +50 -0
  23. data/features/support/_invalid_distro_map.yml +14 -0
  24. data/features/support/env.rb +518 -0
  25. data/features/support/test_distro/.gitignore +9 -0
  26. data/features/support/test_distro/_distro_map.yml +29 -0
  27. data/features/support/test_distro/_images/asciibinder-logo-horizontal.png +0 -0
  28. data/features/support/test_distro/_images/asciibinder_web_logo.svg +125 -0
  29. data/features/support/test_distro/_images/book_pages_bg.jpg +0 -0
  30. data/features/support/test_distro/_images/favicon.ico +0 -0
  31. data/features/support/test_distro/_images/favicon32x32.png +0 -0
  32. data/features/support/test_distro/_javascripts/.gitkeep +0 -0
  33. data/features/support/test_distro/_stylesheets/asciibinder.css +568 -0
  34. data/features/support/test_distro/_templates/_css.html.erb +3 -0
  35. data/features/support/test_distro/_templates/_nav.html.erb +31 -0
  36. data/features/support/test_distro/_templates/page.html.erb +92 -0
  37. data/features/support/test_distro/_topic_map.yml +50 -0
  38. data/features/support/test_distro/index-main.html +10 -0
  39. data/features/support/test_distro/index-test.html +10 -0
  40. data/features/support/test_distro/main_only_topic_group/index.adoc +17 -0
  41. data/features/support/test_distro/test_only_topic_group/index.adoc +17 -0
  42. data/features/support/test_distro/welcome/aliased.adoc +9 -0
  43. data/features/support/test_distro/welcome/index.adoc +17 -0
  44. data/features/support/test_distro/welcome/subtopics/index.adoc +17 -0
  45. data/features/support/test_distro/welcome/subtopics/main_only_topic.adoc +17 -0
  46. data/features/support/test_distro/welcome/subtopics/test_only_topic.adoc +17 -0
  47. data/features/support/test_distro/welcome/subtopics/wildcard_all.adoc +17 -0
  48. data/lib/ascii_binder_gabriel_rh/distro.rb +111 -0
  49. data/lib/ascii_binder_gabriel_rh/distro_branch.rb +97 -0
  50. data/lib/ascii_binder_gabriel_rh/distro_map.rb +67 -0
  51. data/lib/ascii_binder_gabriel_rh/engine.rb +690 -0
  52. data/lib/ascii_binder_gabriel_rh/helpers.rb +172 -0
  53. data/lib/ascii_binder_gabriel_rh/site.rb +52 -0
  54. data/lib/ascii_binder_gabriel_rh/site_info.rb +22 -0
  55. data/lib/ascii_binder_gabriel_rh/site_map.rb +24 -0
  56. data/lib/ascii_binder_gabriel_rh/tasks/guards.rb +15 -0
  57. data/lib/ascii_binder_gabriel_rh/tasks/tasks.rb +41 -0
  58. data/lib/ascii_binder_gabriel_rh/template_renderer.rb +29 -0
  59. data/lib/ascii_binder_gabriel_rh/topic_entity.rb +324 -0
  60. data/lib/ascii_binder_gabriel_rh/topic_map.rb +112 -0
  61. data/lib/ascii_binder_gabriel_rh/version.rb +3 -0
  62. data/lib/ascii_binder_gabriel_rh.rb +5 -0
  63. data/templates/.gitignore +9 -0
  64. data/templates/LICENSE.txt +4 -0
  65. data/templates/README.adoc +11 -0
  66. data/templates/_distro_map.yml +11 -0
  67. data/templates/_images/asciibinder-logo-horizontal.png +0 -0
  68. data/templates/_images/asciibinder_web_logo.svg +125 -0
  69. data/templates/_images/book_pages_bg.jpg +0 -0
  70. data/templates/_images/favicon.ico +0 -0
  71. data/templates/_images/favicon32x32.png +0 -0
  72. data/templates/_javascripts/.gitkeep +0 -0
  73. data/templates/_javascripts/bootstrap-offcanvas.js +6 -0
  74. data/templates/_stylesheets/asciibinder.css +568 -0
  75. data/templates/_templates/_breadcrumb.html.erb +14 -0
  76. data/templates/_templates/_css.html.erb +3 -0
  77. data/templates/_templates/_nav.html.erb +14 -0
  78. data/templates/_templates/_title.html.erb +8 -0
  79. data/templates/_templates/page.html.erb +88 -0
  80. data/templates/_topic_map.yml +29 -0
  81. data/templates/index-main.html +89 -0
  82. data/templates/welcome/index.adoc +14 -0
  83. 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