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,130 @@
1
+ <html xmlns="http://www.w3.org/1999/xhtml"
2
+ xmlns:template="http://buildmaster.rubyforge.org/xtemplate/1.0">
3
+ <head>
4
+ <title>#title_header#<template:include elements="/html/head/title/text()"/></title>
5
+ <link rel="stylesheet" type="text/css"><template:href path="buildmaster.css"/></link>
6
+ <template:include elements="/html/head/*[not(name()='title')]"/>
7
+ </head>
8
+
9
+ <body>
10
+ <div class="header">
11
+ <a class="header">
12
+ <template:href path="index.html"/>
13
+ <img id="logo" alt="BuildMaster"><template:href path="logo.gif"/></img>
14
+ </a>
15
+ </div>
16
+
17
+ <div class="left">
18
+ <div class="MenuGroup">
19
+ <h1>Software</h1>
20
+ <ul>
21
+ <li><template:link href="download.html">Download and Dependencies</template:link></li>
22
+ <li><a href="http://rubyforge.org/scm/?group_id=1680">Source Repository</a></li>
23
+ <li><template:link href="/license.html">Project License</template:link></li>
24
+ </ul>
25
+ </div>
26
+
27
+ <div class="MenuGroup">
28
+ <h1><template:link href="/docs/main.html">Documentation...</template:link></h1>
29
+ <ul>
30
+ <li><template:link href="/docs/getting-started.html">Getting Started</template:link></li>
31
+ <li><template:link href="/docs/release-project.html">Project Release</template:link></li>
32
+ <li><template:link href="/docs/build-site.html">Site Building</template:link></li>
33
+ <li class="More"><a><template:href path="docs/main.html"/>More...</a></li>
34
+ </ul>
35
+ </div>
36
+
37
+ <div class="MenuGroup">
38
+ <h1>User Support</h1>
39
+ <ul>
40
+ <li><a href="http://groups.google.com/group/buildmaster">Mailing List</a></li>
41
+ <li><a href="http://rubyforge.org/tracker/?group_id=1680">Issue Tracker</a></li>
42
+ <li><template:link href="/news-rss2.xml">News Feed (RSS 2.0)</template:link></li>
43
+ </ul>
44
+ </div>
45
+
46
+ <div class="MenuGroup">
47
+ <h1>Development</h1>
48
+ <ul>
49
+ <li><template:link href="/road-map.html">Road Map</template:link></li>
50
+ <li><template:link href="/how-to-contribute.html">How to Contribute</template:link></li>
51
+ <li><template:link href="/team.html">Development Team</template:link></li>
52
+ </ul>
53
+ </div>
54
+
55
+ <div class="MenuGroup">
56
+ <h1><template:link href="references.html">Related Sites</template:link></h1>
57
+ <ul>
58
+ <li><a href="http://www.pragmaticprogrammer.com/sk/auto/">Pragmatic Project Automation</a></li>
59
+ <li><a href="http://hobix.com/textile/">Textile Reference</a></li>
60
+ <li><a href="http://www.thoughtworks.com">Partially on ThoughtWorks beach</a></li>
61
+ <li class="More"><a><template:href path="references.html"/>More...</a></li>
62
+ </ul>
63
+ </div>
64
+ <div class="logo">
65
+ <a href="http://rubyforge.org/projects/buildmaster/">
66
+ <img alt="Rubyforge Logo" src="http://rubyforge.org/themes/osx/images/logohover.png" width="170"/>
67
+ </a>
68
+ </div>
69
+ </div>
70
+
71
+ <template:when test="index_file?">
72
+ <div class="right">
73
+ <div class="NewsGroup">
74
+ <h1>Latest Versions</h1>
75
+ <table>
76
+ <tr>
77
+ <td><template:link href="download.html#stable">Stable:</template:link></td>
78
+ <td><template:link href="download.html#stable"><template:text property="release"/></template:link></td>
79
+ </tr>
80
+ <tr>
81
+ <td><template:link href="download.html#prerelease">Prerelease:</template:link></td>
82
+ <td><template:link href="download.html#prerelease"><template:text property="prerelease"/></template:link></td>
83
+ </tr>
84
+ <tr>
85
+ <td><template:link href="download.html#snapshot">Snapshot:</template:link></td>
86
+ <td><template:link href="download.html#snapshot"><template:text property="snapshot"/></template:link></td>
87
+ </tr>
88
+ </table>
89
+ <p class="NewsMore"><template:link href="versioning.html">About BuildMaster version numbers...</template:link></p>
90
+ </div>
91
+ <div class="NewsGroup">
92
+ <h1>Recent News</h1>
93
+ <template:each source="news-rss2.xml" select="/rss/channel/item" count="3">
94
+ <div class="NewsItem">
95
+ <p class="NewsTitle"><template:include elements="./title/text()"/></p>
96
+ <p class="NewsDate"><template:include elements="./pubDate/text()"/></p>
97
+ <p class="NewsText"><template:include elements="./xhtml:div/node()"/></p>
98
+ </div>
99
+ </template:each>
100
+
101
+ <p class="NewsMore"><template:link href="/news-rss2.xml">News feed (RSS 2.0)</template:link></p>
102
+ </div>
103
+ </div>
104
+ </template:when>
105
+
106
+ <div>
107
+ <template:attribute name="class" eval="center_class"/>
108
+ <div class="content"><template:include elements="/html/body/*"/></div>
109
+ <div class="source">
110
+ <a><template:attribute name="href" eval="doc_source_url"/>Document Source</a>
111
+ (<a><template:attribute name="href" eval="doc_history_url"/>History</a>)
112
+ </div>
113
+ </div>
114
+
115
+ <div class="footer">
116
+ <div class="bottomshadow"/>
117
+ <div class="poweredby">
118
+ Powered by <a href="http://buildmaster.rubyforge.org" class="footer">BuildMaster</a>
119
+ -
120
+ <a href="http://rubyforge.org/tracker/?group_id=1680" class="footer">Bug/feature request</a>
121
+ -
122
+ <a href="http://groups.google.com/group/buildmaster" class="footer">Contact Administrators</a>
123
+ <br/>
124
+ </div>
125
+ </div>
126
+ <div>
127
+ <script language="JavaScript" type="text/javascript" src="http://www.webpasties.com/pastie.php?mode=tracker&tid=457&mid=44"/>
128
+ </div>
129
+ </body>
130
+ </html>
@@ -0,0 +1,276 @@
1
+ require 'rexml/document'
2
+ require 'rexml/xpath'
3
+
4
+ module BuildMaster
5
+ class Logo
6
+ attr_accessor :path, :link, :text
7
+
8
+ def initialize
9
+ @link = 'index.html'
10
+ @text = 'logo'
11
+ end
12
+ end
13
+
14
+ class MenuGroup
15
+ attr_reader :title, :link, :items, :more
16
+ attr_writer :title, :link, :more
17
+
18
+ def initialize(title, link)
19
+ @title = title
20
+ @link = link
21
+ @items = Array.new
22
+ end
23
+
24
+ def add_to_menu_items
25
+ item = MenuItem.new('item', nil)
26
+ @items.push(item)
27
+ return item
28
+ end
29
+
30
+ def menu_item(title, link)
31
+ add_item(MenuItem.new(title, link))
32
+ end
33
+
34
+ def add_item(item)
35
+ @items.push(item)
36
+ end
37
+
38
+ end
39
+
40
+ class MenuItem
41
+ attr_reader :title, :link
42
+ attr_writer :title, :link
43
+
44
+ def initialize(title, link)
45
+ @title = title
46
+ @link = link
47
+ end
48
+ end
49
+
50
+ class Releases
51
+ attr_reader :stable_version, :pre_release_version, :snap_shot_version, :download_link, :versioning_link
52
+ attr_writer :stable_version, :pre_release_version, :snap_shot_version, :download_link, :versioning_link
53
+
54
+ def initialize
55
+ @pre_release_version = 'n/a'
56
+ @snap_shot_version = 'n/a'
57
+ @download_link = 'download.html'
58
+ @versioning_link = 'versioning.html'
59
+ end
60
+ end
61
+
62
+ class TemplateBuilder
63
+ attr_accessor :title_header, :css_path, :news_rss, :contact_admin
64
+ attr_reader :logo, :menu_groups
65
+
66
+ def initialize
67
+ @title_header = ''
68
+ @css_path = 'buildmaster.css'
69
+ @logo = Logo.new
70
+ @menu_groups = Array.new
71
+ @contact_admin = 'contact.html'
72
+ end
73
+
74
+ def add_to_menu_groups
75
+ group = MenuGroup.new('group', nil)
76
+ menu_groups.push(group)
77
+ return group
78
+ end
79
+
80
+ def menu_group(title, link = nil)
81
+ group = MenuGroup.new(title, link)
82
+ menu_groups.push(group)
83
+ return group
84
+ end
85
+
86
+ def left_bottom_logo
87
+ if (@left_bottom_logo.nil?)
88
+ @left_bottom_logo = Logo.new
89
+ end
90
+ return @left_bottom_logo
91
+ end
92
+
93
+ def releases
94
+ if (@releases.nil?)
95
+ @releases = Releases.new
96
+ end
97
+ return @releases
98
+ end
99
+
100
+ def generate
101
+ return load_template
102
+ end
103
+
104
+ def content
105
+ return load_template_content
106
+ end
107
+
108
+ private
109
+ def load_template
110
+ content = load_template_content
111
+ return REXML::Document.new(content)
112
+ end
113
+
114
+ def generate_logo_text
115
+ if (logo.path)
116
+ return "<img id=\"logo\" alt=\"#{logo.text}\"><template:href url=\"#{logo.path}\"/></img>"
117
+ else
118
+ return logo.text
119
+ end
120
+ end
121
+
122
+ def generate_menu_groups
123
+ result = ""
124
+ menu_groups.each do |menu_group|
125
+ menu_group_content = <<CONTENT
126
+ <div class="MenuGroup">
127
+ <h1>#{generate_menu_group_content(menu_group)}</h1>
128
+ <ul>
129
+ #{generate_menu_group_item_content(menu_group.items)}
130
+ #{generate_more_item(menu_group.more)}
131
+ </ul>
132
+ </div>
133
+ CONTENT
134
+ result += menu_group_content
135
+ end
136
+ return result
137
+ end
138
+
139
+ def generate_menu_group_content(menu_group)
140
+ if (menu_group.link)
141
+ return "<template:link href=\"#{menu_group.link}\">#{menu_group.title}</template:link>"
142
+ else
143
+ return menu_group.title
144
+ end
145
+ end
146
+
147
+ def generate_menu_group_item_content(items)
148
+ result = ''
149
+ items.each do |item|
150
+ item_content = <<CONTENT
151
+ <li><template:link href=\"#{item.link}\">#{item.title}</template:link></li>
152
+ CONTENT
153
+ result = result + item_content
154
+ end
155
+ return result
156
+ end
157
+
158
+ def generate_more_item(link)
159
+ return '' unless link
160
+ return "<li class=\"More\"><a><template:href url=\"#{link}\"/>More...</a></li>"
161
+ end
162
+
163
+ def generate_left_bottom_logo()
164
+ content = ''
165
+ logo = left_bottom_logo()
166
+ if (logo.path)
167
+ content = <<CONTENT
168
+ <div class="logo">
169
+ <a href="#{logo.link}">
170
+ <img alt="#{logo.text}" src="#{logo.path}" width="170"/>
171
+ </a>
172
+ </div>
173
+ CONTENT
174
+ end
175
+ return content
176
+ end
177
+
178
+ def generate_releases
179
+ if (releases.download_link.nil?)
180
+ return ''
181
+ end
182
+ content = <<CONTENT
183
+ <div class="NewsGroup">
184
+ <h1>Latest Versions</h1>
185
+ <table>
186
+ <tr>
187
+ <td><template:link href="#{releases.download_link}#stable">Stable:</template:link></td>
188
+ <td><template:link href="#{releases.download_link}#stable">#{releases.stable_version}</template:link></td>
189
+ </tr>
190
+ <tr>
191
+ <td><template:link href="#{releases.download_link}#prerelease">Prerelease:</template:link></td>
192
+ <td><template:link href="#{releases.download_link}#prerelease">#{releases.pre_release_version}</template:link></td>
193
+ </tr>
194
+ <tr>
195
+ <td><template:link href="#{releases.download_link}#snapshot">Snapshot:</template:link></td>
196
+ <td><template:link href="#{releases.download_link}#snapshot">#{releases.snap_shot_version}</template:link></td>
197
+ </tr>
198
+ </table>
199
+ <p class="NewsMore"><template:link href="#{releases.versioning_link}">About version numbers...</template:link></p>
200
+ </div>
201
+ CONTENT
202
+ return content
203
+ end
204
+
205
+ def generate_news
206
+ if (news_rss.nil?)
207
+ return ''
208
+ end
209
+ content = <<CONTENT
210
+ <div class="NewsGroup">
211
+ <h1>Recent News</h1>
212
+ <template:each source="#{news_rss}" select="/rss/channel/item" count="3">
213
+ <div class="NewsItem">
214
+ <p class="NewsTitle"><template:include elements="./title/text()"/></p>
215
+ <p class="NewsDate"><template:include elements="./pubDate/text()"/></p>
216
+ <p class="NewsText"><template:include elements="./xhtml:div/node()"/></p>
217
+ </div>
218
+ </template:each>
219
+
220
+ <p class="NewsMore"><template:link href="#{news_rss}">News feed (RSS 2.0)</template:link></p>
221
+ </div>
222
+ CONTENT
223
+ end
224
+
225
+ def load_template_content
226
+ return <<CONTENT
227
+ <html xmlns="http://www.w3.org/1999/xhtml"
228
+ xmlns:template="http://buildmaster.rubyforge.org/xtemplate/1.0">
229
+ <head>
230
+ <title>#{title_header}<template:include elements="/html/head/title/text()"/></title>
231
+ <link rel="stylesheet" type="text/css"><template:href url="#{css_path}"/></link>
232
+ <template:include elements="/html/head/*[not(title()='title')]"/>
233
+ </head>
234
+
235
+ <body>
236
+ <div class="header">
237
+ <a class="header">
238
+ <template:href url="#{logo.link}"/>
239
+ #{generate_logo_text}
240
+ </a>
241
+ </div>
242
+
243
+ <div class="left">
244
+ #{generate_menu_groups}
245
+ #{generate_left_bottom_logo}
246
+ </div>
247
+
248
+ <template:when test="index_file?">
249
+ <div class="right">
250
+ #{generate_releases}
251
+ #{generate_news}
252
+ </div>
253
+ </template:when>
254
+
255
+ <div>
256
+ <template:attribute name="class" eval="center_class"/>
257
+ <div class="content"><template:include elements="/html/body/*"/></div>
258
+ </div>
259
+
260
+ <div class="footer">
261
+ <div class="bottomshadow"/>
262
+ <div class="poweredby">
263
+ Powered by <a href="http://buildmaster.rubyforge.org" class="footer">BuildMaster</a>
264
+ -
265
+ <a class="footer"><template:href url="#{contact_admin}" />Contact Administrators</a>
266
+ <br/>
267
+ </div>
268
+ </div>
269
+ <div>
270
+ </div>
271
+ </body>
272
+ </html>
273
+ CONTENT
274
+ end
275
+ end
276
+ end
@@ -0,0 +1,33 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'webrick'
4
+ require 'source_file_handler'
5
+
6
+ module BuildMaster
7
+ class SiteServer
8
+ def initialize(port_number=2000, log_file=$stdout, level=WEBrick::Log::INFO, access_log=nil)
9
+ mime_types = WEBrick::HTTPUtils::DefaultMimeTypes.update(
10
+ {"textile" => "text/plain"}
11
+ )
12
+ @server = WEBrick::HTTPServer.new(
13
+ :Port => port_number,
14
+ :Logger => WEBrick::Log.new(log_file, level),
15
+ :MimeTypes => mime_types,
16
+ :AccessLog => access_log
17
+ )
18
+ end
19
+
20
+ def start(spec)
21
+ @server.mount('/', SourceFileHandler, spec)
22
+ @server.mount('/source', WEBrick::HTTPServlet::FileHandler, spec.content_dir, true)
23
+ ['INT', 'TERM'].each { |signal|
24
+ trap(signal){ stop}
25
+ }
26
+ @server.start
27
+ end
28
+
29
+ def stop
30
+ @server.shutdown
31
+ end
32
+ end
33
+ end
@@ -1,12 +1,42 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
1
3
  require 'pathname'
