autobuild 0.4 → 0.5

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.
@@ -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
+