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.
Files changed (72) hide show
  1. data/README +6 -29
  2. data/lib/buildmaster.rb +0 -2
  3. data/lib/buildmaster/ant_driver.rb +13 -12
  4. data/lib/buildmaster/build_number_file.rb +2 -12
  5. data/lib/buildmaster/buildnumber +1 -1
  6. data/lib/buildmaster/cotta.rb +4 -0
  7. data/lib/buildmaster/cotta/command_error.rb +5 -0
  8. data/lib/buildmaster/cotta/cotta.rb +35 -0
  9. data/lib/buildmaster/cotta/cotta_dir.rb +73 -0
  10. data/lib/buildmaster/cotta/cotta_file.rb +99 -0
  11. data/lib/buildmaster/cotta/file_not_found_error.rb +13 -0
  12. data/lib/buildmaster/cotta/in_memory_system.rb +160 -0
  13. data/lib/buildmaster/cotta/physical_system.rb +64 -0
  14. data/lib/buildmaster/cvs_driver.rb +5 -13
  15. data/lib/buildmaster/file_processor.rb +34 -33
  16. data/lib/buildmaster/java_manifest.rb +3 -3
  17. data/lib/buildmaster/site/site.rb +11 -22
  18. data/lib/buildmaster/site_spec.rb +15 -13
  19. data/lib/buildmaster/source_file_handler.rb +1 -1
  20. data/lib/buildmaster/svn_driver.rb +14 -20
  21. data/lib/buildmaster/{template_exception.rb → template_error.rb} +1 -1
  22. data/lib/buildmaster/template_runner.rb +2 -2
  23. data/lib/buildmaster/templatelets/attribute.rb +1 -1
  24. data/lib/buildmaster/templatelets/href.rb +1 -1
  25. data/lib/buildmaster/templatelets/text.rb +1 -1
  26. data/lib/buildmaster/templatelets/when.rb +1 -1
  27. data/lib/buildmaster/windows.rb +3 -0
  28. data/lib/buildmaster/windows/iis_driver.rb +33 -0
  29. data/lib/buildmaster/windows/sql_server_driver.rb +27 -0
  30. data/test/buildmaster/cotta/content.txt +3 -0
  31. data/test/buildmaster/cotta/cotta_specifications.rb +172 -0
  32. data/test/buildmaster/cotta/physical_system_stub.rb +85 -0
  33. data/test/buildmaster/cotta/system_file_specifications.rb +131 -0
  34. data/test/buildmaster/cotta/tc_cotta.rb +33 -0
  35. data/test/buildmaster/cotta/tc_cotta_dir_in_memory.rb +23 -0
  36. data/test/buildmaster/cotta/tc_cotta_dir_physical.rb +17 -0
  37. data/test/buildmaster/cotta/tc_cotta_file_in_memory.rb +20 -0
  38. data/test/buildmaster/cotta/tc_cotta_file_physical.rb +17 -0
  39. data/test/buildmaster/cotta/tc_in_memory_system.rb +25 -0
  40. data/test/buildmaster/cotta/tc_physical_system.rb +26 -0
  41. data/test/buildmaster/manifest.mf +1 -1
  42. data/test/buildmaster/site/tc_site.rb +58 -34
  43. data/test/buildmaster/site/tc_template_builder.rb +32 -31
  44. data/test/buildmaster/tc_ant_driver.rb +11 -13
  45. data/test/buildmaster/tc_build_number_file.rb +21 -16
  46. data/test/buildmaster/tc_cvs_driver.rb +35 -37
  47. data/test/buildmaster/tc_file_processor.rb +58 -34
  48. data/test/buildmaster/tc_java_manifest.rb +37 -9
  49. data/test/buildmaster/tc_site_spec.rb +20 -15
  50. data/test/buildmaster/tc_source_file_handler.rb +4 -4
  51. data/test/buildmaster/tc_svn_driver.rb +51 -38
  52. data/test/buildmaster/tc_template_runner.rb +19 -18
  53. data/test/buildmaster/tc_tree_to_object.rb +47 -46
  54. data/test/buildmaster/tc_xtemplate.rb +52 -38
  55. data/test/buildmaster/templatelets/common_templatelet_test.rb +9 -8
  56. data/test/buildmaster/templatelets/tc_attribute.rb +26 -23
  57. data/test/buildmaster/templatelets/tc_each.rb +27 -26
  58. data/test/buildmaster/templatelets/tc_href.rb +14 -13
  59. data/test/buildmaster/templatelets/tc_include.rb +11 -4
  60. data/test/buildmaster/templatelets/tc_link.rb +18 -12
  61. data/test/buildmaster/templatelets/tc_text.rb +12 -7
  62. data/test/buildmaster/templatelets/tc_when.rb +11 -5
  63. data/test/buildmaster/windows/tc_iis_driver.rb +29 -0
  64. data/test/buildmaster/windows/tc_sql_server_driver.rb +24 -0
  65. data/test/spec_runner.rb +27 -0
  66. data/test/ts_buildmaster.rb +2 -19
  67. metadata +34 -10
  68. data/lib/buildmaster/release_control.rb +0 -22
  69. data/lib/buildmaster/shell_command.rb +0 -39
  70. data/test/buildmaster/tc_release_control.rb +0 -27
  71. data/test/buildmaster/ts_site.rb +0 -4
  72. data/test/buildmaster/ts_templatelets.rb +0 -10
