BuildMaster 0.7.0 → 0.8.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 (56) hide show
  1. data/README +26 -0
  2. data/lib/buildmaster.rb +2 -1
  3. data/lib/buildmaster/build_number_file.rb +27 -0
  4. data/lib/buildmaster/buildnumber +1 -0
  5. data/lib/buildmaster/file_processor.rb +114 -25
  6. data/lib/buildmaster/java_manifest.rb +4 -0
  7. data/lib/buildmaster/{site.rb → site/site.rb} +11 -46
  8. data/lib/buildmaster/site/template/buildmaster.css +340 -0
  9. data/lib/buildmaster/site/template/buildmaster_template.xml +130 -0
  10. data/lib/buildmaster/site/template_builder.rb +276 -0
  11. data/lib/buildmaster/site_server.rb +33 -0
  12. data/lib/buildmaster/site_spec.rb +74 -22
  13. data/lib/buildmaster/site_tester.rb +14 -2
  14. data/lib/buildmaster/source_content.rb +11 -0
  15. data/lib/buildmaster/source_file_handler.rb +7 -2
  16. data/lib/buildmaster/svn_driver.rb +23 -11
  17. data/lib/buildmaster/template_exception.rb +8 -0
  18. data/lib/buildmaster/template_runner.rb +19 -86
  19. data/lib/buildmaster/templatelets.rb +23 -0
  20. data/lib/buildmaster/templatelets/attribute.rb +16 -0
  21. data/lib/buildmaster/templatelets/each.rb +43 -0
  22. data/lib/buildmaster/templatelets/href.rb +39 -0
  23. data/lib/buildmaster/templatelets/include.rb +30 -0
  24. data/lib/buildmaster/templatelets/link.rb +41 -0
  25. data/lib/buildmaster/templatelets/text.rb +14 -0
  26. data/lib/buildmaster/templatelets/when.rb +24 -0
  27. data/lib/buildmaster/tree_to_object.rb +76 -0
  28. data/lib/buildmaster/xtemplate.rb +10 -11
  29. data/test/buildmaster/manifest.mf +1 -1
  30. data/test/buildmaster/{content → site/content}/index.html +0 -0
  31. data/test/buildmaster/site/content/markdown.markdown +0 -0
  32. data/test/buildmaster/site/content/textile.textile +0 -0
  33. data/test/buildmaster/{tc_site.rb → site/tc_site.rb} +1 -1
  34. data/test/buildmaster/site/tc_template_builder.rb +128 -0
  35. data/test/buildmaster/tc_build_number_file.rb +31 -0
  36. data/test/buildmaster/tc_file_processor.rb +81 -14
  37. data/test/buildmaster/tc_site_spec.rb +26 -42
  38. data/test/buildmaster/tc_source_file_handler.rb +55 -0
  39. data/test/buildmaster/tc_template_runner.rb +42 -1
  40. data/test/buildmaster/tc_tree_to_object.rb +120 -0
  41. data/test/buildmaster/tc_xtemplate.rb +13 -233
  42. data/test/buildmaster/templatelets/common_templatelet_test.rb +27 -0
  43. data/test/buildmaster/templatelets/tc_attribute.rb +57 -0
  44. data/test/buildmaster/templatelets/tc_each.rb +69 -0
  45. data/test/buildmaster/templatelets/tc_href.rb +48 -0
  46. data/test/buildmaster/templatelets/tc_include.rb +34 -0
  47. data/test/buildmaster/templatelets/tc_link.rb +70 -0
  48. data/test/buildmaster/templatelets/tc_text.rb +36 -0
  49. data/test/buildmaster/templatelets/tc_when.rb +59 -0
  50. data/test/buildmaster/ts_site.rb +4 -0
  51. data/test/buildmaster/ts_templatelets.rb +10 -0
  52. data/test/tmp/output/index.html +8 -0
  53. data/test/tmp/output/markdown.html +8 -0
  54. data/test/tmp/output/textile.html +8 -0
  55. data/test/ts_buildmaster.rb +15 -3
  56. metadata +102 -53
