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



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
394
395
# File 'lib/amp/support/support.rb', line 350

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



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

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.



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

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



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

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.



317
318
319
# File 'lib/amp/support/support.rb', line 317

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



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

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



496
497
498
# File 'lib/amp/support/support.rb', line 496

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:



450
451
452
453
454
# File 'lib/amp/support/support.rb', line 450

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



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

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.



508
509
510
511
512
# File 'lib/amp/support/support.rb', line 508

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.



53
54
55
# File 'lib/amp/support/ruby_19_compatibility.rb', line 53

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.



65
66
67
# File 'lib/amp/support/ruby_19_compatibility.rb', line 65

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.



59
60
61
# File 'lib/amp/support/ruby_19_compatibility.rb', line 59

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



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

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.



438
439
440
441
442
443
# File 'lib/amp/support/support.rb', line 438

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)



290
291
292
# File 'lib/amp/support/support.rb', line 290

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