#!/usr/bin/env ruby require 'readline' require 'English' require 'slop' ENV['RACK_ENV'] ||= 'production' # display name for tools like `ps` $PROGRAM_NAME = 'sequenceserver' # Given a url downloads the archive into a temporary file # and and extratcs it into ~/.sequenceserver def download_from_url(url) archive = File.join('/tmp', File.basename(url)) # -ip4 is required to avoid this curl bug http://sourceforge.net/p/curl/bugs/1424/?limit=25 # see also https://github.com/yannickwurm/sequenceserver/issues/139 cmd = "curl -ip4 -C - #{url} -o #{archive} && " \ 'mkdir -p ~/.sequenceserver && ' \ "tar xvf #{archive} -C ~/.sequenceserver" system cmd end begin Slop.parse!(:strict => true, :help => true) do banner < true on 'config=', 'Same as --config_file (deprecated)', :argument => true on 'b', 'bin=', 'Load BLAST+ binaries from this directory', :argument => true on 'd', 'database_dir=', 'Read FASTA and BLAST database from this directory', :argument => true on 'n', 'num_threads=', 'Number of threads to use to run a BLAST search', :argument => true on 'r', 'require=', 'Load extension from this file', :argument => true on 'H', 'host=', 'Host to run SequenceServer on', :argument => true on 'p', 'port=', 'Port to run SequenceServer on', :argument => true on 's', 'set', 'Set configuration value in default or given config file' on 'm', 'make-blast-databases', 'Create BLAST databases' on 'download-taxdb', 'Download the taxdb files' on 'l', 'list_databases', 'List BLAST databases' on 'u', 'list-unformatted-fastas', 'List unformatted FASTA files' on 'i', 'interactive', 'Run SequenceServer in interactive mode' on 'D', 'devel', 'Start SequenceServer in development mode' on '-v', '--version', 'Print version number of SequenceServer that will be loaded' on '-h', '--help', 'Display this help message' clean_opts = lambda do |hash| hash.delete_if { |k, v| k == :set || v.nil? } hash[:config_file] ||= hash.delete(:config) hash end run do if version? require 'sequenceserver/version' puts SequenceServer::VERSION exit end ENV['RACK_ENV'] = 'development' if devel? # Exit gracefully on SIGINT. stty = `stty -g`.chomp trap('INT') do puts '' puts 'Aborted.' system('stty', stty) exit end require 'sequenceserver' begin SequenceServer.init clean_opts[to_h] # The aim of following error recovery scenarios is to guide user to a # working SequenceServer installation. We expect to land following # error scenarios either when creating a new SequenceServer (first # time or later), or updating config values using -s CLI option. rescue SequenceServer::CONFIG_FILE_ERROR, SequenceServer::BLAST_DATABASE_ERROR => e puts e exit! rescue SequenceServer::BIN_DIR_NOT_FOUND => e puts e unless bin? puts 'You can set the correct value by running:' puts puts ' sequenceserver -s -b ' puts end exit! rescue SequenceServer::DATABASE_DIR_NOT_FOUND => e puts e unless database_dir? puts 'You can set the correct value by running:' puts puts ' sequenceserver -s -d ' puts end exit! rescue SequenceServer::NUM_THREADS_INCORRECT => e puts e unless num_threads? puts 'You can set the correct value by running:' puts puts ' sequenceserver -s -n ' puts end exit! rescue SequenceServer::EXTENSION_FILE_NOT_FOUND => e puts e unless require? puts 'You can set the correct value by running:' puts puts ' sequenceserver -s -r ' puts end exit! rescue SequenceServer::BLAST_NOT_INSTALLED, SequenceServer::BLAST_NOT_EXECUTABLE, SequenceServer::BLAST_NOT_COMPATIBLE => e # Show original error message first. puts puts e # Set a flag so that if we recovered from error resulting config can be # saved. Config will be saved unless invoked with -b option. fetch_option(:set).value = !bin? # Ask user if she already has BLAST+ downloaded or offer to download # BLAST+ for her. puts puts <> ').to_s.strip if response.empty? puts puts 'Installing NCBI BLAST+.' puts "RUBY_PLATFORM #{RUBY_PLATFORM}" version = SequenceServer::MINIMUM_BLAST_VERSION url = case RUBY_PLATFORM when /i686-linux/ # 32 bit Linux 'ftp://ftp.ncbi.nlm.nih.gov/blast/executables/blast+/' \ "#{version.chop}/ncbi-blast-#{version}-ia32-linux.tar.gz" when /x86_64-linux/ # 64 bit Linux 'ftp://ftp.ncbi.nlm.nih.gov/blast/executables/blast+/' \ "#{version.chop}/ncbi-blast-#{version}-x64-linux.tar.gz" when /darwin/ # Mac 'ftp://ftp.ncbi.nlm.nih.gov/blast/executables/blast+/' \ "#{version.chop}/" \ "ncbi-blast-#{version}-universal-macosx.tar.gz" else puts < e # Show original error message. puts puts e # Set a flag so that if we recovered from error resulting config can be # saved. Config will be saved unless invoked with -d option. fetch_option(:set).value = !database_dir? # Ask user for the directory containing sequences or BLAST+ # databases. puts puts <> ').to_s.strip fetch_option(:database_dir).value = response redo rescue SequenceServer::NO_BLAST_DATABASE_FOUND => e unless list_databases? || list_unformatted_fastas? || make_blast_databases? # Print error raised. puts puts e # Offer user to format the FASTA files. database_dir = SequenceServer.config[:database_dir] puts puts <> ' response = STDIN.gets.to_s.strip unless response.match(/^[n]$/i) puts puts 'Searching ...' if SequenceServer::Database.unformatted_fastas.empty? puts "Couldn't find any FASTA files." exit! else formatted = SequenceServer::Database.make_blast_databases exit! if formatted.empty? && !set? redo unless set? end else exit! unless set? end end rescue => e # This will catch any unhandled error and some very special errors. # Ideally we will never hit this block. If we do, there's a bug in # SequenceServer or something really weird going on. If we hit this # error block we show the stacktrace to the user requesting them to # post the same to our Google Group. puts < e puts e puts "Run '#{$PROGRAM_NAME} -h' for help with command line options." exit end