<commit_before>require 'rubygems'
require 'thor'
require 'passify/version'

module Passify
  class CLI < Thor
    include Thor::Actions
    
    APACHE_CONF = '/etc/apache2/httpd.conf'
    VHOSTS_DIR = '/private/etc/apache2/passenger_pane_vhosts'

    desc "add", "Creates an application from the current working directory."
    def add(name = nil)
      error("Passify is currently not installed. Please run `passify install` first.") unless passify_installed?
      error("This directory can not be served with Passenger. Please create a `config.ru`-file.") unless is_valid_app?
      name = File.basename(pwd) if name.nil? || name.empty?
      name = urlify(name)
      host = "#{name}.local"
      if app_exists?(host)
        if is_same_app?(host, pwd)
          notice("This directory is already being served from http://#{host}. Run `passify open #{name}` to view it.")
        else
          exit if no?("A different app already exists with under http://#{host}. Do you want to overwrite it?")
          remove(name)
        end
      end
      
      sudome
      create_vhost(host, pwd)
      register_host(host)
      system("apachectl graceful > /dev/null 2>&1")
      say "The application was successfully set up and can be reached from http://#{host} . Run `passify open #{name}` to view it."
    end
    
    desc "remove", "Removes an existing link to the current working directory."
    def remove(name = nil)
      error("Passify is currently not installed. Please run `passify install` first.") unless passify_installed?
      name = File.basename(pwd) if name.nil? || name.empty?
      name = urlify(name)
      host = "#{name}.local"
      notice("No application exists under http://#{host} .") unless app_exists?(host)
      sudome
      remove_file(vhost_file(host))
      unregister_host(host)
    end
    
    desc "install", "Installs passify into the local Apache installation."
    def install
      error("Passenger seems not to be installed. Refer to http://www.modrails.com/ for installation instructions.") unless passenger_installed?
      notice("passify is already installed.") if passify_installed?
      sudome
      append_to_file APACHE_CONF, <<-eos
