benry-config 0.1.0 → 0.2.0
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 +5 -5
- data/CHANGES.md +19 -0
- data/{MIT-LICENSE.txt → MIT-LICENSE} +1 -1
- data/README.md +99 -36
- data/Rakefile.rb +14 -0
- data/benry-config.gemspec +32 -0
- data/doc/benry-config.html +139 -0
- data/doc/css/style.css +168 -0
- data/examples/config/app.rb +13 -0
- data/examples/config/app.secret +5 -0
- data/examples/config/app_dev.rb +7 -0
- data/examples/config/app_prod.rb +10 -0
- data/examples/main.rb +25 -0
- data/lib/benry/config.rb +93 -51
- data/task/common-task.rb +144 -0
- data/task/package-task.rb +72 -0
- data/task/readme-task.rb +125 -0
- data/task/test-task.rb +81 -0
- data/test/config_test.rb +272 -95
- metadata +34 -35
- data/Rakefile +0 -83
data/lib/benry/config.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
3
|
###
|
4
|
-
### $Release: 0.
|
5
|
-
### $Copyright: copyright(c) 2016
|
4
|
+
### $Release: 0.2.0 $
|
5
|
+
### $Copyright: copyright(c) 2016 kwatch@gmail.com $
|
6
6
|
### $License: MIT License $
|
7
7
|
###
|
8
8
|
|
@@ -14,69 +14,62 @@ module Benry
|
|
14
14
|
end
|
15
15
|
|
16
16
|
|
17
|
-
|
18
|
-
## Configuration class.
|
19
|
-
##
|
20
|
-
## ex:
|
21
|
-
##
|
22
|
-
## #----- config/common.rb -----
|
23
|
-
## require 'benry/config'
|
24
|
-
## class CommonConfig < Benry::BaseConfig
|
25
|
-
## add :db_user , "user1"
|
26
|
-
## add :db_pass , ABSTRACT
|
27
|
-
## add :session_cooie , "SESS"
|
28
|
-
## add :session_secret , SECRET
|
29
|
-
## end
|
30
|
-
##
|
31
|
-
## #----- config/development.rb -----
|
32
|
-
## require 'config/common'
|
33
|
-
## class Config < TestCommonConfig
|
34
|
-
## set :db_pass , "pass1"
|
35
|
-
## end
|
36
|
-
##
|
37
|
-
## #----- config/development.private -----
|
38
|
-
## class Config
|
39
|
-
## set :session_secret , "abc123"
|
40
|
-
## end
|
41
|
-
##
|
42
|
-
## #----- main.rb -----
|
43
|
-
## rack_env = ENV['RACK_ENV'] or raise "$RACK_ENV required."
|
44
|
-
## require "./config/#{rack_env}.rb"
|
45
|
-
## load "./config/#{rack_env}.private"
|
46
|
-
## #
|
47
|
-
## $config = Config.new.freeze
|
48
|
-
## p $config.db_user #=> "user1"
|
49
|
-
## p $config.db_pass #=> "pass1"
|
50
|
-
## p $config.session_cookie #=> "SESS"
|
51
|
-
## p $config.session_secret #=> "abc123"
|
52
|
-
## #
|
53
|
-
## p $config.get_all(:db_) #=> {:user=>"user1", :pass=>"pass1"}
|
54
|
-
## p $config.get_all(:session_) #=> {:cookie=>"SESS", :secret=>"abc123"}
|
55
|
-
##
|
56
|
-
class BaseConfig
|
17
|
+
class Config
|
57
18
|
|
58
19
|
class AbstractValue
|
20
|
+
|
21
|
+
def initialize(envvar=nil)
|
22
|
+
#; [!6hcf9] accepts environment variable name.
|
23
|
+
@envvar = envvar
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :envvar
|
27
|
+
|
28
|
+
def [](envvar)
|
29
|
+
#; [!p0acp] returns new object with environment variable name.
|
30
|
+
return self.class.new(envvar)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
class SecretValue < AbstractValue
|
59
36
|
end
|
60
37
|
|
61
38
|
ABSTRACT = AbstractValue.new # represents 'should be set in subclass'
|
62
|
-
SECRET =
|
39
|
+
SECRET = SecretValue.new # represents 'should be set in private config file'
|
63
40
|
|
64
41
|
def initialize
|
65
42
|
#; [!7rdq4] traverses parent class and gathers config values.
|
66
|
-
|
67
|
-
pr.call(cls.superclass) if cls.superclass
|
68
|
-
d = cls.instance_variable_get('@__dict')
|
69
|
-
d.each {|k, v| instance_variable_set("@#{k}", v) } if d
|
70
|
-
}
|
71
|
-
pr.call(self.class)
|
72
|
-
#; [!z9mno] raises ConfigError when ABSTRACT or SECRET is not overriden.
|
43
|
+
_traverse(self.class) {|k, v| instance_variable_set("@#{k}", v) }
|
73
44
|
instance_variables().each do |ivar|
|
74
45
|
val = instance_variable_get(ivar)
|
75
|
-
|
46
|
+
next unless val.is_a?(AbstractValue)
|
47
|
+
#; [!v9f3k] when envvar name not specified...
|
48
|
+
if val.envvar == nil
|
49
|
+
#; [!z9mno] raises ConfigError if ABSTRACT or SECRET is not overriden.
|
76
50
|
raise ConfigError.new("config ':#{ivar.to_s[1..-1]}' should be set, but not.")
|
51
|
+
#; [!ida3r] when envvar name specified...
|
52
|
+
else
|
53
|
+
#; [!txl88] raises ConfigError when envvar not set.
|
54
|
+
envvar = val.envvar
|
55
|
+
begin
|
56
|
+
val = ENV.fetch(envvar.to_s)
|
57
|
+
rescue KeyError
|
58
|
+
raise ConfigError.new("environment variable '$#{envvar}' should be set for config item ':#{ivar.to_s[1..-1]}'.")
|
59
|
+
end
|
60
|
+
#; [!y47ul] sets envvar value as config value if envvar provided.
|
61
|
+
instance_variable_set(ivar, val)
|
62
|
+
end
|
77
63
|
end
|
78
64
|
end
|
79
65
|
|
66
|
+
def _traverse(cls, &b)
|
67
|
+
_traverse(cls.superclass, &b) if cls.superclass && cls.superclass < BaseConfig
|
68
|
+
dict = cls.instance_variable_get(:@__dict)
|
69
|
+
dict.each(&b) if dict
|
70
|
+
end
|
71
|
+
private :_traverse
|
72
|
+
|
80
73
|
## Add new config. Raises ConfigError when already defined.
|
81
74
|
def self.add(key, value, desc=nil)
|
82
75
|
#; [!m7w96] raises ConfigError when already added.
|
@@ -134,7 +127,56 @@ module Benry
|
|
134
127
|
return d
|
135
128
|
end
|
136
129
|
|
130
|
+
def defined?(key)
|
131
|
+
#; [!y1fsh] returns true if config key defined.
|
132
|
+
#; [!k1b5q] returns false if config key not defined.
|
133
|
+
return instance_variable_defined?("@#{key}")
|
134
|
+
end
|
135
|
+
|
136
|
+
def each(sort=false, &b)
|
137
|
+
#; [!f4ljv] returns Enumerator object if block not given.
|
138
|
+
return to_enum(:each, sort) unless block_given?()
|
139
|
+
#; [!4wqpu] yields each key and val with hiding secret values.
|
140
|
+
#; [!a9glw] sorts keys if 'true' specified as the first argument.
|
141
|
+
_each(sort, true, &b)
|
142
|
+
#; [!wggik] returns self if block given.
|
143
|
+
return self
|
144
|
+
end
|
145
|
+
|
146
|
+
def each!(sort=false, &b)
|
147
|
+
#; [!zd9lk] returns Enumerator object if block not given.
|
148
|
+
return to_enum(:each!, sort) unless block_given?()
|
149
|
+
#; [!7i5p2] yields each key and val without hiding secret values.
|
150
|
+
#; [!aib7c] sorts keys if 'true' specified as the first argument.
|
151
|
+
_each(sort, false, &b)
|
152
|
+
#; [!2abgb] returns self if block given.
|
153
|
+
return self
|
154
|
+
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def _each(sort, hide_secret, &b)
|
159
|
+
keys_d = {}
|
160
|
+
secrets_d = {}
|
161
|
+
_traverse(self.class) do |key, val|
|
162
|
+
keys_d[key] = true
|
163
|
+
secrets_d[key] = val if val.is_a?(SecretValue)
|
164
|
+
end
|
165
|
+
#; [!6yvgd] sorts keys if 'sort' is true.
|
166
|
+
keys = keys_d.keys()
|
167
|
+
keys.sort!() if sort
|
168
|
+
keys.each do |key|
|
169
|
+
#; [!5ledb] hides value if 'hide_secret' is true and value is Secretvalue object.
|
170
|
+
hide_p = hide_secret && secrets_d.key?(key)
|
171
|
+
val = hide_p ? "(secret)" : instance_variable_get("@#{key}".intern)
|
172
|
+
yield key, val
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
137
176
|
end
|
138
177
|
|
139
178
|
|
179
|
+
BaseConfig = Config # for backward compatibility
|
180
|
+
|
181
|
+
|
140
182
|
end
|
data/task/common-task.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
|
4
|
+
defined? PROJECT or abort "PROJECT required."
|
5
|
+
defined? RELEASE or abort "RELEASE required."
|
6
|
+
defined? COPYRIGHT or abort "COPYRIGHT required."
|
7
|
+
defined? LICENSE or abort "LICENSE required."
|
8
|
+
|
9
|
+
RELEASE =~ /\A\d+\.\d+\.\d+/ or abort "RELEASE=#{RELEASE}: invalid release number."
|
10
|
+
|
11
|
+
|
12
|
+
require 'rake/clean'
|
13
|
+
CLEAN << "build"
|
14
|
+
CLEAN.concat Dir.glob("#{PROJECT}-*.gem").collect {|x| x.sub(/\.gem$/, '') }
|
15
|
+
CLOBBER.concat Dir.glob("#{PROJECT}-*.gem")
|
16
|
+
|
17
|
+
|
18
|
+
task :default do
|
19
|
+
sh "rake -T", verbose: false
|
20
|
+
end unless Rake::Task.task_defined?(:default)
|
21
|
+
|
22
|
+
|
23
|
+
desc "show release guide"
|
24
|
+
task :guide do
|
25
|
+
do_guide()
|
26
|
+
end
|
27
|
+
|
28
|
+
def do_guide()
|
29
|
+
RELEASE != '0.0.0' or abort "** ERROR: 'RELEASE=X.X.X' required."
|
30
|
+
puts guide_message(PROJECT, RELEASE)
|
31
|
+
end
|
32
|
+
|
33
|
+
def guide_message(project, release)
|
34
|
+
target = "#{project}-#{release}"
|
35
|
+
tag = "#{project}-#{release}"
|
36
|
+
puts <<END
|
37
|
+
How to release:
|
38
|
+
|
39
|
+
$ git diff .
|
40
|
+
$ git status .
|
41
|
+
$ which ruby
|
42
|
+
$ rake test
|
43
|
+
$ rake test:all
|
44
|
+
$ rake doc
|
45
|
+
$ rake doc:export RELEASE=#{release}
|
46
|
+
$ rake readme:execute # optional
|
47
|
+
$ rake readme:toc # optional
|
48
|
+
$ rake package RELEASE=#{release}
|
49
|
+
$ rake package:extract # confirm files in gem file
|
50
|
+
$ (cd #{target}/data; find . -type f)
|
51
|
+
$ gem install #{target}.gem # confirm gem package
|
52
|
+
$ gem uninstall #{project}
|
53
|
+
$ gem push #{target}.gem # publish gem to rubygems.org
|
54
|
+
$ git tag #{tag} # or: git tag ruby-#{tag}
|
55
|
+
$ git push --tags
|
56
|
+
$ rake clean
|
57
|
+
$ mv #{target}.gem archive/
|
58
|
+
$ cd ../docs/
|
59
|
+
$ git add #{target}.html
|
60
|
+
$ git commit -m "[main] docs: update '#{target}.html'"
|
61
|
+
$ git push
|
62
|
+
END
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
desc "create 'README.md' and 'doc/*.html'"
|
67
|
+
task :doc do
|
68
|
+
x = PROJECT
|
69
|
+
cd "doc" do
|
70
|
+
sh "../../docs/md2 --md #{x}.mdx > ../README.md"
|
71
|
+
sh "../../docs/md2 #{x}.mdx > #{x}.html"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
desc "copy 'doc/*.html' to '../docs/'"
|
76
|
+
task 'doc:export' do
|
77
|
+
RELEASE != '0.0.0' or abort "** ERROR: 'RELEASE=X.X.X' required."
|
78
|
+
x = PROJECT
|
79
|
+
cp "doc/#{x}.html", "../docs/"
|
80
|
+
edit_file!("../docs/#{x}.html")
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
desc "edit metadata in files"
|
85
|
+
task :edit do
|
86
|
+
do_edit()
|
87
|
+
end
|
88
|
+
|
89
|
+
def do_edit()
|
90
|
+
target_files().each do |fname|
|
91
|
+
edit_file!(fname)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def target_files()
|
96
|
+
$_target_files ||= begin
|
97
|
+
spec_src = File.read("#{PROJECT}.gemspec", encoding: 'utf-8')
|
98
|
+
spec = eval spec_src
|
99
|
+
spec.name == PROJECT or
|
100
|
+
abort "** ERROR: '#{PROJECT}' != '#{spec.name}' (project name in gemspec file)"
|
101
|
+
spec.files + Dir.glob("doc/*.mdx")
|
102
|
+
end
|
103
|
+
return $_target_files
|
104
|
+
end
|
105
|
+
|
106
|
+
def edit_file!(filename, verbose: true)
|
107
|
+
changed = edit_file(filename) do |s|
|
108
|
+
s = s.gsub(/\$Release[:].*?\$/, "$"+"Release: #{RELEASE} $")
|
109
|
+
s = s.gsub(/\$Copyright[:].*?\$/, "$"+"Copyright: #{COPYRIGHT} $")
|
110
|
+
s = s.gsub(/\$License[:].*?\$/, "$"+"License: #{LICENSE} $")
|
111
|
+
s
|
112
|
+
end
|
113
|
+
if verbose
|
114
|
+
puts "[C] #{filename}" if changed
|
115
|
+
puts "[U] #{filename}" unless changed
|
116
|
+
end
|
117
|
+
return changed
|
118
|
+
end
|
119
|
+
|
120
|
+
def edit_file(filename)
|
121
|
+
File.open(filename, 'rb+') do |f|
|
122
|
+
s1 = f.read()
|
123
|
+
s2 = yield s1
|
124
|
+
if s1 != s2
|
125
|
+
f.rewind()
|
126
|
+
f.truncate(0)
|
127
|
+
f.write(s2)
|
128
|
+
true
|
129
|
+
else
|
130
|
+
false
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
desc nil
|
137
|
+
task :'relink' do
|
138
|
+
Dir.glob("task/*.rb").each do |x|
|
139
|
+
src = "../" + x
|
140
|
+
next if File.identical?(src, x)
|
141
|
+
rm x
|
142
|
+
ln src, x
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
|
4
|
+
desc "create package (*.gem)"
|
5
|
+
task :package do
|
6
|
+
do_package()
|
7
|
+
end
|
8
|
+
|
9
|
+
def do_package()
|
10
|
+
RELEASE != '0.0.0' or abort "** ERROR: 'RELEASE=X.X.X' required."
|
11
|
+
## copy
|
12
|
+
dir = "build"
|
13
|
+
rm_rf dir if File.exist?(dir)
|
14
|
+
mkdir dir
|
15
|
+
target_files().each do |file|
|
16
|
+
dest = File.join(dir, File.dirname(file))
|
17
|
+
mkdir_p dest, :verbose=>false unless File.exist?(dest)
|
18
|
+
cp file, "#{dir}/#{file}"
|
19
|
+
end
|
20
|
+
## edit
|
21
|
+
Dir.glob("#{dir}/**/*").each do |file|
|
22
|
+
next unless File.file?(file)
|
23
|
+
edit_file!(file, verbose: false)
|
24
|
+
end
|
25
|
+
## build
|
26
|
+
chdir dir do
|
27
|
+
sh "gem build #{PROJECT}.gemspec"
|
28
|
+
end
|
29
|
+
mv "#{dir}/#{PROJECT}-#{RELEASE}.gem", "."
|
30
|
+
rm_rf dir
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
desc "extract latest gem file"
|
35
|
+
task :'package:extract' do
|
36
|
+
do_package_extract()
|
37
|
+
end
|
38
|
+
|
39
|
+
def do_package_extract()
|
40
|
+
gemfile = Dir.glob("#{PROJECT}-*.gem").sort_by {|x| File.mtime(x) }.last
|
41
|
+
dir = gemfile.sub(/\.gem$/, '')
|
42
|
+
rm_rf dir if File.exist?(dir)
|
43
|
+
mkdir dir
|
44
|
+
mkdir "#{dir}/data"
|
45
|
+
cd dir do
|
46
|
+
sh "tar xvf ../#{gemfile}"
|
47
|
+
sh "gunzip *.gz"
|
48
|
+
cd "data" do
|
49
|
+
sh "tar xvf ../data.tar"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
desc "upload gem file to rubygems.org"
|
56
|
+
task :publish do
|
57
|
+
do_publish()
|
58
|
+
end
|
59
|
+
|
60
|
+
def do_publish()
|
61
|
+
RELEASE != '0.0.0' or abort "** ERROR: 'RELEASE=X.X.X' required."
|
62
|
+
gemfile = "#{PROJECT}-#{RELEASE}.gem"
|
63
|
+
print "** Are you sure to publish #{gemfile}? [y/N]: "
|
64
|
+
answer = $stdin.gets().strip()
|
65
|
+
if answer.downcase == "y"
|
66
|
+
sh "gem push #{gemfile}"
|
67
|
+
#sh "git tag ruby-#{PROJECT}-#{RELEASE}"
|
68
|
+
sh "git tag #{PROJECT}-#{RELEASE}"
|
69
|
+
sh "#git push"
|
70
|
+
sh "#git push --tags"
|
71
|
+
end
|
72
|
+
end
|
data/task/readme-task.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
README_FILE = "README.md" unless defined? README_FILE
|
4
|
+
README_EXTRACT = /^[Ff]ile: +(\S+)/ unless defined? README_EXTRACT
|
5
|
+
README_CODESTART = /^```\w+$/ unless defined? README_CODESTART
|
6
|
+
README_CODEEND = /^```$/ unless defined? README_CODEEND
|
7
|
+
README_DESTDIR = "tmp/readme" unless defined? README_DESTDIR
|
8
|
+
|
9
|
+
require 'rake/clean'
|
10
|
+
CLEAN << "README.html"
|
11
|
+
|
12
|
+
|
13
|
+
def readme_extract_callback(filename, str)
|
14
|
+
return str
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
namespace :readme do
|
19
|
+
|
20
|
+
|
21
|
+
desc "retrieve scripts from #{README_FILE}"
|
22
|
+
task :retrieve do
|
23
|
+
do_readme_retrieve()
|
24
|
+
end
|
25
|
+
|
26
|
+
def do_readme_retrieve()
|
27
|
+
dir = README_DESTDIR
|
28
|
+
rm_rf dir if File.exist?(dir)
|
29
|
+
mkdir_p dir
|
30
|
+
s = File.read(README_FILE, encoding: 'utf-8')
|
31
|
+
filename = nil
|
32
|
+
buf = nil
|
33
|
+
s.each_line do |line|
|
34
|
+
case line
|
35
|
+
when README_EXTRACT
|
36
|
+
filename = $1
|
37
|
+
next
|
38
|
+
when README_CODESTART
|
39
|
+
if filename
|
40
|
+
buf = []
|
41
|
+
end
|
42
|
+
next
|
43
|
+
when README_CODEEND
|
44
|
+
if filename && buf
|
45
|
+
newfile = "#{dir}/#{filename}"
|
46
|
+
unless File.exist?(File.dirname(newfile))
|
47
|
+
mkdir_p File.dirname(newfile)
|
48
|
+
end
|
49
|
+
str = readme_extract_callback(filename, buf.join())
|
50
|
+
File.write(newfile, str, encoding: 'utf-8')
|
51
|
+
puts "[retrieve] #{newfile}"
|
52
|
+
end
|
53
|
+
filename = nil
|
54
|
+
buf = nil
|
55
|
+
next
|
56
|
+
end
|
57
|
+
#
|
58
|
+
if buf
|
59
|
+
buf << line
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
desc "execute code in readme file"
|
66
|
+
task :execute => :retrieve do
|
67
|
+
do_readme_execute()
|
68
|
+
end
|
69
|
+
|
70
|
+
def do_readme_execute()
|
71
|
+
Dir.glob(README_DESTDIR+'/**/*.rb').sort.each do |fpath|
|
72
|
+
puts "========================================"
|
73
|
+
sh "ruby -I lib #{fpath}" do end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
desc "builds table of contents"
|
79
|
+
task :toc do
|
80
|
+
do_readme_toc()
|
81
|
+
end
|
82
|
+
|
83
|
+
def do_readme_toc()
|
84
|
+
url = ENV['README_URL'] or abort "$README_URL required."
|
85
|
+
mkdir "tmp" unless Dir.exist?("tmp")
|
86
|
+
htmlfile = "tmp/README.html"
|
87
|
+
sh "curl -s -o #{htmlfile} #{url}"
|
88
|
+
#rexp = /<h(\d) dir="auto"><a id="(.*?)" class="anchor".*><\/a>(.*)<\/h\1>/
|
89
|
+
rexp = /<h(\d) id="user-content-.*?" dir="auto"><a class="heading-link" href="#(.*?)">(.*)<svg/
|
90
|
+
html_str = File.read(htmlfile, encoding: 'utf-8')
|
91
|
+
buf = []
|
92
|
+
html_str.scan(rexp) do
|
93
|
+
level = $1.to_i
|
94
|
+
id = $2
|
95
|
+
title = $3
|
96
|
+
next if title =~ /Table of Contents/
|
97
|
+
title = title.gsub(/<\/?code>/, '`')
|
98
|
+
anchor = id.sub(/^user-content-/, '')
|
99
|
+
indent = " " * (level - 1)
|
100
|
+
buf << "#{indent}* <a href=\"##{anchor}\">#{title}</a>\n"
|
101
|
+
end
|
102
|
+
buf.shift() if buf[0] && buf[0] =~ /^\* /
|
103
|
+
toc_str = buf.join()
|
104
|
+
#
|
105
|
+
mdfile = README_FILE
|
106
|
+
changed = File.open(mdfile, "r+", encoding: 'utf-8') do |f|
|
107
|
+
s1 = f.read()
|
108
|
+
s2 = s1.sub(/(<!-- TOC -->\n).*(<!-- \/TOC -->\n)/m) {
|
109
|
+
[$1, toc_str, $2].join("\n")
|
110
|
+
}
|
111
|
+
if s1 != s2
|
112
|
+
f.rewind()
|
113
|
+
f.truncate(0)
|
114
|
+
f.write(s2)
|
115
|
+
true
|
116
|
+
else
|
117
|
+
false
|
118
|
+
end
|
119
|
+
end
|
120
|
+
puts "[changed] #{mdfile}" if changed
|
121
|
+
puts "[not changed] #{mdfile}" unless changed
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
end
|
data/task/test-task.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
|
4
|
+
unless defined?(RUBY_VERSIONS)
|
5
|
+
RUBY_VERSIONS = (
|
6
|
+
if ENV['RUBY_VERSIONS']
|
7
|
+
ENV['RUBY_VERSIONS'].split()
|
8
|
+
else
|
9
|
+
["3.2", "3.1", "3.0", "2.7", "2.6", "2.5", "2.4", "2.3"]
|
10
|
+
end
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
desc "run test"
|
16
|
+
task :test do
|
17
|
+
do_test()
|
18
|
+
end
|
19
|
+
|
20
|
+
def do_test()
|
21
|
+
run_test()
|
22
|
+
end
|
23
|
+
|
24
|
+
def run_test(ruby=nil, &b)
|
25
|
+
run_oktest(ruby, &b)
|
26
|
+
end
|
27
|
+
|
28
|
+
def run_minitest(ruby=nil, &b)
|
29
|
+
files = File.exist?("test/run_all.rb") \
|
30
|
+
? ["test/run_all.rb"] \
|
31
|
+
: Dir.glob("test/**/*_test.rb")
|
32
|
+
if ruby
|
33
|
+
sh(ruby, *files, &b)
|
34
|
+
else
|
35
|
+
ruby(*files, &b)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def run_oktest(ruby=nil, &b)
|
40
|
+
argstr = "-r oktest -e Oktest.main -- test -sp"
|
41
|
+
if ruby
|
42
|
+
sh("#{ruby} #{argstr}", &b)
|
43
|
+
else
|
44
|
+
ruby(argstr, &b)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
desc "run test in different ruby versions"
|
50
|
+
task :'test:all' do
|
51
|
+
do_test_all()
|
52
|
+
end
|
53
|
+
|
54
|
+
def do_test_all()
|
55
|
+
ENV['VS_HOME'] or
|
56
|
+
abort "[ERROR] rake test:all: '$VS_HOME' environment var required."
|
57
|
+
vs_home = ENV['VS_HOME'].split(/[:;]/).first
|
58
|
+
ruby_versions = RUBY_VERSIONS
|
59
|
+
test_all(vs_home, ruby_versions)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_all(vs_home, ruby_versions)
|
63
|
+
header = proc {|s| "\033[0;36m=============== #{s} ===============\033[0m" }
|
64
|
+
error = proc {|s| "\033[0;31m** #{s}\033[0m" }
|
65
|
+
comp = proc {|x, y| x.to_s.split('.').map(&:to_i) <=> y.to_s.split('.').map(&:to_i) }
|
66
|
+
ruby_versions.each do |ver|
|
67
|
+
dir = Dir.glob("#{vs_home}/ruby/#{ver}.*/").sort_by(&comp).last
|
68
|
+
puts ""
|
69
|
+
if dir
|
70
|
+
puts header.("#{ver} (#{dir})")
|
71
|
+
run_test("#{dir}/bin/ruby") do |ok, res|
|
72
|
+
$stderr.puts error.("test failed") unless ok
|
73
|
+
end
|
74
|
+
sleep 0.2
|
75
|
+
else
|
76
|
+
puts header.(ver)
|
77
|
+
$stderr.puts error.("ruby #{ver} not found")
|
78
|
+
sleep 1.0
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|