Module: Fontist::Utils::FileOps

Defined in:
lib/fontist/utils/file_ops.rb

Class Method Summary collapse

Class Method Details

.safe_cp_r(src, dest, **options) ⇒ Object

Safe file copy with Windows compatibility

Parameters:

  • src (String)

    Source path

  • dest (String)

    Destination path

  • options (Hash)

    Options passed to FileUtils.cp_r



55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/fontist/utils/file_ops.rb', line 55

def self.safe_cp_r(src, dest, **options)
  FileUtils.cp_r(src, dest, **options)
rescue Errno::EACCES
  if System.windows?
    # Retry once after brief pause on Windows
    sleep(0.1)
    GC.start
    FileUtils.cp_r(src, dest, **options)
  else
    raise
  end
end

.safe_mkdir_p(path, **options) ⇒ Object

Safe directory creation with Windows compatibility

Parameters:

  • path (String)

    Directory path to create

  • options (Hash)

    Options passed to FileUtils.mkdir_p



72
73
74
75
76
77
78
79
80
81
82
# File 'lib/fontist/utils/file_ops.rb', line 72

def self.safe_mkdir_p(path, **options)
  FileUtils.mkdir_p(path, **options)
rescue Errno::EACCES
  if System.windows?
    # Retry once after brief pause on Windows
    sleep(0.1)
    FileUtils.mkdir_p(path, **options)
  else
    raise
  end
end

.safe_rm_rf(path, retries: 3) ⇒ Boolean

Safe file/directory deletion with Windows retry logic

Windows file locking can cause intermittent failures when deleting files that were recently accessed. This method implements retry logic with exponential backoff to handle these cases gracefully.

Parameters:

  • path (String)

    Path to file or directory to delete

  • retries (Integer) (defaults to: 3)

    Number of retry attempts (default: 3)

Returns:

  • (Boolean)

    true if deletion succeeded

Raises:

  • (Errno::EACCES, Errno::ENOTEMPTY)

    if all retries exhausted



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/fontist/utils/file_ops.rb', line 16

def self.safe_rm_rf(path, retries: 3)
  return FileUtils.rm_rf(path) unless System.windows?

  # Windows file locking retry with exponential backoff
  retries.times do |attempt|
    FileUtils.rm_rf(path)
    return true
  rescue Errno::EACCES, Errno::ENOTEMPTY
    if attempt < retries - 1
      # Exponential backoff: 0.1s, 0.2s, 0.3s
      sleep(0.1 * (attempt + 1))
      GC.start # Force garbage collection to release file handles
      next
    end
    raise
  end
end

.with_file_cleanup(_path) { ... } ⇒ Object

Ensure file handles are released before deletion (Windows-specific)

On Windows, file handles may not be immediately released after operations, causing deletion failures. This method ensures cleanup.

Parameters:

  • path (String)

    Path to file or directory

Yields:

  • Block to execute before cleanup



41
42
43
44
45
46
47
48
# File 'lib/fontist/utils/file_ops.rb', line 41

def self.with_file_cleanup(_path)
  yield
ensure
  if System.windows?
    GC.start
    sleep(0.05) # Brief pause to allow handle release
  end
end