#!/usr/bin/ruby
##############################################################################
# Etch configuration file management tool
##############################################################################

# Ensure we can find etch/client.rb when run within the development repository
$:.unshift(File.join(File.dirname(File.dirname(__FILE__)), 'lib'))

require 'optparse'
require 'etch/client'

#
# Parse the command line options
#

options = {}
@generateall = nil

# Extra options to OptionParser reduce the amount of whitespace it introduces
# into the help message, making it easier to make the help message fit in a
# 80x24 window.
opts = OptionParser.new(nil, 24, '  ')
opts.banner = 'Usage: etch [options] [/path/to/config/file | command] [otherfile ...]'
opts.on('--generate-all', 'Request all configuration.') do |opt|
  @generateall = opt
end
opts.on('--dry-run', '-n', 'Make no changes.') do |opt|
  options[:dryrun] = opt
end
opts.on('--damp-run', "Perform a dry run but run 'setup' entries for files.") do |opt|
  # Rather than sprinkle checks of two different variables throught the code, if
  # we're asked to do a damp run then just set the dry run flag to a unique
  # value.  Then we can just check for that specific value at the one place where
  # the two modes differ:  enabling or disabling the execution of 'setup'
  # entries.
  options[:dryrun] = 'damp'
end
opts.on('--list-files', 'Just list the files that would be configured') do |opt|
  options[:listfiles] = opt
  # generate all is implied
  @generateall = true
  # Set :dryrun as a extra measure to make sure we don't change anything
  options[:dryrun] = 'listfiles'
end
opts.on('--interactive', 'Prompt for confirmation before each change.') do |opt|
  options[:interactive] = opt
end
opts.on('--full-file', 'Display full new file contents instead of a diff.') do |opt|
  options[:fullfile] = opt
end
opts.on('--filename-only', 'Display filename of changed files instead of a diff.') do |opt|
  options[:filenameonly] = opt
end
opts.on('--disable-force', 'Ignore the disable_etch file.  Use with caution.') do |opt|
  options[:disableforce] = opt
end
opts.on('--lock-force', 'Force the removal of any existing lockfiles.') do |opt|
  options[:lockforce] = opt
end
opts.on('--local DIR', 'Read configuration from local directory, not server.') do |opt|
  options[:local] = opt
end
opts.on('--server SERVER', 'Point etch to an alternate server.') do |opt|
  options[:server] = opt
end
opts.on('--tag TAG', 'Request a specific repository tag from the server.') do |opt|
  options[:tag] = opt
end
opts.on('--key PRIVATE_KEY', 'Use this private key for signing messages to server.') do |opt|
  options[:key] = opt
end
opts.on('--configdir DIR', 'Directory containing etch.conf, defaults to /etc') do |opt|
  options[:configdir] = opt
end
opts.on('--vardir DIR', 'Directory for etch state, defaults to /var/etch') do |opt|
  options[:vardir] = opt
end
opts.on('--test-root TESTDIR', 'For use by the test suite only.') do |opt|
  options[:file_system_root] = opt
end
opts.on('--debug', 'Print lots of messages about what etch is doing.') do |opt|
  options[:debug] = opt
end
opts.on('--version', 'Show etch client version.') do |opt|
  puts Etch::Client::VERSION
  exit
end
opts.on_tail('-h', '--help', 'Show this message.') do
  puts opts
  exit
end

leftovers = opts.parse(ARGV)
files = []
commands = []
leftovers.each do |leftover|
  if leftover[0,1] == File::SEPARATOR
    files << leftover
  else
    commands << leftover
  end
end

# Display a usage message if the user did not specify a valid action to perform.
if files.empty? && commands.empty? && !@generateall
  puts opts
  exit
end

#
# Do stuff
#

etchclient = Etch::Client.new(options)
status = etchclient.process_until_done(files, commands)
exit status

