BuildMaster 0.9.1 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (174) hide show
  1. data/bin/svnfix.rb +3 -0
  2. data/lib/buildmaster/ci/server.rb +55 -0
  3. data/lib/buildmaster/common.rb +3 -0
  4. data/lib/buildmaster/common/properties.rb +28 -0
  5. data/lib/buildmaster/{tree_to_object.rb → common/tree_to_object.rb} +0 -0
  6. data/lib/buildmaster/cotta.rb +1 -1
  7. data/lib/buildmaster/cotta/command_error.rb +6 -1
  8. data/lib/buildmaster/cotta/command_interface.rb +44 -0
  9. data/lib/buildmaster/cotta/command_runner.rb +39 -0
  10. data/lib/buildmaster/cotta/cotta.rb +40 -3
  11. data/lib/buildmaster/cotta/cotta_dir.rb +28 -7
  12. data/lib/buildmaster/cotta/cotta_file.rb +14 -2
  13. data/lib/buildmaster/cotta/cotta_pathname.rb +9 -0
  14. data/lib/buildmaster/cotta/in_memory_system.rb +20 -9
  15. data/lib/buildmaster/cotta/physical_system.rb +4 -8
  16. data/lib/buildmaster/project.rb +10 -0
  17. data/lib/buildmaster/{ant_driver.rb → project/ant_driver.rb} +0 -0
  18. data/lib/buildmaster/project/build.rb +3 -0
  19. data/lib/buildmaster/{build_number_file.rb → project/build_number_file.rb} +4 -0
  20. data/lib/buildmaster/project/ci.rb +3 -0
  21. data/lib/buildmaster/{cvs_driver.rb → project/cvs_driver.rb} +0 -0
  22. data/lib/buildmaster/project/ftp_driver.rb +64 -0
  23. data/lib/buildmaster/{java_manifest.rb → project/java_manifest.rb} +0 -0
  24. data/lib/buildmaster/project/pscp_driver.rb +17 -0
  25. data/lib/buildmaster/project/release.rb +67 -0
  26. data/lib/buildmaster/project/ruby_forge_project.rb +26 -0
  27. data/lib/buildmaster/{run_ant.rb → project/run_ant.rb} +0 -0
  28. data/lib/buildmaster/project/server_manager.rb +64 -0
  29. data/lib/buildmaster/project/svn_admin_driver.rb +20 -0
  30. data/lib/buildmaster/project/svn_driver.rb +94 -0
  31. data/lib/buildmaster/project/svn_helper.rb +113 -0
  32. data/lib/buildmaster/project/svn_status_info.rb +54 -0
  33. data/lib/buildmaster/{try.rb → project/try.rb} +0 -0
  34. data/lib/buildmaster/project/version_number_file.rb +45 -0
  35. data/lib/buildmaster/{windows → project/windows}/iis_driver.rb +4 -4
  36. data/lib/buildmaster/{windows → project/windows}/sql_server_driver.rb +0 -0
  37. data/lib/buildmaster/site.rb +5 -0
  38. data/lib/buildmaster/site/about_handler.rb +43 -0
  39. data/lib/buildmaster/site/content_engine_repository.rb +83 -0
  40. data/lib/buildmaster/site/element_processor_by_name.rb +18 -0
  41. data/lib/buildmaster/site/file_processor.rb +59 -0
  42. data/lib/buildmaster/site/site.rb +29 -6
  43. data/lib/buildmaster/site/site_server.rb +56 -0
  44. data/lib/buildmaster/{site_spec.rb → site/site_spec.rb} +63 -38
  45. data/lib/buildmaster/{site_tester.rb → site/site_tester.rb} +0 -0
  46. data/lib/buildmaster/site/source_content.rb +12 -0
  47. data/lib/buildmaster/{source_file_handler.rb → site/source_file_handler.rb} +13 -27
  48. data/lib/buildmaster/site/template_builder.rb +4 -0
  49. data/lib/buildmaster/site/template_error.rb +18 -0
  50. data/lib/buildmaster/{template_runner.rb → site/template_runner.rb} +6 -16
  51. data/lib/buildmaster/{templatelets.rb → site/templatelets.rb} +3 -1
  52. data/lib/buildmaster/site/templatelets/attribute.rb +21 -0
  53. data/lib/buildmaster/site/templatelets/code.rb +82 -0
  54. data/lib/buildmaster/{templatelets → site/templatelets}/each.rb +7 -5
  55. data/lib/buildmaster/{templatelets → site/templatelets}/href.rb +1 -1
  56. data/lib/buildmaster/{templatelets → site/templatelets}/include.rb +0 -0
  57. data/lib/buildmaster/{templatelets → site/templatelets}/link.rb +2 -3
  58. data/lib/buildmaster/{templatelets → site/templatelets}/text.rb +1 -1
  59. data/lib/buildmaster/{templatelets → site/templatelets}/when.rb +4 -7
  60. data/lib/buildmaster/site/templates/buildmaster/content/border_bottom.gif +0 -0
  61. data/lib/buildmaster/site/templates/buildmaster/content/buildmaster.css +370 -0
  62. data/lib/buildmaster/site/templates/buildmaster/content/logo.gif +0 -0
  63. data/lib/buildmaster/site/templates/buildmaster/content/news-rss2.xml +4 -0
  64. data/lib/buildmaster/site/templates/buildmaster/content/print.css +65 -0
  65. data/lib/buildmaster/site/templates/buildmaster/content/ruby.css +14 -0
  66. data/lib/buildmaster/site/templates/buildmaster/template.html +121 -0
  67. data/lib/buildmaster/site/templates/cotta/content/border_bottom.gif +0 -0
  68. data/lib/buildmaster/site/templates/cotta/content/cotta.css +363 -0
  69. data/lib/buildmaster/site/templates/cotta/content/cotta.gif +0 -0
  70. data/lib/buildmaster/site/templates/cotta/content/news-rss2.xml +2 -0
  71. data/lib/buildmaster/site/templates/cotta/template.html +106 -0
  72. data/lib/buildmaster/site/xtemplate.rb +26 -0
  73. data/lib/buildmaster/version +1 -0
  74. data/test/buildmaster/common/tc_properties.rb +24 -0
  75. data/test/buildmaster/{tc_tree_to_object.rb → common/tc_tree_to_object.rb} +18 -18
  76. data/test/buildmaster/cotta/cotta_specifications.rb +88 -64
  77. data/test/buildmaster/cotta/physical_system_stub.rb +3 -3
  78. data/test/buildmaster/cotta/system_file_specifications.rb +38 -47
  79. data/test/buildmaster/cotta/tc_command_interface.rb +46 -0
  80. data/test/buildmaster/cotta/tc_command_runner.rb +28 -0
  81. data/test/buildmaster/cotta/tc_cotta.rb +35 -9
  82. data/test/buildmaster/cotta/tc_cotta_dir_in_memory.rb +10 -5
  83. data/test/buildmaster/cotta/tc_cotta_file_in_memory.rb +3 -3
  84. data/test/buildmaster/cotta/tc_in_memory_system.rb +7 -2
  85. data/test/buildmaster/cotta/tc_pathname.rb +22 -0
  86. data/test/buildmaster/cotta/tc_physical_system.rb +12 -2
  87. data/test/buildmaster/{build.xml → project/build.xml} +0 -0
  88. data/test/buildmaster/{manifest.mf → project/manifest.mf} +0 -0
  89. data/test/buildmaster/{tc_ant_driver.rb → project/tc_ant_driver.rb} +3 -3
  90. data/test/buildmaster/{tc_build_number_file.rb → project/tc_build_number_file.rb} +7 -7
  91. data/test/buildmaster/{tc_cvs_driver.rb → project/tc_cvs_driver.rb} +14 -14
  92. data/test/buildmaster/{tc_java_manifest.rb → project/tc_java_manifest.rb} +7 -7
  93. data/test/buildmaster/project/tc_release.rb +61 -0
  94. data/test/buildmaster/project/tc_server_manager.rb +70 -0
  95. data/test/buildmaster/project/tc_svn_driver.rb +104 -0
  96. data/test/buildmaster/project/tc_svn_status_info.rb +37 -0
  97. data/test/buildmaster/project/tc_version_number_file.rb +46 -0
  98. data/test/buildmaster/{windows → project/windows}/tc_iis_driver.rb +5 -4
  99. data/test/buildmaster/{windows → project/windows}/tc_sql_server_driver.rb +4 -4
  100. data/test/buildmaster/site/content/tc_content_engine_repository.rb +63 -0
  101. data/test/buildmaster/site/tc_element_processor_by_name.rb +29 -0
  102. data/test/buildmaster/site/tc_file_processor.rb +141 -0
  103. data/test/buildmaster/site/tc_site.rb +42 -11
  104. data/test/buildmaster/site/tc_site_server.rb +43 -0
  105. data/test/buildmaster/{tc_site_spec.rb → site/tc_site_spec.rb} +9 -9
  106. data/test/buildmaster/{tc_source_file_handler.rb → site/tc_source_file_handler.rb} +10 -9
  107. data/test/buildmaster/site/tc_template_builder.rb +23 -23
  108. data/test/buildmaster/site/tc_template_error.rb +15 -0
  109. data/test/buildmaster/{tc_template_runner.rb → site/tc_template_runner.rb} +22 -17
  110. data/test/buildmaster/site/tc_templatelets.rb +37 -0
  111. data/test/buildmaster/{tc_xtemplate.rb → site/tc_xtemplate.rb} +14 -15
  112. data/test/buildmaster/{template.xhtml → site/template.xhtml} +0 -0
  113. data/test/buildmaster/{templatelets → site/templatelets}/common_templatelet_test.rb +11 -7
  114. data/test/buildmaster/{templatelets → site/templatelets}/tc_attribute.rb +14 -10
  115. data/test/buildmaster/site/templatelets/tc_code.rb +132 -0
  116. data/test/buildmaster/{templatelets → site/templatelets}/tc_each.rb +25 -12
  117. data/test/buildmaster/{templatelets → site/templatelets}/tc_href.rb +6 -8
  118. data/test/buildmaster/{templatelets → site/templatelets}/tc_include.rb +3 -12
  119. data/test/buildmaster/{templatelets → site/templatelets}/tc_link.rb +11 -18
  120. data/test/buildmaster/{templatelets → site/templatelets}/tc_text.rb +2 -9
  121. data/test/buildmaster/{templatelets → site/templatelets}/tc_when.rb +8 -15
  122. data/test/manual/bms.rb +10 -0
  123. data/test/tmp/svn_test/repository/README.txt +5 -0
  124. data/test/tmp/svn_test/repository/conf/authz +21 -0
  125. data/test/tmp/svn_test/repository/conf/passwd +8 -0
  126. data/test/tmp/svn_test/repository/conf/svnserve.conf +30 -0
  127. data/test/tmp/svn_test/repository/db/current +1 -0
  128. data/test/tmp/svn_test/repository/db/format +1 -0
  129. data/test/tmp/svn_test/repository/db/fs-type +1 -0
  130. data/test/tmp/svn_test/repository/db/revprops/0 +5 -0
  131. data/test/tmp/svn_test/repository/db/revprops/1 +13 -0
  132. data/test/tmp/svn_test/repository/db/revprops/2 +13 -0
  133. data/test/tmp/svn_test/repository/db/revprops/3 +13 -0
  134. data/test/tmp/svn_test/repository/db/revprops/4 +13 -0
  135. data/test/tmp/svn_test/repository/db/revs/0 +11 -0
  136. data/test/tmp/svn_test/repository/db/revs/1 +25 -0
  137. data/test/tmp/svn_test/repository/db/revs/2 +29 -0
  138. data/test/tmp/svn_test/repository/db/revs/3 +33 -0
  139. data/test/tmp/svn_test/repository/db/revs/4 +0 -0
  140. data/test/tmp/svn_test/repository/db/uuid +1 -0
  141. data/test/tmp/svn_test/repository/db/write-lock +0 -0
  142. data/test/tmp/svn_test/repository/format +1 -0
  143. data/test/tmp/svn_test/repository/hooks/post-commit.tmpl +51 -0
  144. data/test/tmp/svn_test/repository/hooks/post-lock.tmpl +44 -0
  145. data/test/tmp/svn_test/repository/hooks/post-revprop-change.tmpl +56 -0
  146. data/test/tmp/svn_test/repository/hooks/post-unlock.tmpl +42 -0
  147. data/test/tmp/svn_test/repository/hooks/pre-commit.tmpl +70 -0
  148. data/test/tmp/svn_test/repository/hooks/pre-lock.tmpl +64 -0
  149. data/test/tmp/svn_test/repository/hooks/pre-revprop-change.tmpl +66 -0
  150. data/test/tmp/svn_test/repository/hooks/pre-unlock.tmpl +60 -0
  151. data/test/tmp/svn_test/repository/hooks/start-commit.tmpl +54 -0
  152. data/test/tmp/svn_test/repository/locks/db-logs.lock +3 -0
  153. data/test/tmp/svn_test/repository/locks/db.lock +3 -0
  154. data/test/tmp/svn_test/second/test.txt +1 -0
  155. data/test/tmp/svn_test/workdir/test.txt +1 -0
  156. data/test/ts_buildmaster.rb +0 -1
  157. metadata +168 -69
  158. data/lib/buildmaster.rb +0 -10
  159. data/lib/buildmaster/build_file.rb +0 -11
  160. data/lib/buildmaster/buildnumber +0 -1
  161. data/lib/buildmaster/file_processor.rb +0 -138
  162. data/lib/buildmaster/site_server.rb +0 -33
  163. data/lib/buildmaster/source_content.rb +0 -11
  164. data/lib/buildmaster/svn_driver.rb +0 -78
  165. data/lib/buildmaster/template_error.rb +0 -8
  166. data/lib/buildmaster/templatelets/attribute.rb +0 -16
  167. data/lib/buildmaster/xtemplate.rb +0 -27
  168. data/lib/mock.rb +0 -3
  169. data/lib/mock/mock_base.rb +0 -24
  170. data/test/buildmaster/tc_file_processor.rb +0 -125
  171. data/test/buildmaster/tc_svn_driver.rb +0 -81
  172. data/test/tmp/output/index.html +0 -8
  173. data/test/tmp/output/markdown.html +0 -8
  174. data/test/tmp/output/textile.html +0 -8
