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.
@@ -1,20 +1,22 @@
1
1
  require 'autobuild/timestamps'
2
2
  require 'autobuild/package'
3
3
 
4
- class ImporterPackage < Package
5
- def installstamp
6
- "#{srcdir}/#{STAMPFILE}"
7
- end
8
- def initialize(target, options)
9
- super(target, options)
10
- source_tree srcdir, installstamp
11
- file installstamp => srcdir do
12
- touch_stamp installstamp
4
+ module Autobuild
5
+ class ImporterPackage < Package
6
+ def installstamp
7
+ "#{srcdir}/#{STAMPFILE}"
13
8
  end
14
- end
15
- def prepare; end
9
+ def initialize(target, options)
10
+ super(target, options)
11
+ source_tree srcdir, installstamp
12
+ file installstamp => srcdir do
13
+ touch_stamp installstamp
14
+ end
15
+ end
16
+ def prepare; end
16
17
 
17
- factory :import, ImporterPackage
18
+ factory :import, ImporterPackage
19
+ end
18
20
  end
19
21
 
20
22
 
@@ -2,77 +2,113 @@ require 'rmail'
2
2
  require 'rmail/serialize'
3
3
  require 'net/smtp'
4
4
  require 'socket'
5
+ require 'etc'
5
6
 
6
- module Reporting
7
- def self.report
8
- begin
9
- yield
10
- rescue Exception => e
11
- raise unless e.respond_to?(:target)
12
- error(e)
13
- exit(1) if e.fatal?
7
+ require 'autobuild/exceptions'
8
+
9
+ module Autobuild
10
+ class Reporting
11
+ @@reporters = Array.new
12
+
13
+ def self.report
14
+ begin
15
+ yield
16
+ rescue Autobuild::Exception => e
17
+ raise unless e.kind_of?(Autobuild::Exception)
18
+ error(e)
19
+ exit(1) if e.fatal?
20
+ end
21
+ end
22
+
23
+ def self.success
24
+ @@reporters.each do |rep| rep.success end
25
+ end
26
+
27
+ def self.error(error)
28
+ @@reporters.each do |rep| rep.error(error) end
14
29
  end
15
- end
16
-
17
- def self.success
18
- message = "Build finished successfully at #{Time.now}"
19
- puts message
20
- send_mail("Build success", message) if $MAIL
21
- end
22
30
 
23
- def self.error(object)
24
- if object.kind_of?(SubcommandFailed)
25
- body = <<EOF
26
- #{object.target}: #{object.message}
27
- command '#{object.command}' failed with status #{object.status}
28
- see #{File.basename(object.logfile)} for details
29
- EOF
30
-
31
- message = <<EOF
32
- #{object.target}: #{object.message}
33
- command '#{object.command}' failed with status #{object.status}
34
- see #{object.logfile} for details
35
- EOF
36
- else
37
- body = message = "#{object.target}: #{object.message}"
31
+ def self.<<(reporter)
32
+ @@reporters << reporter
38
33
  end
39
34
 
40
- puts message
41
- send_mail("Build failed", body) if $MAIL && object.mail?
35
+ def self.each_log(&iter)
36
+ Dir.glob("#{$LOGDIR}/*.log", &iter)
37
+ end
42
38
  end
43
39
 
44
- private
40
+ class Reporter
41
+ def error(error); end
42
+ def success; end
43
+ end
45
44
 
46
- def self.send_mail(subject, body)
47
- from = ($MAIL[:from] || "autobuild@#{Socket.gethostname}")
48
- to = $MAIL[:to]
49
- smtp = ($MAIL[:smtp] || "localhost" )
45
+ class StdoutReporter < Reporter
46
+ def error(error)
47
+ puts "Build failed: #{error}"
48
+ end
49
+ def success
50
+ puts "Build finished successfully at #{Time.now}"
51
+ end
52
+ end
50
53
 
51
- mail = RMail::Message.new
52
- mail.header.date = Time.now
53
- mail.header.from = from
54
- mail.header.to = to
55
- mail.header.subject = subject
54
+ class MailReporter < Reporter
55
+ def default_mail
56
+ Etc::endpwent
57
+ uname = while (pwent = Etc::getpwent)
58
+ break (pwent.name) if pwent.uid == Process.uid
59
+ end
56
60
 
