xot 0.4.0 → 0.5.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.
@@ -0,0 +1,106 @@
1
+ require 'tmpdir'
2
+ require 'xot/rake/util'
3
+ require 'xot/rake/changelog'
4
+
5
+
6
+ module Xot
7
+
8
+
9
+ module Rake
10
+
11
+ MONOREPO = 'xord/all'
12
+ MONOREPO_DIR = '../all'
13
+ MONOREPO_FETCH_DEPTH = 100
14
+
15
+ def setup_dependencies(only: nil, ext: true)
16
+ deps = dependency_names
17
+ deps &= Array(only).map(&:to_s) if only
18
+ return if deps.empty?
19
+
20
+ checkout_monorepo
21
+ link_monorepo deps, ext: ext
22
+ end
23
+
24
+ def setup_monorepo(ref, *libraries)
25
+ raise 'no libraries of the monorepo to set up' if libraries.empty?
26
+ sh 'git', 'init', '-q', MONOREPO_DIR
27
+ Dir.chdir MONOREPO_DIR do
28
+ sh 'git', 'fetch', '-q', '--depth', '1', "https://github.com/#{MONOREPO}.git", ref
29
+ sh 'git', 'checkout', '-q', 'FETCH_HEAD'
30
+ end
31
+ link_monorepo libraries
32
+ end
33
+
34
+ MESA_VERSION = '26.2.0'
35
+
36
+ def setup_mesa(version = MESA_VERSION)
37
+ name = "mesa3d-#{version}-release-msvc"
38
+ url = "https://github.com/pal1000/mesa-dist-win/releases/download/#{version}/#{name}.7z"
39
+ Dir.mktmpdir do |dir|
40
+ Dir.chdir dir do
41
+ sh 'curl', '-sSfL', '-o', 'mesa.7z', url
42
+ sh '7z', 'x', 'mesa.7z'
43
+ sh 'powershell.exe', '.\\systemwidedeploy.cmd', '1'
44
+ end
45
+ end
46
+ File.open(ENV['GITHUB_ENV'], 'a') {|f| f.puts 'GALLIUM_DRIVER=llvmpipe'}
47
+ end
48
+
49
+ def dependency_names()
50
+ File.readlines('Rakefile')
51
+ .filter_map {_1[%r{^\s*require\W+([\w\-]+)/extension\W+$}, 1]}
52
+ .reject {File.file? "lib/#{_1}/extension.rb"} # of this repository
53
+ end
54
+
55
+ def checkout_monorepo()
56
+ uuid = git('log', '-1', '--format=%B')[/^\[\[([0-9a-fA-F-]+)\]\]$/, 1] ||
57
+ raise('no UUID of the monorepo in the last commit')
58
+ commit = fetch_monorepo(uuid) ||
59
+ raise("no commit of the monorepo with the UUID #{uuid}")
60
+
61
+ Dir.chdir(MONOREPO_DIR) {sh 'git', 'checkout', '-q', commit}
62
+ end
63
+
64
+ def release_on_github(*paths, tag: ENV['GITHUB_REF_NAME'], notes: nil)
65
+ raise 'no tag to release' unless tag
66
+ notes ||= ChangeLog.new.changes(tag).to_s
67
+ sh('gh', 'release', 'create', tag, *paths, '--notes', notes) {|ok, _| ok} ||
68
+ sh('gh', 'release', 'upload', tag, *paths, '--clobber')
69
+ end
70
+
71
+ private
72
+
73
+ def link_monorepo(libraries, ext: true)
74
+ libraries.each {|lib| sh %( cd #{MONOREPO_DIR}/#{lib} && rake ext )} if ext
75
+ libraries.each do |lib|
76
+ if win32?
77
+ rm_rf "../#{lib}"
78
+ cp_r "#{MONOREPO_DIR}/#{lib}", "../#{lib}"
79
+ else
80
+ sh 'ln', '-snf', "#{File.basename MONOREPO_DIR}/#{lib}", "../#{lib}"
81
+ end
82
+ end
83
+ end
84
+
85
+ def fetch_monorepo(uuid)
86
+ unless File.directory? MONOREPO_DIR
87
+ sh 'git', 'clone', '--no-tags', '--depth', MONOREPO_FETCH_DEPTH.to_s,
88
+ "https://github.com/#{MONOREPO}.git", MONOREPO_DIR
89
+ end
90
+ Dir.chdir MONOREPO_DIR do
91
+ loop do
92
+ commit = git('log', 'origin/HEAD', '-F', "--grep=[[#{uuid}]]", '--format=%H', '-1').strip
93
+ return commit unless commit.empty?
94
+
95
+ count = git('rev-list', '--count', 'HEAD').to_i
96
+ sh 'git', 'fetch', '--deepen', MONOREPO_FETCH_DEPTH.to_s
97
+ return nil if git('rev-list', '--count', 'HEAD').to_i == count
98
+ end
99
+ end
100
+ end
101
+
102
+
103
+ end# Rake
104
+
105
+
106
+ end# Xot
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Writes the version of the section added to a ChangeLog.md in the commit
4
+ # into the VERSION beside it, and adds it to the commit.
5
+ #
6
+ # Copied into .git/hooks by 'rake hooks' of xot as it is, so that it runs
7
+ # with any ruby, requiring nothing.
8
+
9
+
10
+ def git(*args)
11
+ IO.popen ['git', *args], &:read
12
+ end
13
+
14
+ def added_version(changelog)
15
+ git('diff', '--cached', '--', changelog)
16
+ .slice(/^\+\s*##\s*\[\s*v(\d[\d\.]*)\s*\]\s*-\s*\d{4}-\d{2}-\d{2}\s*$/, 1)
17
+ end
18
+
19
+ git('ls-files').lines(chomp: true)
20
+ .grep(%r{(\A|/)VERSION\z})
21
+ .map {[_1.sub(/VERSION\z/, 'ChangeLog.md'), _1]}
22
+ .select {|paths| paths.all? {File.file? _1}}
23
+ .each do |changelog, version|
24
+ ver = added_version changelog
25
+ next if !ver || ver == File.read(version)[/[\d\.]+/]
26
+
27
+ abort "pre-commit: #{version} has changes not to be overwritten" unless
28
+ git('diff', '--', version).empty?
29
+
30
+ File.write version, ver
31
+ system 'git', 'add', version, exception: true
32
+ end
data/lib/xot/rake/util.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'erb'
2
+ require 'fileutils'
2
3
  require 'rbconfig'
3
4
  require 'xot/util'
5
+ require 'xot/rake/changelog'
4
6
 
5
7
 
6
8
  module Xot
@@ -125,37 +127,6 @@ module Xot
125
127
  excludes.any? {|s| path =~ %r{#{s}}}
126
128
  end
127
129
 
128
- def glob(*patterns)
129
- paths = []
130
- patterns.each do |pattern|
131
- paths.concat Dir.glob(pattern)
132
- end
133
- paths
134
- end
135
-
136
- def rake_puts(*args)
137
- $stderr.puts(*args)
138
- end
139
-
140
- def verbose_puts(*args)
141
- rake_puts(*args) if ::Rake.verbose
142
- end
143
-
144
- def noverbose_puts(*args)
145
- rake_puts(*args) unless ::Rake.verbose
146
- end
147
-
148
- def filter_file(path, &block)
149
- File.write path, block.call(File.read path)
150
- end
151
-
152
- def cd_sh(dir, cmd)
153
- Dir.chdir dir do
154
- rake_puts "(in #{Dir.pwd})"
155
- sh cmd
156
- end
157
- end
158
-
159
130
  def compile_erb(path, out)
160
131
  open(path) do |input|
161
132
  open(out, 'w') do |output|
@@ -187,16 +158,19 @@ module Xot
187
158
  a = defs.dup
188
159
  a << (debug? ? '_DEBUG' : 'NDEBUG')
189
160
  a << target_name.gsub('-', '_').upcase
190
- a << $~[0].upcase if RUBY_PLATFORM =~ /mswin|mingw|cygwin|darwin/i
191
- a << 'WIN32' if win32?
192
- a << 'OSX' if osx?
193
- a << 'IOS' if ios?
194
- a << 'LINUX' if linux?
195
- a << 'WASM' if wasm?
196
- a << 'GCC' if gcc?
197
- a << 'CLANG' if clang?
198
- a << '_USE_MATH_DEFINES' if gcc?
199
- a << '_THREAD_SAFE' if linux?
161
+ a << $~[0].upcase if RUBY_PLATFORM =~ /mswin|mingw|cygwin|darwin/i
162
+ a << 'WIN32' if win32?
163
+ a << 'OSX' if osx?
164
+ a << 'IOS' if ios?
165
+ a << 'LINUX' if linux?
166
+ a << 'WASM' if wasm?
167
+ a << 'GCC' if gcc?
168
+ a << 'CLANG' if clang?
169
+ a << '_USE_MATH_DEFINES' if gcc?
170
+ a << '_THREAD_SAFE' if linux?
171
+ a << 'GL_SILENCE_DEPRECATION' if osx?
172
+ a << 'GLES_SILENCE_DEPRECATION' if ios?
173
+ a << 'OPENAL_DEPRECATED=' if osx? || ios?
200
174
  a
201
175
  end
202
176
 
@@ -224,7 +198,7 @@ module Xot
224
198
  s << " -arch arm64" if osx? && arm64?
225
199
  s << " -std=#{std}" if clang? || gcc? || emcc?
226
200
  s << " -stdlib=#{stdlib}" if clang? && stdlib
227
- s << ' -mmacosx-version-min=10.10' if clang? && osx?
201
+ s << ' -mmacosx-version-min=11.0' if clang? && osx?
228
202
  s << ' ' + RbConfig::CONFIG['debugflags'] if debug?
229
203
  s.gsub!(/-O\d?\w*/, '-O0') if debug?
230
204
  s << warn_opts.map {|s| " -W#{s}"}.join
@@ -278,6 +252,51 @@ module Xot
278
252
  flags
279
253
  end
280
254
 
255
+ def install_hooks()
256
+ dir = git('rev-parse', '--git-path', 'hooks').strip
257
+ FileUtils.mkdir_p dir
258
+ Dir.glob(File.join __dir__, 'hooks', '*').each do |hook|
259
+ FileUtils.cp hook, dir
260
+ FileUtils.chmod 0755, File.join(dir, File.basename(hook))
261
+ end
262
+ end
263
+
264
+ def version_changes(dir = '.')
265
+ commit = git('log', '-1', '--format=%H', '--', File.join(dir, 'VERSION')).strip
266
+ range = commit.empty? ? 'HEAD' : "#{commit}..HEAD"
267
+ git('log', '--first-parent', '--reverse', '--format=%x00%P%n%B', range, '--', dir)
268
+ .split("\0")
269
+ .drop(1)
270
+ .map do |log|
271
+ parents, *lines = log.lines(chomp: true)
272
+ lines = lines.reject {_1.strip.empty?}
273
+ merge = parents.split.size > 1 && lines.first&.start_with?('Merge branch ')
274
+ (merge && lines[1]) || lines.first
275
+ end
276
+ end
277
+
278
+ def next_version(dir = '.')
279
+ nums = File.read(File.join dir, 'VERSION')[/[\d\.]+/].split('.').map(&:to_i)
280
+ nums = (nums + [0, 0, 0]).first(3)
281
+ nums[2] += 1
282
+ nums.join '.'
283
+ end
284
+
285
+ def tag_versions()
286
+ changelog = ChangeLog.new
287
+ tags = git('tag').lines chomp: true
288
+ versions = git('log', '--format=%H', '--', 'VERSION').lines(chomp: true)
289
+ .map {[git('show', "#{_1}:VERSION")[/[\d\.]+/], _1]}
290
+ .select {|version, _| version}
291
+ .uniq {|version, _| version} # the newest commit of a version
292
+
293
+ versions.each do |version, commit|
294
+ tag = "v#{version}"
295
+ break if tags.include? tag
296
+ sh 'git', 'tag', '-a', '-m', changelog.changes(version).to_s, tag, commit
297
+ end
298
+ end
299
+
281
300
  def default_tasks(default = nil)
282
301
  verbose? get_env(:VERBOSE, false)
283
302
 
@@ -296,6 +315,43 @@ module Xot
296
315
  end
297
316
  end
298
317
 
318
+ private
319
+
320
+ def glob(*patterns)
321
+ paths = []
322
+ patterns.each do |pattern|
323
+ paths.concat Dir.glob(pattern)
324
+ end
325
+ paths
326
+ end
327
+
328
+ def rake_puts(*args)
329
+ $stderr.puts(*args)
330
+ end
331
+
332
+ def verbose_puts(*args)
333
+ rake_puts(*args) if ::Rake.verbose
334
+ end
335
+
336
+ def noverbose_puts(*args)
337
+ rake_puts(*args) unless ::Rake.verbose
338
+ end
339
+
340
+ def filter_file(path, &block)
341
+ File.write path, block.call(File.read path)
342
+ end
343
+
344
+ def cd_sh(dir, cmd)
345
+ Dir.chdir dir do
346
+ rake_puts "(in #{Dir.pwd})"
347
+ sh cmd
348
+ end
349
+ end
350
+
351
+ def git(*args, **opts)
352
+ IO.popen ['git', *args], **opts, &:read
353
+ end
354
+
299
355
 
300
356
  end# Rake
301
357
 
data/lib/xot/rake.rb CHANGED
@@ -3,6 +3,7 @@ require 'rake'
3
3
  require 'rake/loaders/makefile'
4
4
  require 'rake/testtask'
5
5
  require 'xot/rake/alias_task'
6
+ require 'xot/rake/github'
6
7
  require 'xot/rake/util'
7
8
  #require 'xot/rake/escalation'
8
9
 
@@ -258,6 +259,34 @@ module Xot
258
259
  end
259
260
  end
260
261
 
262
+ def automate_release()
263
+ desc 'install the git hooks'
264
+ task :hooks do
265
+ install_hooks
266
+ end
267
+
268
+ namespace :changelog do
269
+ desc 'show the commits for the next version'
270
+ task :check => :hooks do
271
+ puts version_changes
272
+ end
273
+
274
+ desc 'add the section of the next version'
275
+ task :update => :hooks do
276
+ changes = version_changes
277
+ next puts 'no changes since VERSION was changed, skipped' if changes.empty?
278
+ ChangeLog.new.add ENV['version'] || next_version, changes
279
+ end
280
+ end
281
+
282
+ namespace :version do
283
+ desc 'tag the new version'
284
+ task :tag do
285
+ tag_versions
286
+ end
287
+ end
288
+ end
289
+
261
290
  def install_packages(osx: [], mingw: [], apt: [])
262
291
  desc "install packages"
263
292
  task :packages do
data/lib/xot/setter.rb CHANGED
@@ -14,11 +14,11 @@ module Xot
14
14
 
15
15
  private
16
16
 
17
- def set_value__(name, *values)
18
- raise ArgumentError, "set '#{values}' to '#{name}'" if
19
- !name || name.empty? || values.empty?
20
- __send__ "#{name}=", *values
21
- end
17
+ def set_value__(name, *values)
18
+ raise ArgumentError, "set '#{values}' to '#{name}'" if
19
+ !name || name.empty? || values.empty?
20
+ __send__ "#{name}=", *values
21
+ end
22
22
 
23
23
  end# Setter
24
24
 
@@ -10,19 +10,19 @@ module Xot
10
10
 
11
11
  private
12
12
 
13
- def define_universal_accessor(name, options = {})
14
- set = "ua_set_#{name}__"
15
- get = "ua_get_#{name}__"
16
- class_eval <<-END
17
- alias_method :#{set}, options[:writer] || :#{name}=
18
- alias_method :#{get}, options[:reader] || :#{name}
19
- private :#{set}, :#{get}
20
- def #{name}(*args, **kwargs)
21
- #{set}(*args, **kwargs) unless args.empty? && args.empty?
22
- #{get}
23
- end
24
- END
25
- end
13
+ def define_universal_accessor(name, options = {})
14
+ set = "ua_set_#{name}__"
15
+ get = "ua_get_#{name}__"
16
+ class_eval <<-END
17
+ alias_method :#{set}, options[:writer] || :#{name}=
18
+ alias_method :#{get}, options[:reader] || :#{name}
19
+ private :#{set}, :#{get}
20
+ def #{name}(*args, **kwargs)
21
+ #{set}(*args, **kwargs) unless args.empty? && kwargs.empty?
22
+ #{get}
23
+ end
24
+ END
25
+ end
26
26
 
27
27
  end# UniversalAccessor
28
28
 
data/src/util.cpp CHANGED
@@ -53,22 +53,6 @@ namespace Xot
53
53
  }
54
54
 
55
55
 
56
- static HintMemoryUsageFun hint_memory_usage_fun = NULL;
57
-
58
- void
59
- set_hint_memory_usage_fun (HintMemoryUsageFun fun)
60
- {
61
- hint_memory_usage_fun = fun;
62
- }
63
-
64
- void
65
- hint_memory_usage (ssize_t size)
66
- {
67
- if (hint_memory_usage_fun && size != 0)
68
- hint_memory_usage_fun(size);
69
- }
70
-
71
-
72
56
  #if defined(OSX) || defined(IOS)
73
57
 
74
58
  void
data/test/helper.rb CHANGED
@@ -6,6 +6,57 @@ require 'xot'
6
6
  require 'xot/test'
7
7
  require_relative '../ext/xot/tester'
8
8
 
9
+ require 'fileutils'
10
+ require 'tmpdir'
9
11
  require 'test/unit'
10
12
 
11
13
  include Xot::Test
14
+
15
+
16
+ module GitRepo
17
+
18
+ GIT_ENV = {
19
+ 'GIT_CONFIG_GLOBAL' => File::NULL,
20
+ 'GIT_CONFIG_NOSYSTEM' => '1',
21
+ 'GIT_AUTHOR_NAME' => 'test',
22
+ 'GIT_AUTHOR_EMAIL' => 'test@example.com',
23
+ 'GIT_COMMITTER_NAME' => 'test',
24
+ 'GIT_COMMITTER_EMAIL' => 'test@example.com'
25
+ }
26
+
27
+ CHANGELOG = "# app ChangeLog\n\n\n## [v0.1.0] - 2026-10-01\n\n- First\n"
28
+
29
+ def repo(&block)
30
+ Dir.mktmpdir do |dir|
31
+ Dir.chdir dir do
32
+ with_env GIT_ENV do
33
+ git! 'init', '-q'
34
+ commit 'Start', 'VERSION' => '0.1.0', 'ChangeLog.md' => CHANGELOG
35
+ block.call dir
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ def commit(message, files = {})
42
+ files.each do |path, text|
43
+ FileUtils.mkdir_p File.dirname(path)
44
+ File.write path, text
45
+ end
46
+ git! 'add', '-A'
47
+ git! 'commit', '-q', '-m', message
48
+ end
49
+
50
+ def git!(*args)
51
+ system 'git', *args, exception: true, out: File::NULL, err: File::NULL
52
+ end
53
+
54
+ def with_env(env, &block)
55
+ saved = env.to_h {|key, _| [key, ENV[key]]}
56
+ env.each {|key, value| ENV[key] = value}
57
+ block.call
58
+ ensure
59
+ saved.each {|key, value| ENV[key] = value}
60
+ end
61
+
62
+ end# GitRepo
@@ -16,39 +16,45 @@ class TestBitFlag < Test::Unit::TestCase
16
16
  end
17
17
 
18
18
  def test_bits2symbols()
19
- assert_equal [], flag.bits2symbols(0)
20
- assert_equal [:bit1], flag.bits2symbols(bit 1)
21
- assert_equal [:bit2], flag.bits2symbols(bit 2)
22
- assert_equal [:bit5], flag.bits2symbols(bit 5)
23
- assert_equal [:bit1, :bit2], flag.bits2symbols(bit 1, 2)
24
- assert_equal [:bit1, :bit5], flag.bits2symbols(bit 1, 5)
25
- assert_equal [:bit3, :bit5], flag.bits2symbols(bit 3, 5)
19
+ assert_equal [], flag.bits2symbols(0)
20
+ assert_equal [:bit1], flag.bits2symbols(bit 1)
21
+ assert_equal [:bit2], flag.bits2symbols(bit 2)
22
+ assert_equal [:bit5], flag.bits2symbols(bit 5)
23
+ assert_equal [:bit1, :bit2], flag.bits2symbols(bit 1, 2)
24
+ assert_equal [:bit1, :bit5], flag.bits2symbols(bit 1, 5)
25
+ assert_equal [:bit3, :bit5], flag.bits2symbols(bit 3, 5)
26
26
  assert_equal [:bit1, :bit2, :bit3, :bit5], flag.bits2symbols(bit 1, 2, 3, 5)
27
27
 
28
- assert_raise(RuntimeError) {flag.bits2symbols(bit 0)}
29
- assert_raise(RuntimeError) {flag.bits2symbols(bit 4)}
30
- assert_raise(RuntimeError) {flag.bits2symbols(bit 6)}
31
- assert_raise(RuntimeError) {flag.bits2symbols(bit 0, 1)}
28
+ assert_raise(ArgumentError) {flag.bits2symbols(bit 0)}
29
+ assert_raise(ArgumentError) {flag.bits2symbols(bit 4)}
30
+ assert_raise(ArgumentError) {flag.bits2symbols(bit 6)}
31
+ assert_raise(ArgumentError) {flag.bits2symbols(bit 0, 1)}
32
+
33
+ Xot::BitFlag.new.tap do |bf|
34
+ bf.flag :first, bit(9)
35
+ bf.flag :second, bit(1)
36
+ assert_equal [:first, :second], bf.bits2symbols(bit 1, 9)
37
+ end
32
38
  end
33
39
 
34
40
  def test_symbols2bits()
35
- assert_equal bit(1), flag.symbols2bits(:bit1)
36
- assert_equal bit(2), flag.symbols2bits(:bit2)
37
- assert_equal bit(5), flag.symbols2bits(:bit5)
38
- assert_equal bit(1, 2), flag.symbols2bits(:bit1, :bit2)
39
- assert_equal bit(1, 5), flag.symbols2bits(:bit1, :bit5)
40
- assert_equal bit(3, 5), flag.symbols2bits(:bit3, :bit5)
41
+ assert_equal bit(1), flag.symbols2bits(:bit1)
42
+ assert_equal bit(2), flag.symbols2bits(:bit2)
43
+ assert_equal bit(5), flag.symbols2bits(:bit5)
44
+ assert_equal bit(1, 2), flag.symbols2bits(:bit1, :bit2)
45
+ assert_equal bit(1, 5), flag.symbols2bits(:bit1, :bit5)
46
+ assert_equal bit(3, 5), flag.symbols2bits(:bit3, :bit5)
41
47
  assert_equal bit(1, 2, 3, 5), flag.symbols2bits(:bit1, :bit2, :bit3, :bit5)
42
48
 
43
49
  assert_equal 0, flag.symbols2bits(:none)
44
50
  assert_equal 0, flag.symbols2bits(:no)
45
51
  assert_equal 0, flag.symbols2bits(:none, :no)
46
52
 
47
- assert_raise(RuntimeError) {flag.symbols2bits(:bit0)}
48
- assert_raise(RuntimeError) {flag.symbols2bits(:bit4)}
49
- assert_raise(RuntimeError) {flag.symbols2bits(:bit6)}
50
- assert_raise(RuntimeError) {flag.symbols2bits(:bit0, :bit1)}
51
- assert_raise(RuntimeError) {flag.symbols2bits(nil)}
53
+ assert_raise(ArgumentError) {flag.symbols2bits(:bit0)}
54
+ assert_raise(ArgumentError) {flag.symbols2bits(:bit4)}
55
+ assert_raise(ArgumentError) {flag.symbols2bits(:bit6)}
56
+ assert_raise(ArgumentError) {flag.symbols2bits(:bit0, :bit1)}
57
+ assert_raise(ArgumentError) {flag.symbols2bits(nil)}
52
58
  end
53
59
 
54
60
  end# TestBitFlag
data/test/test_rake.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require_relative 'helper'
2
+ require 'stringio'
2
3
  require 'xot/rake'
3
4
 
4
5
 
@@ -15,7 +16,17 @@ FalseStr = 'false'
15
16
 
16
17
  class TestRake < Test::Unit::TestCase
17
18
 
19
+ include Rake::DSL
18
20
  include Xot::Rake
21
+ include GitRepo
22
+
23
+ def stdout(&block)
24
+ out, $stdout = $stdout, StringIO.new
25
+ block.call
26
+ $stdout.string
27
+ ensure
28
+ $stdout = out
29
+ end
19
30
 
20
31
  def test_set()
21
32
  assert_equal 'const', get_env(:Const, :dummy)
@@ -29,4 +40,23 @@ class TestRake < Test::Unit::TestCase
29
40
  assert_equal false, get_env(:FalseStr, :dummy)
30
41
  end
31
42
 
43
+ def test_automate_release()
44
+ automate_release
45
+ %w[hooks changelog:check changelog:update version:tag].each do |name|
46
+ assert Rake::Task.task_defined?(name), name
47
+ end
48
+
49
+ update = -> {stdout {Rake::Task['changelog:update'].tap(&:reenable).invoke}}
50
+ repo do
51
+ assert_match(/no changes/, update.call)
52
+ assert File.file?('.git/hooks/pre-commit')
53
+ assert_equal CHANGELOG, File.read('ChangeLog.md')
54
+
55
+ commit 'Add a', 'a.rb' => ''
56
+ update.call
57
+ assert_equal %w[0.1.1 0.1.0], Xot::ChangeLog.new.versions
58
+ assert_equal '- Add a', Xot::ChangeLog.new.changes('0.1.1')
59
+ end
60
+ end
61
+
32
62
  end# TestRake