autobuild 0.4 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +57 -0
- data/README +29 -46
- data/Rakefile +161 -0
- data/lib/autobuild/config-interpolator.rb +80 -91
- data/lib/autobuild/config.rb +21 -6
- data/lib/autobuild/environment.rb +13 -11
- data/lib/autobuild/exceptions.rb +46 -45
- data/lib/autobuild/import/cvs.rb +34 -39
- data/lib/autobuild/import/svn.rb +23 -29
- data/lib/autobuild/import/tar.rb +120 -0
- data/lib/autobuild/importer.rb +4 -6
- data/lib/autobuild/options.rb +18 -11
- data/lib/autobuild/package.rb +1 -1
- data/lib/autobuild/packages/autotools.rb +107 -121
- data/lib/autobuild/packages/genom.rb +56 -62
- data/lib/autobuild/packages/import.rb +14 -12
- data/lib/autobuild/reporting.rb +91 -55
- data/lib/autobuild/subcommand.rb +89 -46
- data/lib/autobuild/timestamps.rb +47 -37
- metadata +43 -78
- data/bin/autobuild +0 -83
- data/test/base.rb +0 -8
- data/test/tc_config.rb +0 -40
- data/test/tc_config_interpolation.rb +0 -57
- data/test/tc_import.rb +0 -77
- data/test/tc_subcommand.rb +0 -61
- data/test/tools.rb +0 -39
data/lib/autobuild/config.rb
CHANGED
@@ -29,7 +29,7 @@ class Hash
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
module Config
|
32
|
+
module Autobuild::Config
|
33
33
|
def self.check_backward_compatibility(config)
|
34
34
|
if config.has_key?('autobuild-config')
|
35
35
|
puts 'WARNING: the \'autobuild-config\' block is now named \'autobuild\''
|
@@ -70,7 +70,7 @@ module Config
|
|
70
70
|
end
|
71
71
|
}
|
72
72
|
|
73
|
-
$VERBOSE = autobuild_config[:verbose]
|
73
|
+
$verbose = $VERBOSE = autobuild_config[:verbose]
|
74
74
|
$trace = $DEBUG = autobuild_config[:debug]
|
75
75
|
|
76
76
|
get_autobuild_config(config)
|
@@ -81,9 +81,10 @@ module Config
|
|
81
81
|
$PROGRAMS = (config[:programs] or "make")
|
82
82
|
|
83
83
|
autobuild = config[:autobuild]
|
84
|
-
$SRCDIR
|
85
|
-
$PREFIX
|
86
|
-
$LOGDIR
|
84
|
+
$SRCDIR = File.expand_path(autobuild[:srcdir], Dir.pwd)
|
85
|
+
$PREFIX = File.expand_path(autobuild[:prefix], Dir.pwd)
|
86
|
+
$LOGDIR = File.expand_path(autobuild[:logdir] || "autobuild/log", $PREFIX)
|
87
|
+
$CACHEDIR = File.expand_path(autobuild[:cachedir] || "autobuild/cache", $PREFIX)
|
87
88
|
|
88
89
|
FileUtils.mkdir_p $SRCDIR if !File.directory?($SRCDIR)
|
89
90
|
FileUtils.mkdir_p $LOGDIR if !File.directory?($LOGDIR)
|
@@ -92,7 +93,21 @@ module Config
|
|
92
93
|
FileUtils.rm_rf Dir.glob("#{$LOGDIR}/*.log")
|
93
94
|
end
|
94
95
|
|
95
|
-
$
|
96
|
+
FileUtils.mkdir_p $CACHEDIR if !File.directory?($CACHEDIR)
|
97
|
+
|
98
|
+
if autobuild[:mail]
|
99
|
+
if autobuild[:mail].respond_to?(:[])
|
100
|
+
mail_config = autobuild[:mail]
|
101
|
+
elsif autobuild[:mail].respond_to?(:to_str)
|
102
|
+
Hash[:to => autobuild[:mail].to_str]
|
103
|
+
elsif autobuild[:mail] == true
|
104
|
+
mail_config = {}
|
105
|
+
else
|
106
|
+
raise ConfigException, "mail configuration should be either a option hash or a string"
|
107
|
+
|
108
|
+
end
|
109
|
+
Reporting << MailReporter.new(mail_config)
|
110
|
+
end
|
96
111
|
$UPDATE = autobuild[:update]
|
97
112
|
$NICE = autobuild[:nice]
|
98
113
|
|
@@ -1,16 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
module Autobuild
|
2
|
+
def self.pathvar(path, varname)
|
3
|
+
if File.directory?(path)
|
4
|
+
oldpath = ENV[varname]
|
5
|
+
if oldpath.empty?
|
6
|
+
ENV[varname] = path
|
7
|
+
else
|
8
|
+
ENV[varname] = "#{path}:#{oldpath}"
|
9
|
+
end
|
8
10
|
end
|
9
11
|
end
|
10
|
-
end
|
11
12
|
|
12
|
-
def update_environment(newprefix)
|
13
|
-
|
14
|
-
|
13
|
+
def self.update_environment(newprefix)
|
14
|
+
pathvar("#{newprefix}/bin", 'PATH')
|
15
|
+
pathvar("#{newprefix}/lib/pkgconfig", 'PKG_CONFIG_PATH')
|
16
|
+
end
|
15
17
|
end
|
16
18
|
|
data/lib/autobuild/exceptions.rb
CHANGED
@@ -1,51 +1,52 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
def initialize(target = nil)
|
19
|
-
@target = target
|
1
|
+
module Autobuild
|
2
|
+
class Exception < RuntimeError
|
3
|
+
def mail?; false end
|
4
|
+
def fatal?; true end
|
5
|
+
attr_accessor :target, :phase
|
6
|
+
|
7
|
+
def initialize(target = nil, phase = nil)
|
8
|
+
@target = target
|
9
|
+
@phase = phase
|
10
|
+
end
|
11
|
+
|
12
|
+
alias :exception_message :to_s
|
13
|
+
def to_s
|
14
|
+
"#{target}: failed in #{phase} phase"
|
15
|
+
" #{super}"
|
16
|
+
end
|
20
17
|
end
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
class PackageException < Exception
|
25
|
-
def mail?; true end
|
26
|
-
def fatal?; true end
|
27
|
-
|
28
|
-
def initialize(target = nil)
|
29
|
-
@target = target
|
18
|
+
class ConfigException < Exception; end
|
19
|
+
class PackageException < Exception
|
20
|
+
def mail?; true end
|
30
21
|
end
|
31
|
-
attr_accessor :target
|
32
|
-
end
|
33
|
-
|
34
|
-
class ImportException < SubcommandFailed
|
35
|
-
def mail?; true end
|
36
|
-
def fatal?; true end
|
37
|
-
|
38
|
-
def initialize(subcommand)
|
39
|
-
super(subcommand.target, subcommand.command, subcommand.logfile, subcommand.status)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
class BuildException < SubcommandFailed
|
44
|
-
def mail?; true end
|
45
|
-
def fatal?; true end
|
46
22
|
|
47
|
-
|
48
|
-
|
23
|
+
class CommandNotFound < Exception; end
|
24
|
+
class SubcommandFailed < Exception
|
25
|
+
def mail?; true end
|
26
|
+
attr_reader :command, :logfile, :status
|
27
|
+
def initialize(*args)
|
28
|
+
if args.size == 1
|
29
|
+
sc = args[0]
|
30
|
+
target, command, logfile, status =
|
31
|
+
sc.target, sc.command, sc.logfile, sc.status
|
32
|
+
@orig_message = sc.exception_message
|
33
|
+
elsif args.size == 4
|
34
|
+
target, command, logfile, status = *args
|
35
|
+
else
|
36
|
+
raise ArgumentError, "wrong number of arguments, should be 1 or 4"
|
37
|
+
end
|
38
|
+
|
39
|
+
super(target)
|
40
|
+
@command = command
|
41
|
+
@logfile = logfile
|
42
|
+
@status = status
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
prefix = "#{super}\n command '#{command}' failed"
|
47
|
+
prefix << ": " + @orig_message if @orig_message
|
48
|
+
prefix << "\n see #{File.basename(logfile)} for details\n"
|
49
|
+
end
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
data/lib/autobuild/import/cvs.rb
CHANGED
@@ -1,51 +1,46 @@
|
|
1
1
|
require 'autobuild/subcommand'
|
2
2
|
require 'autobuild/importer'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
module Autobuild
|
5
|
+
class CVSImporter < Importer
|
6
|
+
def initialize(root, name, options)
|
7
|
+
@root = root
|
8
|
+
@module = name
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
@program = ($PROGRAMS[:cvs] || 'cvs')
|
11
|
+
@options_up = ( options[:cvsup] || '-dP' ).to_a
|
12
|
+
@options_co = ( options[:cvsco] || '-P' ).to_a
|
13
|
+
super(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def modulename
|
17
|
+
@module
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
+
private
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
raise ImportException.new(e), "failed to update #{modulename}"
|
27
|
-
end
|
28
|
-
}
|
29
|
-
end
|
22
|
+
def update(package)
|
23
|
+
Dir.chdir(package.srcdir) {
|
24
|
+
Subprocess.run(package.target, :import, @program, 'up', *@options_up)
|
25
|
+
}
|
26
|
+
end
|
30
27
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
42
|
-
}
|
28
|
+
def checkout(package)
|
29
|
+
head, tail = File.split(package.srcdir)
|
30
|
+
cvsroot = @root
|
31
|
+
|
32
|
+
FileUtils.mkdir_p(head) if !File.directory?(head)
|
33
|
+
Dir.chdir(head) {
|
34
|
+
options = [ @program, '-d', cvsroot, 'co', '-d', tail ] + @options_co + [ modulename ]
|
35
|
+
Subprocess.run(package.target, :import, *options)
|
36
|
+
}
|
37
|
+
end
|
43
38
|
end
|
44
|
-
end
|
45
39
|
|
46
|
-
module Import
|
47
|
-
|
48
|
-
|
40
|
+
module Import
|
41
|
+
def self.cvs(source, package_options)
|
42
|
+
CVSImporter.new(source[0], source[1], package_options)
|
43
|
+
end
|
49
44
|
end
|
50
45
|
end
|
51
46
|
|
data/lib/autobuild/import/svn.rb
CHANGED
@@ -1,41 +1,35 @@
|
|
1
|
-
require 'autobuild/subcommand'
|
1
|
+
require 'autobuild/subcommand'
|
2
2
|
require 'autobuild/importer'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
module Autobuild
|
5
|
+
class SVNImporter < Importer
|
6
|
+
def initialize(source, options)
|
7
|
+
@source = source.to_a.join("/")
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
9
|
+
@program = ($PROGRAMS[:svn] || 'svn')
|
10
|
+
@options_up = options[:svnup].to_a
|
11
|
+
@options_co = options[:svnco].to_a
|
12
|
+
super(options)
|
13
|
+
end
|
14
14
|
|
15
|
-
|
15
|
+
private
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
raise ImportException.new(e), "failed to update #{package.target}"
|
23
|
-
end
|
24
|
-
}
|
25
|
-
end
|
17
|
+
def update(package)
|
18
|
+
Dir.chdir(package.srcdir) {
|
19
|
+
Subprocess.run(package.target, :import, @program, 'up', *@options_up)
|
20
|
+
}
|
21
|
+
end
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
rescue SubcommandFailed => e
|
31
|
-
raise ImportException.new(e), "failed to check out #{package.target}"
|
23
|
+
def checkout(package)
|
24
|
+
options = [ @program, 'co' ] + @options_co + [ @source, package.srcdir ]
|
25
|
+
Subprocess.run(package.target, :import, *options)
|
32
26
|
end
|
33
27
|
end
|
34
|
-
end
|
35
28
|
|
36
|
-
module Import
|
37
|
-
|
38
|
-
|
29
|
+
module Import
|
30
|
+
def self.svn(source, options)
|
31
|
+
SVNImporter.new(source, options)
|
32
|
+
end
|
39
33
|
end
|
40
34
|
end
|
41
35
|
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
module Autobuild
|
4
|
+
class TarImporter < Importer
|
5
|
+
Plain = 0
|
6
|
+
Gzip = 1
|
7
|
+
Bzip = 2
|
8
|
+
|
9
|
+
TAR_OPTION = {
|
10
|
+
Plain => '',
|
11
|
+
Gzip => 'z',
|
12
|
+
Bzip => 'j'
|
13
|
+
}
|
14
|
+
|
15
|
+
VALID_URI_SCHEMES = [ 'file', 'http', 'ftp' ]
|
16
|
+
|
17
|
+
def self.url_to_mode(url)
|
18
|
+
ext = File.extname(url)
|
19
|
+
mode = case ext
|
20
|
+
when '.tar'; Plain
|
21
|
+
when '.gz'; Gzip
|
22
|
+
when '.bz2'; Bzip
|
23
|
+
end
|
24
|
+
|
25
|
+
unless ext == '.tar'
|
26
|
+
raise "Invalid file type in #{url}" unless File.basename(url, ext) != '.tar'
|
27
|
+
end
|
28
|
+
mode
|
29
|
+
end
|
30
|
+
|
31
|
+
def update_cache
|
32
|
+
do_update = true
|
33
|
+
|
34
|
+
if File.file?(cachefile)
|
35
|
+
cached_size = File.lstat(cachefile).size
|
36
|
+
cached_mtime = File.lstat(cachefile).mtime
|
37
|
+
|
38
|
+
size, mtime = nil
|
39
|
+
open @url, :content_length_proc => lambda { |size| } do |file|
|
40
|
+
mtime = file.last_modified
|
41
|
+
end
|
42
|
+
|
43
|
+
if mtime && size
|
44
|
+
do_update = (size != cached_size || mtime > cached_mtime)
|
45
|
+
elsif mtime
|
46
|
+
$stderr.puts "WARNING: size is not available for #{@url}, relying on modification time"
|
47
|
+
do_update = (mtime > cached_mtime)
|
48
|
+
elsif size
|
49
|
+
$stderr.puts "WARNING: modification time is not available for #{@url}, relying on size"
|
50
|
+
do_update = (size != cached_size)
|
51
|
+
else
|
52
|
+
$stderr.puts "WARNING: neither size nor modification time available for #{@url}, will always update"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
if do_update
|
57
|
+
puts "downloading #{url}"
|
58
|
+
FileUtils.mkdir_p(cachedir)
|
59
|
+
File.open(cachefile, 'w') do |cache|
|
60
|
+
open @url do |file|
|
61
|
+
while block = file.read(4096)
|
62
|
+
cache.write block
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
true
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def url=(url)
|
71
|
+
@url = URI.parse(url)
|
72
|
+
raise ConfigException, "invalid URL #{url}" unless VALID_URI_SCHEMES.include?(@url.scheme)
|
73
|
+
|
74
|
+
@mode = TarImporter.url_to_mode(url)
|
75
|
+
if @url.scheme == 'file'
|
76
|
+
@cachefile = @url
|
77
|
+
else
|
78
|
+
@cachefile = File.join(cachedir, File.basename(@url.path))
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
attr_reader :url, :cachefile, :mode
|
83
|
+
def cachedir; @options[:cachedir] end
|
84
|
+
|
85
|
+
def initialize(url, options)
|
86
|
+
@options = options.dup
|
87
|
+
@options[:cachedir] ||= $CACHEDIR
|
88
|
+
self.url = url
|
89
|
+
end
|
90
|
+
|
91
|
+
def update(package)
|
92
|
+
checkout if update_cache
|
93
|
+
rescue OpenURI::HTTPError
|
94
|
+
raise Autobuild::Exception.new(package.target, :import)
|
95
|
+
end
|
96
|
+
|
97
|
+
def checkout(package)
|
98
|
+
update_cache
|
99
|
+
|
100
|
+
base_dir = File.dirname(package.srcdir)
|
101
|
+
FileUtils.mkdir_p base_dir
|
102
|
+
cmd = [ 'tar', "x#{TAR_OPTION[mode]}f", cachefile, '-C', base_dir ]
|
103
|
+
|
104
|
+
Subprocess.run(package.target, :import, *cmd)
|
105
|
+
|
106
|
+
rescue OpenURI::HTTPError
|
107
|
+
raise Autobuild::Exception.new(package.target, :import)
|
108
|
+
rescue SubcommandFailed
|
109
|
+
FileUtils.rm_f cachefile
|
110
|
+
raise
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
module Import
|
115
|
+
def self.tar(source, package_options)
|
116
|
+
TarImporter.new(source, package_options)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|