tty-file 0.7.0 → 0.7.1
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/CHANGELOG.md +10 -0
- data/lib/tty/file.rb +35 -21
- data/lib/tty/file/version.rb +1 -1
- data/spec/spec_helper.rb +4 -0
- data/spec/unit/append_to_file_spec.rb +96 -71
- data/spec/unit/binary_spec.rb +19 -1
- data/spec/unit/checksum_file_spec.rb +9 -0
- data/spec/unit/chmod_spec.rb +65 -51
- data/spec/unit/copy_directory_spec.rb +110 -96
- data/spec/unit/copy_file_spec.rb +117 -102
- data/spec/unit/create_directory_spec.rb +83 -69
- data/spec/unit/create_file_spec.rb +96 -82
- data/spec/unit/diff_spec.rb +97 -83
- data/spec/unit/download_file_spec.rb +49 -35
- data/spec/unit/inject_into_file_spec.rb +162 -148
- data/spec/unit/prepend_to_file_spec.rb +109 -83
- data/spec/unit/remove_file_spec.rb +45 -31
- data/spec/unit/replace_in_file_spec.rb +127 -113
- data/spec/unit/tail_file_spec.rb +61 -47
- data/tty-file.gemspec +4 -4
- metadata +12 -13
@@ -1,79 +1,93 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
RSpec.describe TTY::File,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
3
|
+
RSpec.describe TTY::File, "#create_directory" do
|
4
|
+
shared_context "creating directories" do
|
5
|
+
it "creates empty directory" do
|
6
|
+
app_dir = tmp_path('app')
|
7
|
+
|
8
|
+
TTY::File.create_directory(app_dir, verbose: false)
|
9
|
+
|
10
|
+
expect(File.exist?(app_dir)).to eq(true)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "logs status" do
|
14
|
+
doc_dir = tmp_path('doc')
|
15
|
+
|
16
|
+
expect {
|
17
|
+
TTY::File.create_dir(doc_dir, verbose: true)
|
18
|
+
}.to output(%r{ \e\[32mcreate\e\[0m(.*)doc\n}).to_stdout_from_any_process
|
19
|
+
end
|
20
|
+
|
21
|
+
it "logs status wihtout color" do
|
22
|
+
doc_dir = tmp_path('doc')
|
23
|
+
|
24
|
+
expect {
|
25
|
+
TTY::File.create_dir(doc_dir, verbose: true, color: false)
|
26
|
+
}.to output(%r{ create(.*)doc\n}).to_stdout_from_any_process
|
27
|
+
end
|
28
|
+
|
29
|
+
it "creates tree of dirs and files" do
|
30
|
+
app_dir = tmp_path('app')
|
31
|
+
|
32
|
+
tree = {
|
33
|
+
app_dir => [
|
34
|
+
'empty_file',
|
35
|
+
['full_file', 'File with contents'],
|
36
|
+
'subdir' => [
|
37
|
+
'empty_file_subdir',
|
38
|
+
['full_file_subdir', 'File with contents']
|
39
|
+
],
|
40
|
+
'empty' => []
|
41
|
+
]
|
42
|
+
}
|
43
|
+
|
44
|
+
TTY::File.create_directory(tree, verbose: false)
|
45
|
+
|
46
|
+
expect(Find.find(app_dir.to_s).to_a).to eq([
|
47
|
+
tmp_path('app'),
|
48
|
+
tmp_path('app/empty'),
|
49
|
+
tmp_path('app/empty_file'),
|
50
|
+
tmp_path('app/full_file'),
|
51
|
+
tmp_path('app/subdir'),
|
52
|
+
tmp_path('app/subdir/empty_file_subdir'),
|
53
|
+
tmp_path('app/subdir/full_file_subdir'),
|
54
|
+
])
|
55
|
+
|
56
|
+
expect(::File.read(tmp_path('app/subdir/full_file_subdir'))).to eq('File with contents')
|
57
|
+
end
|
58
|
+
|
59
|
+
it "creates tree of dirs in parent directory" do
|
60
|
+
app_dir = tmp_path('parent')
|
61
|
+
|
62
|
+
tree = {
|
63
|
+
'app' => [
|
64
|
+
['file', "File multi\nline contents"],
|
65
|
+
'subdir' => ['file1', 'file2']
|
66
|
+
]
|
67
|
+
}
|
68
|
+
|
69
|
+
TTY::File.create_dir(tree, app_dir, verbose: false)
|
70
|
+
|
71
|
+
expect(Find.find(app_dir.to_s).to_a).to eq([
|
72
|
+
tmp_path('parent'),
|
73
|
+
tmp_path('parent/app'),
|
74
|
+
tmp_path('parent/app/file'),
|
75
|
+
tmp_path('parent/app/subdir'),
|
76
|
+
tmp_path('parent/app/subdir/file1'),
|
77
|
+
tmp_path('parent/app/subdir/file2')
|
78
|
+
])
|
79
|
+
end
|
18
80
|
end
|
19
81
|
|
20
|
-
|
21
|
-
|
82
|
+
context "when passed a String instance for the directory argument" do
|
83
|
+
let(:path_factory) { method(:tmp_path) }
|
22
84
|
|
23
|
-
|
24
|
-
TTY::File.create_dir(doc_dir, verbose: true, color: false)
|
25
|
-
}.to output(%r{ create(.*)doc\n}).to_stdout_from_any_process
|
85
|
+
include_context "creating directories"
|
26
86
|
end
|
27
87
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
tree = {
|
32
|
-
tmp_path('app') => [
|
33
|
-
'empty_file',
|
34
|
-
['full_file', 'File with contents'],
|
35
|
-
'subdir' => [
|
36
|
-
'empty_file_subdir',
|
37
|
-
['full_file_subdir', 'File with contents']
|
38
|
-
],
|
39
|
-
'empty' => []
|
40
|
-
]
|
41
|
-
}
|
42
|
-
|
43
|
-
TTY::File.create_directory(tree, verbose: false)
|
44
|
-
|
45
|
-
expect(Find.find(app_dir).to_a).to eq([
|
46
|
-
tmp_path('app'),
|
47
|
-
tmp_path('app/empty'),
|
48
|
-
tmp_path('app/empty_file'),
|
49
|
-
tmp_path('app/full_file'),
|
50
|
-
tmp_path('app/subdir'),
|
51
|
-
tmp_path('app/subdir/empty_file_subdir'),
|
52
|
-
tmp_path('app/subdir/full_file_subdir'),
|
53
|
-
])
|
54
|
-
|
55
|
-
expect(::File.read(tmp_path('app/subdir/full_file_subdir'))).to eq('File with contents')
|
56
|
-
end
|
88
|
+
context "when passed a Pathname instance for the directory argument" do
|
89
|
+
let(:path_factory) { method(:tmp_pathname) }
|
57
90
|
|
58
|
-
|
59
|
-
app_dir = tmp_path('parent')
|
60
|
-
|
61
|
-
tree = {
|
62
|
-
'app' => [
|
63
|
-
['file', "File multi\nline contents"],
|
64
|
-
'subdir' => ['file1', 'file2']
|
65
|
-
]
|
66
|
-
}
|
67
|
-
|
68
|
-
TTY::File.create_dir(tree, app_dir, verbose: false)
|
69
|
-
|
70
|
-
expect(Find.find(app_dir).to_a).to eq([
|
71
|
-
tmp_path('parent'),
|
72
|
-
tmp_path('parent/app'),
|
73
|
-
tmp_path('parent/app/file'),
|
74
|
-
tmp_path('parent/app/subdir'),
|
75
|
-
tmp_path('parent/app/subdir/file1'),
|
76
|
-
tmp_path('parent/app/subdir/file2')
|
77
|
-
])
|
91
|
+
include_context "creating directories"
|
78
92
|
end
|
79
93
|
end
|
@@ -1,116 +1,130 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
RSpec.describe TTY::File,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
expect(File.exist?(tmp_path('doc/README.md'))).to eq(true)
|
11
|
-
end
|
3
|
+
RSpec.describe TTY::File, "#create_file" do
|
4
|
+
shared_context "creating files" do
|
5
|
+
context 'when new file' do
|
6
|
+
it "creates file" do
|
7
|
+
expect {
|
8
|
+
TTY::File.create_file(path_factory.call('doc/README.md'))
|
9
|
+
}.to output(/create/).to_stdout_from_any_process
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
TTY::File.create_file(file, '# Title', verbose: false)
|
11
|
+
expect(File.exist?(tmp_path('doc/README.md'))).to eq(true)
|
12
|
+
end
|
16
13
|
|
17
|
-
|
18
|
-
|
14
|
+
it "creates file with content" do
|
15
|
+
file = path_factory.call('doc/README.md')
|
16
|
+
TTY::File.create_file(file, '# Title', verbose: false)
|
19
17
|
|
20
|
-
|
21
|
-
file = tmp_path('doc/README.md')
|
22
|
-
TTY::File.create_file(file, verbose: false) do
|
23
|
-
"# Title"
|
18
|
+
expect(File.read(file)).to eq('# Title')
|
24
19
|
end
|
25
20
|
|
26
|
-
|
27
|
-
|
21
|
+
it "creates file with content in a block" do
|
22
|
+
file = path_factory.call('doc/README.md')
|
23
|
+
TTY::File.create_file(file, verbose: false) do
|
24
|
+
"# Title"
|
25
|
+
end
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
TTY::File.create_file(file, '# Title', noop: true, verbose: false)
|
27
|
+
expect(File.read(file)).to eq('# Title')
|
28
|
+
end
|
32
29
|
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
it "doesn't create file if :noop is true" do
|
31
|
+
file = path_factory.call('doc/README.md')
|
32
|
+
TTY::File.create_file(file, '# Title', noop: true, verbose: false)
|
36
33
|
|
37
|
-
|
38
|
-
context 'and is identical' do
|
39
|
-
it "logs identical status" do
|
40
|
-
file = tmp_path('README.md')
|
41
|
-
TTY::File.create_file(file, '# Title', verbose: false)
|
42
|
-
expect {
|
43
|
-
TTY::File.create_file(file, '# Title', verbose: true)
|
44
|
-
}.to output(/identical/).to_stdout_from_any_process
|
34
|
+
expect(File.exist?(file)).to eq(false)
|
45
35
|
end
|
46
36
|
end
|
47
37
|
|
48
|
-
context '
|
49
|
-
context 'and
|
50
|
-
it "logs
|
51
|
-
file =
|
38
|
+
context 'when file exists' do
|
39
|
+
context 'and is identical' do
|
40
|
+
it "logs identical status" do
|
41
|
+
file = path_factory.call('README.md')
|
52
42
|
TTY::File.create_file(file, '# Title', verbose: false)
|
53
43
|
expect {
|
54
|
-
TTY::File.create_file(file, '#
|
55
|
-
}.to output(/
|
44
|
+
TTY::File.create_file(file, '# Title', verbose: true)
|
45
|
+
}.to output(/identical/).to_stdout_from_any_process
|
56
46
|
end
|
47
|
+
end
|
57
48
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
49
|
+
context 'and is not identical' do
|
50
|
+
context 'and :force is true' do
|
51
|
+
it "logs forced status to stdout" do
|
52
|
+
file = path_factory.call('README.md')
|
53
|
+
TTY::File.create_file(file, '# Title', verbose: false)
|
54
|
+
expect {
|
55
|
+
TTY::File.create_file(file, '# Header', verbose: true, force: true)
|
56
|
+
}.to output(/force/).to_stdout_from_any_process
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'overrides the previous file' do
|
60
|
+
file = path_factory.call('README.md')
|
61
|
+
TTY::File.create_file(file, '# Title', verbose: false)
|
62
|
+
TTY::File.create_file(file, '# Header', force: true, verbose: false)
|
63
|
+
content = File.read(file)
|
64
|
+
expect(content).to eq('# Header')
|
65
|
+
end
|
64
66
|
end
|
65
|
-
end
|
66
67
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
68
|
+
it "displays collision menu and overwrites" do
|
69
|
+
test_prompt = TTY::TestPrompt.new
|
70
|
+
test_prompt.input << "\n"
|
71
|
+
test_prompt.input.rewind
|
72
|
+
allow(TTY::Prompt).to receive(:new).and_return(test_prompt)
|
72
73
|
|
73
|
-
|
74
|
-
|
74
|
+
file = path_factory.call('README.md')
|
75
|
+
TTY::File.create_file(file, '# Title', verbose: false)
|
75
76
|
|
76
|
-
|
77
|
-
|
78
|
-
|
77
|
+
expect {
|
78
|
+
TTY::File.create_file(file, '# Header', verbose: true)
|
79
|
+
}.to output(/collision/).to_stdout_from_any_process
|
79
80
|
|
80
|
-
|
81
|
-
|
81
|
+
expect(File.read(file)).to eq('# Header')
|
82
|
+
end
|
82
83
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
84
|
+
it "displays collision menu and doesn't overwrite" do
|
85
|
+
test_prompt = TTY::TestPrompt.new
|
86
|
+
test_prompt.input << "n\n"
|
87
|
+
test_prompt.input.rewind
|
88
|
+
allow(TTY::Prompt).to receive(:new).and_return(test_prompt)
|
88
89
|
|
89
|
-
|
90
|
-
|
90
|
+
file = path_factory.call('README.md')
|
91
|
+
TTY::File.create_file(file, '# Title', verbose: false)
|
91
92
|
|
92
|
-
|
93
|
-
|
94
|
-
|
93
|
+
expect {
|
94
|
+
TTY::File.create_file(file, '# Header', verbose: true)
|
95
|
+
}.to output(/collision/).to_stdout_from_any_process
|
95
96
|
|
96
|
-
|
97
|
-
|
97
|
+
expect(File.read(file)).to eq('# Title')
|
98
|
+
end
|
98
99
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
100
|
+
it "displays collision menu and aborts" do
|
101
|
+
test_prompt = TTY::TestPrompt.new
|
102
|
+
test_prompt.input << "q\n"
|
103
|
+
test_prompt.input.rewind
|
104
|
+
allow(TTY::Prompt).to receive(:new).and_return(test_prompt)
|
104
105
|
|
105
|
-
|
106
|
-
|
106
|
+
file = path_factory.call('README.md')
|
107
|
+
TTY::File.create_file(file, '# Title', verbose: false)
|
107
108
|
|
108
|
-
|
109
|
-
|
110
|
-
|
109
|
+
expect {
|
110
|
+
TTY::File.create_file(file, '# Header', verbose: false)
|
111
|
+
}.to raise_error(SystemExit)
|
111
112
|
|
112
|
-
|
113
|
+
expect(File.read(file)).to eq('# Title')
|
114
|
+
end
|
113
115
|
end
|
114
116
|
end
|
115
117
|
end
|
118
|
+
|
119
|
+
context 'when passed a String instance as the file argument' do
|
120
|
+
let(:path_factory) { method(:tmp_path) }
|
121
|
+
|
122
|
+
include_context "creating files"
|
123
|
+
end
|
124
|
+
|
125
|
+
context 'when passed a Pathname instance as the file argument' do
|
126
|
+
let(:path_factory) { method(:tmp_pathname) }
|
127
|
+
|
128
|
+
include_context "creating files"
|
129
|
+
end
|
116
130
|
end
|
data/spec/unit/diff_spec.rb
CHANGED
@@ -1,93 +1,107 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
RSpec.describe TTY::File,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
3
|
+
RSpec.describe TTY::File, "#diff" do
|
4
|
+
shared_context "diffing files" do
|
5
|
+
it "diffs two files" do
|
6
|
+
file_a = path_factory.call('diff/file_a')
|
7
|
+
file_b = path_factory.call('diff/file_b')
|
8
|
+
|
9
|
+
diff = TTY::File.diff(file_a, file_b, verbose: false)
|
10
|
+
|
11
|
+
expect(diff).to eq(strip_heredoc(<<-EOS
|
12
|
+
@@ -1,4 +1,4 @@
|
13
|
+
aaa
|
14
|
+
-bbb
|
15
|
+
+xxx
|
16
|
+
ccc
|
17
|
+
EOS
|
18
|
+
))
|
19
|
+
end
|
20
|
+
|
21
|
+
it "diffs identical files" do
|
22
|
+
src_a = path_factory.call('diff/file_a')
|
23
|
+
|
24
|
+
expect(TTY::File.diff(src_a, src_a, verbose: false)).to eq('')
|
25
|
+
end
|
26
|
+
|
27
|
+
it "diffs a file and a string" do
|
28
|
+
src_a = path_factory.call('diff/file_a')
|
29
|
+
src_b = "aaa\nxxx\nccc\n"
|
30
|
+
|
31
|
+
diff = TTY::File.diff(src_a, src_b, verbose: false)
|
32
|
+
|
33
|
+
expect(diff).to eq(strip_heredoc(<<-EOS
|
34
|
+
@@ -1,4 +1,4 @@
|
35
|
+
aaa
|
36
|
+
-bbb
|
37
|
+
+xxx
|
38
|
+
ccc
|
39
|
+
EOS
|
40
|
+
))
|
41
|
+
end
|
42
|
+
|
43
|
+
it "diffs two strings" do
|
44
|
+
file_a = "aaa\nbbb\nccc\n"
|
45
|
+
file_b = "aaa\nxxx\nccc\n"
|
46
|
+
|
47
|
+
diff = TTY::File.diff(file_a, file_b, verbose: false)
|
48
|
+
|
49
|
+
expect(diff).to eq(strip_heredoc(<<-EOS
|
50
|
+
@@ -1,4 +1,4 @@
|
51
|
+
aaa
|
52
|
+
-bbb
|
53
|
+
+xxx
|
54
|
+
ccc
|
55
|
+
EOS
|
56
|
+
))
|
57
|
+
end
|
58
|
+
|
59
|
+
it "logs status" do
|
60
|
+
file_a = path_factory.call('diff/file_a')
|
61
|
+
file_b = path_factory.call('diff/file_b')
|
62
|
+
|
63
|
+
expect {
|
64
|
+
TTY::File.diff_files(file_a, file_b, verbose: true)
|
65
|
+
}.to output(%r{diff(.*)/diff/file_a(.*)/diff/file_b}).to_stdout_from_any_process
|
66
|
+
end
|
67
|
+
|
68
|
+
it "doesn't diff files when :noop option is given" do
|
69
|
+
file_a = path_factory.call('diff/file_a')
|
70
|
+
file_b = path_factory.call('diff/file_b')
|
71
|
+
|
72
|
+
diff = TTY::File.diff(file_a, file_b, verbose: false, noop: true)
|
73
|
+
|
74
|
+
expect(diff).to eq('')
|
75
|
+
end
|
76
|
+
|
77
|
+
it "doesn't diff if first file is too large" do
|
78
|
+
file_a = path_factory.call('diff/file_a')
|
79
|
+
file_b = path_factory.call('diff/file_b')
|
80
|
+
|
81
|
+
expect {
|
82
|
+
TTY::File.diff(file_a, file_b, threshold: 10)
|
83
|
+
}.to raise_error(ArgumentError, /file size of (.*) exceeds 10 bytes/)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "doesn't diff binary files" do
|
87
|
+
file_a = path_factory.call('blackhole.png')
|
88
|
+
file_b = path_factory.call('diff/file_b')
|
89
|
+
|
90
|
+
expect {
|
91
|
+
TTY::File.diff(file_a, file_b)
|
92
|
+
}.to raise_error(ArgumentError, /is binary, diff output suppressed/)
|
93
|
+
end
|
18
94
|
end
|
19
95
|
|
20
|
-
|
21
|
-
|
96
|
+
context "when passed String instances for the file arguments" do
|
97
|
+
let(:path_factory) { method(:tmp_path) }
|
22
98
|
|
23
|
-
|
99
|
+
include_context "diffing files"
|
24
100
|
end
|
25
101
|
|
26
|
-
|
27
|
-
|
28
|
-
src_b = "aaa\nxxx\nccc\n"
|
102
|
+
context "when passed Pathname instances for the file arguments" do
|
103
|
+
let(:path_factory) { method(:tmp_pathname) }
|
29
104
|
|
30
|
-
|
31
|
-
|
32
|
-
expect(diff).to eq(strip_heredoc(<<-EOS
|
33
|
-
@@ -1,4 +1,4 @@
|
34
|
-
aaa
|
35
|
-
-bbb
|
36
|
-
+xxx
|
37
|
-
ccc
|
38
|
-
EOS
|
39
|
-
))
|
40
|
-
end
|
41
|
-
|
42
|
-
it "diffs two strings" do
|
43
|
-
file_a = "aaa\nbbb\nccc\n"
|
44
|
-
file_b = "aaa\nxxx\nccc\n"
|
45
|
-
|
46
|
-
diff = TTY::File.diff(file_a, file_b, verbose: false)
|
47
|
-
|
48
|
-
expect(diff).to eq(strip_heredoc(<<-EOS
|
49
|
-
@@ -1,4 +1,4 @@
|
50
|
-
aaa
|
51
|
-
-bbb
|
52
|
-
+xxx
|
53
|
-
ccc
|
54
|
-
EOS
|
55
|
-
))
|
56
|
-
end
|
57
|
-
|
58
|
-
it "logs status" do
|
59
|
-
file_a = tmp_path('diff/file_a')
|
60
|
-
file_b = tmp_path('diff/file_b')
|
61
|
-
|
62
|
-
expect {
|
63
|
-
TTY::File.diff_files(file_a, file_b, verbose: true)
|
64
|
-
}.to output(%r{diff(.*)/diff/file_a(.*)/diff/file_b}).to_stdout_from_any_process
|
65
|
-
end
|
66
|
-
|
67
|
-
it "doesn't diff files when :noop option is given" do
|
68
|
-
file_a = tmp_path('diff/file_a')
|
69
|
-
file_b = tmp_path('diff/file_b')
|
70
|
-
|
71
|
-
diff = TTY::File.diff(file_a, file_b, verbose: false, noop: true)
|
72
|
-
|
73
|
-
expect(diff).to eq('')
|
74
|
-
end
|
75
|
-
|
76
|
-
it "doesn't diff if first file is too large" do
|
77
|
-
file_a = tmp_path('diff/file_a')
|
78
|
-
file_b = tmp_path('diff/file_b')
|
79
|
-
|
80
|
-
expect {
|
81
|
-
TTY::File.diff(file_a, file_b, threshold: 10)
|
82
|
-
}.to raise_error(ArgumentError, /file size of (.*) exceeds 10 bytes/)
|
83
|
-
end
|
84
|
-
|
85
|
-
it "doesn't diff binary files" do
|
86
|
-
file_a = tmp_path('blackhole.png')
|
87
|
-
file_b = tmp_path('diff/file_b')
|
88
|
-
|
89
|
-
expect {
|
90
|
-
TTY::File.diff(file_a, file_b)
|
91
|
-
}.to raise_error(ArgumentError, /is binary, diff output suppressed/)
|
105
|
+
include_context "diffing files"
|
92
106
|
end
|
93
107
|
end
|