BuildMaster 0.8.1 → 0.9.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.
- data/README +6 -29
- data/lib/buildmaster.rb +0 -2
- data/lib/buildmaster/ant_driver.rb +13 -12
- data/lib/buildmaster/build_number_file.rb +2 -12
- data/lib/buildmaster/buildnumber +1 -1
- data/lib/buildmaster/cotta.rb +4 -0
- data/lib/buildmaster/cotta/command_error.rb +5 -0
- data/lib/buildmaster/cotta/cotta.rb +35 -0
- data/lib/buildmaster/cotta/cotta_dir.rb +73 -0
- data/lib/buildmaster/cotta/cotta_file.rb +99 -0
- data/lib/buildmaster/cotta/file_not_found_error.rb +13 -0
- data/lib/buildmaster/cotta/in_memory_system.rb +160 -0
- data/lib/buildmaster/cotta/physical_system.rb +64 -0
- data/lib/buildmaster/cvs_driver.rb +5 -13
- data/lib/buildmaster/file_processor.rb +34 -33
- data/lib/buildmaster/java_manifest.rb +3 -3
- data/lib/buildmaster/site/site.rb +11 -22
- data/lib/buildmaster/site_spec.rb +15 -13
- data/lib/buildmaster/source_file_handler.rb +1 -1
- data/lib/buildmaster/svn_driver.rb +14 -20
- data/lib/buildmaster/{template_exception.rb → template_error.rb} +1 -1
- data/lib/buildmaster/template_runner.rb +2 -2
- data/lib/buildmaster/templatelets/attribute.rb +1 -1
- data/lib/buildmaster/templatelets/href.rb +1 -1
- data/lib/buildmaster/templatelets/text.rb +1 -1
- data/lib/buildmaster/templatelets/when.rb +1 -1
- data/lib/buildmaster/windows.rb +3 -0
- data/lib/buildmaster/windows/iis_driver.rb +33 -0
- data/lib/buildmaster/windows/sql_server_driver.rb +27 -0
- data/test/buildmaster/cotta/content.txt +3 -0
- data/test/buildmaster/cotta/cotta_specifications.rb +172 -0
- data/test/buildmaster/cotta/physical_system_stub.rb +85 -0
- data/test/buildmaster/cotta/system_file_specifications.rb +131 -0
- data/test/buildmaster/cotta/tc_cotta.rb +33 -0
- data/test/buildmaster/cotta/tc_cotta_dir_in_memory.rb +23 -0
- data/test/buildmaster/cotta/tc_cotta_dir_physical.rb +17 -0
- data/test/buildmaster/cotta/tc_cotta_file_in_memory.rb +20 -0
- data/test/buildmaster/cotta/tc_cotta_file_physical.rb +17 -0
- data/test/buildmaster/cotta/tc_in_memory_system.rb +25 -0
- data/test/buildmaster/cotta/tc_physical_system.rb +26 -0
- data/test/buildmaster/manifest.mf +1 -1
- data/test/buildmaster/site/tc_site.rb +58 -34
- data/test/buildmaster/site/tc_template_builder.rb +32 -31
- data/test/buildmaster/tc_ant_driver.rb +11 -13
- data/test/buildmaster/tc_build_number_file.rb +21 -16
- data/test/buildmaster/tc_cvs_driver.rb +35 -37
- data/test/buildmaster/tc_file_processor.rb +58 -34
- data/test/buildmaster/tc_java_manifest.rb +37 -9
- data/test/buildmaster/tc_site_spec.rb +20 -15
- data/test/buildmaster/tc_source_file_handler.rb +4 -4
- data/test/buildmaster/tc_svn_driver.rb +51 -38
- data/test/buildmaster/tc_template_runner.rb +19 -18
- data/test/buildmaster/tc_tree_to_object.rb +47 -46
- data/test/buildmaster/tc_xtemplate.rb +52 -38
- data/test/buildmaster/templatelets/common_templatelet_test.rb +9 -8
- data/test/buildmaster/templatelets/tc_attribute.rb +26 -23
- data/test/buildmaster/templatelets/tc_each.rb +27 -26
- data/test/buildmaster/templatelets/tc_href.rb +14 -13
- data/test/buildmaster/templatelets/tc_include.rb +11 -4
- data/test/buildmaster/templatelets/tc_link.rb +18 -12
- data/test/buildmaster/templatelets/tc_text.rb +12 -7
- data/test/buildmaster/templatelets/tc_when.rb +11 -5
- data/test/buildmaster/windows/tc_iis_driver.rb +29 -0
- data/test/buildmaster/windows/tc_sql_server_driver.rb +24 -0
- data/test/spec_runner.rb +27 -0
- data/test/ts_buildmaster.rb +2 -19
- metadata +34 -10
- data/lib/buildmaster/release_control.rb +0 -22
- data/lib/buildmaster/shell_command.rb +0 -39
- data/test/buildmaster/tc_release_control.rb +0 -27
- data/test/buildmaster/ts_site.rb +0 -4
- data/test/buildmaster/ts_templatelets.rb +0 -10
data/README
CHANGED
@@ -20,32 +20,9 @@ A ruby version of the project building and releasing script as described in
|
|
20
20
|
A simple template engine that can build a website by producing the content pages based on the specified source
|
21
21
|
and decrorating the content pages with a skin.
|
22
22
|
|
23
|
-
The supported content sources are <a href="http://www.w3.org/TR/xhtml11/">XHTML</a>
|
24
|
-
|
25
|
-
|
26
|
-
==
|
27
|
-
|
28
|
-
|
29
|
-
255)
|
30
|
-
* Use RDoc format for content
|
31
|
-
|
32
|
-
require 'rdoc/template'
|
33
|
-
HTML = %{Hello, %name%.
|
34
|
-
<p>
|
35
|
-
The reasons you gave were:
|
36
|
-
<ul>
|
37
|
-
START:reasons
|
38
|
-
<li>%reason_name% (%rank%)
|
39
|
-
END:reasons
|
40
|
-
</ul>
|
41
|
-
}
|
42
|
-
data = {
|
43
|
-
'name' => 'Dave Thomas',
|
44
|
-
'reasons' => [
|
45
|
-
{ 'reason_name' => 'flexible', 'rank' => '87' },
|
46
|
-
{ 'reason_name' => 'transparent', 'rank' => '76' },
|
47
|
-
{ 'reason_name' => 'fun', 'rank' => '94' },
|
48
|
-
]
|
49
|
-
}
|
50
|
-
t = TemplatePage.new(HTML)
|
51
|
-
t.write_html_on(STDOUT, data)
|
23
|
+
The supported content sources are <a href="http://www.w3.org/TR/xhtml11/">XHTML</a>
|
24
|
+
, <a href="http://hobix.com/textile/">Textile</a> and <a href="http://daringfireball.net/projects/markdown/">Markdown</a>.
|
25
|
+
|
26
|
+
== Cotta
|
27
|
+
|
28
|
+
A wrapper of Ruby file operations in an object-oriented way.
|
data/lib/buildmaster.rb
CHANGED
@@ -2,8 +2,6 @@ $:.unshift(File.dirname(__FILE__))
|
|
2
2
|
|
3
3
|
require 'buildmaster/build_number_file'
|
4
4
|
require 'buildmaster/java_manifest'
|
5
|
-
require 'buildmaster/shell_command'
|
6
|
-
require 'buildmaster/release_control'
|
7
5
|
require 'buildmaster/ant_driver'
|
8
6
|
require 'buildmaster/cvs_driver'
|
9
7
|
require 'buildmaster/svn_driver'
|
@@ -1,14 +1,16 @@
|
|
1
1
|
module BuildMaster
|
2
2
|
|
3
3
|
class AntDriver
|
4
|
-
include Shell
|
5
4
|
def AntDriver.from_file(ant_file)
|
6
5
|
return AntDriver.new(ant_file)
|
7
6
|
end
|
8
7
|
|
9
|
-
def initialize(ant_file = nil
|
8
|
+
def initialize(ant_file = nil)
|
9
|
+
@cotta = Cotta.new(ant_file.system)
|
10
10
|
@ant_file = ant_file
|
11
|
-
|
11
|
+
ant_path = @cotta.environment!('ANT_HOME')
|
12
|
+
@ant_home = @cotta.dir(ant_path)
|
13
|
+
raise 'ANT_HOME need to point to ANT home directory' unless @ant_home.exists?
|
12
14
|
#ISSUE: what java wants to split up classpath varies from platform to platform
|
13
15
|
#and ruby, following perl, is not too hot at hinting which box it is on.
|
14
16
|
#here I assume ":" except on win32, dos, and netware. Add extra tests here as needed.
|
@@ -21,19 +23,18 @@ class AntDriver
|
|
21
23
|
@path_seperator='/'
|
22
24
|
end
|
23
25
|
@java_command = get_java_command()
|
24
|
-
@ant_options =
|
25
|
-
@ant_arguments =
|
26
|
+
@ant_options = @cotta.environment('ANT_OPTS').split(' ')
|
27
|
+
@ant_arguments = @cotta.environment('ANT_ARGS').split(' ')
|
26
28
|
@ant_options.putsh(ENV['JIKESPATH']) if ENV['JIKESPATH']
|
27
29
|
@classpath=ENV['CLASSPATH']
|
28
|
-
@command_runner = command_runner
|
29
30
|
end
|
30
31
|
|
31
32
|
def get_java_command
|
32
|
-
java_home =
|
33
|
+
java_home = @cotta.environment('JAVA_HOME')
|
33
34
|
if java_home
|
34
35
|
command = [java_home, 'bin', 'java'].join(@path_seperator)
|
35
36
|
else
|
36
|
-
command =
|
37
|
+
command = @cotta.environment('JAVA_CMD', 'java')
|
37
38
|
end
|
38
39
|
return command
|
39
40
|
end
|
@@ -47,19 +48,19 @@ class AntDriver
|
|
47
48
|
end
|
48
49
|
|
49
50
|
def launch(arguments)
|
50
|
-
local_path = "#{@ant_home}/lib/ant-launcher.jar"
|
51
|
+
local_path = "#{@ant_home.path}/lib/ant-launcher.jar"
|
51
52
|
if (@classpath and @classpath.length() > 0)
|
52
53
|
local_path = "#{local_path}#{@class_path_delimiter}#{@classpath}"
|
53
54
|
end
|
54
55
|
all_arguments = Array.new()
|
55
56
|
all_arguments.push(@ant_options)
|
56
57
|
all_arguments.push('-classpath', local_path)
|
57
|
-
all_arguments.push("-Dant.home=#{@ant_home}")
|
58
|
+
all_arguments.push("-Dant.home=#{@ant_home.path}")
|
58
59
|
all_arguments.push('org.apache.tools.ant.launch.Launcher', @ant_arguments);
|
59
|
-
all_arguments.push('-f', @ant_file) if @ant_file
|
60
|
+
all_arguments.push('-f', @ant_file.path) if @ant_file
|
60
61
|
all_arguments.push(arguments)
|
61
62
|
command_line = "#{@java_command} #{all_arguments.join(' ')}"
|
62
|
-
|
63
|
+
@cotta.shell(command_line)
|
63
64
|
end
|
64
65
|
|
65
66
|
def method_missing(method, *args)
|
@@ -5,23 +5,13 @@ class BuildNumberFile
|
|
5
5
|
|
6
6
|
def initialize(path)
|
7
7
|
@path = path
|
8
|
-
@number =
|
8
|
+
@number = @path.load().strip.to_i
|
9
9
|
end
|
10
10
|
|
11
11
|
def increase_build
|
12
12
|
@number = @number + 1
|
13
|
-
|
13
|
+
@path.save(@number)
|
14
14
|
end
|
15
15
|
|
16
|
-
private
|
17
|
-
def load_content()
|
18
|
-
content = nil
|
19
|
-
File.open(@path, 'r') {|file| content = file.gets}
|
20
|
-
return content
|
21
|
-
end
|
22
|
-
|
23
|
-
def save_content
|
24
|
-
File.open(@path, 'w') {|file| file.puts @number}
|
25
|
-
end
|
26
16
|
end
|
27
17
|
end
|
data/lib/buildmaster/buildnumber
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
22
|
@@ -0,0 +1,35 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'physical_system'
|
4
|
+
require 'cotta_dir'
|
5
|
+
require 'cotta_file'
|
6
|
+
require 'pathname'
|
7
|
+
|
8
|
+
module BuildMaster
|
9
|
+
class Cotta
|
10
|
+
def initialize(system=PhysicalSystem.new)
|
11
|
+
@system = system
|
12
|
+
end
|
13
|
+
|
14
|
+
def shell(command_line)
|
15
|
+
puts "$> #{command_line}"
|
16
|
+
@system.shell(command_line)
|
17
|
+
end
|
18
|
+
|
19
|
+
def dir(path)
|
20
|
+
return CottaDir.new(@system, Pathname.new(path))
|
21
|
+
end
|
22
|
+
|
23
|
+
def file(path)
|
24
|
+
return CottaFile.new(@system, Pathname.new(path))
|
25
|
+
end
|
26
|
+
|
27
|
+
def environment!(variable)
|
28
|
+
@system.environment!(variable)
|
29
|
+
end
|
30
|
+
|
31
|
+
def environment(variable, default = '')
|
32
|
+
@system.environment(variable, default)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'cotta_file'
|
4
|
+
|
5
|
+
module BuildMaster
|
6
|
+
class CottaDir
|
7
|
+
attr_reader :path, :system
|
8
|
+
|
9
|
+
def initialize(system, path)
|
10
|
+
@system = system
|
11
|
+
@path = path
|
12
|
+
@name = @path.basename.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
def cotta
|
16
|
+
return Cotta.new(@system)
|
17
|
+
end
|
18
|
+
|
19
|
+
def name
|
20
|
+
return @path.basename.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
def exists?
|
24
|
+
return @system.dir_exists?(@path)
|
25
|
+
end
|
26
|
+
|
27
|
+
def parent
|
28
|
+
if (@name == '.')
|
29
|
+
return nil
|
30
|
+
end
|
31
|
+
return CottaDir.new(@system, @path.parent)
|
32
|
+
end
|
33
|
+
|
34
|
+
def dir(name)
|
35
|
+
return CottaDir.new(@system, @path.join(name))
|
36
|
+
end
|
37
|
+
|
38
|
+
def file(name)
|
39
|
+
return CottaFile.new(@system, @path.join(name))
|
40
|
+
end
|
41
|
+
|
42
|
+
def mkdirs
|
43
|
+
if (not exists?)
|
44
|
+
parent.mkdirs
|
45
|
+
@system.mkdir @path
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def delete
|
50
|
+
list.each {|children| children.delete}
|
51
|
+
@system.delete_dir(@path)
|
52
|
+
end
|
53
|
+
|
54
|
+
def list
|
55
|
+
@system.list(@path).collect do |item|
|
56
|
+
candidate = dir(item)
|
57
|
+
if (not candidate.exists?)
|
58
|
+
candidate = file(item)
|
59
|
+
end
|
60
|
+
candidate
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def ==(other)
|
65
|
+
return @path == other.path && @system == other.system
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_s
|
69
|
+
return "#{super}-#@system-#@path"
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module BuildMaster
|
4
|
+
class CottaFile
|
5
|
+
attr_reader :system, :path
|
6
|
+
|
7
|
+
def initialize(system, path)
|
8
|
+
@system = system
|
9
|
+
@path = path
|
10
|
+
end
|
11
|
+
|
12
|
+
def cotta
|
13
|
+
return Cotta.new(system)
|
14
|
+
end
|
15
|
+
|
16
|
+
def name
|
17
|
+
return @path.basename.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
def parent
|
21
|
+
return CottaDir.new(@system, @path.parent)
|
22
|
+
end
|
23
|
+
|
24
|
+
def extname
|
25
|
+
return @path.extname
|
26
|
+
end
|
27
|
+
|
28
|
+
def basename
|
29
|
+
return @path.basename(extname).to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
def exists?
|
33
|
+
return @system.file_exists?(@path)
|
34
|
+
end
|
35
|
+
|
36
|
+
def copy_to(target_file)
|
37
|
+
target_file.parent.mkdirs
|
38
|
+
@system.copy(path, target_file.path)
|
39
|
+
end
|
40
|
+
|
41
|
+
def move_to(target_file)
|
42
|
+
target_file.parent.mkdirs
|
43
|
+
@system.move(path, target_file.path)
|
44
|
+
end
|
45
|
+
|
46
|
+
def save(content = '')
|
47
|
+
write {|file| file.printf content.to_s}
|
48
|
+
end
|
49
|
+
|
50
|
+
def write(&block)
|
51
|
+
parent.mkdirs
|
52
|
+
open('w', &block)
|
53
|
+
end
|
54
|
+
|
55
|
+
def load
|
56
|
+
content = nil
|
57
|
+
read {|file| content = file.read}
|
58
|
+
return content
|
59
|
+
end
|
60
|
+
|
61
|
+
def read(&block)
|
62
|
+
open('r', &block)
|
63
|
+
end
|
64
|
+
|
65
|
+
def foreach()
|
66
|
+
open('r') do |file|
|
67
|
+
file.each {|line| yield line}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def delete
|
72
|
+
@system.delete_file(@path)
|
73
|
+
end
|
74
|
+
|
75
|
+
def ==(other)
|
76
|
+
return false unless other.kind_of? CottaFile
|
77
|
+
return @system == other.system && @path == other.path
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_s
|
81
|
+
return "#{super}-#@system-#@path"
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def open(*args)
|
87
|
+
result = f = @system.io(@path, *args)
|
88
|
+
if block_given?
|
89
|
+
begin
|
90
|
+
result = yield f
|
91
|
+
ensure
|
92
|
+
f.close
|
93
|
+
end
|
94
|
+
end
|
95
|
+
return result
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
require 'file_not_found_error'
|
5
|
+
|
6
|
+
module BuildMaster
|
7
|
+
class InMemorySystem
|
8
|
+
|
9
|
+
attr_reader :executed_commands
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@executed_commands = []
|
13
|
+
@content = ""
|
14
|
+
@file_system = Hash.new
|
15
|
+
@file_system[Pathname.new('/')] = DirectoryContent.new('/')
|
16
|
+
@file_system[Pathname.new('.')] = DirectoryContent.new('.')
|
17
|
+
end
|
18
|
+
|
19
|
+
def shell(command)
|
20
|
+
@executed_commands.push(command)
|
21
|
+
end
|
22
|
+
|
23
|
+
def dir_exists?(pathname)
|
24
|
+
content = path_content(pathname)
|
25
|
+
return !content.nil? && content.directory?
|
26
|
+
end
|
27
|
+
|
28
|
+
def file_exists?(pathname)
|
29
|
+
content = path_content(pathname)
|
30
|
+
return !content.nil? && content.file?
|
31
|
+
end
|
32
|
+
|
33
|
+
def list(pathname)
|
34
|
+
content = path_content(pathname)
|
35
|
+
return content.children.collect {|item| item.name}
|
36
|
+
end
|
37
|
+
|
38
|
+
def mkdir(pathname)
|
39
|
+
path_content(pathname.parent).add(create_dir(pathname))
|
40
|
+
end
|
41
|
+
|
42
|
+
def io(*args)
|
43
|
+
file_content = retrieve_file_content(args[0], args[1])
|
44
|
+
return StringIO.new(file_content.content, *args[1, args.size - 1])
|
45
|
+
end
|
46
|
+
|
47
|
+
def copy(source, target)
|
48
|
+
file_content = retrieve_file_content(source, 'r').content
|
49
|
+
create_file(target).content = file_content.clone
|
50
|
+
end
|
51
|
+
|
52
|
+
def move(source, target)
|
53
|
+
copy(source, target)
|
54
|
+
delete_file(source)
|
55
|
+
end
|
56
|
+
|
57
|
+
def delete_file(pathname)
|
58
|
+
raise Errno::ENOENT.new(pathname) unless file_exists? pathname
|
59
|
+
delete_entry(pathname)
|
60
|
+
end
|
61
|
+
|
62
|
+
def delete_dir(pathname)
|
63
|
+
raise Errno::ENOENT.new(pathname) unless dir_exists? pathname
|
64
|
+
delete_entry(pathname)
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_s
|
68
|
+
return 'InMemorySystem'
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
def gather_paths_to_create(pathname)
|
73
|
+
paths = Array.new
|
74
|
+
path_to_create = pathname
|
75
|
+
while (! dir_exists?(path_to_create))
|
76
|
+
paths.push(path_to_create)
|
77
|
+
path_to_create = path_to_create.parent
|
78
|
+
end
|
79
|
+
return paths
|
80
|
+
end
|
81
|
+
|
82
|
+
def create_dir(pathname)
|
83
|
+
content = DirectoryContent.new(pathname.basename.to_s)
|
84
|
+
@file_system[pathname] = content
|
85
|
+
return content
|
86
|
+
end
|
87
|
+
|
88
|
+
def create_file(pathname)
|
89
|
+
content = FileContent.new(pathname.basename.to_s)
|
90
|
+
@file_system[pathname] = content
|
91
|
+
return content
|
92
|
+
end
|
93
|
+
|
94
|
+
def path_content(pathname)
|
95
|
+
return @file_system[pathname]
|
96
|
+
end
|
97
|
+
|
98
|
+
def retrieve_file_content(pathname, options)
|
99
|
+
file_content = path_content(pathname)
|
100
|
+
if (file_content.nil?)
|
101
|
+
if (options =~ /r/)
|
102
|
+
raise Errno::ENOENT.new(pathname)
|
103
|
+
end
|
104
|
+
parent_dir = pathname.parent
|
105
|
+
file_content = create_file(pathname)
|
106
|
+
path_content(parent_dir).add(file_content)
|
107
|
+
end
|
108
|
+
return file_content
|
109
|
+
end
|
110
|
+
|
111
|
+
def delete_entry(pathname)
|
112
|
+
@file_system.delete pathname
|
113
|
+
@file_system[pathname.parent].delete(pathname.basename.to_s)
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
class DirectoryContent
|
119
|
+
attr_reader :name, :children
|
120
|
+
|
121
|
+
def initialize(name)
|
122
|
+
@name = name
|
123
|
+
@children = Array.new
|
124
|
+
end
|
125
|
+
|
126
|
+
def file?
|
127
|
+
return false
|
128
|
+
end
|
129
|
+
|
130
|
+
def directory?
|
131
|
+
return true
|
132
|
+
end
|
133
|
+
|
134
|
+
def add(content)
|
135
|
+
@children.push(content)
|
136
|
+
end
|
137
|
+
|
138
|
+
def delete(name)
|
139
|
+
@children.delete_if {|file_content| file_content.name == name}
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
class FileContent
|
144
|
+
attr_reader :name, :content
|
145
|
+
attr_writer :content
|
146
|
+
|
147
|
+
def initialize(name)
|
148
|
+
@name = name
|
149
|
+
@content = ''
|
150
|
+
end
|
151
|
+
|
152
|
+
def file?
|
153
|
+
return true
|
154
|
+
end
|
155
|
+
|
156
|
+
def directory?
|
157
|
+
return false
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|