@@ -0,0 +1,3 @@
1
+ require 'buildmaster/svn_helper'
2
+
3
+ BuildMaster::SvnHelper.from_directory('.').fix
@@ -0,0 +1,55 @@
1
+ module BuildMaster
2
+ module CI
3
+
4
+ =begin rdoc
5
+ A CI (Continuous Integration) server that does the following loop
6
+ * check for modifications
7
+ * if modification set found,
8
+ ** update
9
+ ** make
10
+ ** publish (update site, email notification)
11
+ =end
12
+ class Server
13
+
14
+ def initialize
15
+ @modification_checker = Array.new
16
+ @updator = Array.new
17
+ end
18
+
19
+ def serve
20
+ pid = fork {start}
21
+ if (pid)
22
+ ['INT', 'TERM'].each { |signal|
23
+ trap(signal){Process.kill('break', pid)}
24
+ }
25
+ end
26
+ end
27
+
28
+ def start
29
+ puts "server started"
30
+ until @stopped
31
+ if check_modifications
32
+ build_loop
33
+ end
34
+ sleep 30
35
+ end
36
+ end
37
+
38
+ def stop
39
+ @stopped = true
40
+ Thread.current.raise 'shutting down'
41
+ end
42
+
43
+ private
44
+ def check_modifications
45
+ end
46
+
47
+ def build_loop
48
+ update
49
+ result = build
50
+ publish(result)
51
+ end
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,3 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'common')
2
+ require 'properties'
3
+ require 'tree_to_object'
@@ -0,0 +1,28 @@
1
+ module BuildMaster
2
+ module Common
3
+
4
+ class Properties
5
+ def Properties::parse_io(io)
6
+ hash = Hash.new
7
+ io.each_line do |line|
8
+ line.strip!
9
+ if (line[0..0] != '#')
10
+ parse_into_hash(hash, line)
11
+ end
12
+ end
13
+ return hash
14
+ end
15
+
16
+ private
17
+ def Properties::parse_into_hash(hash, line)
18
+ index = line.index(':')
19
+ if (index)
20
+ property = line[0, index].strip
21
+ value = line[index + 1, line.length - index - 1].strip
22
+ hash[property] = value
23
+ end
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -1,4 +1,4 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__))
2
2
 