@@ -0,0 +1,14 @@
1
+ module BuildMaster
2
+ class Text
3
+ def initialize(properties)
4
+ @properties = properties
5
+ end
6
+
7
+ def process(target, template, source)
8
+ property = template.attribute_value!('property')
9
+ value = @properties[property]
10
+ raise TemplateException, "property value for '#{property}' not found" unless value
11
+ target.add(REXML::Text.new(value))
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..')
2
+
3
+ require 'template_runner'
4
+
5
+ module BuildMaster
6
+ class When
7
+ def initialize(site_spec, expression_evaluator)
8
+ @site_spec = site_spec
9
+ @evaluator = expression_evaluator
10
+ end
11
+
12
+ def process(target, template, source)
13
+ eval = template.attribute_value!('test')
14
+ if (not @evaluator.respond_to?(eval))
15
+ raise TemplateException, "#{@evaluator.class} cannot evaluate expression #{eval}"
16
+ end
17
+ if (@evaluator.send(eval, source.path))
18
+ runner = TemplateRunner.new(target, template, source)
19
+ runner.templatelets = @site_spec.load_templatelets
20
+ runner.process
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,76 @@
1
+ require 'yaml'
2
+
3
+ module BuildMaster
4
+
5
+ class PropertyMatchError < StandardError
6
+
7
+ attr_reader :property, :type, :target
8
+
9
+ def initialize(property, type, target)
10
+ @property = property
11
+ @type = type
12
+ @target = target
13
+ end
14
+ end
15
+
16
+ class TreeToObject
17
+ def initialize(tree, object)
18
+ @tree = tree
19
+ @object = object
20
+ end
21
+
22
+ def TreeToObject.from_yaml(content, object)
23
+ tree = {}
24
+ if (content.chomp!)
25
+ tree = YAML.load(content)
26
+ if (not tree.kind_of?(Hash))
27
+ raise "Format error for content:\n#{content}"
28
+ end
29
+ end
30
+ return TreeToObject.new(tree, object).convert
31
+ end
32
+
33
+
34
+ def convert
35
+ @tree.each_pair do |key, value|
36
+ if (value.kind_of?(Array))
37
+ convert_array(key, value)
38
+ elsif (value.kind_of?(Hash))
39
+ convert_hash(key, value)
40
+ else
41
+ convert_property(key, value)
42
+ end
43
+ end
44
+ return @object
45
+ end
46
+
47
+ private
48
+ def convert_hash(field, hash)
49
+ return TreeToObject.new(hash, property("#{field}", field, 'sub property')).convert
50
+ end
51
+
52
+ def convert_array(field, array)
53
+ array.each do |item|
54
+ TreeToObject.new(item, property("add_to_#{field}", field, 'array')).convert
55
+ end
56
+ end
57
+
58
+ def convert_property(field, value)
59
+ method = "#{field}="
60
+ check_property(method, field, 'string')
61
+ @object.send("#{field}=", value)
62
+ end
63
+
64
+ def property(method, field, type)
65
+ check_property(method, field, type)
66
+ @object.send(method)
67
+ end
68
+
69
+ def check_property(method, field, type)
70
+ if not @object.respond_to? method
71
+ message = "#{field} does not exist as #{type} in #{@object}"
72
+ raise PropertyMatchError.new(field, type, @object), message, caller
73
+ end
74
+ end
75
+ end
76
+ end
@@ -4,25 +4,24 @@ require 'rexml/document'
4
4
  require 'template_runner'
5
5
 
6
6
  module BuildMaster
7
- class TemplateException < Exception
8
- end
9
-
10
7
  class XTemplate
11
- def initialize(template_file)
8
+ def initialize(template_file, templatelets = Hash.new)
12
9
  @template = REXML::Document.new(template_file)
10
+ @templatelets = templatelets
13
11
  end
14
12
 
15
- def process(content, &evaluator)
16
- content_xml = REXML::Document.new(content)
17
- output_xml = process_xml(content_xml, &evaluator)
13
+ def process(source, &evaluator)
14
+ output_xml = process_xml(source, &evaluator)
18
15
  return output_xml
19
16
  end
20
17
 
21
18
  private
22
- def process_xml(content_xml, &evaluator)
23
- result_xml = REXML::Document.new
24
- TemplateRunner.new(result_xml, @template, content_xml, &evaluator).process
25
- return result_xml
19
+ def process_xml(source, &evaluator)
20
+ output_xml = REXML::Document.new
21
+ runner = TemplateRunner.new(output_xml, @template, source, &evaluator)
22
+ runner.templatelets = @templatelets
23
+ runner.process
24
+ return output_xml
26
25
  end
