BuildMaster 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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