PageRenderTime 117ms CodeModel.GetById 81ms app.highlight 33ms RepoModel.GetById 1ms app.codeStats 0ms

/tools/Ruby/lib/ruby/1.8/ftools.rb

http://github.com/agross/netopenspace
Ruby | 261 lines | 145 code | 28 blank | 88 comment | 32 complexity | 48354c76b5350cd539146263ec6d320a MD5 | raw file
  1# 
  2# = ftools.rb: Extra tools for the File class
  3#
  4# Author:: WATANABE, Hirofumi
  5# Documentation:: Zachary Landau
  6#
  7# This library can be distributed under the terms of the Ruby license.
  8# You can freely distribute/modify this library.
  9#
 10# It is included in the Ruby standard library.
 11#
 12# == Description
 13#
 14# ftools adds several (class, not instance) methods to the File class, for
 15# copying, moving, deleting, installing, and comparing files, as well as
 16# creating a directory path.  See the File class for details.
 17#
 18# FileUtils contains all or nearly all the same functionality and more, and
 19# is a recommended option over ftools 
 20#
 21# When you
 22#
 23#   require 'ftools'
 24#
 25# then the File class aquires some utility methods for copying, moving, and
 26# deleting files, and more.
 27#
 28# See the method descriptions below, and consider using FileUtils as it is
 29# more comprehensive.
 30#
 31class File
 32end
 33
 34class << File
 35
 36  BUFSIZE = 8 * 1024
 37
 38  #
 39  # If +to+ is a valid directory, +from+ will be appended to +to+, adding
 40  # and escaping backslashes as necessary. Otherwise, +to+ will be returned.
 41  # Useful for appending +from+ to +to+ only if the filename was not specified
 42  # in +to+. 
 43  #
 44  def catname(from, to)
 45    if directory? to
 46      join to.sub(%r([/\\]$), ''), basename(from)
 47    else
 48      to
 49    end
 50  end
 51
 52  #
 53  # Copies a file +from+ to +to+. If +to+ is a directory, copies +from+
 54  # to <tt>to/from</tt>.
 55  #
 56  def syscopy(from, to)
 57    to = catname(from, to)
 58
 59    fmode = stat(from).mode
 60    tpath = to
 61    not_exist = !exist?(tpath)
 62
 63    from = open(from, "rb")
 64    to = open(to, "wb")
 65
 66    begin
 67      while true
 68	to.syswrite from.sysread(BUFSIZE)
 69      end
 70    rescue EOFError
 71      ret = true
 72    rescue
 73      ret = false
 74    ensure
 75      to.close
 76      from.close
 77    end
 78    chmod(fmode, tpath) if not_exist
 79    ret
 80  end
 81
 82  #
 83  # Copies a file +from+ to +to+ using #syscopy. If +to+ is a directory,
 84  # copies +from+ to <tt>to/from</tt>. If +verbose+ is true, <tt>from -> to</tt>
 85  # is printed.
 86  #
 87  def copy(from, to, verbose = false)
 88    $stderr.print from, " -> ", catname(from, to), "\n" if verbose
 89    syscopy from, to
 90  end
 91
 92  alias cp copy
 93
 94  #
 95  # Moves a file +from+ to +to+ using #syscopy. If +to+ is a directory,
 96  # copies from +from+ to <tt>to/from</tt>. If +verbose+ is true, <tt>from ->
 97  # to</tt> is printed.
 98  #
 99  def move(from, to, verbose = false)
