Class: File

Inherits:
Object show all
Defined in:
lib/amp/dependencies/zip/stdrubyext.rb,
lib/amp/support/ruby_19_compatibility.rb,
lib/amp/support/support.rb

Direct Known Subclasses

BugFix::Tempfile

Defined Under Namespace

Classes: Stat

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.amp_atomic_write(file_name, mode = 'w', default_mode = nil, temp_dir = Dir.tmpdir, &block) ⇒ Object

taken from Rails’ ActiveSupport all or nothing babyyyyyyyy use this only for writes, otherwise it’s just inefficient file_name is FULL PATH



348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
# File 'lib/amp/support/support.rb', line 348

def self.amp_atomic_write(file_name, mode='w', default_mode=nil, temp_dir=Dir.tmpdir, &block)
  File.makedirs(File.dirname(file_name))
  FileUtils.touch(file_name) unless File.exists? file_name
  # this is sorta like "checking out" a file
  # but only if we're *just* writing
  new_path = join temp_dir, amp_make_tmpname(basename(file_name))
  unless mode == 'w'
    copy(file_name, new_path) # allowing us to use mode "a" and others
  end

  
  # open and close it
  val = Kernel::open new_path, mode, &block
  
  begin
    # Get original file permissions
    old_stat = stat(file_name)
  rescue Errno::ENOENT
    # No old permissions, write a temp file to determine the defaults
    check_name = ".permissions_check.#{Thread.current.object_id}.#{Process.pid}.#{rand(1000000)}"
    Kernel::open(check_name, "w") { }
    old_stat = stat(check_name)
    unlink(check_name)
    delete(check_name)
  end
  
  # do a chmod, pretty much
  begin
    nlink = File.amp_num_hardlinks(file_name)
  rescue Errno::ENOENT, OSError
    nlink = 0
    d = File.dirname(file_name)
    File.mkdir_p(d, default_mode) unless File.directory? d
  end
  
  new_mode = default_mode & 0666 if default_mode
  
  # Overwrite original file with temp file
  amp_force_rename(new_path, file_name)
  
  # Set correct permissions on new file
  chown(old_stat.uid, old_stat.gid, file_name)
  chmod(new_mode || old_stat.mode, file_name)
  
  val
end

.amp_directories_to(path, empty = false) ⇒ Array

All directories leading up to this path

Examples:

directories_to “/Users/ari/src/monkey.txt” # =>

["/Users/ari/src", "/Users/ari", "/Users"]

directories_to “/Users/ari/src/monkey.txt”, true # =>

["/Users/ari/src", "/Users/ari", "/Users", ""]

Parameters:

  • path (String)

    the path to the file we’re examining

  • empty (Boolean) (defaults to: false)

    whether or not to return an empty string as well

Returns:

  • (Array)

    the directories leading up to this path



464
465
466
467
468
469
470
471
# File 'lib/amp/support/support.rb', line 464

def self.amp_directories_to(path, empty=false)
  dirs = path.split('/')[0..-2]
  ret  = []
  
  dirs.size.times { ret << dirs.join('/'); dirs.pop }
  ret << '' if empty
  ret
end

.amp_find_executable(command) ⇒ String?

TODO:

Add Windows Version.

Finds an executable for Amp::KernelMethods#command. Searches like the OS does. If command is a basename then PATH is searched for Amp::KernelMethods#command. PATH isn’t searched if command is an absolute or relative path. If command isn’t found, nil is returned. *nix only.

Parameters:

  • command (String)

    the executable to find

Returns:

  • (String, nil)

    If the executable is found, the full path is returned.



328
329
330
331
332
333
334
335
336
337
338
339
340
341
# File 'lib/amp/support/support.rb', line 328

def self.amp_find_executable(command)
  find_if_exists = proc do |executable|
    return executable if File.exist? executable
    return nil
  end
  
  return find_if_exists[command] if command.include?(File::SEPARATOR)
  ENV["PATH"].split(File::PATH_SEPARATOR).each do |path|
    executable = find_if_exists[File.join(path, command)]
    return executable if executable
  end
  
  nil
end

.amp_force_rename(file, dst) ⇒ Object

Forces a rename from file to dst, removing the dst file if it already exists. Avoids system exceptions that might result.

Parameters:

  • file (String)

    the source file path

  • dst (String)

    the destination file path



479
480
481
482
483
484
485
486
487
# File 'lib/amp/support/support.rb', line 479

def self.amp_force_rename(file, dst)
  return unless File.exist? file
  if File.exist? dst
    File.unlink dst
    File.rename file, dst
  else
    File.rename file, dst
  end
end

.amp_lookup_reg(a, b) ⇒ Object

TODO:

Add Windows Version

Does a registry lookup. *nix version.



315
316
317
# File 'lib/amp/support/support.rb', line 315

def self.amp_lookup_reg(a,b)
  nil
end

.amp_make_tmpname(basename) ⇒ String

Makes a fancy, quite-random name for a temporary file. Uses the file’s name, the current time, the process number, a random number, and the file’s extension to make a very random filename.

Of course, it could still fail.

Parameters:

  • basename (String)

    The base name of the file - just the file’s name and extension