27
26
  end
28
27
  end
@@ -1,5 +1,5 @@
1
1
  Implementation-Version: 2.3.3
2
- Implementation-Build: 1000
2
+ Implementation-Build: 1114
3
3
 
4
4
  Implementation-Vendor: Vendor
5
5
  Implementation-Number: Number
File without changes
File without changes
@@ -1,4 +1,4 @@
1
- $:.unshift File.join(File.dirname(__FILE__), "..", "..", "lib")
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "..", '..', "lib")
2
2
 
3
3
  require 'test/unit'
4
4
  require 'buildmaster'
@@ -0,0 +1,128 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', '..', 'lib')
2
+
3
+ require 'test/unit'
4
+ require 'rexml/xpath'
5
+ require 'buildmaster/site/template_builder'
6
+ require 'buildmaster/tree_to_object'
7
+ require 'yaml'
8
+
9
+ module BuildMaster
10
+ class TemplateBuilderTest < Test::Unit::TestCase
11
+ def test_should_generate_template_document
12
+ builder = TemplateBuilder.new
13
+ document = builder.generate
14
+ assert_equal('include', REXML::XPath.first(document, '/html/head/title/*').name)
15
+ assert_css_path(document, 'buildmaster.css')
16
+ end
17
+
18
+ def test_should_update_header_with_title_and_css
19
+ builder = TemplateBuilder.new
20
+ builder.title_header = 'Title Header - '
21
+ builder.css_path = 'mycss.css'
22
+ document = builder.generate
23
+ first_child = REXML::XPath.first(document, '/html/head/title').children[0]
24
+ assert_equal(REXML::Text, first_child.class)
25
+ assert_equal('Title Header - ', first_child.value)
26
+ assert_css_path(document, 'mycss.css')
27
+ end
28
+
29
+ def test_should_have_logo_defaults
30
+ builder = TemplateBuilder.new
31
+ assert_equal(nil, builder.logo.path)
32
+ assert_equal('index.html', builder.logo.link)
33
+ end
34
+
35
+ def test_should_generate_logo_and_link
36
+ builder = TemplateBuilder.new
37
+ builder.logo.path = 'gif/logo.gif'
38
+ builder.logo.link = 'main.html'
39
+ document = builder.generate
40
+ header = assert_first(document, '/html/body/div[@class="header"]')
41
+ anchor_href = assert_first(header, 'a/template:href')
42
+ assert_equal('main.html', anchor_href.attributes['url'])
43
+ img_href = assert_first(header, 'a/img/template:href')
44
+ assert_equal('gif/logo.gif', img_href.attributes['url'])
45
+ end
46
+
47
+ def test_should_build_left_menu
48
+ builder = TemplateBuilder.new
49
+ builder.left_bottom_logo.path='http://www.example.com/logo.gif'
50
+ group = builder.menu_group('Software')
51
+ group.menu_item('Download', 'download.html')
52
+ group.menu_item('License', 'license.html')
53
+ group.more='more.html'
54
+ group = builder.menu_group('Documentation', 'doc/index.html')
55
+ group.menu_item('Getting Started', 'doc/getting-started')
56
+ document = builder.generate
57
+ groups = REXML::XPath.match(document, '/html/body/div[@class="left"]/div[@class="MenuGroup"]')
58
+ assert_equal(2, groups.size)
59
+ first_group = groups[0]
60
+ header = assert_first(first_group, 'h1')
61
+ assert_equal('Software', header.text)
62
+ items = REXML::XPath.match(first_group, 'ul/li')
63
+ assert_equal(3, items.size)
64
+ first_item = items[0]
65
+ anchor = assert_first(first_item, 'template:link')
66
+ assert_equal('download.html', anchor.attributes['href'])
67
+ assert_equal('Download', anchor.text)
68
+ more = items[2]
69
+ assert_equal('More', more.attributes['class'])
70
+ end
71
+
72
+ def test_should_have_releases_info
73
+ builder = TemplateBuilder.new
74
+ releases = builder.releases
75
+ releases.stable_version = '0.6'
76
+ releases.pre_release_version = '0.7'
77
+ releases.snap_shot_version = 'n/a'
78
+ releases.download_link = 'download.html'
79
+ releases.versioning_link = 'versioning.html'
80
+ builder.generate
81
+ end
82
+
83
+ def test_should_read_from_yaml
84
+ content = <<CONTENT
85
+ title_header: BuilderMaster -
86
+ logo:
87
+ path: logo.gif
88
+ link: index.html
89
+ menu_groups:
90
+ - title: Software
91
+ menu_items:
92
+ - title: Download
93
+ link: download.html
94
+ - title: Source Repository
95
+ link: http://rubyforge.org/scm/?group_id=1680
96
+ - title: Project License
97
+ link: license.html
98
+ - title: Documentation...
99
+ link: document.html
100
+ menu_items:
101
+ - title: Getting Started
102
+ link: getting-started.html
103
+ - title: Project Release
104
+ link: release-project.html
105
+ - title: Site Building
106
+ link: build-site.html
107
+ more: doc/index.html
108
+ CONTENT
109
+ builder = TreeToObject.from_yaml(content, TemplateBuilder.new)
110
+ assert_equal('BuilderMaster -', builder.title_header)
111
+ assert_equal('logo.gif', builder.logo.path)
112
+ assert_equal('index.html', builder.logo.link)
113
+ end
114
+
115
+ private
116
+ def assert_css_path(document, expected)
117
+ href = REXML::XPath.first(document, '/html/head/link/*')
118
+ assert_equal('href', href.name)
119
+ assert_equal(expected, href.attributes['url'])
120
+ end
121
+
122
+ def assert_first(xml_model, xpath)
123
+ first = REXML::XPath.first(xml_model, xpath)
124
+ assert_not_nil(first)
125
+ return first
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,31 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
2
+
3
+ require 'test/unit'
4
+
5
+ require 'buildmaster/build_number_file'
6
+
7
+ module BuildMaster
8
+ class BuildNumberFileTest < Test::Unit::TestCase
9
+ def test_load_file
10
+ path = tmp_file(2)
11
+ build_number = BuildNumberFile.new(path)
12
+ assert_equal(2, build_number.number)
13
+ end
14
+
15
+ def test_increase_build
16
+ path = tmp_file(3)
17
+ build_number = BuildNumberFile.new(path)
18
+ build_number.increase_build
19
+ assert_equal(4, build_number.number)
20
+ reloaded = BuildNumberFile.new(path)
21
+ assert_equal(4, reloaded.number)
22
+ end
23
+
24
+ private
25
+ def tmp_file(build_number)
26
+ path = File.join(File.dirname(__FILE__), '..', '..', 'tmp', 'buildnumber')
27
+ File.open(path, "w") {|file| file.puts build_number}
28
+ return path
29
+ end
30
+ end
31
+ end
@@ -2,32 +2,99 @@ $:.unshift File.join(File.dirname(__FILE__), "..", "..", "lib")
2
2
 