@@ -2,7 +2,7 @@ $:.unshift File.dirname(__FILE__)
2
2
 
3
3
  module BuildMaster
4
4
 
5
- class TemplateException < Exception
5
+ class TemplateError < StandardError
6
6
  end
7
7
 
8
8
  end
@@ -1,6 +1,6 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
2
 
3
- require 'template_exception'
3
+ require 'template_error'
4
4
 
5
5
  module BuildMaster
6
6
  class TemplateRunner
@@ -50,7 +50,7 @@ module BuildMaster
50
50
  message = "process_#{template_element.name}_directive"
51
51
  templatelet = @templatelets[template_element.name]
52
52
  if (not templatelet)
53
- raise TemplateException, "unable to process element template:#{template_element.name}"
53
+ raise TemplateError, "unable to process element template:#{template_element.name}"
54
54
  end
55
55
  templatelet.process(target, template_element, @source_instance)
56
56
  end
@@ -8,7 +8,7 @@ class Attribute
8
8
  name = template.attribute_value!('name')
9
9
  eval = template.attribute_value!('eval')
10
10
  if (not @evaluator.respond_to?(eval))
11
- raise TemplateException, '#{@evaluator.class} cannot evaluate expression #{eval}'
11
+ raise TemplateError, '#{@evaluator.class} cannot evaluate expression #{eval}'
12
12
  end
13
13
  target.attributes[name] = @evaluator.send(eval, source.path)
14
14
  end
@@ -2,7 +2,7 @@ $:.unshift(File.join('..', File.dirname(__FILE__)))
2
2
 
3
3
  require 'uri'
4
4
 
5
- require 'template_exception'
5
+ require 'template_error'
6
6
  require 'template_runner'
7
7
 
8
8
  module BuildMaster
@@ -7,7 +7,7 @@ class Text
7
7
  def process(target, template, source)
8
8
  property = template.attribute_value!('property')
9
9
  value = @properties[property]
10
- raise TemplateException, "property value for '#{property}' not found" unless value
10
+ raise TemplateError, "property value for '#{property}' not found" unless value
11
11
  target.add(REXML::Text.new(value))
12
12
  end
13
13
  end
@@ -12,7 +12,7 @@ class When
12
12
  def process(target, template, source)
13
13
  eval = template.attribute_value!('test')
14
14
  if (not @evaluator.respond_to?(eval))
15
- raise TemplateException, "#{@evaluator.class} cannot evaluate expression #{eval}"
15
+ raise TemplateError, "#{@evaluator.class} cannot evaluate expression #{eval}"
16
16
  end
17
17
  if (@evaluator.send(eval, source.path))
18
18
  runner = TemplateRunner.new(target, template, source)
@@ -0,0 +1,3 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ require 'windows/iis_driver'
3
+ require 'windows/sql_server_driver'
@@ -0,0 +1,33 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..')
2
+ require 'cotta/cotta'
3
+ require 'cotta/in_memory_system'
4
+
5
+ module BuildMaster
6
+ class IisDriver
7
+ def initialize(cotta=Cotta.new)
8
+ @cotta = cotta
9
+ @executable = 'C:\\WINDOWS\\system32\\iisreset.exe'
10
+ if (not File.exists?(@executable))
11
+ raise "#{@executable} not found"
12
+ end
13
+ end
14
+
15
+ def status
16
+ execute('query')
17
+ end
18
+
19
+ def start
20
+ execute('start')
21
+ end
22
+
23
+ def stop
24
+ execute('stop')
25
+ end
26
+
27
+ private
28
+ def execute(command)
29
+ #@cotta.shell("#{@executable} /#{command}")
30
+ @cotta.shell("sc #{command} W3SVC")
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'cotta')
2
+ module BuildMaster
3
+
4
+ class SqlServerDriver
5
+ def initialize(cotta=Cotta.new)
6
+ @instance_name = 'MSSQLSERVER'
7
+ @cotta = cotta
8
+ end
9
+
10
+ def start
11
+ execute('start')
12
+ end
13
+
14
+ def status
15
+ execute('query')
16
+ end
17
+
18
+ def stop
19
+ execute('stop')
20
+ end
21
+
22
+ private
23
+ def execute(command)
24
+ @cotta.shell("sc #{command} #{@instance_name}")
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ line one
2
+ line two
3
+ line three
@@ -0,0 +1,172 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', '..', 'lib')
2
+
3
+ require 'buildmaster/cotta'
4
+ require 'buildmaster/cotta/cotta_file'
5
+ require 'buildmaster/cotta/cotta_dir'
6
+ require 'buildmaster/cotta/in_memory_system'
7
+ require 'spec'
8
+ require 'pathname'
9
+
10
+ module CottaSpecifications
11
+
12
+ def register_cotta_file_specifications
13
+ setup do
14
+ @file = BuildMaster::CottaFile.new(@system, Pathname.new('dir/file.txt'))
15
+ end
16
+
17
+ specify 'file can be created with system and pathname' do
18
+ @file.name.should_equal 'file.txt'
19
+ @file.path.should_equal Pathname.new('dir/file.txt')
20
+ @file.exists?.should_equal false
21
+ end
22
+
23
+ specify 'file should know properties like parent, name, etc.' do
24
+ @file.parent.should_equal BuildMaster::CottaDir.new(@system, Pathname.new('dir'))
25
+ @file.name.should_equal 'file.txt'
26
+ @file.path.should_equal Pathname.new('dir/file.txt')
27
+ @file.extname.should_equal '.txt'
28
+ @file.basename.should_equal 'file'
29
+ end
30
+
31
+ specify 'should load and save file content' do
32
+ @file.exists?.should_equal false
33
+ @file.parent.exists?.should_equal false
34
+ @file.save("content to save\nsecond line")
35
+ @file.exists?.should_equal true
36
+ @file.load.should_equal("content to save\nsecond line")
37
+ end
38
+
39
+ specify 'should open file to read' do
40
+ @file.save("one\ntwo")
41
+ @file.read do |file|
42
+ file.gets.should_equal("one\n")
43
+ file.gets.should_equal('two')
44
+ end
45
+ end
46
+
47
+ specify 'should equal if same system and pathname' do
48
+ file2 = BuildMaster::CottaFile.new(@system, Pathname.new('dir/file.txt'))
49
+ file2.should_equal @file
50
+ end
51
+
52
+ specify 'should copy to another file' do
53
+ file2 = BuildMaster::CottaFile.new(@system, Pathname.new('dir2/file.txt'))
54
+ file2.exists?.should_equal false
55
+ @file.save('my content')
56
+ @file.copy_to(file2)
57
+ file2.exists?.should_equal true
58
+ file2.load.should_equal 'my content'
59
+ end
60
+
61
+ specify 'should move file' do
62
+ file2 = BuildMaster::CottaFile.new(@system, Pathname.new('dir2/file.txt'))
63
+ file2.exists?.should_equal false
64
+ @file.save('content')
65
+ @file.move_to(file2)
66
+ file2.exists?.should_equal true
67
+ file2.load.should_equal 'content'
68
+ @file.exists?.should_equal false
69
+ end
70
+
71
+ specify 'should support foreach' do
72
+ @file.write do |file|
73
+ file.puts 'line one'
74
+ file.puts 'line two'
75
+ end
76
+ collected = Array.new
77
+ @file.foreach do |line|
78
+ collected.push line
79
+ end
80
+ collected.size.should_equal 2
81
+ collected[0].should_equal "line one\n"
82
+ collected[1].should_equal "line two\n"
83
+ end
84
+
85
+ specify 'should delete file' do
86
+ @file.save
87
+ @file.exists?.should_equal true
88
+ @file.delete
89
+ @file.exists?.should_equal false
90
+ end
91
+
92
+ specify 'should raise error if file to delete does not exist' do
93
+ lambda {@file.delete}.should_raise Errno::ENOENT
94
+ end
95
+
96
+ end
97
+
98
+ def register_cotta_dir_specifications
99
+ setup do
100
+ @dir = BuildMaster::CottaDir.new(@system, Pathname.new('dir'))
101
+ end
102
+
103
+ specify 'load dir with basic information' do
104
+ @dir.name.should_equal 'dir'
105
+ end
106
+
107
+ specify 'dir objects are value objects, equal on system and path' do
108
+ (BuildMaster::CottaDir.new(@system, Pathname.new('dir')) == @dir).should_equal true
109
+ end
110
+
111
+ specify 'dir should not be equal if path different' do
112
+ (BuildMaster::CottaDir.new(@system, Pathname.new('/dir')) == @dir).should_equal false
113
+ end
114
+
115
+ specify 'dir should know its parent' do
116
+ @dir.parent.name.should_equal '.'
117
+ @dir.parent.parent.should_equal nil
118
+ end
119
+
120
+ specify 'dir should return sub directory' do
121
+ @dir.dir('sub').path.should_equal Pathname.new('dir/sub')
122
+ @dir.dir('sub').parent.should_equal @dir
123
+ end
124
+
125
+ specify 'dir should return a directory from a relative pathname' do
126
+ @dir.dir(Pathname.new('one/two/three')).should_equal @dir.dir('one').dir('two').dir('three')
127
+ end
128
+
129
+ specify 'should get file in current directory' do
130
+ file = @dir.file('file.txt')
131
+ file.name.should_equal 'file.txt'
132
+ file.path.should_equal Pathname.new('dir/file.txt')
133
+ file.parent.should_equal @dir
134
+ end
135
+
136
+ specify 'should create dir and its parent' do
137
+ dir = @dir.dir('one').dir('two')
138
+ dir.exists?.should_equal false
139
+ dir.parent.exists?.should_equal false
140
+ dir.mkdirs
141
+ dir.exists?.should_equal true
142
+ dir.parent.exists?.should_equal true
143
+ end
144
+
145
+ specify 'should delete dir and its children' do
146
+ dir = @dir.dir('one').dir('two').dir('three')
147
+ dir.mkdirs
148
+ @dir.exists?.should_equal true
149
+ @dir.delete
150
+ dir.exists?.should_equal false
151
+ @dir.exists?.should_equal false
152
+ end
153
+
154
+ specify 'should do nothing if dir already exists' do
155
+ dir = @dir.dir('one').dir('two')
156
+ dir.mkdirs
157
+ dir.mkdirs
158
+ end
159
+
160
+ specify 'should list dirs' do
161
+ @dir.dir('one').mkdirs
162
+ @dir.file('one.txt').save
163
+ actual_dir_list = @dir.list
164
+ actual_dir_list.size.should_equal 2
165
+ actual_dir_list[0].name.should_equal 'one'
166
+ actual_dir_list[0].list.size.should_equal 0
167
+ actual_dir_list[1].name.should_equal 'one.txt'
168
+ actual_dir_list[1].save
169
+ end
170
+ end
171
+
172
+ end
@@ -0,0 +1,85 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', '..', 'lib')
2
+ require 'buildmaster/cotta/physical_system'
3
+
4
+ module BuildMaster
5
+ class PhysicalSystemStub
6
+ attr_reader :executed_commands
7
+
8
+ def initialize
9
+ @executed_commands = Array.new
10
+ tmp_path = File.join(File.dirname(__FILE__), '..', '..', '..', 'tmp')
11
+ @system = PhysicalSystem.new
12
+ ensure_clean_directory(tmp_path)
13
+ Dir.mkdir(File.join(tmp_path, 'current'))
14
+ Dir.mkdir(File.join(tmp_path, 'root'))
15
+ @tmp_path = Pathname.new(tmp_path)
16
+ end
17
+
18
+ def shell(command)
19
+ @executed_commands.push command
20
+ end
21
+
22
+ def dir_exists?(pathname)
23
+ @system.dir_exists?(relative_from_tmp(pathname))
24
+ end
25
+
26
+ def file_exists?(pathname)
27
+ @system.file_exists?(relative_from_tmp(pathname))
28
+ end
29
+
30
+ def list(pathname)
31
+ @system.list(relative_from_tmp(pathname))
32
+ end
33
+
34
+ def mkdir(pathname)
35
+ @system.mkdir(relative_from_tmp(pathname))
36
+ end
37
+
38
+ def delete_file(pathname)
39
+ @system.delete_file(relative_from_tmp(pathname))
40
+ end
41
+
42
+ def delete_dir(pathname)
43
+ @system.delete_dir(relative_from_tmp(pathname))
44
+ end
45
+
46
+ def io(pathname, arguments)
47
+ @system.io(relative_from_tmp(pathname), arguments)
48
+ end
49
+
50
+ def copy(source, target)
51
+ @system.copy(relative_from_tmp(source), relative_from_tmp(target))
52
+ end
53
+
54
+ def move(source, target)
55
+ @system.move(relative_from_tmp(source), relative_from_tmp(target))
56
+ end
57
+
58
+ private
59
+ def relative_from_tmp(pathname)
60
+ tmp_pathname = nil
61
+ if (pathname.absolute?)
62
+ tmp_pathname = Pathname.new("root#{pathname}")
63
+ else
64
+ tmp_pathname = Pathname.new("current").join(pathname)
65
+ end
66
+ return @tmp_path.join(tmp_pathname)
67
+ end
68
+
69
+ def ensure_clean_directory(path)
70
+ Dir.mkdir path unless File.directory? path
71
+ Dir.foreach(path) do |name|
72
+ if (name != '.' && name != '..')
73
+ child_path = File.join(path, name)
74
+ if (File.directory? child_path)
75
+ ensure_clean_directory(child_path)
76
+ Dir.rmdir(child_path)
77
+ else
78
+ File.delete(child_path)
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,131 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', '..', 'lib')
2
+
3
+ require 'buildmaster/cotta'
4
+ require 'pathname'
5
+
6
+ def register_system_file_specifications
7
+ specify 'Log all the shell commands' do
8
+ @system.shell('my command')
9
+ @system.executed_commands.length.should_equal(1)
10
+ @system.executed_commands[0].should_equal 'my command'
11
+ end
12
+
13
+ specify 'root directory always exists' do
14
+ @system.dir_exists?(Pathname.new('/')).should_equal true
15
+ end
16
+
17
+ specify 'current directory always exists' do
18
+ @system.dir_exists?(Pathname.new('.')).should_equal true
19
+ end
20
+
21
+ specify 'mkdir should create directory' do
22
+ pathname = Pathname.new('/one')
23
+ @system.dir_exists?(pathname).should_equal false
24
+ @system.mkdir(pathname)
25
+ @system.dir_exists?(pathname).should_equal true
26
+ end
27
+
28
+ specify 'mkdir raise error if dir already exists' do
29
+ pathname = Pathname.new('/one')
30
+ @system.mkdir(pathname)
31
+ lambda {@system.mkdir}.should_raise StandardError
32
+ end
33
+
34
+ specify 'io returns IO handle' do
35
+ pathname = Pathname.new('file.txt')
36
+ @system.file_exists?(pathname).should_equal false
37
+ write_io = load_io(pathname, 'w')
38
+ write_io.puts 'content'
39
+ write_io.close
40
+ @system.file_exists?(pathname).should_equal true
41
+ read_io = load_io(pathname, 'r')
42
+ read_io.gets.should_equal "content\n"
43
+ read_io.close
44
+ @system.delete_file(pathname)
45
+ end
46
+
47
+ specify 'file creation should leave file system consistent' do
48
+ pathname = Pathname.new('dir/sub/file.txt')
49
+ @system.mkdir(pathname.parent.parent)
50
+ @system.mkdir(pathname.parent)
51
+ @system.file_exists?(pathname).should_equal false
52
+ @system.dir_exists?(pathname.parent).should_equal true
53
+ load_io(pathname, 'w').close
54
+ @system.file_exists?(pathname).should_equal true
55
+ @system.dir_exists?(pathname).should_equal false
56
+ @system.dir_exists?(pathname.parent).should_equal true
57
+ children = @system.list(pathname.parent)
58
+ children.size.should_equal 1
59
+ children[0].should_equal pathname.basename.to_s
60
+ end
61
+
62
+ specify 'directory creation should leave file system consistent' do
63
+ pathname = Pathname.new('root/dir/sub')
64
+ @system.dir_exists?(pathname).should_equal false
65
+ @system.file_exists?(pathname).should_equal false
66
+ @system.dir_exists?(pathname.parent).should_equal false
67
+ @system.mkdir(pathname.parent.parent)
68
+ @system.mkdir(pathname.parent)
69
+ @system.mkdir(pathname)
70
+ @system.dir_exists?(pathname).should_equal true
71
+ @system.file_exists?(pathname).should_equal false
72
+ @system.dir_exists?(pathname.parent).should_equal true
73
+ list = @system.list(pathname.parent)
74
+ list.size.should_equal 1
75
+ list[0].should_equal(pathname.basename.to_s)
76
+ end
77
+
78
+ specify 'read io should raise error if file does not exists' do
79
+ pathname = Pathname.new('dir/file.txt')
80
+ Proc.new {@system.io(pathname, 'r')}.should_raise Errno::ENOENT
81
+ end
82
+
83
+ specify 'delete dir' do
84
+ pathname = Pathname.new('dir')
85
+ @system.mkdir(pathname)
86
+ @system.delete_dir(pathname)
87
+ @system.dir_exists?(pathname).should_equal false
88
+ end
89
+
90
+ specify 'deleting dir that does not exist should raise error' do
91
+ pathname = Pathname.new('dir/dir2')
92
+ Proc.new {@system.delete_dir(pathname)}.should_raise Errno::ENOENT
93
+ end
94
+
95
+ specify 'copy file' do
96
+ pathname = Pathname.new('file1')
97
+ write_io = load_io(pathname, 'w')
98
+ write_io.puts 'line'
99
+ write_io.close
100
+ target = Pathname.new('target')
101
+ @system.copy(pathname, target)
102
+ @system.file_exists?(target).should_equal true
103
+ read_io = load_io(target, 'r')
104
+ read_io.gets.should_equal "line\n"
105
+ read_io.close
106
+ end
107
+
108
+ specify 'move file' do
109
+ pathname = Pathname.new('file1')
110
+ write_io = load_io(pathname, 'w')
111
+ write_io.puts 'line'
112
+ write_io.close
113
+ target = Pathname.new('target')
114
+ @system.move(pathname, target)
115
+ @system.file_exists?(target).should_equal true
116
+ read_io = load_io(target, 'r')
117
+ read_io.gets.should_equal "line\n"
118
+ read_io.close
119
+ @system.file_exists?(pathname).should_equal false
120
+ end
121
+
122
+ end
123
+ def load_io(*args)
124
+ io = @system.io(*args)
125
+ if (io)
126
+ @ios.push(io)
127
+ else
128
+ raise "IO is null for: #{args}"
129
+ end
130
+ return io
131
+ end