autobuild 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES ADDED
@@ -0,0 +1,57 @@
1
+ = Autobuild changelog
2
+
3
+ == Version 0.5
4
+
5
+ Fixes the mail default behaviour. Added the 'tar' importer.
6
+
7
+ * all the API is now in a separate module
8
+ * genflags has been renamed back to genomflags. The convention is now to
9
+ have a <tool>flags option. For instance: genomflags, configureflags
10
+ * added the --[no-]build option to do only import
11
+ * changed behaviour for mail reports:
12
+ - set sensible default options for mail
13
+ - mail: true uses default options
14
+ - mail: <string> is equivalent to
15
+ mail:
16
+ to: <string>
17
+ * if a value is undefined in the config file, parameter expansion tries to get
18
+ it from the program environment, and raises an error if it is not present in
19
+ the environment vars
20
+ * changed the names of log files. All importers now uses <package>-<import>.log
21
+ * added the 'tar' importer, which downloads and uncompress a tarball
22
+
23
+
24
+ == Version 0.4
25
+
26
+ * added support to split import and build. For instance
27
+
28
+ whole_tree:
29
+ type: import
30
+ import: cvs
31
+ source: [ a, repository ]
32
+
33
+ package1:
34
+ type: autotools
35
+ srcdir: whole_tree/package1
36
+ depends: whole_tree
37
+
38
+ package2:
39
+ type: autotools
40
+ srcdir: whole_tree/package2
41
+ depends: whole_tree
42
+
43
+ Works as it should
44
+
45
+ * the <tt>autotools</tt> package has now an <tt>autogen</tt> options, which gives a name for a script
46
+ which creates the autotools environment
47
+ * renamed 'genomflags' -> 'genflags'
48
+ * variable interpolation checks for environment variables
49
+ * bugfixes
50
+
51
+ == Version 0.3
52
+
53
+ * added support for patching source code. Add patch: [ patches ] to the package configuration
54
+ * renamed autobuild-config, common-config and clean-log to autobuild, common and clean_log. Autobuild
55
+ warns if it finds one the previous spelling but ignores it anyway
56
+
57
+
data/README CHANGED
@@ -109,6 +109,7 @@ Autobuild uses three sections:
109
109
  *update*:: if false, do not update the packages that are already imported (default: true). You
110
110
  can also use the <tt>--no-update</tt> on the command line
111
111
 
112
+
112
113
  === Directories (<tt>autobuild/srcdir</tt>, <tt>autobuild/prefix</tt> and <tt>autobuild/logdir</tt>)
113
114
  *srcdir*:: the path where programs are to be imported. See <b>Packages configuration</b> for
114
115
  more information on how this option is used.
@@ -144,30 +145,27 @@ sets
144
145
 
145
146
 
146
147
  === Mail (<tt>autobuild/mail</tt>)
147
- If you want to receive a mail when the build has finished (on success and failures), set
148
- at least the +to+ option, like this:
148
+ Use this options if you want to receive a mail when the build has finished (on success and failures)
149
149
 
150
150
  autobuild:
151
- mail:
152
- from: autobuild@mymachine.rubyrules.org
153
- to: myself+autobuild@rubyrules.org
154
- smtp: localhost
151
+ mail: true
155
152
 
156
- Other options are:
157
- *from*:: what to set in the <tt>From:</tt> field, default is <tt>autobuild@hostname</tt>
153
+ Valid options are:
154
+ *to*:: the mail destination, default is <tt>user@hostname</tt> (for instance sylvain@localhost for a user 'sylvain')
155
+ *from*:: the mail source, default is <tt>user@hostname</tt>
158
156
  *smtp*:: the stmp server to use. Default is +localhost+
157
+ *port*:: the port the server is running on. Default is the smtp port (25)
159
158
 
160
159
  All log files relative to the current build are attached to the mail.
161
160
 
162
161
 