4
+ require 'templatelets'
5
+ require 'tree_to_object'
6
+ require 'site/template_builder'
2
7
 
3
8
  module BuildMaster
9
+
4
10
  class SiteSpec
5
- def self.get_instance
6
- self.new()
11
+ attr_reader :output_dir
12
+ attr_accessor :content_dir, :template, :template_file
13
+
14
+ def initialize(file = nil)
15
+ @root = File.dirname(file) if file
16
+ if (block_given?)
17
+ yield self
18
+ end
19
+ end
20
+
21
+ def output_dir=(path)
22
+ if (@root)
23
+ @output_dir = File.join(@root, path)
24
+ else
25
+ @output_dir = path
26
+ end
27
+ end
28
+
29
+ def content_dir=(path)
30
+ if (@root)
31
+ @content_dir = File.join(@root, path)
32
+ else
33
+ @content_dir = path
34
+ end
35
+ end
36
+
37
+ def page_layout=(yaml)
38
+ @template = TreeToObject.from_yaml(yaml, TemplateBuilder.new).content
7
39
  end
8
-
9
- attr_accessor :output_dir, :content_dir, :template, :template_file
10
40
 
11
41
  def properties
12
42
  @properties = Hash.new unless @properties
@@ -18,12 +48,34 @@ module BuildMaster
18
48
  end
