您最多选择25个主题
主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
160 行
4.0 KiB
160 行
4.0 KiB
#!/usr/bin/ruby |
|
|
|
require 'optparse' |
|
require 'yaml' |
|
require 'fileutils' |
|
require 'pathname' |
|
|
|
@options = {} |
|
|
|
def system!(cmd) |
|
system(cmd) or raise "failed to run #{cmd}" |
|
end |
|
|
|
def sanitize(str, where) |
|
raise "unsanitary string in #{where}" if (str =~ /[^\w.-]/) |
|
str |
|
end |
|
|
|
def info(str) |
|
puts str unless @options[:quiet] |
|
end |
|
|
|
OptionParser.new do |opts| |
|
opts.banner = "Usage: build [options] <build-description>.yml" |
|
|
|
opts.on("-i", "--skip-image", "reuse current target image") do |v| |
|
@options[:skip_image] = v |
|
end |
|
opts.on("-q", "--quiet", "be quiet") do |v| |
|
@options[:skip_image] = v |
|
end |
|
end.parse! |
|
|
|
base_dir = Pathname.new(__FILE__).expand_path.dirname.parent |
|
libexec_dir = base_dir + 'libexec' |
|
|
|
ENV['PATH'] = libexec_dir.to_s + ":" + ENV['PATH'] |
|
ENV['GITIAN_BASE'] = base_dir.to_s |
|
|
|
build_desc_file = ARGV.shift or raise "must supply YAML build description file" |
|
|
|
in_sums = [] |
|
|
|
build_desc = YAML.load_file(build_desc_file) |
|
|
|
package_name = build_desc["name"] or raise "must supply name" |
|
package_name = sanitize(package_name, "package name") |
|
|
|
desc_sum = `sha256sum #{build_desc_file}` |
|
desc_sum = desc_sum.sub(build_desc_file, "#{package_name}-desc.yml") |
|
in_sums << desc_sum |
|
|
|
reference_datetime = build_desc["reference_datetime"] or raise "must supply reference_datetime" |
|
|
|
build_dir = 'build' |
|
result_dir = 'result' |
|
|
|
FileUtils.rm_rf(build_dir) |
|
FileUtils.mkdir(build_dir) |
|
FileUtils.mkdir_p(result_dir) |
|
|
|
info "Stopping target if it is up" |
|
system "stop-target" |
|
|
|
sleep 1 |
|
|
|
unless @options[:skip_image] |
|
info "Making a new image copy" |
|
system! "cp base.qcow2 target.qcow2" |
|
end |
|
|
|
info "Starting target" |
|
system! "start-target &" |
|
|
|
$stdout.write "Checking if target is up" |
|
|
|
(1..10).each do |
|
system "on-target true 2> /dev/null" and break |
|
sleep 2 |
|
$stdout.write '.' |
|
end |
|
|
|
info '' |
|
|
|
system! "on-target true" |
|
|
|
info "Preparing build environment" |
|
system! "on-target bash < target-bin/init-build.sh" |
|
|
|
build_desc["files"].each do |filename| |
|
filename = sanitize(filename, "files section") |
|
system! "cd inputs && copy-to-target #{filename} build/" |
|
in_sums << `cd inputs && sha256sum #{filename}` |
|
end |
|
|
|
info "Installing additional packages (log in var/install.log)" |
|
system! "on-target -u root apt-get -y install #{build_desc["packages"].join(" ")} > var/install.log 2>&1" |
|
|
|
info "Grabbing package manifest" |
|
system! "on-target -u root bash < target-bin/grab-packages.sh > var/base.manifest" |
|
|
|
info "Creating build script (var/build-script)" |
|
|
|
File.open("var/build-script", "w") do |script| |
|
script.puts "#!/bin/bash" |
|
script.puts "set -e" |
|
script.puts "export OUTDIR=$HOME/out" |
|
script.puts "MAKEOPTS=(-j2)" |
|
(ref_date, ref_time) = reference_datetime.split |
|
script.puts "REFERENCE_DATETIME='#{reference_datetime}'" |
|
script.puts "REFERENCE_DATE='#{ref_date}'" |
|
script.puts "REFERENCE_TIME='#{ref_time}'" |
|
script.puts |
|
build_desc["remotes"].each do |remote| |
|
script.puts "git clone -q #{remote["url"]} build/#{remote["dir"]}" |
|
script.puts "(cd build/#{remote["dir"]} && git checkout -q #{remote["commit"]})" |
|
end |
|
script.puts "cd build" |
|
script.puts build_desc["script"] |
|
end |
|
|
|
info "Running build script (log in var/build.log)" |
|
system! "on-target bash < var/build-script > var/build.log 2>&1" |
|
|
|
info "Grabbing results" |
|
system! "copy-from-target out #{build_dir}" |
|
|
|
out_dir = File.join(build_dir, "out") |
|
out_sums = {} |
|
|
|
info "Generating report" |
|
Dir.new(out_dir).each do |file| |
|
next if file.start_with?(".") |
|
file = sanitize(file, out_dir) |
|
out_sums[file] = `cd #{out_dir} && sha256sum #{file}` |
|
raise "failed to sum #{file}" unless $? == 0 |
|
puts out_sums[file] unless @options[:quiet] |
|
end |
|
|
|
out_manifest = out_sums.keys.sort.map { |key| out_sums[key] }.join('') |
|
|
|
base_manifest = File.read('var/base.manifest') |
|
|
|
in_manifest = in_sums.join('') |
|
|
|
# Use Omap to keep result deterministic |
|
report = YAML::Omap[ |
|
'out_manifest', out_manifest, |
|
'in_manifest', in_manifest, |
|
'base_manifest', base_manifest, |
|
] |
|
|
|
result_file = "#{package_name}-res.yml" |
|
File.open(File.join(result_dir, result_file), "w") do |io| |
|
io.write report.to_yaml |
|
end |
|
|
|
system!("cd #{result_dir} && sha256sum #{result_file}") unless @options[:quiet] |
|
|
|
info "Done."
|
|
|