lib/rbsync.rb in rbsync-0.0.9 vs lib/rbsync.rb in rbsync-0.0.10
- old
+ new
@@ -77,27 +77,46 @@
# require 'rbsync'
# rsync =RbSync.new
# rsync.updated_file_only = true
# rsync.sync( "src", "dest" )
# rsync.sync( "dest", "src" )# swap src to dest , dest to src
+#### TODO:
+## FileUtils/Dir.chdir をSSH対応に切替える
+## progress 表示のために fileutils.copy を 自作する
class RbSync
attr_accessor :conf
+ # for ruby 1.8.7 (2008-08-11 patchlevel 72) [i386-cygwin]
+ # File.dirname of cygwin doesn't work corrently for JAPANESE hiragana pathname
+ # Cygwinの日本語UTF8/SJIS環境だと「ひらがな」パス名が正しく扱えないのでmonkey patch
+ if ((RUBY_PLATFORM =~ /cygwin/) and RUBY_VERSION == "1.8.7")then
+ def File.dirname(e)
+ paths = e.split("/")
+ paths.pop
+ paths.join("/")
+ end
+ def FileUtils.mkdir_p(e)
+ `mkdir -p "#{e}"`
+ end
+ end
def initialize()
@conf ={}
@conf[:update] = false
@conf[:excludes] = []
@conf[:preserve] = true
end
# collect file paths. paths are relatetive path.
def find_as_relative(dir_name,excludes=[])
files =[]
excludes = [] unless excludes
+ #todo write this two line . exculude initialize test
+ excludes = excludes.split(",") if excludes.class == String
+ excludes = [excludes] unless excludes.class == Array
+
Dir.chdir(dir_name){
files = Dir.glob "./**/*", File::FNM_DOTMATCH
exclude_files =[]
exclude_files = excludes.map{|g| Dir.glob "./**/#{g}",File::FNM_DOTMATCH }
- #files.each{|e|pp [e, File.directory?(e)] }
files = files.reject{|e| File.directory?(e) }
files = files - exclude_files.flatten
}
files = files.reject{|e| [".",".."].any?{|s| s== File::basename(e) }}
end
@@ -167,37 +186,44 @@
puts "同期に失敗したみたい" if ret.select{|e|!e}.size != 0 && self.debug?
end
def collet_hash(file_names,basedir,options={})
#prepare
require 'thread'
+ self.patch_digest_base
threads =[]
output = Hash.new{|s,key| s[key]=[] }
q = Queue.new
limitsize = options[:hash_limit_size]
# compute digests
file_names.each{|e| q.push e }
- 5.times{
+ 3.times{
threads.push(
Thread.start{
while(!q.empty?)
name = q.pop
+ #$stdout.puts "reading #{name}" if options[:verbose]
+ #$stdout.flush if options[:verbose]
hash = compute_digest_file(File.expand_path(name,basedir),limitsize)
output[hash].push name
end
}
)
}
+ if options[:verbose] then
+ t = Thread.start{
+ until(q.empty?)
+ puts( "#{q.size}/#{file_names.size}");
+ $stdout.flush;
+ sleep 1;
+ end
+ }
+ threads.push(t )
+ end
threads.each{|t|t.join}
return output
end
- # compute digest md5
- # ==limitsize
- # If file size is very large,
- # and a few bytes at head of file is enough to compare.
- # for speed-up, Set limit size to enable to avoid reading a whole of file.
- # もしファイルがとても巨大で、かつ、先頭の数キロバイトが比較に十分であれば、limitsize 以降をスキップする
- def compute_digest_file(filename, limitsize=nil)
+ def patch_digest_base()
require 'digest/md5'
s = %{
class Digest::Base
def self.open(path,limitsize=nil)
obj = new
@@ -211,10 +237,18 @@
return obj
end
end
}
eval s
+ end
+ # compute digest md5
+ # ==limitsize
+ # If file size is very large,
+ # and a few bytes at head of file is enough to compare.
+ # for speed-up, Set limit size to enable to avoid reading a whole of file.
+ # もしファイルがとても巨大で、かつ、先頭の数キロバイトが比較に十分であれば、limitsize 以降をスキップする
+ def compute_digest_file(filename, limitsize=nil)
Digest::MD5.open(filename,limitsize).hexdigest
end
# called from sync
def sync_normally(src,dest,options={})
@@ -312,25 +346,38 @@
$stdout.flush
end
#main
copy_thread = Thread.start{
FileUtils.mkdir_p File.dirname(e[1]) unless File.exists?(File.dirname(e[1]))
+ ## todo copy file as stream for progress
FileUtils.copy( e[0] , e[1] ,{:preserve=>self.preserve?,:verbose=>self.verbose? } )
}
+
#progress of each file
progress_thread = nil
if(@conf[:progress])
progress_thread = Thread.start{
bar = ProgressBar.new
bar.size = 30
src_size = File.size(e[0])
dst_size = -1
- bar.start("copying #{e[0]} to #{e[1]}")
+ bar.start("copying #{e[0]} \r\n to #{e[1]}")
+ cnt = 0
while(src_size!=dst_size)
+ unless File.exists?(e[1]) then
+ cnt = cnt + 1
+ if cnt > 10 then
+ puts "copying #{e[1]} timeout error"
+ throw Error
+ break
+ end
+ sleep 0.05
+ next
+ end
src_size = File.size(e[0]).to_f
dst_size = File.size(e[1]).to_f
- break if dst_size == 0
+ next if dst_size == 0 # preven zero divide
percent = dst_size/src_size*100
bar.progress(percent.to_int)
sleep 0.2
end
bar.end("done")
@@ -341,10 +388,10 @@
}
end
def sync(src,dest,options={})
options[:excludes] = self.excludes.push(options[:excludes]).flatten.uniq if options[:excludes]
options[:update] = @conf[:update] if options[:update] == nil
- options[:check_hash] = options[:check_hash] and @conf[:check_hash]
+ options[:check_hash] = options[:check_hash] or @conf[:check_hash]
options[:hash_limit_size] = @conf[:hash_limit_size] if options[:hash_limit_size] == nil
options[:overwrite] = @conf[:overwrite] if options[:overwrite] == nil
options[:overwrite] = false if options[:no_overwrite]
FileUtils.mkdir_p dest unless File.exists? dest
if options[:rename]