#!/usr/bin/env ruby require "libdolt" require "tiltout" require "thin" require "sinatra/base" require "cgi" require "trollop" ### TODO: Extract this into a testable API class DoltApp def initialize(layout_base) @layout_base = layout_base end def is_git_repo?(dir) Dolt::Git.git_repo?(dir) end def create_app(dir, view) if is_git_repo?(dir) dir = File.expand_path(dir) resolver = Dolt::DiskRepoResolver.new(File.dirname(dir)) lookup = Dolt::RepositoryLookup.new(resolver) view.helper(Dolt::View::SingleRepository) require "dolt/sinatra/single_repo_browser" Dolt::Sinatra::SingleRepoBrowser.new(File.basename(dir), lookup, view) else resolver = Dolt::DiskRepoResolver.new(dir) lookup = Dolt::RepositoryLookup.new(resolver) view.helper(Dolt::View::MultiRepository) require "dolt/sinatra/multi_repo_browser" Dolt::Sinatra::MultiRepoBrowser.new(lookup, view) end end def run(root, options) view = Tiltout.new(Dolt.template_dir, { :cache => false, :layout => "layout" }) view.helper(Dolt::View::Object) view.helper(Dolt::View::Urls) view.helper(Dolt::View::Blob) view.helper(Dolt::View::Blame) view.helper(Dolt::View::Breadcrumb) view.helper(Dolt::View::Tree) view.helper(Dolt::View::Commit) view.helper(Dolt::View::Gravatar) view.helper(Dolt::View::TabWidth) view.helper(Dolt::View::BinaryBlobEmbedder) view.helper(:tab_width => options[:tab_width], :maxdepth => 3) # Configure blob rendering module # Attempt to syntax highlight every blob # view.helper(Dolt::View::SyntaxHighlight) # Attempt to render every blob as markup # view.helper(Dolt::View::Markup) # Render supported formats as markup, syntax highlight the rest view.helper(Dolt::View::SmartBlobRenderer) Sinatra::Base.set(:public_folder, File.join(@layout_base, "vendor/ui")) server = create_app(root, view) thin_server = if options[:socket] Thin::Server.new(options[:socket], server) else Thin::Server.new(options[:ip], options[:port], server) end if options[:pidfile] thin_server.pid_file = options[:pidfile] thin_server.log_file = options[:logfile] thin_server.daemonize end puts ">> Starting Dolt #{Dolt::VERSION} from #{root}" begin thin_server.start rescue RuntimeError => e abort "\nUnable to start Dolt. Message:\n- #{e}\n\n" end end end # Use option if given, otherwise ENV var if given, otherwise default value def option_from_options_or_env(option_name, env_name, default, options) return options[option_name] if options[option_name] return ENV[env_name] || default end given_root = ARGV.pop parser = Trollop::Parser.new do version "Dolt #{Dolt::VERSION}" banner <<-END_HELP Dolt is a Git repository browser. Usage: #{$0} [options] ROOT where ROOT is either the path to a repository or a directory containing repositories. Valid options are: END_HELP opt :socket, "A socket to listen to", :type => :string opt :port, "A port to listen to", :type => :integer opt :bind, "An IP address to bind to", :type => :string opt :tabwidth, "The number of spaces to use as a tab", :type => :integer, :default => 4 opt :pidfile, "Run as daemon with pidfile stored here", :type => :string opt :logfile, "Use as log file. Assumes --pidfile option", :type => :string end params = Trollop::with_standard_exception_handling(parser) do raise Trollop::HelpNeeded if given_root.nil? raise Trollop::HelpNeeded unless File.exist?(given_root) parser.parse(ARGV) end options = {} options[:root] = File.expand_path(given_root) if params[:socket] options[:socket] = params[:socket] else options[:port] = option_from_options_or_env(:port, "PORT", 3000, params).to_i options[:ip] = option_from_options_or_env(:ip, "IP", "0.0.0.0", params) end if params[:pidfile] options[:pidfile] = params[:pidfile] options[:logfile] = params[:logfile] || "/tmp/dolt.log" end options[:tab_width] = params[:tabwidth] DoltApp.new(File.join(File.dirname(__FILE__), "..")).run(options.delete(:root), options)