100    to = catname(from, to)
101    $stderr.print from, " -> ", to, "\n" if verbose
102
103    if RUBY_PLATFORM =~ /djgpp|(cyg|ms|bcc)win|mingw/ and file? to
104      unlink to
105    end
106    fstat = stat(from)
107    begin
108      rename from, to
109    rescue
110      begin
111        symlink readlink(from), to and unlink from
112      rescue
113	from_stat = stat(from)
114	syscopy from, to and unlink from
115	utime(from_stat.atime, from_stat.mtime, to)
116	begin
117	  chown(fstat.uid, fstat.gid, to)
118	rescue
119	end
120      end
121    end
122  end
123
124  alias mv move
125
126  #
127  # Returns +true+ if and only if the contents of files +from+ and +to+ are
128  # identical. If +verbose+ is +true+, <tt>from <=> to</tt> is printed.
129  #
130  def compare(from, to, verbose = false)
131    $stderr.print from, " <=> ", to, "\n" if verbose
132
133    return false if stat(from).size != stat(to).size
134
135    from = open(from, "rb")
136    to = open(to, "rb")
137
138    ret = false
139    fr = tr = ''
140
141    begin
142      while fr == tr
143	fr = from.read(BUFSIZE)
144	if fr
145	  tr = to.read(fr.size)
146	else
147	  ret = to.read(BUFSIZE)
148	  ret = !ret || ret.length == 0
149	  break
150	end
151      end
152    rescue
153      ret = false
154    ensure
155      to.close
156      from.close
157    end
158    ret
159  end
160
161  alias cmp compare
162
163  #
164  # Removes a list of files. Each parameter should be the name of the file to
165  # delete. If the last parameter isn't a String, verbose mode will be enabled.
166  # Returns the number of files deleted.
167  #
168  def safe_unlink(*files)
169    verbose = if files[-1].is_a? String then false else files.pop end
170    files.each do |file|
171      begin
172        unlink file
173        $stderr.print "removing ", file, "\n" if verbose
174      rescue Errno::EACCES # for Windows
175        continue if symlink? file
176        begin
177          mode = stat(file).mode
178          o_chmod mode | 0200, file
179          unlink file
180          $stderr.print "removing ", file, "\n" if verbose
181        rescue
182          o_chmod mode, file rescue nil
183        end
184      rescue
185      end
186    end
187  end
188
189  alias rm_f safe_unlink
190
191  #
192  # Creates a directory and all its parent directories.
193  # For example,
194  #
195  #	File.makedirs '/usr/lib/ruby'
196  #
197  # causes the following directories to be made, if they do not exist.
198  #	* /usr
199  #	* /usr/lib
200  #	* /usr/lib/ruby
201  #
202  # You can pass several directories, each as a parameter. If the last
203  # parameter isn't a String, verbose mode will be enabled.
204  #
205  def makedirs(*dirs)
206    verbose = if dirs[-1].is_a? String then false else dirs.pop end
207    mode = 0755
208    for dir in dirs
209      parent = dirname(dir)
210      next if parent == dir or directory? dir
211      makedirs parent unless directory? parent
212      $stderr.print "mkdir ", dir, "\n" if verbose
213      if basename(dir) != ""
214        begin
215          Dir.mkdir dir, mode
216        rescue SystemCallError
217          raise unless directory? dir
218        end
219      end
220    end
221  end
222
223  alias mkpath makedirs
224
225  alias o_chmod chmod
226
227  vsave, $VERBOSE = $VERBOSE, false
228
229  #
230  # Changes permission bits on +files+ to the bit pattern represented
231  # by +mode+. If the last parameter isn't a String, verbose mode will
232  # be enabled.
233  #
234  #   File.chmod 0755, 'somecommand'
235  #   File.chmod 0644, 'my.rb', 'your.rb', true
236  #
237  def chmod(mode, *files)
238    verbose = if files[-1].is_a? String then false else files.pop end
239    $stderr.printf "chmod %04o %s\n", mode, files.join(" ") if verbose
240    o_chmod mode, *files
241  end
242  $VERBOSE = vsave
243
244  #
245  # If +src+ is not the same as +dest+, copies it and changes the permission
246  # mode to +mode+. If +dest+ is a directory, destination is <tt>dest/src</tt>.
247  # If +mode+ is not set, default is used. If +verbose+ is set to true, the
248  # name of each file copied will be printed.
249  #
250  def install(from, to, mode = nil, verbose = false)
251    to = catname(from, to)
252    unless exist? to and cmp from, to
253      safe_unlink to if exist? to
254      cp from, to, verbose
255      chmod mode, to, verbose if mode
256    end
257  end
258
259end
260
261# vi:set sw=2: