ascii_binder 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 01e8b7c8975f779411765ecd4db541dbbda03745
4
- data.tar.gz: 9daf86717b278c2b10c6e59c0b554641fc1f9127
3
+ metadata.gz: 6fff45d8fcc35d2040f7f230045cabeeac556192
4
+ data.tar.gz: 61fa8923622f4aa924de6fab5c2cd47bcacc384b
5
5
  SHA512:
6
- metadata.gz: 0e955da364eb1b81d49415c5b000b0cf06a83ad699e5085e5a72918b45a51f4f263cdcaf3871f6290198b2fd3d57603dc6558a5c577782d2d9c08d8e5c206ade
7
- data.tar.gz: 6238794ecb04f36e2d65d30b06a3ec7c6b5e6a036d55051b2cc7726a389fa628ee14547a7942d88be007e44654329f7febda8f6493b13c171f99594cb80530c1
6
+ metadata.gz: f54679707ec775f4863468e85458960c1a5786b5d297be87bc704812f06dae8ec1744bc94217719293d97703cf99bd1d6d34760166def138effda3c0a0c9088d
7
+ data.tar.gz: 9afc02f88169c7e8790c8e9b6819c55d0283197f96e2801b54662d4f77aa8bd68d036bf2ef4c34778d57bf74eced650c340486ce726107bc2ca3d3be1c46ec9c
@@ -0,0 +1,18 @@
1
+ FROM centos/ruby-22-centos7
2
+
3
+ RUN scl enable rh-ruby22 -- gem install ascii_binder
4
+ USER root
5
+ RUN yum install -y java-1.7.0-openjdk && \
6
+ yum clean all
7
+
8
+ LABEL url="http://www.asciibinder.org" \
9
+ summary="a documentation system built on Asciidoctor" \
10
+ description="AsciiBinder is for documenting versioned, interrelated projects. Run this container image from the documentation repository, which is mounted into the container. Note: Generated files will be owned by root." \
11
+ RUN="docker run -it --rm \
12
+ -v `pwd`:/docs:z \
13
+ IMAGE"
14
+
15
+ ENV JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.95-2.6.4.0.el7_2.x86_64/jre/
16
+ ENV LANG=en_US.UTF-8
17
+ WORKDIR /docs
18
+ CMD asciibinder package
@@ -7,23 +7,33 @@ require 'trollop'
7
7
 
8
8
  include AsciiBinder::Helpers
9
9
 
10
- def call_generate(distro,page=nil)
10
+ def call_generate(branch_group, distro, page)
11
11
  if page == ''
12
12
  page = nil
13
13
  end
14
14
  begin
15
- generate_docs(distro,page)
16
- rescue Exception => e
17
- Trollop::die "Could not generate docs: #{e.message}"
15
+ generate_docs(branch_group, distro, page)
16
+ rescue => e
17
+ message = "#{e.class.name}: #{e.message} at\n #{e.backtrace.join("\n ")}"
18
+ Trollop::die "Could not generate docs:\n#{message}"
18
19
  end
19
20
  end
20
21
 
21
22
  def repo_check(repo_dir)
22
- ['.git','_build_cfg.yml','_distro_map.yml','_templates'].each do |file|
23
+ missing_files = false
24
+ # These must all be present
25
+ ['.git','_distro_map.yml','_templates'].each do |file|
23
26
  unless File.exist?(File.join(repo_dir, file))
24
- Trollop::die "The specified repo directory '#{repo_dir}' does not appear to be an AsciiBinder repo."
27
+ missing_files = true
25
28
  end
26
29
  end
30
+ # Either of these must be present
31
+ unless File.exist?(File.join(repo_dir, '_build_cfg.yml')) or File.exist?(File.join(repo_dir, '_topic_map.yml'))
32
+ missing_files = true
33
+ end
34
+ if missing_files
35
+ Trollop::die "The specified repo directory '#{repo_dir}' does not appear to be an AsciiBinder repo."
36
+ end
27
37
  end
28
38
 
29
39
  SUB_COMMANDS = %w{help version build watch package clean create clone}
@@ -82,13 +92,20 @@ Description:
82
92
  branch of the indicated repo directory and based on that, proceeds to
83
93
  build the working branch version of the documentation for each distro.
84
94
 
85
- Once the working branch version is built, AsciiBinder cycles through
86
- the other branches named in the _distro_config.yml file until all of
87
- the permutations have been built.
95
+ If you use the --all_branches flag, AsciiBinder behaves as described
96
+ above, and then once the working branch version is built, AsciiBinder
97
+ cycles through the other branches named in the _distro_config.yml file
98
+ until all of the permutations have been built.
99
+
100
+ If you want to limit the scope of the build work for faster builds,
101
+ you have two targeted options:
102
+
103
+ --distro=<distro_key> - Only builds the specified distro and branches
104
+ associated with this distro.
105
+
106
+ --page=<page_path> - Only builds the specified page for all distros.
88
107
 
89
- The available options enable you to limit the scope of the build work,
90
- as described by the options themselves. Note that the format for the
91
- "--page" option is:
108
+ Note that the format for the "--page" option is:
92
109
 
93
110
  <topic_group>:<topic_file>
94
111
 
@@ -98,10 +115,11 @@ Description:
98
115
 
99
116
  However, if you want to use the --page option extensively, then be
100
117
  aware of the `asciibinder watch` function, which does this for you
101
- automatically as you change .adoc files in your working branch.
118
+ automatically as you change any .adoc files in your working branch.
102
119
 
103
120
  Options:
104
121
  EOF
122
+ opt :all_branches, "Instead of building only the current working branch, build all branches", :default => false
105
123
  opt :distro, "Instead of building all distros, build branches only for the specified distro.", :default => ''
106
124
  opt :page, "Build only the specified page for all distros and only the current working branch.", :default => ''
107
125
  conflicts :distro, :page
@@ -267,12 +285,13 @@ end
267
285
  # Do the things with the stuff
268
286
  case cmd
269
287
  when "build"
270
- build_distro = cmd_opts[:build] || ''
271
- refresh_page = cmd_opts[:page] || ''
272
- call_generate(build_distro,refresh_page)
288
+ branch_group = cmd_opts[:all_branches] ? :all : :working_only
289
+ build_distro = cmd_opts[:distro] || ''
290
+ refresh_page = cmd_opts[:page] || nil
291
+ call_generate(branch_group,build_distro,refresh_page)
273
292
  when "package"
274
293
  clean_up
275
- call_generate('')
294
+ call_generate(:publish,'',nil)
276
295
  package_site = cmd_opts[:site] || ''
277
296
  package_docs(package_site)
278
297
  when "watch"
@@ -7,23 +7,33 @@ require 'trollop'
7
7
 
8
8
  include AsciiBinder::Helpers
9
9
 
10
- def call_generate(distro,page=nil)
10
+ def call_generate(branch_group, distro, page)
11
11
  if page == ''
12
12
  page = nil
13
13
  end
14
14
  begin
15
- generate_docs(distro,page)
16
- rescue Exception => e
17
- Trollop::die "Could not generate docs: #{e.message}"
15
+ generate_docs(branch_group, distro, page)
16
+ rescue => e
17
+ message = "#{e.class.name}: #{e.message} at\n #{e.backtrace.join("\n ")}"
18
+ Trollop::die "Could not generate docs:\n#{message}"
18
19
  end
19
20
  end
20
21
 
21
22
  def repo_check(repo_dir)
22
- ['.git','_build_cfg.yml','_distro_map.yml','_templates'].each do |file|
23
+ missing_files = false
24
+ # These must all be present
25
+ ['.git','_distro_map.yml','_templates'].each do |file|
23
26
  unless File.exist?(File.join(repo_dir, file))
24
- Trollop::die "The specified repo directory '#{repo_dir}' does not appear to be an AsciiBinder repo."
27
+ missing_files = true
25
28
  end
26
29
  end
30
+ # Either of these must be present
31
+ unless File.exist?(File.join(repo_dir, '_build_cfg.yml')) or File.exist?(File.join(repo_dir, '_topic_map.yml'))
32
+ missing_files = true
33
+ end
34
+ if missing_files
35
+ Trollop::die "The specified repo directory '#{repo_dir}' does not appear to be an AsciiBinder repo."
36
+ end
27
37
  end
28
38
 
29
39
  SUB_COMMANDS = %w{help version build watch package clean create clone}
@@ -82,13 +92,20 @@ Description:
82
92
  branch of the indicated repo directory and based on that, proceeds to
83
93
  build the working branch version of the documentation for each distro.
84
94
 
85
- Once the working branch version is built, AsciiBinder cycles through
86
- the other branches named in the _distro_config.yml file until all of
87
- the permutations have been built.
95
+ If you use the --all_branches flag, AsciiBinder behaves as described
96
+ above, and then once the working branch version is built, AsciiBinder
97
+ cycles through the other branches named in the _distro_config.yml file
98
+ until all of the permutations have been built.
99
+
100
+ If you want to limit the scope of the build work for faster builds,
101
+ you have two targeted options:
102
+
103
+ --distro=<distro_key> - Only builds the specified distro and branches
104
+ associated with this distro.
105
+
106
+ --page=<page_path> - Only builds the specified page for all distros.
88
107
 
89
- The available options enable you to limit the scope of the build work,
90
- as described by the options themselves. Note that the format for the
91
- "--page" option is:
108
+ Note that the format for the "--page" option is:
92
109
 
93
110
  <topic_group>:<topic_file>
94
111
 
@@ -98,10 +115,11 @@ Description:
98
115
 
99
116
  However, if you want to use the --page option extensively, then be
100
117
  aware of the `asciibinder watch` function, which does this for you
101
- automatically as you change .adoc files in your working branch.
118
+ automatically as you change any .adoc files in your working branch.
102
119
 
103
120
  Options:
104
121
  EOF
122
+ opt :all_branches, "Instead of building only the current working branch, build all branches", :default => false
105
123
  opt :distro, "Instead of building all distros, build branches only for the specified distro.", :default => ''
106
124
  opt :page, "Build only the specified page for all distros and only the current working branch.", :default => ''
107
125
  conflicts :distro, :page
@@ -267,12 +285,13 @@ end
267
285
  # Do the things with the stuff
268
286
  case cmd
269
287
  when "build"
270
- build_distro = cmd_opts[:build] || ''
271
- refresh_page = cmd_opts[:page] || ''
272
- call_generate(build_distro,refresh_page)
288
+ branch_group = cmd_opts[:all_branches] ? :all : :working_only
289
+ build_distro = cmd_opts[:distro] || ''
290
+ refresh_page = cmd_opts[:page] || nil
291
+ call_generate(branch_group,build_distro,refresh_page)
273
292
  when "package"
274
293
  clean_up
275
- call_generate('')
294
+ call_generate(:publish,'',nil)
276
295
  package_site = cmd_opts[:site] || ''
277
296
  package_docs(package_site)
278
297
  when "watch"
@@ -71,8 +71,8 @@ module AsciiBinder
71
71
  def_delegators self, :source_dir, :set_source_dir, :template_dir, :preview_dir, :package_dir, :gem_root_dir, :stylesheet_dir, :javascript_dir, :image_dir
72
72
 
73
73
  BUILD_FILENAME = '_build_cfg.yml'
74
+ TOPIC_MAP_FILENAME = '_topic_map.yml'
74
75
  DISTRO_MAP_FILENAME = '_distro_map.yml'
75
- BUILDER_DIRNAME = '_build_system'
76
76
  PREVIEW_DIRNAME = '_preview'
77
77
  PACKAGE_DIRNAME = '_package'
78
78
  STYLESHEET_DIRNAME = '_stylesheets'
@@ -133,7 +133,14 @@ module AsciiBinder
133
133
  end
134
134
 
135
135
  def build_config_file
136
- @build_config_file ||= File.join(source_dir,BUILD_FILENAME)
136
+ use_file = TOPIC_MAP_FILENAME
137
+ unless File.exist?(File.join(source_dir,TOPIC_MAP_FILENAME))
138
+ # The new filename '_topic_map.yml' couldn't be found;
139
+ # switch to the old one and warn the user.
140
+ use_file = BUILD_FILENAME
141
+ puts "WARNING: '#{BUILD_FILENAME}' is a deprecated filename. Rename this to '#{TOPIC_MAP_FILENAME}'."
142
+ end
143
+ use_file
137
144
  end
138
145
 
139
146
  def distro_map_file
@@ -146,18 +153,14 @@ module AsciiBinder
146
153
 
147
154
  # Protip: Don't cache this! It needs to be reread every time we change branches.
148
155
  def build_config
149
- validate_config(YAML.load_stream(open(build_config_file)))
156
+ validate_config(YAML.load_stream(open(File.join(source_dir,build_config_file))))
150
157
  end
151
158
 
152
159
  def create_new_repo
153
160
  gem_template_dir = File.join(gem_root_dir,"templates")
154
161
 
155
162
  # Create the new repo dir
156
- begin
157
- Dir.mkdir(source_dir)
158
- rescue Exception => e
159
- raise "Could not create directory '#{source_dir}': #{e.message}"
160
- end
163
+ FileUtils.mkdir_p(source_dir)
161
164
 
162
165
  # Copy the basic repo content into the new repo dir
163
166
  Find.find(gem_template_dir).each do |path|
@@ -171,13 +174,8 @@ module AsciiBinder
171
174
  end
172
175
  end
173
176
 
174
- # Initialize the git repo and check everything in
175
- g = nil
176
- begin
177
- g = Git.init(source_dir)
178
- rescue Exception => e
179
- raise "Could not initialize git repo in '#{source_dir}': #{e.message}"
180
- end
177
+ # Initialize the git repo
178
+ Git.init(source_dir)
181
179
  end
182
180
 
183
181
  def find_topic_files
@@ -217,7 +215,7 @@ module AsciiBinder
217
215
  end
218
216
  end
219
217
  if nonexistent_topics.length > 0
220
- puts "\nWARNING: The _build_cfg.yml file on branch '#{branch}' references nonexistant topics:\n" + nonexistent_topics.map{ |topic| "- #{topic}" }.join("\n")
218
+ puts "\nWARNING: The #{build_config_file} file on branch '#{branch}' references nonexistant topics:\n" + nonexistent_topics.map{ |topic| "- #{topic}" }.join("\n")
221
219
  end
222
220
  end
223
221
 
@@ -237,9 +235,17 @@ module AsciiBinder
237
235
  end
238
236
 
239
237
  def distro_branches(use_distro='')
240
- @distro_branches ||= begin
241
- use_distro_list = use_distro == '' ? distro_map.keys : [use_distro]
242
- distro_map.select{ |dkey,dval| use_distro_list.include?(dkey) }.map{ |distro,dconfig| dconfig["branches"].keys }.flatten
238
+ use_distro_list = use_distro == '' ? distro_map.keys : [use_distro]
239
+ distro_map.select{ |dkey,dval| use_distro_list.include?(dkey) }.map{ |distro,dconfig| dconfig["branches"].keys }.flatten
240
+ end
241
+
242
+ def branch_group_branches
243
+ @branch_group_branches ||= begin
244
+ group_branches = Hash.new
245
+ group_branches[:working_only] = [local_branches[0]]
246
+ group_branches[:publish] = distro_branches
247
+ group_branches[:all] = local_branches
248
+ group_branches
243
249
  end
244
250
  end
245
251
 
@@ -468,7 +474,7 @@ module AsciiBinder
468
474
  ].concat(more_attrs)
469
475
  end
470
476
 
471
- def generate_docs(build_distro,single_page=nil)
477
+ def generate_docs(branch_group,build_distro,single_page)
472
478
  # First, test to see if the docs repo has any commits. If the user has just
473
479
  # run `asciibinder create`, there will be no commits to work from, yet.
474
480
  if local_branches.empty?
@@ -507,8 +513,11 @@ module AsciiBinder
507
513
  puts "The build will proceed but these branches will not be generated."
508
514
  end
509
515
 
