#!/usr/bin/env ruby # frozen_string_literal: true require 'entangler' require 'optparse' require 'to_regexp' def bool_opt(options, opts, key, *args) opts.on(*args) do options[key] = true end end def value_opt(options, opts, key, *args) opts.on(*args) do |val| options[key] = val end end options = {} OptionParser.new do |opts| opts.banner = %(Entangler v#{Entangler::VERSION} Usage: entangler master @: [options] entangler master [options]) opts.separator '' opts.separator 'Options:' opts.on('-i', "--ignore '.git'", "Ignore path when syncing, string is regex if surrounded by '/'", 'All paths should be relative to the base sync directory.') do |ignore| options[:ignore] ||= [] options[:ignore] << ignore end value_opt(options, opts, :port, '-p', '--port PORT', 'Overwrite the SSH port (usually 22)', "(doesn't do anything in slave mode)") bool_opt(options, opts, :verbose, '-v', '--verbose', 'Log Debug lines') bool_opt(options, opts, :quiet, '-q', '--quiet', "Don't log to stdout in master process") opts.on_tail('--version', 'Show version number') do puts Entangler::VERSION exit end opts.on_tail('-h', '--help', 'Show this message') do puts opts exit end end.parse! mode = ARGV.shift unless mode && %w[master slave].include?(mode) puts "Mode unknown, please read help:\nentangler -h" exit 1 end base_dir = ARGV.shift unless base_dir puts 'Missing base directory' exit 1 end if mode == 'master' remote_information = ARGV.shift unless remote_information puts 'Missing destination information' exit 1 end user = host = path = error = nil remote_mode = false if remote_information =~ /[^@]+@[^:]+:.+/ remote_mode = true user, rest = remote_information.split('@', 2) host, path = (rest || '').split(':', 2) error = 'Missing remote user' unless user error = 'Missing remote host' unless host error = 'Missing remote path' unless path else path = remote_information end unless error.nil? puts error exit 1 end opts = { remote_base_dir: path, remote_mode: remote_mode } if remote_mode opts[:remote_user] = user opts[:remote_host] = host end opts[:remote_port] = options[:port] if options[:port] else opts = { mode: 'slave' } end if options[:ignore] opts[:ignore] = options[:ignore].map do |opt| opt = opt[1..-2] if opt.start_with?('"') && opt.end_with?('"') || opt.start_with?("'") && opt.end_with?("'") if ToRegexp::String.literal? opt source, *rest = opt.as_regexp(detect: true) ::Regexp.new "^#{source}(?:/[^/]+)*$", *rest else opt.to_regexp(detect: true) end end end opts[:quiet] = options[:quiet] opts[:verbose] = options[:verbose] begin Entangler.run(base_dir, opts) rescue Entangler::EntanglerError => e puts e.message exit 1 end