nanoc 4.8.10 → 4.8.11
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 +4 -4
- data/.rubocop.yml +6 -0
- data/NEWS.md +7 -0
- data/lib/nanoc.rb +11 -6
- data/lib/nanoc/base.rb +1 -0
- data/lib/nanoc/base/changes_stream.rb +53 -0
- data/lib/nanoc/base/contracts_support.rb +0 -2
- data/lib/nanoc/base/feature.rb +3 -0
- data/lib/nanoc/base/memoization.rb +0 -2
- data/lib/nanoc/base/repos/aggregate_data_source.rb +8 -0
- data/lib/nanoc/base/repos/data_source.rb +12 -0
- data/lib/nanoc/base/repos/in_mem_data_source.rb +10 -1
- data/lib/nanoc/base/repos/prefixed_data_source.rb +8 -0
- data/lib/nanoc/base/repos/site_loader.rb +11 -7
- data/lib/nanoc/base/services/compiler.rb +2 -3
- data/lib/nanoc/base/services/compiler/stages/postprocess.rb +2 -3
- data/lib/nanoc/base/services/compiler/stages/preprocess.rb +1 -1
- data/lib/nanoc/base/services/pruner.rb +0 -2
- data/lib/nanoc/base/services/temp_filename_factory.rb +0 -2
- data/lib/nanoc/checking/checks/external_links.rb +0 -5
- data/lib/nanoc/checking/checks/internal_links.rb +0 -2
- data/lib/nanoc/checking/checks/stale.rb +0 -2
- data/lib/nanoc/cli.rb +7 -1
- data/lib/nanoc/cli/commands/compile_listeners/diff_generator.rb +0 -3
- data/lib/nanoc/cli/commands/live.rb +30 -0
- data/lib/nanoc/cli/commands/view.rb +4 -5
- data/lib/nanoc/cli/error_handler.rb +52 -36
- data/lib/nanoc/cli/logger.rb +0 -2
- data/lib/nanoc/cli/stack_trace_writer.rb +50 -0
- data/lib/nanoc/data_sources/filesystem.rb +25 -0
- data/lib/nanoc/extra.rb +1 -0
- data/lib/nanoc/extra/jruby_nokogiri_warner.rb +0 -2
- data/lib/nanoc/extra/link_collector.rb +0 -2
- data/lib/nanoc/extra/live_recompiler.rb +131 -0
- data/lib/nanoc/extra/parallel_collection.rb +0 -2
- data/lib/nanoc/extra/piper.rb +0 -2
- data/lib/nanoc/filters/relativize_paths.rb +8 -7
- data/lib/nanoc/helpers/link_to.rb +0 -2
- data/lib/nanoc/rule_dsl/action_provider.rb +2 -2
- data/lib/nanoc/version.rb +1 -1
- data/nanoc.gemspec +15 -4
- data/nanoc.manifest +545 -0
- data/spec/manifest_spec.rb +22 -0
- data/spec/nanoc/base/changes_stream_spec.rb +45 -0
- data/spec/nanoc/base/checksummer_spec.rb +0 -2
- data/spec/nanoc/base/directed_graph_spec.rb +66 -0
- data/spec/nanoc/base/entities/code_snippet_spec.rb +9 -0
- data/spec/nanoc/base/entities/context_spec.rb +26 -0
- data/spec/nanoc/base/entities/identifiable_collection_spec.rb +53 -0
- data/spec/nanoc/base/repos/aggregate_data_source_spec.rb +87 -0
- data/spec/nanoc/base/repos/data_source_spec.rb +95 -0
- data/spec/nanoc/base/repos/in_mem_data_source_spec.rb +39 -0
- data/spec/nanoc/base/repos/prefixed_data_source_spec.rb +39 -0
- data/spec/nanoc/cli/error_handler_spec.rb +43 -0
- data/spec/nanoc/cli/stack_trace_writer_spec.rb +156 -0
- data/spec/nanoc/data_sources/filesystem_spec.rb +46 -0
- data/spec/nanoc/extra/live_recompiler_spec.rb +129 -0
- data/spec/nanoc/helpers/blogging_spec.rb +1 -1
- data/spec/spec_helper.rb +60 -0
- data/test/base/test_compiler.rb +11 -11
- data/test/cli/test_cli.rb +0 -1
- data/test/cli/test_error_handler.rb +4 -5
- data/test/filters/test_relativize_paths.rb +30 -0
- data/test/filters/test_sass.rb +3 -3
- data/test/rule_dsl/test_compiler_dsl.rb +2 -2
- metadata +39 -43
- data/.github/CONTRIBUTING.md +0 -17
- data/.github/ISSUE_TEMPLATE.md +0 -23
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -18
- data/.gitignore +0 -10
- data/.travis.yml +0 -27
- data/Gemfile +0 -73
- data/Guardfile +0 -5
- data/scripts/release +0 -95
- data/test/base/test_code_snippet.rb +0 -17
- data/test/base/test_context.rb +0 -35
- data/test/base/test_data_source.rb +0 -60
- data/test/base/test_directed_graph.rb +0 -56
- data/test/base/test_item_array.rb +0 -37
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe Nanoc::Int::InMemDataSource, stdio: true do
|
4
|
+
let(:klass) do
|
5
|
+
Class.new(Nanoc::DataSource) do
|
6
|
+
def item_changes
|
7
|
+
%i[one_foo one_bar]
|
8
|
+
end
|
9
|
+
|
10
|
+
def layout_changes
|
11
|
+
%i[one_foo one_bar]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:original_data_source) do
|
17
|
+
klass.new({}, nil, nil, {})
|
18
|
+
end
|
19
|
+
|
20
|
+
subject(:data_source) do
|
21
|
+
described_class.new([], [], original_data_source)
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#item_changes' do
|
25
|
+
subject { data_source.item_changes }
|
26
|
+
|
27
|
+
it 'yields changes from the original' do
|
28
|
+
expect(subject).to eq(original_data_source.item_changes)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#layout_changes' do
|
33
|
+
subject { data_source.layout_changes }
|
34
|
+
|
35
|
+
it 'yields changes from the original' do
|
36
|
+
expect(subject).to eq(original_data_source.layout_changes)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe Nanoc::Int::PrefixedDataSource, stdio: true do
|
4
|
+
let(:klass) do
|
5
|
+
Class.new(Nanoc::DataSource) do
|
6
|
+
def item_changes
|
7
|
+
%i[one_foo one_bar]
|
8
|
+
end
|
9
|
+
|
10
|
+
def layout_changes
|
11
|
+
%i[one_foo one_bar]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:original_data_source) do
|
17
|
+
klass.new({}, nil, nil, {})
|
18
|
+
end
|
19
|
+
|
20
|
+
subject(:data_source) do
|
21
|
+
described_class.new(original_data_source, '/itemz', '/layoutz')
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#item_changes' do
|
25
|
+
subject { data_source.item_changes }
|
26
|
+
|
27
|
+
it 'yields changes from the original' do
|
28
|
+
expect(subject).to eq(original_data_source.item_changes)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#layout_changes' do
|
33
|
+
subject { data_source.layout_changes }
|
34
|
+
|
35
|
+
it 'yields changes from the original' do
|
36
|
+
expect(subject).to eq(original_data_source.layout_changes)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe Nanoc::CLI::ErrorHandler do
|
4
|
+
subject(:error_handler) { described_class.new }
|
5
|
+
|
6
|
+
describe '#forwards_stack_trace?' do
|
7
|
+
subject { error_handler.forwards_stack_trace? }
|
8
|
+
|
9
|
+
context 'feature enabled' do
|
10
|
+
around do |ex|
|
11
|
+
Nanoc::Feature.enable(Nanoc::Feature::SENSIBLE_STACK_TRACES) do
|
12
|
+
ex.run
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'Ruby 2.4' do
|
17
|
+
it { is_expected.to be(true) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'Ruby 2.5' do
|
21
|
+
it { is_expected.to be(true) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'feature not enabled' do
|
26
|
+
context 'Ruby 2.4' do
|
27
|
+
before do
|
28
|
+
expect(error_handler).to receive(:ruby_version).and_return('2.4.2')
|
29
|
+
end
|
30
|
+
|
31
|
+
it { is_expected.to be(false) }
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'Ruby 2.5' do
|
35
|
+
before do
|
36
|
+
expect(error_handler).to receive(:ruby_version).and_return('2.5.0')
|
37
|
+
end
|
38
|
+
|
39
|
+
it { is_expected.to be(true) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe Nanoc::CLI::StackTraceWriter do
|
4
|
+
subject(:writer) do
|
5
|
+
described_class.new(io, forwards: forwards)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:io) { StringIO.new }
|
9
|
+
let(:forwards) { true }
|
10
|
+
|
11
|
+
describe '#write' do
|
12
|
+
let(:exception) do
|
13
|
+
backtrace_generator = lambda do |af|
|
14
|
+
if af.zero?
|
15
|
+
raise 'finally!'
|
16
|
+
else
|
17
|
+
backtrace_generator.call(af - 1)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
begin
|
22
|
+
backtrace_generator.call(3)
|
23
|
+
rescue => e
|
24
|
+
return e
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
subject { writer.write(exception, verbose: verbose) }
|
29
|
+
|
30
|
+
let(:verbose) { false }
|
31
|
+
|
32
|
+
context 'backwards' do
|
33
|
+
let(:forwards) { false }
|
34
|
+
|
35
|
+
context 'verbose' do
|
36
|
+
let(:verbose) { true }
|
37
|
+
|
38
|
+
it 'starts with zero' do
|
39
|
+
expect { subject }
|
40
|
+
.to change { io.string }
|
41
|
+
.from('')
|
42
|
+
.to(start_with(' 0. '))
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'has more recent stack frames at the top' do
|
46
|
+
expect { subject }
|
47
|
+
.to change { io.string }
|
48
|
+
.from('')
|
49
|
+
.to(match(%r{^ 0\. /.+/spec/nanoc/cli/stack_trace_writer_spec\.rb:\d+.*$\n 1\. /.+/spec/nanoc/cli/stack_trace_writer_spec\.rb:\d}m))
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'has more than 10 stack frames' do
|
53
|
+
expect { subject }
|
54
|
+
.to change { io.string }
|
55
|
+
.from('')
|
56
|
+
.to(match(%r{^ 11\. }))
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'does not contain a see-more explanation' do
|
60
|
+
subject
|
61
|
+
expect(io.string).not_to match(/crash\.log/)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'not verbose' do
|
66
|
+
let(:verbose) { false }
|
67
|
+
|
68
|
+
it 'starts with zero' do
|
69
|
+
expect { subject }
|
70
|
+
.to change { io.string }
|
71
|
+
.from('')
|
72
|
+
.to(start_with(' 0. '))
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'has more recent stack frames at the top' do
|
76
|
+
expect { subject }
|
77
|
+
.to change { io.string }
|
78
|
+
.from('')
|
79
|
+
.to(match(%r{^ 0\. /.+/spec/nanoc/cli/stack_trace_writer_spec\.rb:\d+.*$\n 1\. /.+/spec/nanoc/cli/stack_trace_writer_spec\.rb:\d}m))
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'has not more than 10 stack frames' do
|
83
|
+
subject
|
84
|
+
expect(io.string).not_to match(/^ 11\. /)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'does not contain a see-more explanation' do
|
88
|
+
subject
|
89
|
+
expect(io.string).to include(" lines omitted (see crash.log for details)\n")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'forwards' do
|
95
|
+
let(:forwards) { true }
|
96
|
+
|
97
|
+
context 'verbose' do
|
98
|
+
let(:verbose) { true }
|
99
|
+
|
100
|
+
it 'ends with most recent line' do
|
101
|
+
expect { subject }
|
102
|
+
.to change { io.string }
|
103
|
+
.from('')
|
104
|
+
.to(match(%r{^ 1\. from /.+/spec/nanoc/cli/stack_trace_writer_spec\.rb:\d+.*$\n /.+/spec/nanoc/cli}m))
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'has more recent stack frames at the bottom' do
|
108
|
+
expect { subject }
|
109
|
+
.to change { io.string }
|
110
|
+
.from('')
|
111
|
+
.to(match(%r{^ 2\. from /.+/spec/nanoc/cli/stack_trace_writer_spec\.rb:\d+.*$\n 1\. from /.+/spec/nanoc/cli/stack_trace_writer_spec\.rb:\d}m))
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'has more than 10 stack frames' do
|
115
|
+
expect { subject }
|
116
|
+
.to change { io.string }
|
117
|
+
.from('')
|
118
|
+
.to(match(%r{^ 11\. from }))
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'does not contain a see-more explanation' do
|
122
|
+
subject
|
123
|
+
expect(io.string).not_to match(/crash\.log/)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'not verbose' do
|
128
|
+
let(:verbose) { false }
|
129
|
+
|
130
|
+
it 'ends with most recent line' do
|
131
|
+
expect { subject }
|
132
|
+
.to change { io.string }
|
133
|
+
.from('')
|
134
|
+
.to(match(%r{^ 1\. from /.+/spec/nanoc/cli/stack_trace_writer_spec\.rb:\d+.*$\n /.+/spec/nanoc/cli}m))
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'has more recent stack frames at the top' do
|
138
|
+
expect { subject }
|
139
|
+
.to change { io.string }
|
140
|
+
.from('')
|
141
|
+
.to(match(%r{^ 2\. from /.+/spec/nanoc/cli/stack_trace_writer_spec\.rb:\d+.*$\n 1\. from /.+/spec/nanoc/cli/stack_trace_writer_spec\.rb:\d}m))
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'has not more than 10 stack frames' do
|
145
|
+
subject
|
146
|
+
expect(io.string).not_to match(/^ 11\. from /)
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'does not contain a see-more explanation' do
|
150
|
+
subject
|
151
|
+
expect(io.string).to include(" lines omitted (see crash.log for details)\n")
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -79,4 +79,50 @@ describe Nanoc::DataSources::Filesystem do
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
82
|
+
|
83
|
+
describe '#item_changes' do
|
84
|
+
subject { data_source.item_changes }
|
85
|
+
|
86
|
+
it 'returns a stream' do
|
87
|
+
expect(subject).to be_a(Nanoc::ChangesStream)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'contains one element after changing' do
|
91
|
+
FileUtils.mkdir_p('content')
|
92
|
+
|
93
|
+
enum = DDBuffer.new(1).call(subject.to_enum)
|
94
|
+
q = SizedQueue.new(1)
|
95
|
+
Thread.new { q << enum.take(1).first }
|
96
|
+
|
97
|
+
# FIXME: sleep is ugly
|
98
|
+
sleep 0.3
|
99
|
+
File.write('content/wat.md', 'stuff')
|
100
|
+
|
101
|
+
expect(q.pop).to eq(:unknown)
|
102
|
+
subject.stop
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe '#layout_changes' do
|
107
|
+
subject { data_source.layout_changes }
|
108
|
+
|
109
|
+
it 'returns a stream' do
|
110
|
+
expect(subject).to be_a(Nanoc::ChangesStream)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'contains one element after changing' do
|
114
|
+
FileUtils.mkdir_p('layouts')
|
115
|
+
|
116
|
+
enum = DDBuffer.new(1).call(subject.to_enum)
|
117
|
+
q = SizedQueue.new(1)
|
118
|
+
Thread.new { q << enum.take(1).first }
|
119
|
+
|
120
|
+
# FIXME: sleep is ugly
|
121
|
+
sleep 0.3
|
122
|
+
File.write('layouts/wat.md', 'stuff')
|
123
|
+
|
124
|
+
expect(q.pop).to eq(:unknown)
|
125
|
+
subject.stop
|
126
|
+
end
|
127
|
+
end
|
82
128
|
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe Nanoc::Extra::LiveRecompiler, site: true, stdio: true do
|
4
|
+
it 'detects content changes' do
|
5
|
+
command = nil
|
6
|
+
command_runner = Nanoc::CLI::CommandRunner.new({}, [], command)
|
7
|
+
live_recompiler = described_class.new(command_runner: command_runner)
|
8
|
+
|
9
|
+
pid = fork do
|
10
|
+
trap(:INT) { exit(0) }
|
11
|
+
live_recompiler.run
|
12
|
+
end
|
13
|
+
|
14
|
+
# FIXME: wait is ugly
|
15
|
+
sleep 0.5
|
16
|
+
|
17
|
+
File.write('content/lol.html', 'hej')
|
18
|
+
sleep 0.1 until File.file?('output/lol.html')
|
19
|
+
expect(File.read('output/lol.html')).to eq('hej')
|
20
|
+
|
21
|
+
sleep 1.0 # HFS+ mtime resolution is 1s
|
22
|
+
File.write('content/lol.html', 'bye')
|
23
|
+
sleep 0.1 until File.read('output/lol.html') == 'bye'
|
24
|
+
|
25
|
+
# Stop
|
26
|
+
Process.kill('INT', pid)
|
27
|
+
Process.waitpid(pid)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'detects rules changes' do
|
31
|
+
command = nil
|
32
|
+
command_runner = Nanoc::CLI::CommandRunner.new({}, [], command)
|
33
|
+
live_recompiler = described_class.new(command_runner: command_runner)
|
34
|
+
|
35
|
+
pid = fork do
|
36
|
+
trap(:INT) { exit(0) }
|
37
|
+
live_recompiler.run
|
38
|
+
end
|
39
|
+
|
40
|
+
# FIXME: wait is ugly
|
41
|
+
sleep 0.5
|
42
|
+
|
43
|
+
File.write('content/lol.html', '<%= "hej" %>')
|
44
|
+
sleep 0.1 until File.file?('output/lol.html')
|
45
|
+
expect(File.read('output/lol.html')).to eq('<%= "hej" %>')
|
46
|
+
|
47
|
+
sleep 1.0 # HFS+ mtime resolution is 1s
|
48
|
+
File.write('Rules', <<~RULES)
|
49
|
+
compile '/**/*' do
|
50
|
+
filter :erb
|
51
|
+
write item.identifier
|
52
|
+
end
|
53
|
+
RULES
|
54
|
+
sleep 0.1 until File.read('output/lol.html') == 'hej'
|
55
|
+
|
56
|
+
# Stop
|
57
|
+
Process.kill('INT', pid)
|
58
|
+
Process.waitpid(pid)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'detects config changes' do
|
62
|
+
command = nil
|
63
|
+
command_runner = Nanoc::CLI::CommandRunner.new({}, [], command)
|
64
|
+
live_recompiler = described_class.new(command_runner: command_runner)
|
65
|
+
|
66
|
+
File.write('nanoc.yaml', 'site_name: Oldz')
|
67
|
+
File.write('content/lol.html', '<%= @config[:site_name] %>')
|
68
|
+
File.write('Rules', <<~RULES)
|
69
|
+
compile '/**/*' do
|
70
|
+
filter :erb
|
71
|
+
write item.identifier
|
72
|
+
end
|
73
|
+
RULES
|
74
|
+
|
75
|
+
pid = fork do
|
76
|
+
trap(:INT) { exit(0) }
|
77
|
+
live_recompiler.run
|
78
|
+
end
|
79
|
+
|
80
|
+
# FIXME: wait is ugly
|
81
|
+
sleep 0.5
|
82
|
+
|
83
|
+
sleep 0.1 until File.file?('output/lol.html')
|
84
|
+
expect(File.read('output/lol.html')).to eq('Oldz')
|
85
|
+
|
86
|
+
sleep 1.0 # HFS+ mtime resolution is 1s
|
87
|
+
File.write('nanoc.yaml', 'site_name: Newz')
|
88
|
+
sleep 0.1 until File.read('output/lol.html') == 'Newz'
|
89
|
+
|
90
|
+
# Stop
|
91
|
+
Process.kill('INT', pid)
|
92
|
+
Process.waitpid(pid)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'detects config changes' do
|
96
|
+
command = nil
|
97
|
+
command_runner = Nanoc::CLI::CommandRunner.new({}, [], command)
|
98
|
+
live_recompiler = described_class.new(command_runner: command_runner)
|
99
|
+
|
100
|
+
FileUtils.mkdir_p('lib')
|
101
|
+
File.write('lib/lol.rb', 'def greeting; "hi"; end')
|
102
|
+
File.write('content/lol.html', '<%= greeting %>')
|
103
|
+
File.write('Rules', <<~RULES)
|
104
|
+
compile '/**/*' do
|
105
|
+
filter :erb
|
106
|
+
write item.identifier
|
107
|
+
end
|
108
|
+
RULES
|
109
|
+
|
110
|
+
pid = fork do
|
111
|
+
trap(:INT) { exit(0) }
|
112
|
+
live_recompiler.run
|
113
|
+
end
|
114
|
+
|
115
|
+
# FIXME: wait is ugly
|
116
|
+
sleep 0.5
|
117
|
+
|
118
|
+
sleep 0.1 until File.file?('output/lol.html')
|
119
|
+
expect(File.read('output/lol.html')).to eq('hi')
|
120
|
+
|
121
|
+
sleep 1.0 # HFS+ mtime resolution is 1s
|
122
|
+
File.write('lib/lol.rb', 'def greeting; "yo"; end')
|
123
|
+
sleep 0.1 until File.read('output/lol.html') == 'yo'
|
124
|
+
|
125
|
+
# Stop
|
126
|
+
Process.kill('INT', pid)
|
127
|
+
Process.waitpid(pid)
|
128
|
+
end
|
129
|
+
end
|