Returns:

  • (String)

    the pseudo-random name of the file to be created



404
405
406
407
408
409
410
411
412
413
414
# File 'lib/amp/support/support.rb', line 404

def self.amp_make_tmpname(basename)
  case basename
  when Array
    prefix, suffix = *basename
  else
    prefix, suffix = basename, "."+File.extname(basename)
  end

  t = Time.now.strftime("%Y%m%d")
  path = "#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}-#{suffix}"
end

.amp_name(file) ⇒ Object

Returns the full name of the file, excluding path information.

Parameters:

Returns:

  • the name of the file



494
495
496
# File 'lib/amp/support/support.rb', line 494

def self.amp_name(file)
  File.split(file.path).last
end

Finds the number of hard links to the file.

Parameters:

  • file (String)

    the full path to the file to lookup

Returns:

  • (Integer)

    the number of hard links to the file

Raises:



448
449
450
451
452
# File 'lib/amp/support/support.rb', line 448

def self.amp_num_hardlinks(file)
  lstat = File.lstat(file)
  raise OSError.new("no lstat on windows") if lstat.nil?
  lstat.nlink
end

.amp_set_executable(path, executable) ⇒ Object

TODO:

Windows version

Sets a file’s executable bit.

Parameters:

  • path (String)

    the path to the file

  • executable (Boolean)

    sets whether the file is executable or not



298
299
300
301
302
303
304
305
306
307
308
# File 'lib/amp/support/support.rb', line 298

def self.amp_set_executable(path, executable)
  s = File.lstat(path).mode
  sx = s & 0100
  if executable && !sx
    # Turn on +x for every +r bit when making a file executable
    # and obey umask. (direct from merc. source)
    File.chmod(s | (s & 0444) >> 2 & ~(File.umask(0)), path)
  elsif !executable && sx
    File.chmod(s & 0666 , path)
  end
end

.amp_split_extension(path) ⇒ String

Splits the path into two parts: pre-extension, and extension, including the dot. File.amp_split_extension “/usr/bin/conf.ini” => [“conf”,“.ini”]

Parameters:

  • path (String)

    the path to the file to split up

Returns:

  • (String, String)

    the [filename pre extension, file extension] of the file provided.



506
507
508
509
510
# File 'lib/amp/support/support.rb', line 506

def self.amp_split_extension(path)
  ext  = File.extname  path
  base = File.basename path, ext
  [base, ext]
end

.copy(*args) ⇒ Object

This is in ftools in Ruby 1.8.x, but now it’s in FileUtils. So this is essentially an alias to it. Silly ftools, trix are for kids.



50
51
52
# File 'lib/amp/support/ruby_19_compatibility.rb', line 50

def self.copy(*args)
  FileUtils.copy(*args)
end

.makedirs(*args) ⇒ Object

This is in ftools in Ruby 1.8.x, but now it’s in FileUtils. So this is essentially an alias to it. Silly ftools, trix are for kids.



62
63
64
# File 'lib/amp/support/ruby_19_compatibility.rb', line 62

def self.makedirs(*args)
  FileUtils.makedirs(*args)
end

.move(*args) ⇒ Object

This is in ftools in Ruby 1.8.x, but now it’s in FileUtils. So this is essentially an alias to it. Silly ftools, trix are for kids.



56
57
58
# File 'lib/amp/support/ruby_19_compatibility.rb', line 56

def self.move(*args)
  FileUtils.move(*args)
end

.read(fileName) ⇒ Object

singleton method read does not exist in 1.6.x



29
30
31
# File 'lib/amp/dependencies/zip/stdrubyext.rb', line 29

def self.read(fileName)
  open(fileName) { |f| f.read }
end

Instance Method Details

#[](range) ⇒ String

Reads a range from the file.

Parameters:

  • range (Range)

    the byte indices to read between (and including)

Returns:

  • (String)

    the data read from the file



421
422
423
424
425
426
427
# File 'lib/amp/support/support.rb', line 421

def [](range)
  p = pos
  seek(range.first)
  val = read(range.last - range.first + 1)
  seek p
  val
end

#amp_each_chunk(num_bytes = 4.kb) {|the| ... } ⇒ Object

Reads n bytes at a time and yield them from the given file

Parameters:

  • num_bytes (Integer) (defaults to: 4.kb)

    the number of bytes to yield

Yields:

  • Yields a chunk that is at most num_bytes from the file until the file is exhausted. Poor file, it’s so tired.

Yield Parameters:

  • the (String)

    chunk from the file.



436
437
438
439
440
441
# File 'lib/amp/support/support.rb', line 436

def amp_each_chunk(num_bytes = 4.kb)
  buffer = nil
  while buffer = read(num_bytes)
    yield buffer
  end
end

#amp_lexist?(filename) ⇒ Boolean

Checks if a file exists, without following symlinks.

Parameters:

  • filename (String)

    the path to the file to check

Returns:

  • (Boolean)

    whether or not the file exists (ignoring symlinks)



288
289
290
# File 'lib/amp/support/support.rb', line 288

def amp_lexist?(filename)
  !!File.lstat(filename) rescue false
end