From: "NAKAMURA, Hiroshi" Date: 2000-06-25T00:16:37+09:00 Subject: [ruby-dev:10122] [Patch] ftpup -> ftpsync なひです. ちょっとした必要があって,ftpupの一部機能を変更して, localとremoteのsyncをするようなモノを作ってみました. ftpupの機能を向上したり,不具合を修正するものではないので, 取り込む必要はありません(つか,できません ^^;). 判断基準は以下のとおりです. 1. localとremoteのどちらかにファイル/ディレクトリがなければ, 反対側のファイルを取ってきて作成する. 2. localとremoteの両方にファイルがあり,サイズが同じ場合は, タイムスタンプが異なっていても放置(何もしない). 3. 上記サイズが異なる場合,タイムスタンプが新しいほうで, 古いほうを上書きする(古いほうは消えますのでご注意). 今日作ったばかりで,なひもまだろくに運用してないので, ご利用の際は充分注意してください.local/remote両サイドのバックアップが 必須です.なひは今後あちこちに使う予定なので, 不具合にぶちあたったらまたpatchを出すでしょう.^^; ftpup-1.3.3へのpatchです. --- ftpup Tue May 16 17:04:38 2000 +++ ftpsync Sun Jun 25 00:00:25 2000 @@ -103,4 +103,5 @@ EOF update(".") else + raise ArgumentError.new("Argument not allowed.") path.each do |p| update(p) @@ -136,42 +137,63 @@ EOF def updatedir(directory) print directory.sub(/^./, Config::REMOTE_DIR), ":\n" + local_dirs = [] + local_filetimes = {} + local_filesizes = {} + check_local_files(directory, local_dirs, local_filetimes, local_filesizes) remote_dirs = []; remote_filetimes = {} remote_filesizes = {} check_remote_files(directory, remote_dirs, remote_filetimes, remote_filesizes) - Dir.foreach(directory) do |file| - longname = directory + "/" + file - if file != "." && file != ".." - if File.ftype(longname) == "directory" - if longname =~ @ignore_file_regexp - next - end - unless remote_dirs.include?(file) - makedir(longname) - end - updatedir(longname) unless @not_recursive - else - if not longname =~ @ignore_file_regexp and - ((not remote_filesizes.has_key?(file) or - remote_filesizes[file] != File.size(longname)) or - (not remote_filetimes.has_key?(file) or - remote_filetimes[file] < File.mtime(longname).gmtime)) - updatefile(longname) - end - remote_filetimes.delete(file) + (local_filetimes.keys + remote_filetimes.keys).uniq.each do |file| + longname = getlongname(directory, file) + if longname =~ @ignore_file_regexp + # Nothing to do. + elsif not local_filesizes.has_key?(file) + getfile(longname) + elsif not remote_filesizes.has_key?(file) + putfile(longname) + elsif local_filesizes[file] != remote_filesizes[file] + if local_filetimes[file] < remote_filetimes[file] + getfile(longname) + elsif local_filetimes[file] > remote_filetimes[file] + putfile(longname) end end end - if @remove_files - remote_filetimes.each_key do |file| - longname = directory + "/" + file - unless @leave_file_regexp and longname =~ @leave_file_regexp - print "delete ", File.basename(longname), "\n" - @ftp.delete(longname) + (local_dirs + remote_dirs).uniq.each do |dir| + longname = getlongname(directory, dir) + if longname =~ @ignore_file_regexp + next + end + if local_dirs.include?(dir) + unless remote_dirs.include?(dir) + makedir(longname) end + elsif remote_dirs.include?(dir) + Dir.mkdir(longname) end + updatedir(longname) unless @not_recursive end end + def check_local_files(directory, dirs, filetimes, filesizes) + targetDir = Dir.open(directory) + targetDir.each do |file| + longname = getlongname(directory, file) + case File.ftype(longname) + when "directory" + if file != "." && file != ".." + dirs.push(file) + end + when "file" + filetimes[file] = File.mtime(longname).gmtime + filesizes[file] = File.size(longname) + else + print "#{File.ftype(longname)}(#{longname}) found. Skepped.\n" + end + end + targetDir.close + end + def check_remote_files(directory, dirs, filetimes, filesizes) if @list_opts and @list_opts.length > 0 @@ -226,5 +248,22 @@ EOF end + def getfile(file) + print "get ", file, ": " + @ftp.getbinaryfile(file, file, 4096) do |data| + print "."; $>.flush + end + print "\n" + end + + def putfile(file) + print "put ", file, ": " + @ftp.putbinaryfile(file, file, 4096) do |data| + print "."; $>.flush + end + print "\n" + end + def updatefile(file) + raise RuntimeError.new("updatefile is obsolete.") print "put ", file, ": " if file =~ @textfile_regexp @@ -242,4 +281,8 @@ EOF end print "\n" + end + + def getlongname(directory, file) + directory + "/" + file end