benry-config 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|