#!/usr/local/bin/ruby require 'benchmark' require 'fileutils' QUIET = 0 NORMAL = 1 VERBOSE = 2 class Sub DEFAULT_BASE_URL = "svn+ssh://rubyforge.org/var/svn" def self.from_args(args) verbosity = NORMAL still_parsing_options = true command = :up options = {} while still_parsing_options case args[0] when 'up', 'co', 'help' options[:command] = args[0] when '-v', '--verbose' options[:verbosity] = VERBOSE when '-q', '--quiet' options[:verbosity] = QUIET when '-h', '--help' options[:command] = 'help' still_parsing_options = false when '-c', '--clean' options[:clean] = true when '--url' args.shift options[:url] = args[0] when '--version' puts "Sub version #{Sub::VERSION::STRING}" exit 0 else still_parsing_options = false end args.shift if still_parsing_options end Sub.new(options, args) end attr_reader :clean, :command, :args, :url attr_accessor :verbosity def initialize(options = {:verbosity => NORMAL}, args = []) options = defaults.merge(options) @verbosity = options[:verbosity] @clean = options[:clean] @command = options[:command] @url = options[:url] || ENV['SUB_BASE_URL'] || ENV['SVN'] || DEFAULT_BASE_URL @args = args end def defaults { :verbosity => NORMAL, :command => :up, } end def execute self.send(@command) end # commands def up if @args.empty? @args = [`pwd`.chomp] end update_many(@args) end def co if @args.empty? raise "Please specify a project to check out" end project = args.shift dir_name = args.shift || project svn("co #{url}/#{project}/trunk #{dir_name}") end def help puts """ sub - Alex's wrapper for subversion Version: #{Sub::VERSION::STRING} Usage: sub co project_name [dir_name] checks out [base_url]/project_name/trunk into ./project_name (or dir_name if specified) sub up [dir]* fast update (default command, so 'sub dir...' or just 'sub' work too) sub help prints this message Options: --verbose, -v lots of output --quiet, -q no output at all except for errors --help, -h prints this message --clean, -c 'up' command removes all unversioned files and directories --url [base_url] sets base repository url for 'co' command (default is ENV['SUB_BASE_URL'] or ENV['SVN'] or #{DEFAULT_BASE_URL}) --version prints release version """ end # methods def update_many(roots) roots.each do |root| say "Updating #{root}" b = Benchmark.measure { update(root) } say "Updated %s in %.2f sec" % [root, b.real] end end def update(root) Root.new(root, self, clean).update end def externals(root) Root.new(root, self, clean).externals end def parse_externals(st) exts = [] st.split("\n").select do |line| line =~ /^X/ end.collect do |line| line.gsub(/^X */, '').gsub(/\/[^\/]*$/, '') end.uniq.collect do |parent| prop = `svn propget svn:externals #{parent}` prop.split("\n").each do |external| next if external.strip.empty? exts << External.new(parent, external, self) end end exts end def say(msg) puts msg if verbosity > QUIET end def svn(cmd) svncmd = "svn" svncmd += " --quiet" if (cmd =~ /^(up|co)/ && verbosity == QUIET) run("#{svncmd} #{cmd}") end def run(cmd, return_output = false) say("\t#{cmd}") if verbosity == VERBOSE if (return_output) `#{cmd}` else cmd += ">/dev/null"if verbosity == QUIET system(cmd) end end end