57
- part = RMail::Message.new
58
- part.header.set('Content-Type', 'text/plain')
59
- part.body = body
60
- mail.add_part(part)
61
+ raise "FATAL: cannot find a user with uid=#{Process.uid}" unless uname
62
+ "#{pwent.name}@#{Socket.gethostname}"
63
+ end
64
+
65
+ def initialize(config)
66
+ @from = (config[:from] || default_mail)
67
+ @to = (config[:to] || default_mail)
68
+ @smtp = (config[:smtp] || "localhost" )
69
+ @port = Integer(config[:port] || Socket.getservbyname('smtp'))
70
+ end
71
+
72
+ def error(error)
73
+ if error.mail?
74
+ send_mail("Build failed", error.to_s)
75
+ end
76
+ end
61
77
 
62
- # Attach log files
63
- Dir.glob("#{$LOGDIR}/*.log") do |file|
64
- mail.add_file(file)
78
+ def success
79
+ send_mail("Build success", "finished successfully at #{Time.now}")
65
80
  end
66
81
 
67
- # Send the mail
68
- smtp = Net::SMTP.new(smtp, Integer($MAIL[:port] || 25))
69
- smtp.start {
70
- smtp.send_mail RMail::Serialize.write('', mail), from, to
71
- }
82
+ def send_mail(subject, body)
83
+ mail = RMail::Message.new
84
+ mail.header.date = Time.now
85
+ mail.header.from = @from
86
+ mail.header.to = @to
87
+ mail.header.subject = subject
88
+
89
+ part = RMail::Message.new
90
+ part.header.set('Content-Type', 'text/plain')
91
+ part.body = body
92
+ mail.add_part(part)
93
+
94
+ # Attach log files
95
+ Reporting.each_log do |file|
96
+ mail.add_file(file)
97
+ end
98
+
99
+ # Send the mail
100
+ smtp = Net::SMTP.new(@smtp, @port)
101
+ smtp.start {
102
+ smtp.send_mail RMail::Serialize.write('', mail), @from, @to
103
+ }
104
+
105
+ # Notify the sending
106
+ puts "Sent notification mail to #{@to} with source #{@from}"
107
+
108
+ end
72
109
  end
73
110
  end
74
111
 
75
-
76
112
  module RMail
77
113
  class Message
78
114
  def add_file(path, content_type='text/plain')
@@ -1,58 +1,101 @@
1
1
  require 'autobuild/reporting'
2
2
 