3
3
  require 'test/unit'
4
4
  require 'rexml/document'
5
+ require 'pathname'
5
6
  require 'buildmaster/file_processor'
6
7
  require 'buildmaster/xtemplate'
7
8
 
8
9
  module BuildMaster
9
10
  class FileProcessorTest < Test::Unit::TestCase
10
- def test_expression_evaluation
11
- template = XTemplate.new(<<CONTENT
11
+ def test_should_know_content_and_target
12
+ template = XTemplate.new(<<CONTENT
12
13
  <html xmlns="http://www.w3.org/1999/xhtml"
13
14
  xmlns:template="http://buildmaster.rubyforge.org/xtemplate/1.0">
14
- <p>
15
- <template:attribute name="class" eval="method_one"/>
16
- </p>
17
15
  </html>
18
16
  CONTENT
19
17
  )
20
- processor = FileProcessor.new(template, "content_path", self)
21
- document = processor.process_html_content("<html></html>")
22
- assert_equal('method one result',
23
- REXML::XPath.first(REXML::Document.new(document.to_s), '/html/p/@class').value.strip)
24
-
18
+ site_spec = SiteSpec.new
19
+ current_dir = File.dirname(__FILE__)
20
+ site_spec.content_dir = File.join(current_dir, "content")
21
+ site_spec.output_dir = File.join(current_dir, "output")
22
+ processor = FileProcessor.new(template, File.join(current_dir, 'content', 'index.html'), site_spec)
23
+ assert_equal(File.join(current_dir, 'content', 'index.html'), processor.path_to_content_file)
24
+ assert_equal(true, processor.is_html?)
25
25
  end
26
26
 
27
- def evaluate(expression, path)
28
- assert_equal('method_one', expression)
29
- assert_equal('content_path', path)
30
- return "method one result"
27
+ def test_should_know_html_target
28
+ template = XTemplate.new(<<CONTENT
29
+ <html xmlns="http://www.w3.org/1999/xhtml"
30
+ xmlns:template="http://buildmaster.rubyforge.org/xtemplate/1.0">
31
+ </html>
32
+ CONTENT
33
+ )
34
+ site_spec = SiteSpec.new
35
+ current_dir = File.dirname(__FILE__)
36
+ site_spec.content_dir = File.join(current_dir, "content")
37
+ site_spec.output_dir = File.join(current_dir, "output")
38
+ processor = FileProcessor.new(template, File.join(current_dir, 'content', 'index.gif'), site_spec)
39
+ assert_equal(File.join(current_dir, 'content', 'index.gif'), processor.path_to_content_file)
40
+ assert_equal(false, processor.is_html?)
41
+ assert_equal(nil, processor.generate_document)
42
+ end
43
+
44
+ def test_should_load_from_target
45
+ template_content = <<CONTENT
46
+ <html xmlns="http://www.w3.org/1999/xhtml"
47
+ xmlns:template="http://buildmaster.rubyforge.org/xtemplate/1.0">
48
+ </html>
49
+ CONTENT
50
+ site_spec = SiteSpec.new
51
+ current_dir = File.dirname(__FILE__)
52
+ site_spec.template = template_content
53
+ site_spec.content_dir = File.join(current_dir, 'site', 'content')
54
+ site_spec.output_dir = File.join(current_dir, "output")
55
+ processor = FileProcessor.for_request_path('/index.html', site_spec)
56
+ assert_equal(File.join(site_spec.content_dir, 'index.html'), processor.path_to_content_file)
57
+ processor = FileProcessor.for_request_path('/index.gif', site_spec)
58
+ assert_equal(File.join(site_spec.content_dir, 'index.gif'), processor.path_to_content_file)
59
+ processor = FileProcessor.for_request_path('/textile.html', site_spec)
60
+ assert_equal(File.join(site_spec.content_dir, 'textile.textile'), processor.path_to_content_file)
61
+ processor = FileProcessor.for_request_path('/markdown.html', site_spec)
62
+ assert_equal(File.join(site_spec.content_dir, 'markdown.markdown'), processor.path_to_content_file)
63
+ end
64
+
65
+ def output_dir
66
+ return 'tmp'
67
+ end
68
+
69
+ def relative_to_root(path)
70
+ return Pathname.new('tmp')
71
+ end
72
+
73
+ def test_mark_down_support
74
+ template_content = <<CONTENT
75
+ <html xmlns="http://www.w3.org/1999/xhtml"
76
+ xmlns:template="http://buildmaster.rubyforge.org/xtemplate/1.0">
77
+ <head><title><template:include elements="/html/head/title/text()"/></title></head>
78
+ <body>
79
+ <template:include elements="/html/body/*"/>
80
+ </body>
81
+ </html>
82
+ CONTENT
83
+ hash = {'include' => Include.new(self)}
84
+ template = XTemplate.new(template_content, hash)
85
+
86
+ processor = FileProcessor.new(template, "content_path", self)
87
+ markdown_content = <<CONTENT
88
+ --------------------------------------------
89
+ Title Here
90
+ --------------------------------------------
91
+ Header
92
+ =====================
93
+ CONTENT
94
+ document = processor.process_markdown(markdown_content)
95
+ document = REXML::Document.new(document.to_s)
96
+ assert_equal('Title Here', REXML::XPath.first(document, '/html/head/title').text)
97
+ assert_equal('Header', REXML::XPath.first(document, '/html/body/h1').text)
31
98
  end
32
99
 
33
100
  end