\n\n# Added by the Passenger preference pane
# Make sure to include the Passenger configuration (the LoadModule,
# PassengerRoot, and PassengerRuby directives) before this section.
<IfModule passenger_module>
  NameVirtualHost *:80
  <VirtualHost *:80>
    ServerName _default_
  </VirtualHost>
  Include /private/etc/apache2/passenger_pane_vhosts/*.conf
</IfModule>
        eos
      system("apachectl graceful > /dev/null 2>&1")
      FileUtils.mkdir_p(VHOSTS_DIR)
      say "The installation of passify is complete."
    end
    
    desc "uninstall", "Uninstalls passify"
    def uninstall
      notice("passify is not installed.") unless passify_installed?
      sudome
      first_config_line = find_line_in_conf('# Added by the Passenger preference pane').to_i
      system("sed -i '' '#{first_config_line},#{first_config_line+9}d' #{APACHE_CONF}")
      say "The uninstallation of passify is complete. The vhosts in `#{VHOSTS_DIR}` have not been deleted."
    end
    
    desc "restart", "Restart the current application"
    def restart
      notice("The current directory does not seem to be a passenger application.") unless is_valid_app?
      FileUtils.mkdir_p('tmp')
      system "touch tmp/restart.txt"
    end
    
    desc "list", "Lists all applications served with passify."
    def list
      error("Passify is currently not installed. Please run `passify install` first.") unless passify_installed?
      Dir.foreach(VHOSTS_DIR) do |entry|
        if File.file?("#{VHOSTS_DIR}/#{entry}")
          host = entry[0..-12]
          say "  #{host} --> #{directory_for_host(host)}"
        end
      end
    end
    
    desc "open", "Opens the current working directory in browser."
    def open(name = nil)
      error("Passify is currently not installed. Please run `passify install` first.") unless passify_installed?
      name = File.basename(pwd) if name.nil? || name.empty?
      name = urlify(name)
      host = "#{name}.local"
      system("open http://#{host}")
    end
    
    desc "version", "Shows the version"
    def version
       say "passify #{Passify::VERSION}"
    end
    
    private
      # http://jimeh.me/blog/2010/02/22/built-in-sudo-for-ruby-command-line-tools/      
      def sudome
        exec("#{sudo_command} passify #{ARGV.join(' ')}") if ENV["USER"] != "root"
      end
      
      def sudo_command
        rvm_installed? ? 'rvmsudo' : 'sudo'
      end

      def rvm_installed?
        system("which rvm > /dev/null 2>&1")
      end
      
      def passify_installed?
        system("grep 'Include \\/private\\/etc\\/apache2\\/passenger_pane_vhosts\\/\\*\\.conf' #{APACHE_CONF} > /dev/null 2>&1")
      end
      
      def passenger_installed?
        system("grep 'PassengerRuby' #{APACHE_CONF} > /dev/null 2>&1")
      end
      
      def is_valid_app?
        if is_rack_app?
          FileUtils.mkdir_p('public')
          FileUtils.mkdir_p('tmp')
          true
        elsif is_rails2_app?
          true
        elsif is_legacy_app?
          true
        else
          false
        end
      end
      
      def is_rack_app?
        File.exists?('config.ru')
      end
      
      def is_rails2_app?
        system("grep 'RAILS_GEM_VERSION' config/environment.rb > /dev/null 2>&1")
      end
      
      def is_legacy_app?
        File.exists?('index.html') || File.exists?('index.php')
      end
      
      def app_exists?(host)
        File.exists?(vhost_file(host))
      end
      
      def is_same_app?(host, dir)
        directory_for_host(host) == dir
      end
      
      def directory_for_host(host)
        `grep 'DocumentRoot' #{vhost_file(host)}`.scan(/"([^"]*)"/).flatten[0][0..-8]
      end
      
      def find_line_in_conf(pattern)
        `grep -n '#{pattern}' #{APACHE_CONF}`.split(":").first
      end
      
      def pwd
        @pwd ||= Dir.pwd
      end

      def urlify(name)
        name.downcase.gsub(/[\s\_]/, '-').gsub(/[^a-z\d\-]/, '').gsub(/\-+/, '-')
      end
      
      def error(message)
        say message, :red
        exit(false)
      end
      
      def notice(message)
        say message, :yellow
        exit
      end
      
      def create_vhost(host, path)
        if is_legacy_app?
        else
          create_passenger_vhost(host, path)
        end
      end
      
      def create_passenger_vhost(host, path)
        create_file vhost_file(host), <<-eos
<VirtualHost *:80>
  ServerName #{host}
  DocumentRoot "#{path}/public"
  RackEnv development
  <Directory "#{path}/public">
    Allow from all
    Options -MultiViews
  </Directory>
</VirtualHost>
          eos
      end
      
      def create_legacy_vhost(host, path)
        create_file vhost_file(host), <<-eos<commit_msg>no comment<commit_after>require 'rubygems'
require 'thor'
require 'passify/version'

module Passify
  class CLI < Thor
    include Thor::Actions
    
    APACHE_CONF = '/etc/apache2/httpd.conf'
    VHOSTS_DIR = '/private/etc/apache2/passenger_pane_vhosts'

    desc "add", "Creates an application from the current working directory."
    def add(name = nil)
      error("Passify is currently not installed. Please run `passify install` first.") unless passify_installed?
      error("This directory can not be served with Passenger. Please create a `config.ru`-file.") unless is_valid_app?
      name = File.basename(pwd) if name.nil? || name.empty?
      name = urlify(name)
      host = "#{name}.local"
      if app_exists?(host)
        if is_same_app?(host, pwd)
          notice("This directory is already being served from http://#{host}. Run `passify open #{name}` to view it.")
        else
          exit if no?("A different app already exists with under http://#{host}. Do you want to overwrite it?")
          remove(name)
        end
      end
      
      sudome
      create_vhost(host, pwd)
      register_host(host)
      system("apachectl graceful > /dev/null 2>&1")
      say "The application was successfully set up and can be reached from http://#{host} . Run `passify open #{name}` to view it."
    end
    
    desc "remove", "Removes an existing link to the current working directory."
    def remove(name = nil)
      error("Passify is currently not installed. Please run `passify install` first.") unless passify_installed?
      name = File.basename(pwd) if name.nil? || name.empty?
      name = urlify(name)
      host = "#{name}.local"
      notice("No application exists under http://#{host} .") unless app_exists?(host)
      sudome
      remove_file(vhost_file(host))
      unregister_host(host)
    end
    
    desc "install", "Installs passify into the local Apache installation."
    def install
      error("Passenger seems not to be installed. Refer to http://www.modrails.com/ for installation instructions.") unless passenger_installed?
      notice("passify is already installed.") if passify_installed?
      sudome
      append_to_file APACHE_CONF, <<-eos
\n\n# Added by the Passenger preference pane
# Make sure to include the Passenger configuration (the LoadModule,
# PassengerRoot, and PassengerRuby directives) before this section.
<IfModule passenger_module>
  NameVirtualHost *:80
  <VirtualHost *:80>
    ServerName _default_
  </VirtualHost>
  Include /private/etc/apache2/passenger_pane_vhosts/*.conf
</IfModule>
        eos
      system("apachectl graceful > /dev/null 2>&1")
      FileUtils.mkdir_p(VHOSTS_DIR)
      say "The installation of passify is complete."
    end
    
    desc "uninstall", "Uninstalls passify"
    def uninstall
      notice("passify is not installed.") unless passify_installed?
      sudome
      first_config_line = find_line_in_conf('# Added by the Passenger preference pane').to_i
      system("sed -i '' '#{first_config_line},#{first_config_line+9}d' #{APACHE_CONF}")
      say "The uninstallation of passify is complete. The vhosts in `#{VHOSTS_DIR}` have not been deleted."
    end
    
    desc "restart", "Restart the current application"
    def restart
      notice("The current directory does not seem to be a passenger application.") unless is_valid_app?
      FileUtils.mkdir_p('tmp')
      system "touch tmp/restart.txt"
    end
    
    desc "list", "Lists all applications served with passify."
    def list
      error("Passify is currently not installed. Please run `passify install` first.") unless passify_installed?
      Dir.foreach(VHOSTS_DIR) do |entry|
        if File.file?("#{VHOSTS_DIR}/#{entry}")
          host = entry[0..-12]
          say "  #{host} --> #{directory_for_host(host)}"
        end
      end
    end
    
    desc "open", "Opens the current working directory in browser."
    def open(name = nil)
      error("Passify is currently not installed. Please run `passify install` first.") unless passify_installed?
      name = File.basename(pwd) if name.nil? || name.empty?
      name = urlify(name)
      host = "#{name}.local"
      system("open http://#{host}")
    end
    
    desc "version", "Shows the version"
    def version
       say "passify #{Passify::VERSION}"
    end
    
    private
      # http://jimeh.me/blog/2010/02/22/built-in-sudo-for-ruby-command-line-tools/      
      def sudome
        exec("#{sudo_command} passify #{ARGV.join(' ')}") if ENV["USER"] != "root"
      end
      
      def sudo_command
        rvm_installed? ? 'rvmsudo' : 'sudo'
      end

      def rvm_installed?
        system("which rvm > /dev/null 2>&1")
      end
      
      def passify_installed?
        system("grep 'Include \\/private\\/etc\\/apache2\\/passenger_pane_vhosts\\/\\*\\.conf' #{APACHE_CONF} > /dev/null 2>&1")
      end
      
      def passenger_installed?
        system("grep 'PassengerRuby' #{APACHE_CONF} > /dev/null 2>&1")
      end
      
      def is_valid_app?
        if is_rack_app?
          FileUtils.mkdir_p('public')
          FileUtils.mkdir_p('tmp')
          true
        elsif is_rails2_app?
          true
        elsif is_legacy_app?
          true
        else
          false
        end
      end
      
      def is_rack_app?
        File.exists?('config.ru')
      end
      
      def is_rails2_app?
        system("grep 'RAILS_GEM_VERSION' config/environment.rb > /dev/null 2>&1")
      end
      
      def is_legacy_app?
        File.exists?('index.html') || File.exists?('index.php')
      end
      
      def app_exists?(host)
        File.exists?(vhost_file(host))
      end
      
      def is_same_app?(host, dir)
        directory_for_host(host) == dir
      end
      
      def directory_for_host(host)
        `grep 'DocumentRoot' #{vhost_file(host)}`.scan(/"([^"]*)"/).flatten[0][0..-8]
      end
      
      def find_line_in_conf(pattern)
        `grep -n '#{pattern}' #{APACHE_CONF}`.split(":").first
      end
      
      def pwd
        @pwd ||= Dir.pwd
      end

      def urlify(name)
        name.downcase.gsub(/[\s\_]/, '-').gsub(/[^a-z\d\-]/, '').gsub(/\-+/, '-')
      end
      
      def error(message)
        say message, :red
        exit(false)
      end
      
      def notice(message)
        say message, :yellow
        exit
      end
      
      def create_vhost(host, path)
        if is_legacy_app?
          create_legacy_vhost(host, path)
        else
          create_passenger_vhost(host, path)
        end
      end
      
      def create_passenger_vhost(host, path)
        create_file vhost_file(host), <<-eos
<VirtualHost *:80>
  ServerName #{host}
  DocumentRoot "#{path}/public"
  RackEnv development
  <Directory "#{path}/public">
    Allow from all
    Options -MultiViews
  </Directory>
</VirtualHost>
          eos
      end
      
      def create_legacy_vhost(host, path)
        create_file vhost_file(host), <<-eos
{'fraction_non_alphanumeric': 0.11560401473030543, 'fraction_numerical': 0.005632175608347173, 'mean_word_length': 2.379697413372377, 'pattern_counts': {'":': 2, '<': 33, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6229611', 'n_tokens_mistral': 4398, 'n_tokens_neox': 4331, 'n_words': 1156}