3
- def subcommand(target, type, *command)
4
- # Filter nil and empty? in command
5
- command.reject! { |o| o.nil? || (o.respond_to?(:empty?) && o.empty?) }
6
- command.collect! { |o| o.to_s }
7
- logname = "#{$LOGDIR}/#{target}-#{type}.log"
8
- puts "#{target}: running #{command.join(" ")}\n (output goes to #{logname})"
9
-
10
- input_streams = command.collect { |o| $1 if o =~ /^\<(.+)/ }.compact
11
- command.reject! { |o| o =~ /^\<(.+)/ }
12
-
13
- status = File.open(logname, "a") do |logfile|
14
- pread, pwrite = IO.pipe
15
-
16
- pid = fork {
17
- Process.setpriority(Process::PRIO_PROCESS, 0, $NICE) if $NICE
18
- if $VERBOSE
19
- $stderr.dup.reopen(logfile.dup)
20
- $stdout.dup.reopen(logfile.dup)
21
- else
22
- $stderr.reopen(logfile.dup)
23
- $stdout.reopen(logfile.dup)
24
- end
3
+ module Autobuild::Subprocess
4
+ @@nice = 0
5
+ def self.nice=(value)
6
+ @@nice = value
7
+ end
25
8
 
26
- if !input_streams.empty?
27
- pwrite.close
28
- $stdin.reopen(pread)
29
- end
30
-
31
- if !exec(*command)
32
- raise SubcommandFailed.new(target, command.join(" "), logname, 0), "error running command"
9
+ class Failed < Exception
10
+ attr_reader :status
11
+ def initialize(status = 0)
12
+ @status = status
13
+ end
14
+ end
15
+
16
+ CONTROL_COMMAND_NOT_FOUND = 1
17
+ CONTROL_UNEXPECTED = 2
18
+ def self.run(target, phase, *command)
19
+ # Filter nil and empty? in command
20
+ command.reject! { |o| o.nil? || (o.respond_to?(:empty?) && o.empty?) }
21
+ command.collect! { |o| o.to_s }
22
+ logname = "#{$LOGDIR}/#{target}-#{phase}.log"
23
+
24
+ puts "#{target}: running #{command.join(" ")}\n (output goes to #{logname})"
25
+
26
+ input_streams = command.collect { |o| $1 if o =~ /^\<(.+)/ }.compact
27
+ command.reject! { |o| o =~ /^\<(.+)/ }
28
+
29
+ status = File.open(logname, "a") do |logfile|
30
+ pread, pwrite = IO.pipe # to feed subprocess stdin
31
+ cread, cwrite = IO.pipe # to control that exec goes well
32
+
33
+ pid = fork {
34
+ cwrite.sync = true
35
+ begin
36
+ Process.setpriority(Process::PRIO_PROCESS, 0, @@nice)
37
+ if $VERBOSE
38
+ $stderr.dup.reopen(logfile.dup)
39
+ $stdout.dup.reopen(logfile.dup)
40
+ else
41
+ $stderr.reopen(logfile.dup)
42
+ $stdout.reopen(logfile.dup)
43
+ end
44
+
45
+ if !input_streams.empty?
46
+ pwrite.close
47
+ $stdin.reopen(pread)
48
+ end
49
+
50
+ exec(*command)
51
+ rescue Errno::ENOENT
52
+ cwrite.write([CONTROL_COMMAND_NOT_FOUND].pack('I'))
53
+ raise
54
+ rescue Exception
55
+ cwrite.write([CONTROL_UNEXPECTED].pack('I'))
56
+ raise
57
+ end
58
+ }
59
+
60
+ # Feed the input
61
+ pread.close
62
+ begin
63
+ input_streams.each do |infile|
64
+ File.open(infile) do |instream|
65
+ instream.each_line { |line| pwrite.write(line) }
66
+ end
67
+ end
68
+ rescue Errno::ENOENT => e
69
+ raise Failed.new, "cannot open input files: #{e.message}"
33
70
  end
34
- }
35
-
36
- # Feed the input
37
- pread.close
38
- begin
39
- input_streams.each do |infile|
40
- File.open(infile) do |instream|
41
- instream.each_line { |line| pwrite.write(line) }
71
+ pwrite.close
72
+
73
+ # Get control status
74
+ cwrite.close
75
+ value = cread.read(4)
76
+ if value
77
+ # An error occured
78
+ value = value.unpack('I').first
79
+ if value == CONTROL_COMMAND_NOT_FOUND
80
+ raise Failed.new, "file not found"
81
+ else
82
+ raise Failed.new, "something unexpected happened"
42
83
  end
43
84
  end
44
- rescue Errno::ENOENT => e
45
- logfile.puts "Cannot open input files: #{e.message}"
46
- raise SubcommandFailed.new(target, command.join(" "), logname, 0), e.message
85
+
86
+ childpid, childstatus = Process.wait2(pid)
87
+ childstatus
47
88
  end
48
- pwrite.close
49
89
 
50
- childpid, childstatus = Process.wait2(pid)
51
- childstatus
52
- end
90
+ if status.exitstatus > 0
91
+ raise Failed.new(status.exitstatus), "command returned with status #{status.exitstatus}"
92
+ end
53
93
 
54
- if status.exitstatus > 0
55
- raise SubcommandFailed.new(target, command.join(" "), logname, status.exitstatus)
94
+ rescue Failed => e
95
+ error = SubcommandFailed.new(target, command.join(" "), logname, e.status)
96
+ error.phase = phase
97
+ raise error, e.message
56
98
  end
99
+
57
100
  end
58
101
 
@@ -4,47 +4,57 @@ require 'fileutils'
4
4
 