3
3
  require 'cotta/cotta'
4
- require 'cotta/file_not_found_error'
4
+ require 'cotta/file_not_found_error'
@@ -1,5 +1,10 @@
1
1
  module BuildMaster
2
2
  class CommandError < StandardError
3
-
3
+ attr_reader :proc_status, :output
4
+
5
+ def initialize(proc_status, output)
6
+ @proc_status = proc_status
7
+ @output = output
8
+ end
4
9
  end
5
10
  end
@@ -0,0 +1,44 @@
1
+ module BuildMaster
2
+ class CommandInterface
3
+ def initialize(io = SystemIo.new)
4
+ @io = io
5
+ end
6
+
7
+ def puts(content)
8
+ @io.puts(content)
9
+ end
10
+
11
+ def prompt(question)
12
+ puts(question)
13
+ gets
14
+ end
15
+
16
+ def prompt_for_choice(question, candidates)
17
+ puts(question)
18
+ 0.upto(candidates.size - 1) do |index|
19
+ puts "[#{index + 1}] #{candidates[index]}"
20
+ end
21
+ answer = gets.to_i
22
+ seletion = nil
23
+ if answer > 0 && answer <= candidates.size
24
+ selection = candidates[answer - 1]
25
+ end
26
+ return selection
27
+ end
28
+
29
+ def gets
30
+ @io.gets
31
+ end
32
+
33
+ end
34
+
35
+ class SystemIo
36
+ def puts(content)
37
+ $stdout.puts(content)
38
+ end
39
+
40
+ def gets
41
+ $stdin.gets
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,39 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'command_error'
4
+
5
+ module BuildMaster
6
+ class CommandRunner
7
+ attr_reader :outputs
8
+
9
+ def initialize(command)
10
+ @command = command
11
+ end
12
+
13
+ def execute
14
+ id = rand(10000)
15
+ puts "[#{id}]$> #{@command}"
16
+ output = nil
17
+ IO.popen(@command) do |io|
18
+ if (block_given?)
19
+ output = yield io
20
+ else
21
+ output = load_output(id, io)
22
+ end
23
+ end
24
+ last_process = $?
25
+ raise CommandError.new(last_process, output), @command unless last_process.exitstatus == 0
26
+ return output
27
+ end
28
+
29
+ private
30
+ def load_output(id, io)
31
+ output = ''
32
+ while (line = io.gets) do
33
+ puts "[#{id}] #{line}"
34
+ output << line
35
+ end
36
+ return output
37
+ end
38
+ end
39
+ end
@@ -4,26 +4,63 @@ require 'physical_system'
4
4
  require 'cotta_dir'