510
- # Generate all distros for every local branch
511
- local_branches.each do |local_branch|
516
+ # Generate all distros for all branches in the indicated branch group
517
+ branch_group_branches[branch_group].each do |local_branch|
518
+ # Skip known missing branches; this will only come up for the :publish branch group
519
+ next if missing_branches.include?(local_branch)
520
+
512
521
  # Single-page regen only occurs for the working branch
513
522
  if not local_branch == working_branch
514
523
  if single_page.nil?
@@ -537,14 +546,28 @@ module AsciiBinder
537
546
  remove_found_config_files(local_branch,branch_build_config,branch_orphan_files)
538
547
 
539
548
  if branch_orphan_files.length > 0 and single_page.nil?
540
- puts "\nWARNING: Branch '#{local_branch}' includes the following .adoc files that are not referenced in the _build_cfg.yml file:\n" + branch_orphan_files.map{ |file| "- #{file}" }.join("\n")
549
+ puts "\nWARNING: Branch '#{local_branch}' includes the following .adoc files that are not referenced in the #{build_config_file} file:\n" + branch_orphan_files.map{ |file| "- #{file}" }.join("\n")
541
550
  end
542
551
 
543
552
  # Run all distros.
544
553
  distro_map.each do |distro,distro_config|
545
- # Only building a single distro; skip the others.
546
- if not build_distro == '' and not build_distro == distro
547
- next
554
+ if not build_distro == ''
555
+ # Only building a single distro; build for all indicated branches, skip the others.
556
+ if not build_distro == distro
557
+ next
558
+ end
559
+ else
560
+ current_distro_branches = distro_branches(distro)
561
+
562
+ # In publish mode we only build "valid" distro-branch combos from the distro map
563
+ if branch_group == :publish and not current_distro_branches.include?(local_branch)
564
+ next
565
+ end
566
+
567
+ # In "build all" mode we build every distro on the working branch plus the publish distro-branch combos
568
+ if branch_group == :all and not local_branch == working_branch and not current_distro_branches.include?(local_branch)
569
+ next
570
+ end
548
571
  end
549
572
 
550
573
  site_name = distro_config["site_name"]
@@ -720,46 +743,48 @@ module AsciiBinder
720
743
  "product-author=#{distro_config["author"]}"
721
744
  ])
722
745
 