5
5
  STAMPFILE = "autobuild-stamp"
6
6
 
7
- def tree_timestamp(path, *exclude)
8
- latest = Time.at(0)
9
- latest_file = ""
10
- dot = "."[0]
11
-
12
- exclude.collect! { |e| File.expand_path(e, path) }
13
- Find.find(path) { |p|
14
- Find.prune if File.basename(p)[0] == dot
15
- exclude.each { |pattern|
16
- Find.prune if File.fnmatch?(pattern, p)
7
+ module Autobuild
8
+ def tree_timestamp(path, *exclude)
9
+ # Exclude autobuild timestamps
10
+ exclude << "*-#{STAMPFILE}"
11
+
12
+ puts "getting tree timestamp for #{path}" if $DEBUG
13
+ latest = Time.at(0)
14
+ latest_file = ""
15
+
16
+ exclude.collect! { |e| File.expand_path(e, path) }
17
+ Find.find(path) { |p|
18
+ Find.prune if File.basename(p) =~ /^\./
19
+ exclude.each { |pattern|
20
+ if File.fnmatch?(pattern, p)
21
+ puts " excluding #{p}" if $DEBUG
22
+ Find.prune
23
+ end
24
+ }
25
+ next if File.directory?(p)
26
+
27
+ p_time = File.mtime(p)
28
+ if latest < p_time
29
+ latest = p_time
30
+ latest_file = p
31
+ end
17
32
  }
18
- next if File.directory?(p)
19
33
 
20
- p_time = File.mtime(p)
21
- if latest < p_time
22
- latest = p_time
23
- latest_file = p
24
- end
25
- }
26
-
27
- return latest
28
- end
34
+ puts " #{latest}" if $DEBUG
35
+ return latest
36
+ end
29
37
 
30
- class SourceTreeTask < Rake::Task
31
- attr_accessor :exclude
32
- def timestamp
33
- tree_timestamp(name, "*CVS", *@exclude)
38
+ class SourceTreeTask < Rake::Task
39
+ attr_accessor :exclude
40
+ def timestamp
41
+ tree_timestamp(name, "*CVS", *@exclude)
42
+ end
43
+ end
44
+ def source_tree(path, exclude, &block)
45
+ task = SourceTreeTask.define_task(path, &block)
46
+ task.exclude = exclude
47
+ end
48
+
49
+ def get_stamp(stampfile)
50
+ return Time.at(0) if !File.exists?(stampfile)
51
+ return File.mtime(stampfile)
34
52
  end
35
- end
36
- def source_tree(path, exclude, &block)
37
- task = SourceTreeTask.define_task(path, &block)
38
- task.exclude = exclude
39
- end
40
-
41
- def get_stamp(stampfile)
42
- return Time.at(0) if !File.exists?(stampfile)
43
- return File.mtime(stampfile)
44
- end
45
53
 
46
- def touch_stamp(stampfile)
47
- puts "Touching #{stampfile}" if $trace
48
- FileUtils.touch(stampfile)
54
+ def touch_stamp(stampfile)
55
+ puts "Touching #{stampfile}" if $DEBUG
56
+ FileUtils.touch(stampfile)
57
+ sleep(1)
58
+ end
49
59
  end
50
60
 
metadata CHANGED
@@ -3,100 +3,65 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: autobuild
5
5
  version: !ruby/object:Gem::Version
6
- version: "0.4"
7
- date: 2005-09-27 00:00:00 +02:00
6
+ version: "0.5"
7
+ date: 2005-12-09 00:00:00 +01:00
8
8
  summary: Rake-based utility to build and install multiple packages with dependencies
9
9
  require_paths:
10
- - lib
11
- - lib
10
+ - lib
12
11
  email: sylvain.joyeux@m4x.org
13
- homepage:
14
- rubyforge_project:
15
- description: "autobuild imports, configures, builds and installs software packages (mainly
16
- C/C++ autotools packages for now) with dependencies. It can be used in
17
- community-based software development to make sure that nothing is broken in the
18
- build process of a set of packages."
12
+ homepage: http://autobuild.rubyforge.org
13
+ rubyforge_project: autobuild
14
+ description: Autobuild imports, configures, builds and installs various kinds of software packages. It can be used in software development to make sure that nothing is broken in the build process of a set of packages, or can be used as an automated installation tool.
19
15
  autorequire:
