#!/usr/bin/env ruby EXPUNGE_ENV_KEYS = [ 'TMPDIR', 'DOCKER_HOST', 'LOGNAME', 'LANG', 'PWD', 'OLDPWD', 'PS1', 'SHELL', 'USER', '_' ] require 'optparse' require 'pathname' options = {} options[:toolchain_image] = 'bexio/toolchain:latest' toolchain_docker_args = [] toolchain_subcommand_args = ARGV[0..-1] ARGV.clear if subcommand_delim_pos = toolchain_subcommand_args.index('--') toolchain_own_args, toolchain_subcommand_args = toolchain_subcommand_args.partition.each_with_index{ |x, i| i <= subcommand_delim_pos } ARGV.concat(toolchain_own_args[0..-2]) end OptionParser.new do |opts| opts.on("-i", "--image", "Run within the specified toolchain image") do |image_name| options[:toolchain_image] = image_name end opts.on("-b", "--[no-]bind-net", "Run the command in the host's network namespace") do |v| options[:bind_net] = v end end.parse! toolchain_image = (options[:toolchain_image].split(':') + ['latest'])[0, 2].join(':') toolchain_available = system 'docker', 'inspect', '-f', '{{.Id}}', toolchain_image, out: '/dev/null', err: '/dev/null' unless toolchain_available or system('docker', 'pull', toolchain_image) $stderr.puts "could not locate toolchain image '#{toolchain_image}'; aborting" Kernel.exit 1 end # mount options host_cwd = Pathname.pwd host_repo_root = `git rev-parse --show-toplevel 2>/dev/null`.chomp host_repo_root = nil if host_repo_root.empty? if host_repo_root host_repo_root = Pathname.new(host_repo_root) rel_cwd = host_cwd.relative_path_from(host_repo_root) guest_repo_root = Pathname.new('/src') guest_cwd = guest_repo_root + rel_cwd toolchain_docker_args.concat([ '-v', "#{host_repo_root}:#{guest_repo_root}", '-w', '/build' ]) data_container_name = host_repo_root.basename.to_s + "-build" toolchain_docker_args.concat([ "--volumes-from=#{data_container_name}" ]) end # interactivity options if $stdin.tty? and $stdout.tty? toolchain_docker_args.concat(['-i', '-t']) end # environment options exposed_env_keys = ENV.keys - EXPUNGE_ENV_KEYS container_env_keys = `docker inspect -f '{{.Config.Env}}' #{toolchain_image}`.chomp[1..-2].split(' ').map{ |pair| pair.split('=').first } toolchain_docker_args.concat((exposed_env_keys - container_env_keys).map{ |k| ['-e', k] }.flatten) toolchain_docker_args.concat([ '-v', "#{ENV['HOME']}/.ssh:/root/.ssh" ]) # network options if options[:bind_net] toolchain_docker_args.push '--net=host' end docker_bin_path = `which docker`.chomp toolchain = lambda do |*subcommand| Kernel.system docker_bin_path, 'run', '--rm', *toolchain_docker_args, toolchain_image, *subcommand end if data_container_name data_container_image = 'tianon/true:latest' data_container_image_available = system docker_bin_path, 'inspect', '-f', '{{.Id}}', data_container_image, out: '/dev/null', err: '/dev/null' unless data_container_image_available or system(docker_bin_path, 'pull', data_container_image) $stderr.puts "could not locate data-container image '#{data_container_image}'; aborting" Kernel.exit 1 end data_container_exists = system docker_bin_path, 'inspect', '-f', '{{.Id}}', data_container_name, out: '/dev/null', err: '/dev/null' #toolchain.call 'find', '/build', '-mindepth', '1', '-maxdepth', '1', '-type', 'l', '-exec', 'rm', '{}', ';' unless data_container_exists Kernel.system( docker_bin_path, 'run', "--name=#{data_container_name}", '-v', '/build', data_container_image ) toolchain.call 'find', '/src', '-mindepth', '1', '-maxdepth', '1', '-exec', 'ln', '-sF', '{}', ';' end end toolchain.call *toolchain_subcommand_args