5
5
  require 'cotta_file'
6
6
  require 'pathname'
7
+ require 'cotta_pathname'
8
+ require 'command_interface'
7
9
 
8
10
  module BuildMaster
9
11
  class Cotta
12
+ attr_accessor :command_interface
13
+
10
14
  def initialize(system=PhysicalSystem.new)
11
15
  @system = system
16
+ @command_interface = CommandInterface.new
17
+ end
18
+
19
+ def shell(command_line, &block)
20
+ @system.shell(command_line, &block)
12
21
  end
13
22
 
14
- def shell(command_line)
15
- puts "$> #{command_line}"
16
- @system.shell(command_line)
23
+ def command_interface=(value)
24
+ if (value)
25
+ @command_interface = value
26
+ else
27
+ @command_interface = CommandInterface.new
28
+ end
17
29
  end
18
30
 
19
31
  def dir(path)
32
+ return nil unless path
20
33
  return CottaDir.new(@system, Pathname.new(path))
21
34
  end
22
35
 
36
+ def Cotta::dir(path)
37
+ return nil unless path
38
+ return Cotta.new.dir(File.expand_path(path))
39
+ end
40
+
23
41
  def file(path)
42
+ return nil unless path
24
43
  return CottaFile.new(@system, Pathname.new(path))
