bin/powder in powder-0.1.6 vs bin/powder in powder-0.1.7

- old
+ new

@@ -7,84 +7,159 @@ require 'powder/version' module Powder class CLI < Thor include Thor::Actions - default_task :link + default_task :help map '-r' => 'restart' + map '-a' => 'always_restart' map '-l' => 'list' map '-L' => 'link' + map '-d' => 'default' map '-o' => 'open' map '-v' => 'version' map 'update' => 'install' + POWDER_CONFIG = ".powder" POW_PATH = "#{ENV['HOME']}/.pow" POW_DAEMON_PLIST_PATH="#{ENV['HOME']}/Library/LaunchAgents/cx.pow.powd.plist" POW_FIREWALL_PLIST_PATH = "/Library/LaunchDaemons/cx.pow.firewall.plist" desc "up", "Enable pow" def up if File.exists? POW_FIREWALL_PLIST_PATH - %x{sudo launchctl load /Library/LaunchDaemons/cx.pow.firewall.plist} + %x{sudo launchctl load #{POW_FIREWALL_PLIST_PATH}} else say "Pow firewall configuration missing." end + if File.exists? POW_DAEMON_PLIST_PATH + %x{launchctl load #{POW_DAEMON_PLIST_PATH}} + else + say "Pow daemon configuration missing." + end end desc "down", "Disable pow" def down if File.exists? POW_FIREWALL_PLIST_PATH if not %x{sudo launchctl list | grep cx.pow.firewall}.empty? - %x{sudo launchctl unload /Library/LaunchDaemons/cx.pow.firewall.plist} + %x{sudo launchctl unload #{POW_FIREWALL_PLIST_PATH}} end if ports = File.open(POW_FIREWALL_PLIST_PATH).read.match(/fwd .*?,([\d]+).*?dst-port ([\d]+)/) http_port, dst_port = ports[1..2] end end - + + if File.exists? POW_DAEMON_PLIST_PATH + %x{launchctl unload #{POW_DAEMON_PLIST_PATH}} + end + http_port ||= 20559 dst_port ||= 80 - + if rule = %x{sudo ipfw show | grep ",#{http_port} .* dst-port #{dst_port} in"}.split.first %x{sudo ipfw delete #{rule} && sudo sysctl -w net.inet.ip.forwarding=0} end end desc "link", "Link a pow" + method_option :force, :type => :boolean, :default => false, :alias => '-f', :desc => "remove the old configuration, overwrite .powder" + method_option :"no-config", :type => :boolean, :default => false, :alias => '-n', :desc => "do not write a .powder file" def link(name=nil) return unless is_powable? + if File.symlink?(POW_PATH) + current_path = %x{pwd}.chomp + if name + write_pow_config(name) + else + name = get_pow_name + end + symlink_path = "#{POW_PATH}/#{name}" + FileUtils.rm_f(symlink_path) if options[:force] + FileUtils.ln_s(current_path, symlink_path) unless File.exists?(symlink_path) + say "Your application is now available at http://#{name}.#{domain}/" + else + say "Pow is not installed." + end + end + + desc "default", "Set this app as default" + def default(name=nil) + return unless is_powable? current_path = %x{pwd}.chomp - name ||= current_dir_pow_name - symlink_path = "#{POW_PATH}/#{name}" - FileUtils.ln_s(current_path, symlink_path) unless File.exists?(symlink_path) - say "Your application is now available at http://#{name}.#{domain}/" + name ||= get_pow_name + symlink_path = "#{POW_PATH}/default" + FileUtils.rm_f symlink_path if File.exists?(symlink_path) + FileUtils.ln_sf(current_path, symlink_path) + say "Your application(#{name}) is now default at http://localhost/" end + desc "un_default", "remove current default app" + def un_default(name=nil) + name ||= get_pow_name + symlink_path = "#{POW_PATH}/default" + FileUtils.rm_f symlink_path if File.exists?(symlink_path) + end + desc "restart", "Restart current pow" def restart return unless is_powable? FileUtils.mkdir_p('tmp') %x{touch tmp/restart.txt} end + desc "always_restart", "Always restart current pow" + def always_restart + return unless is_powable? + FileUtils.mkdir_p('tmp') + %x{touch tmp/always_restart.txt} + end + + desc "no_restarts", "Reset this app's restart settings" + def no_restarts + return unless is_powable? + FileUtils.rm_f Dir.glob('tmp/*restart.txt') + end + desc "list", "List current pows" def list - Dir[POW_PATH + "/*"].map { |a| say File.basename(a) } + pows = Dir[POW_PATH + "/*"].map do |link| + realpath = File.readlink(link) + app_is_current = (realpath == Dir.pwd) ? '*' : ' ' + [app_is_current, File.basename(link), realpath.gsub(ENV['HOME'], '~')] + end + print_table(pows) end desc "open", "Open a pow in the browser" def open(name=nil) - %x{open http://#{name || current_dir_pow_name}.#{domain}} + %x{open http://#{name || get_pow_name}.#{domain}} end - desc "remove", "Remove a pow" - def remove(name=nil) + desc "unlink", "Unlink a pow app" + method_option :delete, :type => :boolean, :default => false, :alias => '-e', :desc => "delete .powder" + def unlink(name=nil) return unless is_powable? - FileUtils.rm_f POW_PATH + '/' + (name || current_dir_pow_name) + FileUtils.rm_f POW_PATH + '/' + (name || get_pow_name) + say "Successfully removed #{(name || get_pow_name)}" + if options[:delete] + FileUtils.rm_f POWDER_CONFIG + say "Successfully removed #{POWDER_CONFIG}" + end end + desc "remove", "An alias to Unlink (depreciated)" + alias :remove :unlink + + desc "cleanup", "Clean up invalid symbolic link" + def cleanup + Dir[POW_PATH + "/*"].map { |symlink| + FileUtils.rm(symlink) unless File.exists? File.readlink(symlink) + } + end + desc "install", "Installs pow" def install %x{curl get.pow.cx | sh} end @@ -110,11 +185,40 @@ desc "version", "Shows the version" def version say "powder #{Powder::VERSION}" end - + + desc "host", "Updates hosts file to map pow domains to 127.0.0.1" + def host + hosts_file_path = "/etc/hosts" + pow_domain_records = Dir[POW_PATH + "/*"].map { |a| "127.0.0.1\t#{File.basename(a)}.#{domain}\t#powder" } + hosts_file = File.read("/etc/hosts").split("\n").delete_if {|row| row =~ /.+(#powder)/} + first_loopback_index = hosts_file.index {|i| i =~ /^(127.0.0.1).+/} + hosts_file = hosts_file.insert(first_loopback_index + 1, pow_domain_records) + File.open("#{ENV['HOME']}/hosts-powder", "w") do + |file| file.puts hosts_file.join("\n") + end + %x{cp #{hosts_file_path} #{ENV['HOME']}/hosts-powder.bak} + %x{sudo mv #{ENV['HOME']}/hosts-powder #{hosts_file_path}} + %x{dscacheutil -flushcache} + say "Domains added to hosts file, old host file is saved at #{ENV['HOME']}/hosts-powder.bak" + end + + desc "unhost", "Removes pow domains from hostfile" + def unhost + hosts_file_path = "/etc/hosts" + hosts_file = File.read("/etc/hosts").split("\n").delete_if {|row| row =~ /.+(#powder)/} + File.open("#{ENV['HOME']}/hosts-powder", "w") do + |file| file.puts hosts_file.join("\n") + end + %x{cp #{hosts_file_path} #{ENV['HOME']}/hosts-powder.bak} + %x{sudo mv #{ENV['HOME']}/hosts-powder #{hosts_file_path}} + %x{dscacheutil -flushcache} + say "Domains removed from hosts file, old host file is saved at #{ENV['HOME']}/hosts-powder.bak" + end + desc "config", "Shows current pow configuration" def config results = %x{curl --silent -H host:pow localhost/config.json}.gsub(':','=>') return say("Error: Cannot get Pow config. Pow may be down. Try 'powder up' first.") if results.empty? || !(results =~ /^\{/) json = eval results @@ -135,19 +239,52 @@ json = eval results json.each {|k,v| say "#{k.ljust(12, ' ')} #{v}"} end private - + def current_dir_name File.basename(%x{pwd}.chomp) end + def configured_pow_name + return nil unless File.exists?(POWDER_CONFIG) + + File.foreach(POWDER_CONFIG) do |line| + next if line =~ /^($|#)/ + return line.chomp + end + + return nil + end + def current_dir_pow_name current_dir_name.tr('_', '-') end + def get_pow_name + configured_pow_name || current_dir_pow_name + end + + def write_pow_config(name=nil) + return if ! name || options[:"no-config"] + powder_exists = File.exists?(POWDER_CONFIG) + configured_name = get_pow_name + + unlink if powder_exists && configured_name != name + + if options[:force] || ! powder_exists + File.open(POWDER_CONFIG, "w") do |f| + f.puts(name) + end + say "Created powder config #{POWDER_CONFIG}" + elsif !options[:force] && powder_exists && configured_name != name + say "Cowardly refusing to overwrite #{POWDER_CONFIG}" + exit 1 + end + end + def is_powable? if File.exists?('config.ru') || File.exists?('public/index.html') true elsif legacy = (is_rails2_app? || is_radiant_app?) say "This appears to be a #{legacy} applicaton. You need a config.ru file." @@ -169,15 +306,15 @@ return false end end def is_rails2_app? - File.exists?('config/environment.rb') && + File.exists?('config/environment.rb') && !`grep RAILS_GEM_VERSION config/environment.rb`.empty? ? 'Rails 2' : nil end - + def is_radiant_app? - File.exists?('config/environment.rb') && + File.exists?('config/environment.rb') && !`grep Radiant::Initializer config/environment.rb`.empty? ? 'Radiant' : nil end def domain if File.exists? File.expand_path('~/.powconfig')