lib/sub/app.rb in sub-0.1.0 vs lib/sub/app.rb in sub-0.3.0

- old
+ new

@@ -4,98 +4,10 @@ QUIET = 0 NORMAL = 1 VERBOSE = 2 -class External - - def self.externals_in_directory(parent) - exts = [] - prop = `svn propget svn:externals #{parent}` - prop.split("\n").each do |prop_line| - next if prop_line.strip.empty? - exts << External.new(parent, prop_line) - end - exts - end - - attr_reader :name, :path, :url, :revision - - def initialize(parent, property) - match = /^(\S+)\s+(-r\s*\d*\s+)?(\S+)\s*$/.match(property) - @name = match[1] - @revision = match[2] ? match[2].gsub(/\D/,'').to_i : nil - @url = match[3] - @path = "#{parent}/#{@name}" - end - - def ==(other) - (path == other.path and url == other.url) - end - - def to_s - "External[name=#{name}, path=#{path}, url=#{url}, revision=#{revision}]" - end - - def revision_actual - info = `svn info #{@path}` - info.grep(/^Revision:/).first.gsub(/Revision: /, '').to_i - end - - def should_update? - revision == nil || revision_actual != revision - end - -end - -class Status - class Line - def initialize(text) - text.strip! - @modified = /^M/.match(text) ? true : false - @external = /^X/.match(text) ? true : false - @unversioned = /^\?/.match(text) ? true : false - @modified_properties = /^.M/.match(text) ? true : false - @path = text.gsub(/^...... /, '') - end - - attr_reader :path - - def modified? - @modified - end - def external? - @external - end - def unversioned? - @unversioned - end - def modified_properties? - @modified_properties - end - end - - - def initialize(text) - @lines = text.split("\n").collect do |line| - Status::Line.new(line) - end - end - - def modified - @lines.select { |line| line.modified? }.collect {|line| line.path} - end - - def externals - @lines.select { |line| line.external? }.collect {|line| line.path} - end - - def unversioned - @lines.select { |line| line.unversioned? }.collect {|line| line.path} - end -end - class Sub DEFAULT_BASE_URL = "svn+ssh://rubyforge.org/var/svn" def self.from_args(args) verbosity = NORMAL @@ -115,31 +27,33 @@ still_parsing_options = false when '-c', '--clean' options[:clean] = true when '--url' args.shift - options[: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 :verbosity, :clean, :command, :args, :url + 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'] || DEFAULT_BASE_URL + @url = options[:url] || ENV['SUB_BASE_URL'] || ENV['SVN'] || DEFAULT_BASE_URL @args = args - - @status = {} end def defaults { :verbosity => NORMAL, @@ -171,10 +85,12 @@ 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) @@ -190,11 +106,13 @@ 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 #{DEFAULT_BASE_URL}) + (default is ENV['SUB_BASE_URL'] or ENV['SVN'] or #{DEFAULT_BASE_URL}) + --version + prints release version """ end # methods @@ -205,117 +123,28 @@ say "Updated %s in %.2f sec" % [root, b.real] end end def update(root) - if @clean - remove_unversioned(root) - end - - externals_before = externals(root) - svn("up --ignore-externals #{root}") - externals = externals(root) - # for some reason (array - array) doesn't work right here - # so i had to write my own subtract method - removed_externals = externals_before.subtract(externals) - removed_externals.each do |ext| - say "Removed external #{ext}" - FileUtils.rm_rf(ext.path) - end - - added_externals = externals.subtract(externals_before) - existing_externals = externals.subtract(added_externals) - - # todo: extract Processes - processes = [] - def update_external(processes, external) - pid = fork do - say "Updating external #{external.path}" - run("svn cleanup #{external.path}") if File.exists?(external.path) - rev = external.revision.nil? ? '' : "-r#{external.revision}" - svn("up #{rev} #{external.path} | grep -v 'At revision'") - end - processes << {:pid => pid, :external => external} - end - - def checkout_external(processes, external) - pid = fork do - say "Checking out external #{external.path}" - rev = external.revision.nil? ? '' : "-r#{external.revision}" - svn("co #{rev} #{external.url} #{external.path}") - end - processes << {:pid => pid, :external => external} - end - - added_externals.each do |external| - checkout_external(processes, external) - end - - already_up_to_date = [] - existing_externals.each do |external| - if external.should_update? - update_external(processes, external) - else - already_up_to_date << external - end - end - - unless already_up_to_date.empty? - say("External#{'s' if already_up_to_date.size > 1} " + - already_up_to_date.collect {|external| external.name}.join(", ") + - " already up to date") - end - - processes.each do |process| - Process.waitpid(process[:pid], 0) - end + Root.new(root, self, clean).update end - def remove_unversioned(root) - status(root).unversioned.each do |path| - if File.directory?(path) - say "Removing unversioned directory #{path}" - else - say "Removing unversioned file #{path}" - end - FileUtils.rm_rf(path) - end - end - - def status(root) - @status[root] ||= Status.new(run("svn st #{root}", true)) - end - def externals(root) - exts = [] - directories_containing_externals(root).collect do |parent| - exts += External.externals_in_directory(parent) - end - exts + Root.new(root, self, clean).externals end - def directories_containing_externals(root) - status(root).externals.collect do |path| - if (path !~ /\//) - "." - else - path.gsub(/\/[^\/]*$/, '') - end - end.uniq - 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) + exts << External.new(parent, external, self) end end exts end @@ -338,19 +167,5 @@ system(cmd) end end end -class Array - def subtract(other) - self.select do |item| - !other.has?(item) - end - end - - def has?(something) - self.each do |item| - return true if item == something - end - false - end -end