25
44
  end
26
45
 
46
+ def Cotta::file(path)
47
+ return nil unless path
48
+ return Cotta.new.file(File.expand_path(path))
49
+ end
50
+
51
+ def Cotta::parent_of(path)
52
+ return Cotta.file(path).parent
53
+ end
54
+
55
+ def entry(path)
56
+ entry = file(path)
57
+ unless (entry.exists?)
58
+ entry = dir(path)
59
+ raise "#{path} exists as niether file nor directory" unless entry.exists?
60
+ end
61
+ return entry
62
+ end
63
+
27
64
  def environment!(variable)
28
65
  @system.environment!(variable)
29
66
  end
@@ -7,8 +7,8 @@ class CottaDir
7
7
  attr_reader :path, :system
8
8
 
9
9
  def initialize(system, path)
10
- @system = system
11
10
  @path = path
11
+ @system = system
12
12
  @name = @path.basename.to_s
13
13
  end
14
14
 
@@ -17,7 +17,17 @@ class CottaDir
17
17
  end
18
18
 
19
19
  def name
20
- return @path.basename.to_s
20
+ name = nil
21
+ if root?
22
+ name = path.to_s
23
+ else
24
+ name = @path.basename.to_s
25
+ end
26
+ return name
27
+ end
28
+
29
+ def root?
30
+ parent.nil?
21
31
  end
