BuildMaster 0.8.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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
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> and <a href="http://hobix.com/textile/">Textile</a>.
24
-
25
-
26
- == Task List
27
-
28
- * Use RDoc engine (rdoc/template, TemplatePage) to generate template (page
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.
@@ -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, &command_runner)
8
+ def initialize(ant_file = nil)
9
+ @cotta = Cotta.new(ant_file.system)
10
10
  @ant_file = ant_file
11
- @ant_home = check_directory(get_environment('ANT_HOME'))
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 = get_environment_or_default('ANT_OPTS').split(' ')
25
- @ant_arguments = get_environment_or_default('ANT_ARGS').split(' ')
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 = get_environment_or_default('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 = get_environment_or_default('JAVA_CMD', 'java')
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
- run_command(command_line)
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 = load_content().chomp!.to_i
8
+ @number = @path.load().strip.to_i
9
9
  end
10
10
 
11
11
  def increase_build
12
12
  @number = @number + 1
13
- save_content
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
@@ -1 +1 @@
1
- 15
1
+ 22
@@ -0,0 +1,4 @@
1
+ $:.unshift File.join(File.dirname(__FILE__))
2
+
3
+ require 'cotta/cotta'
4
+ require 'cotta/file_not_found_error'
@@ -0,0 +1,5 @@
1
+ module BuildMaster
2
+ class CommandError < StandardError
3
+
4
+ end
5
+ end
@@ -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,13 @@
1
+ module BuildMaster
2
+ class FileNotFoundError < StandardError
3
+ attr_reader :pathname
4
+
5
+ def initialize(pathname)
6
+ @pathname = pathname
7
+ end
8
+
9
+ def message
10
+ "file not found: #{pathname}"
11
+ end
12
+ end
13
+ 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