723
- # Because we render only the body of the article with AsciiDoctor, the full article title
724
- # would be lost in conversion. So, use the _build_cfg.yml 'Name' as a fallback but try
725
- # to read the full article title out of the file itself.
726
- file_lines = topic_adoc.split("\n")
727
- article_title = topic['Name']
728
- if file_lines.length > 0
729
- article_title = file_lines[0].gsub(/^\=\s+/, '').gsub(/\s+$/, '').gsub(/\{product-title\}/, distro_config["name"]).gsub(/\{product-version\}/, branch_config["name"])
730
- end
731
- topic_adoc = file_lines.join("\n")
732
-
733
- topic_html = Asciidoctor.render topic_adoc, :header_footer => false, :safe => :unsafe, :attributes => page_attrs
734
- dir_depth = ''
735
- if branch_config['dir'].split('/').length > 1
736
- dir_depth = '../' * (branch_config['dir'].split('/').length - 1)
737
- end
738
- if not topic_subgroup.nil?
739
- dir_depth = '../' + dir_depth
740
- end
741
- page_args = {
742
- :distro_key => distro,
743
- :distro => distro_config["name"],
744
- :site_name => site_name,
745
- :version => branch_config["name"],
746
- :group_title => topic_group['Name'],
747
- :subgroup_title => topic_subgroup && topic_subgroup['Name'],
748
- :topic_title => topic['Name'],
749
- :article_title => article_title,
750
- :content => topic_html,
751
- :navigation => navigation,
752
- :group_id => topic_group['ID'],
753
- :subgroup_id => topic_subgroup && topic_subgroup['ID'],
754
- :topic_id => topic['ID'],
755
- :css_path => "../../#{dir_depth}#{branch_config["dir"]}/#{STYLESHEET_DIRNAME}/",
756
- :javascripts_path => "../../#{dir_depth}#{branch_config["dir"]}/#{JAVASCRIPT_DIRNAME}/",
757
- :images_path => "../../#{dir_depth}#{branch_config["dir"]}/#{IMAGE_DIRNAME}/",
758
- :site_home_path => "../../#{dir_depth}index.html",
759
- :template_path => template_dir,
760
- }
761
- full_file_text = page(page_args)
762
- File.write(tgt_file_path,full_file_text)
746
+ # Because we render only the body of the article with AsciiDoctor, the full article title
747
+ # would be lost in conversion. So, use the _build_cfg.yml 'Name' as a fallback but try
748
+ # to read the full article title out of the file itself.
749
+ file_lines = topic_adoc.split("\n")
750
+ article_title = topic['Name']
751
+ if file_lines.length > 0
752
+ article_title = file_lines[0].gsub(/^\=\s+/, '').gsub(/\s+$/, '').gsub(/\{product-title\}/, distro_config["name"]).gsub(/\{product-version\}/, branch_config["name"])
753
+ end
754
+ topic_adoc = file_lines.join("\n")
755
+
756
+ topic_html = Asciidoctor.render topic_adoc, :header_footer => false, :safe => :unsafe, :attributes => page_attrs
757
+ dir_depth = ''
758
+ if branch_config['dir'].split('/').length > 1
759
+ dir_depth = '../' * (branch_config['dir'].split('/').length - 1)
760
+ end
761
+ if not topic_subgroup.nil?
762
+ dir_depth = '../' + dir_depth
763
+ end
764
+ page_args = {
765
+ :distro_key => distro,
766
+ :distro => distro_config["name"],
767
+ :site_name => site_name,
768
+ :site_url => distro_config["site_url"],
769
+ :topic_url => "#{branch_config['dir']}/#{topic_path}.html",
770
+ :version => branch_config["name"],
771
+ :group_title => topic_group['Name'],
772
+ :subgroup_title => topic_subgroup && topic_subgroup['Name'],
773
+ :topic_title => topic['Name'],
774
+ :article_title => article_title,
775
+ :content => topic_html,
776
+ :navigation => navigation,
777
+ :group_id => topic_group['ID'],
778
+ :subgroup_id => topic_subgroup && topic_subgroup['ID'],
779
+ :topic_id => topic['ID'],
780
+ :css_path => "../../#{dir_depth}#{branch_config["dir"]}/#{STYLESHEET_DIRNAME}/",
781
+ :javascripts_path => "../../#{dir_depth}#{branch_config["dir"]}/#{JAVASCRIPT_DIRNAME}/",
782
+ :images_path => "../../#{dir_depth}#{branch_config["dir"]}/#{IMAGE_DIRNAME}/",
783
+ :site_home_path => "../../#{dir_depth}index.html",
784
+ :template_path => template_dir,
785
+ }
786
+ full_file_text = page(page_args)
787
+ File.write(tgt_file_path,full_file_text)
763
788
  end
764
789
 
765
790
  # package_docs
@@ -8,7 +8,7 @@ task :build, :build_distro do |task,args|
8
8
  # Figure out which distros we are building.
9
9
  # A blank value here == all distros
10
10
  build_distro = args[:build_distro] || ''
11
- generate_docs(build_distro)
11
+ generate_docs(:all,build_distro,nil)
12
12
  end
13
13
 
14
14
  desc "Package the documentation"
@@ -21,7 +21,7 @@ end
21
21
 
22
22
  desc "Build the documentation and refresh the page"
23
23
  task :refresh_page, :single_page do |task,args|
24
- generate_docs('',args[:single_page])
24
+ generate_docs(:working_only,'',args[:single_page])
25
25
  end
26
26
 
27
27
  desc "Clean all build artifacts"
@@ -1,3 +1,3 @@
1
1
  module AsciiBinder
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ascii_binder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - N. Harrison Ripps
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-03-15 00:00:00.000000000 Z
12
+ date: 2016-04-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -233,6 +233,7 @@ extensions: []
233
233
  extra_rdoc_files: []
234
234
  files:
235
235
  - ".gitignore"
236
+ - Dockerfile
236
237
  - Gemfile
237
238
  - Guardfile
238
239
  - LICENSE.txt