22
32
 
23
33
  def exists?
@@ -25,10 +35,9 @@ class CottaDir
25
35
  end
26
36
 
27
37
  def parent
28
- if (@name == '.')
29
- return nil
30
- end
31
- return CottaDir.new(@system, @path.parent)
38
+ parent_path = @path.cotta_parent
39
+ return nil unless parent_path
40
+ return CottaDir.new(@system, parent_path)
32
41
  end
33
42
 
34
43
  def dir(name)
@@ -56,11 +65,19 @@ class CottaDir
56
65
  @system.move_dir(@path, target.path)
57
66
  end
58
67
 
68
+ def move_to_path(target_path)
69
+ move_to(cotta.dir(target_path))
70
+ end
71
+
59
72
  def copy_to(target)
60
73
  target.parent.mkdirs
61
74
  @system.copy_dir(@path, target.path)
62
75
  end
63
76
 
77
+ def copy_to_path(target_path)
78
+ copy_to(cotta.dir(target_path))
79
+ end
80
+
64
81
  def list
65
82
  @system.list(@path).collect do |item|
66
83
  candidate = dir(item)
@@ -75,8 +92,12 @@ class CottaDir
75
92
  return @path == other.path && @system == other.system
76
93
  end
77
94
 
95
+ def inspect
96
+ return "#{self.class}:#{self.object_id}-#{@system.inspect}-#@path"
97
+ end
98
+
78
99
  def to_s
79
- return "#{super}-#@system-#@path"
100
+ @path
80
101
  end
81
102
 
82
103
  end
@@ -5,8 +5,8 @@ class CottaFile
5
5
  attr_reader :system, :path
6
6
 
7
7
  def initialize(system, path)
8
- @system = system
9
8
  @path = path
9
+ @system = system
10
10
  end
11
11
 
12
12
  def cotta
@@ -38,11 +38,19 @@ class CottaFile
38
38
  @system.copy_file(path, target_file.path)
39
39
  end
40
40
 
41
+ def copy_to_path(target_path)
42
+ copy_to(cotta.file(target_path))
43
+ end
44
+
41
45
  def move_to(target_file)
42
46
  target_file.parent.mkdirs
43
47
  @system.move_file(path, target_file.path)
44
48
  end
45
49
 
