autobuild 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 = File.expand_path(autobuild[:srcdir], Dir.pwd)
85
- $PREFIX = File.expand_path(autobuild[:prefix], Dir.pwd)
86
- $LOGDIR = File.expand_path(autobuild[:logdir] || "autobuild", $PREFIX)
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
- $MAIL = autobuild[:mail]
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
- def pathvar(path, varname)
2
- if File.directory?(path)
3
- oldpath = ENV[varname]
4
- if oldpath.empty?
5
- ENV[varname] = path
6
- else
7
- ENV[varname] = "#{path}:#{oldpath}"
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
- pathvar("#{newprefix}/bin", 'PATH')
14
- pathvar("#{newprefix}/lib/pkgconfig", 'PKG_CONFIG_PATH')
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
 
@@ -1,51 +1,52 @@
1
- class SubcommandFailed < Exception
2
- def mail?; false end
3
- def fatal?; true end
4
-
5
- attr_reader :target, :command, :logfile, :status
6
- def initialize(target, command, logfile, status)
7
- @target = target
8
- @command = command
9
- @logfile = logfile
10
- @status = status
11
- end
12
- end
13
-
14
- class ConfigException < Exception
15
- def mail?; false end
16
- def fatal?; true end
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
- attr_accessor :target
22
- end
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
- def initialize(subcommand)
48
- super(subcommand.target, subcommand.command, subcommand.logfile, subcommand.status)
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
 
@@ -1,51 +1,46 @@
1
1
  require 'autobuild/subcommand'
2
2
  require 'autobuild/importer'
3
3
 
4
- class CVSImporter < Importer
5
- def initialize(root, name, options)
6
- @root = root
7
- @module = name
4
+ module Autobuild
5
+ class CVSImporter < Importer
6
+ def initialize(root, name, options)
7
+ @root = root
8
+ @module = name
8
9
 
9
- @program = ($PROGRAMS[:cvs] || 'cvs')
10
- @up = (options[:cvsup] || '-dP')
11
- @co = (options[:cvsco] || '-P')
12
- super(options)
13
- end
14
-
15
- def modulename
16
- @module
17
- end
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
- private
20
+ private
20
21
 
21
- def update(package)
22
- Dir.chdir(package.srcdir) {
23
- begin
24
- subcommand(package.target, 'cvs', @program, 'up' , @up)
25
- rescue SubcommandFailed => e
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
- def checkout(package)
32
- head, tail = File.split(package.srcdir)
33
- cvsroot = @root
34
-
35
- FileUtils.mkdir_p(head) if !File.directory?(head)
36
- Dir.chdir(head) {
37
- begin
38
- subcommand(package.target, 'cvs', @program, '-d', cvsroot, 'co', @co, '-d', tail, modulename)
39
- rescue SubcommandFailed => e
40
- raise ImportException.new(e), "failed to check out #{modulename}"
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
- def self.cvs(source, package_options)
48
- CVSImporter.new(source[0], source[1], package_options)
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
 
@@ -1,41 +1,35 @@
1
- require 'autobuild/subcommand'
1
+ require 'autobuild/subcommand'
2
2
  require 'autobuild/importer'
3
3
 
4
- class SVNImporter < Importer
5
- def initialize(source, options)
6
- @source = source.to_a.join("/")
4
+ module Autobuild
5
+ class SVNImporter < Importer
6
+ def initialize(source, options)
7
+ @source = source.to_a.join("/")
7
8
 
8
- @program = ($PROGRAMS[:svn] || 'svn')
9
- @up = options[:svnup] || ""
10
- @co = options[:svnco] || ""
11
-
12
- super(options)
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
- private
15
+ private
16
16
 
17
- def update(package)
18
- Dir.chdir(package.srcdir) {
19
- begin
20
- subcommand(package.target, 'svn', @program, 'up', @up)
21
- rescue SubcommandFailed => e
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
- def checkout(package)
28
- begin
29
- subcommand(package.target, 'svn', @program, 'co', @co, @source, package.srcdir)
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
- def self.svn(source, options)
38
- SVNImporter.new(source, options)
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
+