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