50
+ def move_to_path(target_path)
51
+ move_to(cotta.file(target_path))
52
+ end
53
+
46
54
  def save(content = '')
47
55
  write {|file| file.printf content.to_s}
48
56
  end
@@ -78,7 +86,11 @@ class CottaFile
78
86
  end
79
87
 
80
88
  def to_s
81
- return "#{super}-#@system-#@path"
89
+ @path
90
+ end
91
+
92
+ def inspect
93
+ return "#{self.class}:#{self.object_id}-#{@system.inspect}-#@path"
82
94
  end
83
95
 
84
96
  private
@@ -0,0 +1,9 @@
1
+ class Pathname
2
+ def cotta_parent
3
+ parent_path = parent
4
+ if (parent_path == self || parent_path.to_s == '..')
5
+ return nil
6
+ end
7
+ return parent_path
8
+ end
9
+ end
@@ -12,6 +12,7 @@ class InMemorySystem
12
12
  @executed_commands = []
13
13
  @content = ""
14
14
  @file_system = Hash.new
15
+ @file_system[nil] = DirectoryContent.new('')
15
16
  @file_system[Pathname.new('/')] = DirectoryContent.new('/')
16
17
  @file_system[Pathname.new('.')] = DirectoryContent.new('.')
17
18
  @output_map = Hash.new
@@ -19,9 +20,6 @@ class InMemorySystem
19
20
 
20
21
  def shell(command)
21
22
  @executed_commands.push(command)
22
- end
23
-
24
- def shell_output(command)
25
23
  result = @output_map[command]
26
24
  raise "#{command} not found in expectation" unless result
27
25
  return result
@@ -30,9 +28,13 @@ class InMemorySystem
30
28
  def output_for_command(command, output)
31
29
  @output_map[command] = output
32
30
  end
31
+
32
+ def expect_command(command)
33
+ Entry.new(command)
34
+ end
33
35
 
34
36
  def dir_exists?(pathname)
35
- content = path_content(pathname)
37
+ content = path_content(pathname)
36
38
  return !content.nil? && content.directory?
37
39
  end
38
40
 
@@ -47,7 +49,7 @@ class InMemorySystem
47
49
  end
48
50
 
49
51
  def mkdir(pathname)
50
- path_content(pathname.parent).add(create_dir(pathname))
52
+ path_content!(pathname.cotta_parent).add(create_dir(pathname))
51
53
  end
52
54
 
53
55
  def io(*args)
@@ -105,7 +107,7 @@ class InMemorySystem
105
107
  path_to_create = pathname
106
108
  while (! dir_exists?(path_to_create))
107
109
  paths.push(path_to_create)
108
- path_to_create = path_to_create.parent
110
+ path_to_create = path_to_create.cotta_parent
109
111
  end
110
112
  return paths
111
113
  end
@@ -118,14 +120,23 @@ class InMemorySystem
118
120
 
119
121
  def create_file(pathname)
120
122
  content = FileContent.new(pathname.basename.to_s)
121
- parent_dir = pathname.parent
123
+ parent_dir = pathname.cotta_parent
122
124
  path_content(parent_dir).add(content)
123
125
  @file_system[pathname] = content
124
126
  return content
125
127
  end
126
128
 
127
129
  def path_content(pathname)
128
- return @file_system[pathname]
130
+ content = path_content!(pathname)
131
+ if (content.nil? && pathname.cotta_parent.nil?)
132
+ mkdir(pathname)
133
+ content = @file_system[pathname]
134
+ end
135
+ return content
136
+ end
137
+
138
+ def path_content!(pathname)
139
+ @file_system[pathname]
129
140
  end
130
141
 
131
142
  def retrieve_file_content(pathname, options)
@@ -141,7 +152,7 @@ class InMemorySystem
141
152
 
142
153
  def delete_entry(pathname)
143
154
  @file_system.delete pathname
144
- @file_system[pathname.parent].delete(pathname.basename.to_s)
155
+ @file_system[pathname.cotta_parent].delete(pathname.basename.to_s)
145
156
  end
146
157
 
147
158
  end