require 'gpgme' # Note: to encrypt the file after a change use the command line: # gpg -a -c -o config/overrides/#{stage}/filename.yml.asc config/overrides/#{stage}/filename.yml

namespace :deploy do

desc "update encrypted files in `stage` overrides, if necessary, and link"
task :copy_secure_overrides do
  on roles(:all) do
    stage = fetch(:stage)
    Dir.glob(deploy_config_path.expand_path.dirname.join('overrides',stage.to_s,'*.asc')).each do |local_encrypted_file|
      filename = File.split(local_encrypted_file).last.chomp('.asc')
      remote_encrypted_file = "#{shared_path}/config/#{filename}.asc"
      remote_plaintext_file = "#{shared_path}/config/#{filename}"
      remote_override_file  = "#{release_path}/config/overrides/#{stage}/#{filename}"
      if chksums_differ?(local_encrypted_file, remote_encrypted_file)
        plaintext = decrypt(local_encrypted_file)
        execute "mkdir -p '#{shared_path}/config'"
        upload! local_encrypted_file, remote_encrypted_file
        upload! StringIO.new(plaintext), remote_plaintext_file
        execute "chmod 600 #{remote_plaintext_file}"
      end
      execute "mkdir -p '#{release_path}/config/overrides/#{stage}'"
      execute "/bin/ln -nsf #{remote_plaintext_file} #{remote_override_file}"
      execute "rm -f #{remote_override_file}.asc"
    end
  end 
end

end

def decrypt(local_encrypted_file)

got_it = false
while not got_it
  begin
    print "\nPlease enter the passphrase to decrypt %s: " % File.split(local_encrypted_file).last
    password = $stdin.noecho(&:gets).chomp
    crypto = GPGME::Crypto.new(:password => password)
    data = crypto.decrypt File.read(local_encrypted_file)
    plaintext = data.read
    got_it = true
  rescue GPGME::Error::DecryptFailed
    puts "\nInvalid Password, decryption failed"
    puts
  end
end
plaintext

end

def chksums_differ?(local,remote)

local_hasher   = system('which','sha1sum') ? 'sha1sum' : 'shasum'
local_chksum   = `#{local_hasher} "#{local}"`.split(' ').first
remote_chksum  = capture("[ -f #{remote} ] && sha1sum #{remote} || true").split(' ').first || 'file_not_found'
local_chksum != remote_chksum

end