-
Notifications
You must be signed in to change notification settings - Fork 39
/
Copy pathasciibinder
executable file
·350 lines (305 loc) · 10.9 KB
/
asciibinder
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
#!/usr/bin/env ruby
require 'ascii_binder/distro_map'
require 'ascii_binder/engine'
require 'ascii_binder/helpers'
require 'ascii_binder/version'
require 'pathname'
require 'trollop'
include AsciiBinder::Engine
include AsciiBinder::Helpers
def call_generate(branch_group, distro, page)
if page == ''
page = nil
end
begin
generate_docs(branch_group, distro, page)
rescue => e
message = "#{e.class.name}: #{e.message} at\n #{e.backtrace.join("\n ")}"
Trollop::die "Could not generate docs:\n#{message}"
end
end
def repo_check(docs_basedir)
missing_files = false
# These must all be present
['_distro_map.yml','_templates'].each do |file|
unless File.exist?(File.join(docs_basedir, file))
missing_files = true
end
end
# Either of these must be present
# unless File.exist?(File.join("#{docs_basedir}/#{TOPIC_MAP_FOLDER}", '_topic_map.yml'))
# missing_files = true
# end
if missing_files or not in_git_repo(docs_basedir)
Trollop::die "The specified docs base directory '#{docs_basedir}' does not appear to be part of an AsciiBinder-compatible repo."
end
end
def in_git_repo(dir)
git_path = File.join(dir,'.git')
return true if File.exist?(git_path) and File.directory?(git_path)
return false if dir == '/'
in_git_repo(File.expand_path('..',dir))
end
SUB_COMMANDS = %w{help version build watch package clean create clone}
Trollop::options do
version AsciiBinder::VERSION
banner <<-EOF
Usage:
#$0 <command> <docs_basedir>
Commands:
build (default action)
Builds the HTML docs within the indicated docs base directory
create
Generates a new AsciiBinder repo at the indicated dir
clone
Clones an existing AsciiBinder repo to the local filesystem
watch
Starts Guard, which automatically regenerates changed HTML
files on the working branch in the docs base directory dir
package
Builds and packages the static HTML for all of the sites
defined in the _distro_config.yml file
clean
Remove _preview, _publish and _package dirs created by
other AsciiBinder operations.
Options:
EOF
stop_on SUB_COMMANDS
end
cmd = ARGV.shift
docs_basedir = nil
if cmd.nil?
cmd = "build"
elsif !SUB_COMMANDS.include?(cmd)
if ARGV.empty?
docs_basedir = Pathname.new(cmd)
cmd = "build"
else
Trollop::die "'#{cmd}' is not a valid asciibinder subcommand. Legal values are '#{SUB_COMMANDS.join('\', \'')}'."
end
end
cmd_opts = case cmd
when "build"
Trollop::options do
banner <<-EOF
Usage:
#$0 build <options> <docs_basedir>
Description:
This is the default behavior for the asciibinder utility. When run,
AsciiBinder reads the _distro_config.yml file out of the working
branch of the indicated docs base directory and based on that, proceeds
to build the working branch version of the documentation for each distro.
If you use the --all_branches flag, AsciiBinder behaves as described
above, and then once the working branch version is built, AsciiBinder
cycles through the other branches named in the _distro_config.yml file
until all of the permutations have been built.
If you want to limit the scope of the build work for faster builds,
you have two targeted options:
--distro=<distro_key> - Only builds the specified distro and branches
associated with this distro.
--page=<page_path> - Only builds the specified page for all distros.
Note that the format for the "--page" option is:
<topic_group>:<topic_file>
or for subtopics:
<topic_group>/<subtopic_group>:<topic_file>
However, if you want to use the --page option extensively, then be
aware of the `asciibinder watch` function, which does this for you
automatically as you change any .adoc files in your working branch.
Options:
EOF
opt :all_branches, "Instead of building only the current working branch, build all branches", :default => false
opt :distro, "Instead of building all distros, build branches only for the specified distro.", :default => ''
opt :page, "Build only the specified page for all distros and only the current working branch.", :default => ''
opt :log_level, "Set the logging output level for this operation.", :default => 'warn'
opt :toc_depth, "Maximum depth of topics allowed. Use 0 for infinite depth.", :default => 3
conflicts :distro, :page
end
when "create"
Trollop::options do
banner <<-EOF
Usage:
#$0 create <new_docs_basedir>
Description:
Creates a new, bare AsciiBinder repo in the specified directory.
EOF
end
when "clone"
Trollop::options do
banner <<-EOF
Usage:
#$0 clone <options> <git_repo_url>
Description:
Clones an existing AsciiBinder repo to the current directory.
Under the default behavior, AsciiBinder will attempt to set up
tracking branches based on the contents of _distro_map.yml,
but this can be suppressed (see Options).
Options:
EOF
opt :branches, "Create tracking branches after cloning.", :default => true
opt :dir, "Specify the pathname of the local directory for cloning.", :default => ''
opt :log_level, "Set the logging output level for this operation.", :default => 'warn'
end
when "watch"
Trollop::options do
banner <<-EOF
Usage:
#$0 watch <docs_basedir>
Description:
In watch mode, AsciiBinder starts a Guard process in the foreground.
This process watches the docs_basedir for changes to the AsciiDoc (.adoc)
files. When a change occurs, AsciiBinder regenerates the specific
HTML output of the file that was changed, for the working branch only.
This is the equivalent of running:
$ asciibinder build --page='<topic_group>:<affected_file>'
...except that the Guardfile automatically detects and runs this as
you work.
This is meant to be used in conjunction with a web browser that is viewing the
output HTML page. Every time you save a new version of the .adoc file, you can
manually refresh your page to view the newly-generated HTML.
EOF
opt :log_level, "Set the logging output level for this operation.", :default => 'warn'
end
when "package"
Trollop::options do
banner <<-EOF
Usage:
#$0 package <options> <docs_basedir>
Description:
Publish mode is similar to 'build' mode, but once all of the branches' of
HTML are generated, 'publish' goes on to organize the branch / distro
combinations that are described in _distro_config.yml into their "site"
layouts. As a final step, the site layouts are tarred and gzipped for
easy placement onto a production web server.
Options:
EOF
opt :site, "Instead of packaging every docs site, package the specified site only.", :default => ''
opt :log_level, "Set the logging output level for this operation.", :default => 'warn'
opt :toc_depth, "Maximum depth of topics allowed. Use 0 for infinite depth.", :default => 3
end
when "help"
Trollop::educate
when "version"
puts AsciiBinder::VERSION
exit 0
end
if (not docs_basedir.nil? and not ARGV.empty?) or (docs_basedir.nil? and ARGV.length > 1)
Trollop::die "Too many arguments provided to ascii_binder: '#{ARGV.join(' ')}'. Exiting."
elsif docs_basedir.nil?
if ARGV.length == 1
if cmd == 'clone'
cmd_opts[:giturl] = ARGV.shift
if cmd_opts[:dir] != ''
docs_basedir = Pathname.new(cmd_opts[:dir])
else
docs_basedir = Pathname.new(File.join(Pathname.pwd, cmd_opts[:giturl].split('/')[-1].split('.')[0]))
end
else
docs_basedir = Pathname.new(ARGV.shift)
end
else
if cmd != 'create'
if cmd == 'clone'
Trollop::die "Provide a git URL to clone from."
else
docs_basedir = Pathname.pwd
end
else
Trollop::die "Specify a name for the new repo directory."
end
end
end
# Validate the docs_basedir path
if cmd == 'create' or cmd == 'clone'
if docs_basedir.exist?
Trollop::die "The specified new repo directory '#{docs_basedir}' already exists."
end
else
if !docs_basedir.exist?
Trollop::die "The specified docs directory '#{docs_basedir}' does not exist."
elsif !docs_basedir.directory?
Trollop::die "The specified docs directory path '#{docs_basedir}' is not a directory."
elsif !docs_basedir.readable?
Trollop::die "The specified docs directory '#{docs_basedir}' is not readable."
elsif !docs_basedir.writable?
Trollop::die "The specified docs directory '#{docs_basedir}' cannot be written to."
else
repo_check(docs_basedir)
end
end
# Set the repo root
set_docs_root_dir(File.expand_path(docs_basedir))
# Set the log level
user_log_level = :warn
unless cmd_opts.nil? or cmd_opts[:log_level].nil?
user_log_level = cmd_opts[:log_level].to_sym
unless log_levels.has_key?(user_log_level)
Trollop::die "log_level value '#{cmd_opts[:log_level]}' is not recognized. Legal values are " + log_levels.keys.map{ |lvl| "'#{lvl.to_s}'" }.join(', ')
end
end
set_log_level(user_log_level)
# Set the depth level
user_depth = 3
unless cmd_opts.nil? or cmd_opts[:toc_depth].nil?
user_depth = cmd_opts[:toc_depth].to_i
end
set_depth(user_depth)
# Cloning? Time to try it.
if cmd == 'clone'
puts "Cloning #{cmd_opts[:giturl]} to #{docs_basedir}"
system("git clone #{cmd_opts[:giturl]} #{docs_basedir}")
Trollop::die "The git URL could not be cloned: #{err}" if $?.exitstatus != 0
# Make sure this cloned repo is legit.
repo_check(docs_basedir)
if cmd_opts[:branches]
cloned_map = AsciiBinder::DistroMap.new(File.join(docs_basedir,DISTRO_MAP_FILENAME))
unless cloned_map.is_valid?
error_info = cloned_map.errors.join("\n")
Trollop::die "The distro map in the newly cloned repo is invalid, with the following errors:\n#{error_info}"
end
Dir.chdir(docs_basedir)
puts "Tracking branch setup:"
cloned_map.distro_branches.each do |doc_branch|
next if doc_branch == 'main'
puts "- #{doc_branch}"
system("git branch #{doc_branch} origin/#{doc_branch}")
end
else
puts "- Skipping tracking branch setup"
end
# Done and done.
puts "Cloning complete."
exit
end
# Change to the repo dir. This is necessary in order for
# AsciiDoctor to work properly.
if cmd != 'create'
Dir.chdir docs_basedir
end
# Do the things with the stuff
case cmd
when "build"
branch_group = cmd_opts[:all_branches] ? :all : :working_only
build_distro = cmd_opts[:distro] || ''
refresh_page = cmd_opts[:page] || nil
call_generate(branch_group,build_distro,refresh_page)
when "package"
clean_up
package_site = cmd_opts[:site] || ''
branch_group = package_site == '' ? :publish : "publish_#{package_site}".to_sym
call_generate(branch_group,'',nil)
package_docs(package_site)
when "watch"
if !dir_empty?(preview_dir)
guardfile_path = File.join(Gem::Specification.find_by_name("ascii_binder").full_gem_path, 'Guardfile')
exec("guard -G #{guardfile_path}")
else
Trollop::die "Run 'asciibinder build' at least once before running 'asciibinder watch'."
end
when "clean"
clean_up
puts "Cleaned up #{docs_basedir}."
when "create"
create_new_repo
puts "Created new repo in #{docs_basedir}."
end
exit