163
-
164
162
  == Configuring packages (<tt>packages/*</tt>)
165
163
  === The <tt>packages/config</tt> section
166
164
  If you want to add common options in each package, just set it them here. Note that the options
167
- are /merged/ in the package config. It neither replaces the values in the package nor be replaced
168
- by them. The merging strategy depends on the way the <tt>common</tt> is specified:
169
- * if it is an array, the package option is converted to an array and the common option is appended
170
- * if it is a string, the package option is converted to a string and the common option is appended
165
+ are /merged/ in the package config. It neither replaces the values in the package nor the package
166
+ options replaces them. The merging strategy depends on the way the option is specified in this common section:
167
+ * if it is an array, the package option is converted to an array and the common options are appended
168
+ * if it is a string, the package option is converted to a string and the common option are appended
171
169
  with a space inserted between the two
172
170
  * if it is a boolean value, it is <em>overriden</em> by the package value
173
171
  * any other values are forbidden
@@ -231,6 +229,22 @@ source and the builder to build and install it.
231
229
  *svnup*:: options to add to svn up. Defaults to ''
232
230
  *svnco*:: options to add to svn co. Defaults to ''
233
231
 
232
+ === Tar (<tt>type: tar</tt>)
233
+ This importer gets a tarball file, which may be on a remote server, and un-tars
234
+ it. For now, it cannot determine itself what is the directory included in the tarball,
235
+ so you should set the srcdir: appropriately.
236
+
237
+ For instance, a tarball with one directory <tt>package-0.1</tt> in it will
238
+ need a <tt>srcdir</tt> option of <tt>package-0.1</tt>. If you do
239
+ not set +srcdir+, autobuild will untar the package in the global srcdir
240
+ (as intended) but will search for <tt>$global_srcdir/package</tt>
241
+
242
+ *source*:: the source URL. For now, http, ftp and file URLs are supported
243
+ *cachedir*:: the directory where the local copy of the file should be saved
244
+ (for http and ftp URLs only)
245
+
246
+
247
+
234
248
  == Available package types (<tt>packages/</tt><em>name</em><tt>/type</tt>)
235
249
  === Source only (<tt>type: import</tt>)
236
250
  Use +import+ if you need the package sources but don't need to build it. You just need
@@ -275,8 +289,8 @@ The only program used during the build phase is +make+. The make command can too
275
289
  make: gnumake
276
290
 
277
291
  ==== Other options
278
- *builddir*:: the directory where the build takes place. For now, it has to be a relative path,
279
- which is added to the import dir. The default value is "build"
292
+ *builddir*:: the directory where the build takes place. For now, it has to be a relative path,
293
+ which will be considered relative to the source directory.
280
294
  *configureflags*:: array of options to add to the +configure+ command line
281
295
  configureflags: [ --with-bar-source=$srcdir/$bar_srcdir ]
282
296
  depends: bar
@@ -284,37 +298,6 @@ The only program used during the build phase is +make+. The make command can too
284
298
  = Running autobuild in daemon mode
285
299
  The <tt>--daemon</tt> command line options makes autobuild go into daemon mode.
286
300
 
287
- = Changes
288
- == 0.3 to 0.4
289
- * added support to split import and build. For instance
290
-
291
- whole_tree:
292
- type: import
293
- import: cvs
294
- source: [ a, repository ]
295
-
296
- package1:
297
- type: autotools
298
- srcdir: whole_tree/package1
299
- depends: whole_tree
300
-
301
- package2:
302
- type: autotools
303
- srcdir: whole_tree/package2
304
- depends: whole_tree
305
-
306
- Now works well
307
-
308
- * the <tt>autotools</tt> package has now an <tt>autogen</tt> options, which gives a name for the script
309
- to run to create the autoconf environment
310
- * renamed 'genomflags' -> 'genflags'
311
- * variable interpolation checks for environment variables
312
- * bugfixes
313
- == 0.2 to 0.3
314
- * added support for patching source code. Add patch: [ patches ] to the package configuration
315
- * renamed autobuild-config, common-config and clean-log to autobuild, common and clean_log. Autobuild
316
- warns if it finds one the previous spelling but ignores it anyway
317
-
318
301
  = Copyright and license
319
302
  Author:: Sylvain Joyeux <sylvain.joyeux@m4x.org>
320
303
  Copyright:: Copyright (c) 2005 Sylvain Joyeux
@@ -0,0 +1,161 @@
1
+ # Rakefile for Autobuild
2
+ # Copyright 2005 by Sylvain Joyeux (sylvain.joyeux@m4x.org)
3
+
4
+ # Based on the Rakefile for MetaProject
5
+ # Copyright 2005 by Aslak Hellesoy (aslak.hellesoy@gmail.org)
6
+ # All rights reserved.
7
+
8
+ # This file is may be distributed under an MIT style license. See
9
+ # MIT-LICENSE for details.
10
+
11
+ $:.unshift('lib')
12
+ require 'meta_project'
13
+ require 'rake/gempackagetask'
14
+ require 'rake/contrib/rubyforgepublisher'
15
+ require 'rake/contrib/xforge'
16
+ require 'rake/clean'
17
+ require 'rake/testtask'
18
+ require 'rake/rdoctask'
19
+
20
+ # Versioning scheme: MAJOR.MINOR.PATCH
21
+ # MAJOR bumps when API is broken backwards
22
+ # MINOR bumps when the API is broken backwards in a very slight/subtle (but not fatal) way
23
+ # -OR when a new release is made and propaganda is sent out.
24
+ # PATCH is bumped for every API addition and/or bugfix (ideally for every commit)
25
+ # Later DamageControl can bump PATCH automatically.
26
+ #
27
+ # REMEMBER TO KEEP PKG_VERSION IN SYNC WITH THE CHANGES FILE!
28
+ PKG_NAME = "autobuild"
29
+ PKG_VERSION = "0.5"
30
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
31
+ PKG_FILES = FileList[
32
+ '[A-Z]*',
33
+ 'lib/**/*.rb',
34
+ 'doc/**/*'
35
+ ]
36
+
37
+ task :default => [:gem]
38
+
39
+ # Create a task to build the RDOC documentation tree.
40
+ rd = Rake::RDocTask.new("rdoc") do |rdoc|
41
+ rdoc.rdoc_dir = 'html'
42
+ # rdoc.template = 'kilmer'
43
+ # rdoc.template = 'css2'
44
+ # rdoc.template = 'doc/jamis.rb'
45
+ rdoc.title = "Autobuild"
46
+ rdoc.options << '--main' << 'README'
47
+ rdoc.rdoc_files.include('README', 'CHANGES')
48
+ rdoc.rdoc_files.include('lib/**/*.rb', 'doc/**/*.rdoc')
49
+ rdoc.rdoc_files.exclude('doc/**/*_attrs.rdoc')
50
+ end
51
+
52
+ # ====================================================================
53
+ # Create a task that will package the Rake software into distributable
54
+ # tar, zip and gem files.
55
+
56
+ spec = Gem::Specification.new do |s|
57
+
58
+ #### Basic information.
59
+
60
+ s.name = PKG_NAME
61
+ s.version = PKG_VERSION
62
+ s.summary = 'Rake-based utility to build and install multiple packages with dependencies'
63
+ s.description = <<EOF
64
+ Autobuild imports, configures, builds and installs various kinds of software packages.
65
+ It can be used in software development to make sure that nothing is broken in the
66
+ build process of a set of packages, or can be used as an automated installation tool.
67
+ EOF
68
+
69
+ s.files = PKG_FILES.to_a
70
+ s.require_path = 'lib'
71
+
72
+ #### Documentation and testing.
73
+
74
+ s.has_rdoc = true
75
+ s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a
76
+ s.rdoc_options <<
77
+ '--title' << 'Autobuild' <<
78
+ '--main' << 'README'
79
+
80
+ #### Author and project details.
81
+
82
+ s.author = "Sylvain Joyeux"
83
+ s.email = "sylvain.joyeux@m4x.org"
84
+ s.homepage = "http://autobuild.rubyforge.org"
85
+ s.rubyforge_project = "autobuild"
86
+ end
87
+
88
+ # Fix 1.8.4 - 1.8.3 issue
89
+ class << spec
90
+ def to_yaml
91
+ out = super
92
+ out = '--- ' + out unless out =~ /^---/
93
+ out
94
+ end
95
+ end
96
+
97
+ desc "Build Gem"
98
+ Rake::GemPackageTask.new(spec) do |pkg|
99
+ pkg.need_zip = true
100
+ pkg.need_tar = true
101
+ end
102
+
103
+ # Support Tasks ------------------------------------------------------
104
+
105
+ desc "Look for TODO and FIXME tags in the code"
106
+ task :todo do
107
+ Pathname.new(File.dirname(__FILE__)).egrep(/#.*(FIXME|TODO|TBD|DEPRECATED)/) do |match|
108
+ puts match
109
+ end
110
+ end
111
+
112
+ task :release => [:release_files, :publish_doc, :tag] # :publish_news,
113
+
114
+ task :verify_env_vars do
115
+ raise "RUBYFORGE_USER environment variable not set!" unless ENV['RUBYFORGE_USER']
116
+ raise "RUBYFORGE_PASSWORD environment variable not set!" unless ENV['RUBYFORGE_PASSWORD']
117
+ end
118
+
119
+ task :publish_doc => :verify_env_vars do
120
+ publisher = Rake::RubyForgePublisher.new('autobuild', ENV['RUBYFORGE_USER'])
121
+ publisher.upload
122
+ end
123
+
124
+ desc "Release files on RubyForge"
125
+ task :release_files => [:gem, :verify_env_vars] do
126
+ release_files = FileList[
127
+ "pkg/#{PKG_FILE_NAME}.gem"
128
+ ]
129
+
130
+ Rake::XForge::Release.new(MetaProject::Project::XForge::RubyForge.new('autobuild')) do |release|
131
+ # Never hardcode user name and password in the Rakefile!
132
+ release.user_name = ENV['RUBYFORGE_USER']
133
+ release.password = ENV['RUBYFORGE_PASSWORD']
134
+ release.files = release_files.to_a
135
+ release.release_name = "Autobuild #{PKG_VERSION}"
136
+ # The rest of the options are defaults (among others, release_notes and release_changes, parsed from CHANGES)
137
+ end
138
+ end
139
+
140
+ desc "Publish news on RubyForge"
141
+ task :publish_news => [:gem, :verify_env_vars] do
142
+ release_files = FileList[
143
+ "pkg/#{PKG_FILE_NAME}.gem"
144
+ ]
145
+
146
+ Rake::XForge::NewsPublisher.new(MetaProject::Project::XForge::RubyForge.new('autobuild')) do |news|
147
+ # Never hardcode user name and password in the Rakefile!
148
+ news.user_name = ENV['RUBYFORGE_USER']
149
+ news.password = ENV['RUBYFORGE_PASSWORD']
150
+ end
151
+ end
152
+
153
+ desc "Tag all the svn files with the latest release number (REL=x.y.z)"
154
+ task :tag do
155
+ reltag = "RELEASE_#{PKG_VERSION.gsub(/\./, '_')}"
156
+ puts "Tagging svn with [#{reltag}]"
157
+ base_url = %{svn+ssh://#{RUBYFORGE_USER}@rubyforge.org/var/svn/autobuild}
158
+ sh %{svn cp #{base_url}/trunk/autobuild #{base_url}/tags/#{reltag}}
159
+ end
160
+
161
+
@@ -1,117 +1,106 @@
1
1
  require 'autobuild/exceptions'
2
2
 
3
- class Regexp
4
- def each_match(string)
5
- string = string.to_str
6
- while data = match(string)
7
- yield(data)
8
- string = data.post_match
3
+ module Autobuild
4
+ class UndefinedVariable < ConfigException
5
+ attr_reader :name
6
+ attr_accessor :reference
7
+ def initialize(name, reference = [])
8
+ @name = name
9
+ @reference = reference
9
10
  end
10
- end
11
- end
12
11
 
13
- class UndefinedVariable < ConfigException
14
- attr_reader :name
15
- attr_accessor :reference
16
- def initialize(name, reference = [])
17
- @name = name
18
- @reference = reference
12
+ def to_s
13
+ "undefined variable '#{name}' in #{reference.join('/')}"
14
+ end
19
15
  end
20
16
 
21
- def to_s
22
- "undefined variable '#{name}' in #{reference.join('/')}"
23
- end
24
- end
17
+ class Interpolator
18
+ VarDefKey = 'defines'
19
+ MatchExpr = '\$\{([^}]+)\}|\$(\w+)'
20
+ PartialMatch = Regexp.new(MatchExpr)
21
+ WholeMatch = Regexp.new("^(?:#{MatchExpr})$")
25
22
 
26
- class Interpolator
27
- VarDefKey = 'defines'
28
- MatchExpr = '\$\{([^}]+)\}|\$(\w+)'
29
- PartialMatch = Regexp.new(MatchExpr)
30
- WholeMatch = Regexp.new("^(?:#{MatchExpr})$")
23
+ def self.interpolate(config, parent = nil)
24
+ Interpolator.new(config, parent).interpolate
25
+ end
31
26
 
32
- def self.interpolate(config, parent = nil)
33
- Interpolator.new(config, parent).interpolate
34
- end
27
+ def initialize(node, parent = nil, variables = {})
28
+ @node = node
29
+ @variables = {}
30
+ @defines = {}
31
+ @parent = parent
32
+ end
35
33
 
36
- def initialize(node, parent = nil, variables = {})
37
- @node = node
38
- @variables = {}
39
- @defines = {}
40
- @parent = parent
41
- end
34
+ def interpolate
35
+ case @node
36
+ when Hash
37
+ @defines = (@node[VarDefKey] || {})
38
+
39
+ interpolated = Hash.new
40
+ @node.each do |k, v|
41
+ begin
42
+ next if k == VarDefKey
43
+ interpolated[k] = Interpolator.interpolate(v, self)
44
+ rescue UndefinedVariable => e
45
+ e.reference.unshift k
46
+ raise e
47
+ end
48
+ end
49
+
50
+ interpolated
42
51
 
43
- def interpolate
44
- case @node
45
- when Hash
46
- @defines = (@node[VarDefKey] || {})
52
+ when Array
53
+ @node.collect { |v| Interpolator.interpolate(v, self) }
47
54
 
48
- interpolated = Hash.new
49
- @node.each do |k, v|
55
+ else
50
56
  begin
51
- next if k == VarDefKey
52
- interpolated[k] = Interpolator.interpolate(v, self)
57
+ each_interpolation(@node) { |varname| value_of(varname) }
53
58
  rescue UndefinedVariable => e
54
- e.reference.unshift k
59
+ e.reference.unshift @node.to_str if @node.respond_to?(:to_str)
55
60
  raise e
56
61
  end
57
62
  end
58
-
59
- interpolated
60
-
61
- when Array
62
- @node.collect { |v| Interpolator.interpolate(v, self) }
63
-
64
- else
65
- begin
66
- each_interpolation(@node) { |varname| value_of(varname) }
67
- rescue UndefinedVariable => e
68
- e.reference.unshift @node.to_str if @node.respond_to?(:to_str)
69
- raise e
70
- end
71
63
  end
72
- end
73
64
 
74
- def value_of(name)
75
- if @defines.has_key?(name)
76
- value = @defines.delete(name)
77
- @variables[name] = each_interpolation(value) { |varname|
78
- begin
79
- value_of(varname)
80
- rescue UndefinedVariable => e
81
- if e.varname == name
82
- raise ConfigException, "cyclic reference found in definition of '#{name}'"
83
- else
84
- raise
65
+ def value_of(name)
66
+ if @defines.has_key?(name)
67
+ value = @defines.delete(name)
68
+ @variables[name] = each_interpolation(value) { |varname|
69
+ begin
70
+ value_of(varname)
71
+ rescue UndefinedVariable => e
72
+ if e.varname == name
73
+ raise ConfigException, "cyclic reference found in definition of '#{name}'"
74
+ else
75
+ raise
76
+ end
85
77
  end
86
- end
87
- }
88
- elsif @variables.has_key?(name)
89
- @variables[name]
90
- elsif @parent
91
- @parent.value_of(name)
92
- elsif ENV[name.to_s]
93
- ENV[name.to_s]
94
- else
95
- raise UndefinedVariable.new(name)
78
+ }
79
+ elsif @variables.has_key?(name)
80
+ @variables[name]
81
+ elsif @parent
82
+ @parent.value_of(name)
83
+ elsif ENV[name.to_s]
84
+ ENV[name.to_s]
85
+ else
86
+ raise UndefinedVariable.new(name)
87
+ end
96
88
  end
97
- end
98
89
 
99
- def each_interpolation(value)
100
- return value if (!value.respond_to?(:to_str) || value.empty?)
101
-
102
- # Special case: if 'value' is *only* an interpolation, avoid
103
- # conversion to string
104
- WholeMatch.each_match(value) do |data|
105
- return yield(data[1] || data[2])
106
- end
90
+ def each_interpolation(value)
91
+ return value if (!value.respond_to?(:to_str) || value.empty?)
92
+
93
+ # Special case: if 'value' is *only* an interpolation, avoid
94
+ # conversion to string
95
+ if match = WholeMatch.match(value)
96
+ return yield($1 || $2)
97
+ end
107
98
 
108
- interpolated = ''
109
- data = nil
110
- PartialMatch.each_match(value) do |data|
111
- varname = data[1] || data[2]
112
- interpolated << data.pre_match << yield(varname)
99
+ return value.gsub(PartialMatch) { |match|
100
+ varname = $1 || $2
101
+ yield(varname)
102
+ }
113
103
  end
114
- return data ? (interpolated << data.post_match) : value
115
104
  end
116
105
  end
117
106