#!/usr/bin/ruby

EXPUNGE_ENV_KEYS = [
  'TMPDIR',
  'DOCKER_HOST',
  'LOGNAME',
  'LANG',
  'PWD',
  'OLDPWD',
  'PS1',
  'SHELL',
  'SHLVL',
  '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", "--image=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', guest_repo_root.to_s
  ])
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', '/run:/run/host',
  '-v', "#{ENV['HOME']}/.dockercfg:/root/.dockercfg",

  '-v', "#{ENV['HOME']}/.ssh:/root/.ssh",
  '-v', "#{ENV['HOME']}/.gnupg:/root/.gnupg",
])

# network options
if options[:bind_net]
  toolchain_docker_args.push '--net=host'
end



docker_bin_path = `which docker`.chomp
toolchain = lambda do |*subcommand|
  Kernel.exec docker_bin_path, 'run', '--rm',
    *toolchain_docker_args,
    toolchain_image,
    *subcommand
end

toolchain.call *toolchain_subcommand_args