19
49
 
20
50
  def load_template
51
+ templatelets = load_templatelets
52
+ template_source = load_template_source
53
+ return XTemplate.new(template_source, templatelets)
54
+ end
55
+
56
+ def load_templatelets
57
+ hash = Hash.new
58
+ hash['href'] = Href.new(self)
59
+ hash['attribute'] = Attribute.new(self)
60
+ hash['each'] = Each.new(self)
61
+ hash['include'] = Include.new(self)
62
+ hash['link'] = Link.new(self)
63
+ hash['text'] = Text.new(properties)
64
+ hash['when'] = When.new(self, self)
65
+ return hash
66
+ end
67
+
68
+ def load_template_source
21
69
  if (@template)
22
- return XTemplate.new(@template)
70
+ return @template
23
71
  else
24
- return XTemplate.new(File.open(@template_file))
72
+ return File.open(@template_file)
25
73
  end
26
74
  end
75
+
76
+ def load_document(path)
77
+ return REXML::Document.new(File.open(File.join(content_dir, path)))
78
+ end
27
79
 
28
80
  def relative_to_root(path)
29
81
  to = path_name(path)
@@ -31,26 +83,23 @@ module BuildMaster
31
83
  return to.relative_path_from(from)
32
84
  end
33
85
 
34
- def evaluate(expression, path)
35
- value_from_properties = properties()[expression]
36
- if (value_from_properties)
37
- return value_from_properties
38
- end
39
- if (!respond_to?(expression, true))
40
- raise "Neither property nor method found with name '#{expression}'"
41
- end
42
- relative_path = relative_to_root(path)
43
- if (expression == 'relative_to_root')
44
- return relative_path
45
- else
46
- send(expression, relative_to_root(path).to_s)
47
- end
48
- end
49
-
50
86
  def add_property(name, value)
51
87
  properties()[name] = value
52
88
  end
53
89
 
90
+ def center_class(content_path)
91
+ if index_file? content_path
92
+ return 'Content3Column'
93
+ else
94
+ return 'Content2Column'
95
+ end
96
+ end
97
+
98
+ def index_file?(content_path)
99
+ result = content_path.to_s == 'index.html'
100
+ return result
101
+ end
102
+
54
103
  private
55
104
  def path_name(path)
56
105
  return Pathname.new(path.gsub(/\\/, '/'))
@@ -67,7 +116,9 @@ module BuildMaster
67
116
  raise "<#{directory}> should be a directory for #{symbol.id2name}"
68
117
  end
69
118
  end
119
+
70
120
 
121
+ =begin
71
122
  def validate_file(file, symbol)
72
123
  if not file
73
124
  raise "File for #{symbol.id2name} not specified"
@@ -79,6 +130,7 @@ module BuildMaster
79
130
  raise "#<{file} should be a file for #{symbol.id2name}"
80
131
  end
81
132
  end
133
+ =end
82
134
  end
83
135
 
84
136
  end