20
16
  default_executable:
21
17
  bindir: bin
22
18
  has_rdoc: true
23
19
  required_ruby_version: !ruby/object:Gem::Version::Requirement
24
20
  requirements:
25
- -
26
- - ">"
27
- - !ruby/object:Gem::Version
28
- version: 0.0.0
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
29
24
  version:
30
25
  platform: ruby
31
26
  signing_key:
32
27
  cert_chain:
33
28
  authors:
34
- - Sylvain Joyeux
29
+ - Sylvain Joyeux
35
30
  files:
36
- - lib/autobuild/config.rb
37
- - lib/autobuild/environment.rb
38
- - lib/autobuild/importer.rb
39
- - lib/autobuild/reporting.rb
40
- - lib/autobuild/package.rb
41
- - lib/autobuild/subcommand.rb
42
- - lib/autobuild/timestamps.rb
43
- - lib/autobuild/exceptions.rb
44
- - lib/autobuild/options.rb
45
- - lib/autobuild/config-interpolator.rb
46
- - lib/autobuild/import/cvs.rb
47
- - lib/autobuild/import/svn.rb
48
- - lib/autobuild/packages/autotools.rb
49
- - lib/autobuild/packages/genom.rb
50
- - lib/autobuild/packages/import.rb
51
- - bin/autobuild
52
- - README
53
- test_files:
54
- - test/tc_subcommand.rb
55
- - test/tc_config_interpolation.rb
56
- - test/tc_config.rb
57
- - test/tc_import.rb
58
- - test/base.rb
59
- - test/data
60
- - test/tools.rb
31
+ - README
32
+ - Rakefile
33
+ - CHANGES
34
+ - lib/autobuild/importer.rb
35
+ - lib/autobuild/config-interpolator.rb
36
+ - lib/autobuild/subcommand.rb
37
+ - lib/autobuild/options.rb
38
+ - lib/autobuild/environment.rb
39
+ - lib/autobuild/package.rb
40
+ - lib/autobuild/reporting.rb
41
+ - lib/autobuild/timestamps.rb
42
+ - lib/autobuild/exceptions.rb
43
+ - lib/autobuild/config.rb
44
+ - lib/autobuild/import/svn.rb
45
+ - lib/autobuild/import/cvs.rb
46
+ - lib/autobuild/import/tar.rb
47
+ - lib/autobuild/packages/import.rb
48
+ - lib/autobuild/packages/autotools.rb
49
+ - lib/autobuild/packages/genom.rb
50
+ test_files: []
51
+
61
52
  rdoc_options:
62
- - "--title"
63
- - Autobuild
64
- - "--main"
65
- - README
53
+ - --title
54
+ - Autobuild
55
+ - --main
56
+ - README
66
57
  extra_rdoc_files:
67
- - README
68
- executables:
69
- - autobuild
58
+ - README
59
+ - CHANGES
60
+ executables: []
61
+
70
62
  extensions: []
63
+
71
64
  requirements: []
72
- dependencies:
73
- - !ruby/object:Gem::Dependency
74
- name: rake
75
- version_requirement:
76
- version_requirements: !ruby/object:Gem::Version::Requirement
77
- requirements:
78
- -
79
- - ">="
80
- - !ruby/object:Gem::Version
81
- version: 0.6.0
82
- version:
83
- - !ruby/object:Gem::Dependency
84
- name: rmail
85
- version_requirement:
86
- version_requirements: !ruby/object:Gem::Version::Requirement
87
- requirements:
88
- -
89
- - ">"
90
- - !ruby/object:Gem::Version
91
- version: 0.0.0
92
- version:
93
- - !ruby/object:Gem::Dependency
94
- name: daemons
95
- version_requirement:
96
- version_requirements: !ruby/object:Gem::Version::Requirement
97
- requirements:
98
- -
99
- - ">"
100
- - !ruby/object:Gem::Version
101
- version: 0.0.0
102
- version:
65
+
66
+ dependencies: []
67
+