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.
- data/README +26 -0
- data/lib/buildmaster.rb +2 -1
- data/lib/buildmaster/build_number_file.rb +27 -0
- data/lib/buildmaster/buildnumber +1 -0
- data/lib/buildmaster/file_processor.rb +114 -25
- data/lib/buildmaster/java_manifest.rb +4 -0
- data/lib/buildmaster/{site.rb → site/site.rb} +11 -46
- data/lib/buildmaster/site/template/buildmaster.css +340 -0
- data/lib/buildmaster/site/template/buildmaster_template.xml +130 -0
- data/lib/buildmaster/site/template_builder.rb +276 -0
- data/lib/buildmaster/site_server.rb +33 -0
- data/lib/buildmaster/site_spec.rb +74 -22
- data/lib/buildmaster/site_tester.rb +14 -2
- data/lib/buildmaster/source_content.rb +11 -0
- data/lib/buildmaster/source_file_handler.rb +7 -2
- data/lib/buildmaster/svn_driver.rb +23 -11
- data/lib/buildmaster/template_exception.rb +8 -0
- data/lib/buildmaster/template_runner.rb +19 -86
- data/lib/buildmaster/templatelets.rb +23 -0
- data/lib/buildmaster/templatelets/attribute.rb +16 -0
- data/lib/buildmaster/templatelets/each.rb +43 -0
- data/lib/buildmaster/templatelets/href.rb +39 -0
- data/lib/buildmaster/templatelets/include.rb +30 -0
- data/lib/buildmaster/templatelets/link.rb +41 -0
- data/lib/buildmaster/templatelets/text.rb +14 -0
- data/lib/buildmaster/templatelets/when.rb +24 -0
- data/lib/buildmaster/tree_to_object.rb +76 -0
- data/lib/buildmaster/xtemplate.rb +10 -11
- data/test/buildmaster/manifest.mf +1 -1
- data/test/buildmaster/{content → site/content}/index.html +0 -0
- data/test/buildmaster/site/content/markdown.markdown +0 -0
- data/test/buildmaster/site/content/textile.textile +0 -0
- data/test/buildmaster/{tc_site.rb → site/tc_site.rb} +1 -1
- data/test/buildmaster/site/tc_template_builder.rb +128 -0
- data/test/buildmaster/tc_build_number_file.rb +31 -0
- data/test/buildmaster/tc_file_processor.rb +81 -14
- data/test/buildmaster/tc_site_spec.rb +26 -42
- data/test/buildmaster/tc_source_file_handler.rb +55 -0
- data/test/buildmaster/tc_template_runner.rb +42 -1
- data/test/buildmaster/tc_tree_to_object.rb +120 -0
- data/test/buildmaster/tc_xtemplate.rb +13 -233
- data/test/buildmaster/templatelets/common_templatelet_test.rb +27 -0
- data/test/buildmaster/templatelets/tc_attribute.rb +57 -0
- data/test/buildmaster/templatelets/tc_each.rb +69 -0
- data/test/buildmaster/templatelets/tc_href.rb +48 -0
- data/test/buildmaster/templatelets/tc_include.rb +34 -0
- data/test/buildmaster/templatelets/tc_link.rb +70 -0
- data/test/buildmaster/templatelets/tc_text.rb +36 -0
- data/test/buildmaster/templatelets/tc_when.rb +59 -0
- data/test/buildmaster/ts_site.rb +4 -0
- data/test/buildmaster/ts_templatelets.rb +10 -0
- data/test/tmp/output/index.html +8 -0
- data/test/tmp/output/markdown.html +8 -0
- data/test/tmp/output/textile.html +8 -0
- data/test/ts_buildmaster.rb +15 -3
- metadata +102 -53
@@ -2,6 +2,7 @@ module BuildMaster
|
|
2
2
|
|
3
3
|
require 'watir'
|
4
4
|
require 'set'
|
5
|
+
require 'uri'
|
5
6
|
|
6
7
|
class SiteTester
|
7
8
|
URL_PATTERN = /^https?\:\/\/([^\/]*)/
|
@@ -44,10 +45,9 @@ class SiteTester
|
|
44
45
|
end
|
45
46
|
|
46
47
|
def check_page
|
47
|
-
if (
|
48
|
+
if (url_visited?(@ie.url))
|
48
49
|
return
|
49
50
|
end
|
50
|
-
@visited_pages.add(@ie.url)
|
51
51
|
check_links
|
52
52
|
errors = @errors[@ie.url]
|
53
53
|
if (errors && errors.length > 0)
|
@@ -55,6 +55,18 @@ class SiteTester
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
+
def url_visited?(url)
|
59
|
+
index = url.index('#')
|
60
|
+
if (index)
|
61
|
+
url = url[0, index]
|
62
|
+
end
|
63
|
+
if (@visited_pages.include?(url))
|
64
|
+
return true
|
65
|
+
end
|
66
|
+
@visited_pages.add(url)
|
67
|
+
return false
|
68
|
+
end
|
69
|
+
|
58
70
|
def check_links
|
59
71
|
current = @ie.url
|
60
72
|
@ie.links.each do |link|
|
@@ -27,15 +27,20 @@ class SourceFileHandler < WEBrick::HTTPServlet::AbstractServlet
|
|
27
27
|
path = "#{path}index.html"
|
28
28
|
extension = '.html'
|
29
29
|
end
|
30
|
-
|
30
|
+
file_processor = FileProcessor.for_request_path(path, @spec)
|
31
|
+
if (file_processor.is_html?)
|
31
32
|
begin
|
32
|
-
|
33
|
+
content = file_processor.generate_document.to_s
|
33
34
|
rescue Exception
|
34
35
|
@logger.error("error serving the file #{path}")
|
35
36
|
@logger.error($!)
|
36
37
|
raise WEBrick::HTTPStatus::InternalServerError,
|
37
38
|
"#{$!}", caller
|
38
39
|
end
|
40
|
+
res['content-type'] = 'text/html'
|
41
|
+
res['content-length'] = content.length
|
42
|
+
res['last-modified'] = DateTime.new
|
43
|
+
res.body = content
|
39
44
|
else
|
40
45
|
@delegate.service(req, res)
|
41
46
|
end
|
@@ -1,21 +1,33 @@
|
|
1
|
+
require 'stringio'
|
1
2
|
require 'rexml/document'
|
2
3
|
|
3
4
|
module BuildMaster
|
4
5
|
|
5
6
|
class SvnInfo
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
attr_reader :path, :repository_root
|
8
|
+
|
9
|
+
def initialize(path)
|
10
|
+
@path = path
|
11
|
+
analyze_entry_file(File.join(path, ".svn", "entries"))
|
12
|
+
end
|
13
|
+
|
14
|
+
def analyze_entry_file(path)
|
15
|
+
content = load_content(path)
|
16
|
+
xml = REXML::Document.new(content)
|
17
|
+
xml.root.each_element_with_attribute('name', '', 1) do |element|
|
18
|
+
@repository_root = element.attributes['repos']
|
11
19
|
end
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
20
|
+
end
|
21
|
+
|
22
|
+
def load_content(path)
|
23
|
+
buffer = StringIO.new
|
24
|
+
File.open(path, 'r') do |file|
|
25
|
+
while (line = file.gets)
|
26
|
+
buffer.puts(line)
|
27
|
+
end
|
18
28
|
end
|
29
|
+
return buffer.string
|
30
|
+
end
|
19
31
|
end
|
20
32
|
|
21
33
|
class SvnDriver
|
@@ -1,16 +1,24 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'template_exception'
|
4
|
+
|
1
5
|
module BuildMaster
|
2
6
|
class TemplateRunner
|
3
|
-
|
7
|
+
@@NAMESPACE = 'http://buildmaster.rubyforge.org/xtemplate/1.0'
|
8
|
+
attr_reader :templatelets
|
9
|
+
attr_writer :templatelets
|
4
10
|
|
5
|
-
def initialize(
|
6
|
-
@
|
11
|
+
def initialize(target, template, source, &evaluator)
|
12
|
+
@templatelets = Hash.new
|
13
|
+
@target = target
|
7
14
|
@template = template
|
8
|
-
@
|
15
|
+
@source_instance = source
|
16
|
+
@templatelets = templatelets
|
9
17
|
@evaluator = evaluator
|
10
18
|
end
|
11
19
|
|
12
20
|
def process
|
13
|
-
process_children(@
|
21
|
+
process_children(@target, @template)
|
14
22
|
end
|
15
23
|
|
16
24
|
private
|
@@ -35,13 +43,16 @@ module BuildMaster
|
|
35
43
|
end
|
36
44
|
|
37
45
|
def template_directive?(element)
|
38
|
-
element.namespace == NAMESPACE
|
46
|
+
element.namespace == @@NAMESPACE
|
39
47
|
end
|
40
48
|
|
41
49
|
def process_directive(target, template_element)
|
42
50
|
message = "process_#{template_element.name}_directive"
|
43
|
-
|
44
|
-
|
51
|
+
templatelet = @templatelets[template_element.name]
|
52
|
+
if (not templatelet)
|
53
|
+
raise TemplateException, "unable to process element template:#{template_element.name}"
|
54
|
+
end
|
55
|
+
templatelet.process(target, template_element, @source_instance)
|
45
56
|
end
|
46
57
|
|
47
58
|
def clone_element( template_element )
|
@@ -64,83 +75,5 @@ module BuildMaster
|
|
64
75
|
end
|
65
76
|
end
|
66
77
|
|
67
|
-
def process_include_directive(target_element, template_element)
|
68
|
-
elements_attribute = template_element.attributes["elements"]
|
69
|
-
if (elements_attribute)
|
70
|
-
REXML::XPath.match(@source, elements_attribute).each do |matched|
|
71
|
-
target_element.add(deep_clone(matched))
|
72
|
-
end
|
73
|
-
return
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def process_when_directive(target_element, template_element)
|
78
|
-
if evaluate(template_element, 'test')
|
79
|
-
process_children(target_element, template_element)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def process_attribute_directive(target_element, template_element)
|
84
|
-
name = template_element.attributes['name']
|
85
|
-
target_element.attributes[name]=evaluate(template_element, 'eval')
|
86
|
-
end
|
87
|
-
|
88
|
-
def process_text_directive(target_element, template_element)
|
89
|
-
target_element.add(REXML::Text.new(evaluate(template_element, 'eval')))
|
90
|
-
end
|
91
|
-
|
92
|
-
def process_each_directive(target_element, template_element)
|
93
|
-
source_xml = evaluate!(template_element, 'source')
|
94
|
-
matched_element = REXML::XPath.match(REXML::Document.new(source_xml), template_element.attributes['select'])
|
95
|
-
count = attribute!(template_element, 'count')
|
96
|
-
count.to_i.times do |i|
|
97
|
-
TemplateRunner.new(target_element, template_element, matched_element[i], &@evaluator).process
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def process_link_directive(target_element, template_element)
|
102
|
-
current_path = @evaluator.call('relative_to_root')
|
103
|
-
file_name = current_path.basename(current_path.extname).to_s + ".html"
|
104
|
-
current_html_path = current_path.parent().join(file_name)
|
105
|
-
href = Pathname.new(attribute!(template_element, 'href'))
|
106
|
-
if (href.absolute?)
|
107
|
-
href = href.relative_path_from(Pathname.new('/'))
|
108
|
-
end
|
109
|
-
anchor_or_div = nil
|
110
|
-
if (current_html_path == href)
|
111
|
-
anchor_or_div = REXML::Element.new('div')
|
112
|
-
anchor_or_div.attributes['class']='current'
|
113
|
-
else
|
114
|
-
anchor_or_div = REXML::Element.new('a')
|
115
|
-
anchor_or_div.attributes['href'] = href.relative_path_from(current_html_path.parent())
|
116
|
-
end
|
117
|
-
template_element.attributes.each do |name, value|
|
118
|
-
anchor_or_div.attributes[name] = value unless name == 'href'
|
119
|
-
end
|
120
|
-
process_children(anchor_or_div, template_element)
|
121
|
-
target_element.add(anchor_or_div)
|
122
|
-
end
|
123
|
-
|
124
|
-
def evaluate!(xml_element, attribute_name)
|
125
|
-
value = evaluate(xml_element, attribute_name)
|
126
|
-
message = xml_element.attributes[attribute_name]
|
127
|
-
if (not value)
|
128
|
-
raise TemplateException, "#{message} from attribute #{attribute_name} cannot be nil"
|
129
|
-
end
|
130
|
-
return value
|
131
|
-
end
|
132
|
-
|
133
|
-
def evaluate(xml_element, attribute_name)
|
134
|
-
message = attribute!(xml_element, attribute_name)
|
135
|
-
return @evaluator.call(message)
|
136
|
-
end
|
137
|
-
|
138
|
-
def attribute!(xml_element, attribute_name)
|
139
|
-
value = xml_element.attributes[attribute_name]
|
140
|
-
if (not value)
|
141
|
-
raise TemplateException, "attribute #{attribute_name} not found in #{xml_element}"
|
142
|
-
end
|
143
|
-
return value
|
144
|
-
end
|
145
78
|
end
|
146
79
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'templatelets/href'
|
4
|
+
require 'templatelets/attribute'
|
5
|
+
require 'templatelets/each'
|
6
|
+
require 'templatelets/include'
|
7
|
+
require 'templatelets/link'
|
8
|
+
require 'templatelets/text'
|
9
|
+
require 'templatelets/when'
|
10
|
+
|
11
|
+
module REXML
|
12
|
+
class Element
|
13
|
+
def attribute_value!(name)
|
14
|
+
value = attribute_value(name)
|
15
|
+
raise "attribute #{name} not found" unless value
|
16
|
+
return value
|
17
|
+
end
|
18
|
+
|
19
|
+
def attribute_value(name)
|
20
|
+
return attributes[name]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module BuildMaster
|
2
|
+
class Attribute
|
3
|
+
def initialize(expression_evaluator)
|
4
|
+
@evaluator = expression_evaluator
|
5
|
+
end
|
6
|
+
|
7
|
+
def process(target, template, source)
|
8
|
+
name = template.attribute_value!('name')
|
9
|
+
eval = template.attribute_value!('eval')
|
10
|
+
if (not @evaluator.respond_to?(eval))
|
11
|
+
raise TemplateException, '#{@evaluator.class} cannot evaluate expression #{eval}'
|
12
|
+
end
|
13
|
+
target.attributes[name] = @evaluator.send(eval, source.path)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module BuildMaster
|
5
|
+
class Each
|
6
|
+
def initialize(site_spec)
|
7
|
+
@site_spec = site_spec
|
8
|
+
end
|
9
|
+
|
10
|
+
def process(target, template, source)
|
11
|
+
source_xml = load_source_xml(template)
|
12
|
+
matched_element = REXML::XPath.match(source_xml, template.attribute_value!('select'))
|
13
|
+
count = template.attribute_value!('count')
|
14
|
+
count.to_i.times do |i|
|
15
|
+
element_source = SourceContent.new(source.path, matched_element[i])
|
16
|
+
template_runner = TemplateRunner.new(target, template, element_source)
|
17
|
+
template_runner.templatelets = @site_spec.load_templatelets
|
18
|
+
template_runner.process
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def load_source_xml(template)
|
24
|
+
path = template.attribute_value!('source')
|
25
|
+
if (URI.parse(path).scheme.nil?)
|
26
|
+
return @site_spec.load_document(path)
|
27
|
+
end
|
28
|
+
return load_content_through_uri(path)
|
29
|
+
end
|
30
|
+
|
31
|
+
def load_content_through_uri(uri)
|
32
|
+
buffer = StringIO.new
|
33
|
+
begin
|
34
|
+
open(uri) do |file|
|
35
|
+
buffer.puts file.gets
|
36
|
+
end
|
37
|
+
return REXML::Document.new(buffer.string)
|
38
|
+
rescue Exception => exception
|
39
|
+
raise RuntimeError, "Error loading uri: #{uri}", caller
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
$:.unshift(File.join('..', File.dirname(__FILE__)))
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
require 'template_exception'
|
6
|
+
require 'template_runner'
|
7
|
+
|
8
|
+
module BuildMaster
|
9
|
+
|
10
|
+
class Href
|
11
|
+
def initialize(site_spec)
|
12
|
+
@site_spec = site_spec
|
13
|
+
end
|
14
|
+
|
15
|
+
def process(target, template, source)
|
16
|
+
url = template.attribute_value!('url')
|
17
|
+
href = construct_href(url, source.path)
|
18
|
+
target.attributes[name_based_on_target(target)] = href
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def construct_href(url, current_path)
|
23
|
+
href = url
|
24
|
+
if (URI.parse(url).scheme.nil?)
|
25
|
+
href = Pathname.new(url).relative_path_from(current_path.parent)
|
26
|
+
end
|
27
|
+
return href
|
28
|
+
end
|
29
|
+
|
30
|
+
def name_based_on_target(target)
|
31
|
+
name = target.name
|
32
|
+
if (name == 'img')
|
33
|
+
return 'src'
|
34
|
+
else
|
35
|
+
return 'href'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module BuildMaster
|
3
|
+
class Include
|
4
|
+
def initialize(site_spec)
|
5
|
+
@site_spec = site_spec
|
6
|
+
end
|
7
|
+
|
8
|
+
def process(target, template, source)
|
9
|
+
elements_xpath = template.attribute_value!('elements')
|
10
|
+
if (elements_xpath[elements_xpath.length - 1, 1] == '*')
|
11
|
+
elements_xpath = elements_xpath[0, elements_xpath.length - 1]
|
12
|
+
REXML::XPath.each(source.document, elements_xpath) do |matched|
|
13
|
+
matched.each_child {|child| target.add(deep_clone(child))}
|
14
|
+
end
|
15
|
+
else
|
16
|
+
REXML::XPath.each(source.document, elements_xpath) {|matched| target.add(deep_clone(matched))}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def deep_clone(node )
|
22
|
+
if node.kind_of? REXML::Parent
|
23
|
+
node.deep_clone
|
24
|
+
else
|
25
|
+
node.clone
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rexml/element'
|
2
|
+
|
3
|
+
module BuildMaster
|
4
|
+
class Link
|
5
|
+
def initialize(site_spec)
|
6
|
+
@site_spec = site_spec
|
7
|
+
end
|
8
|
+
|
9
|
+
def process(target, template, source)
|
10
|
+
target_path = get_href_as_relative_path(template)
|
11
|
+
result = nil
|
12
|
+
if (target_path == source.path)
|
13
|
+
result = REXML::Element.new('div')
|
14
|
+
result.attributes['class'] = 'current'
|
15
|
+
else
|
16
|
+
result = REXML::Element.new('a')
|
17
|
+
href = target_path.relative_path_from(source.path.parent)
|
18
|
+
result.attributes['href'] = href.to_s
|
19
|
+
end
|
20
|
+
template.attributes.each do |name, value|
|
21
|
+
result.attributes[name] = value unless name == 'href'
|
22
|
+
end
|
23
|
+
template.each_child do |element|
|
24
|
+
runner = TemplateRunner.new(result, template, source)
|
25
|
+
runner.templatelets = @site_spec.load_templatelets
|
26
|
+
runner.process
|
27
|
+
end
|
28
|
+
target.add(result)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def get_href_as_relative_path(template)
|
33
|
+
href = Pathname.new(template.attribute_value!('href'))
|
34
|
+
if (href.absolute?)
|
35
|
+
href = href.relative_path_from(Pathname.new('/'))
|
36
|
+
end
|
37
|
+
return href
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|