Class: Metaclean::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/metaclean/runner.rb

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Runner

Returns a new instance of Runner.



18
19
20
# File 'lib/metaclean/runner.rb', line 18

def initialize(options)
  @options = options
end

Instance Method Details

#clean_paths(paths) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/metaclean/runner.rb', line 42

def clean_paths(paths)
  files = expand_files(paths)
  # See inspect_paths: nothing to act on is a non-zero condition, not success.
  if files.empty?
    Display.warning('No files to process.')
    exit 1
  end

  announce_tools

  # Confirmation prompt — skipped for --force and --dry-run (since
  # dry-run never modifies anything anyway).
  unless @options[:force] || @options[:dry_run]
    action = @options[:in_place] ? 'OVERWRITE' : 'create cleaned copies of'
    puts Display.c("About to #{action} #{files.size} file(s).", :yellow)
    if @options[:in_place]
      puts Display.c('Backups will be saved alongside as <file>.bak.', :gray)
    end
    print Display.c('Proceed? [y/N] ', :bold)
    ans = $stdin.gets&.strip&.downcase # gets → nil on Ctrl-D
    return Display.warning('Aborted.') unless %w[y yes].include?(ans)
  end

  summary = { cleaned: 0, unverified: 0, failed: 0, removed_total: 0, residual_files: 0 }

  # index/total let clean_one render "[3/47]" in batch mode.
  files.each_with_index do |file, idx|
    result = clean_one(file, index: idx + 1, total: files.size)
    summary[result[:status]] += 1
    summary[:removed_total]  += result[:removed].to_i
    summary[:residual_files] += 1 if result[:residual].to_i.positive?
  rescue Error, SystemCallError => e
    # One bad file shouldn't abort the whole batch. SystemCallError
    # (Errno::*: disk full, permission denied, read-only fs) is a SIBLING
    # of our Error, not a subclass, so it must be named explicitly or it
    # would escape this rescue and crash the run with a raw backtrace.
    warn Display.error("#{file}: #{e.message}")
    summary[:failed] += 1
  end

  print_summary(summary)

  # Non-zero exit so CI/scripts can detect a failed or not-fully-verified file.
  exit 1 if summary[:failed].positive? || summary[:unverified].positive?
end

#inspect_paths(paths) ⇒ Object

Public entry points: one for ‘–inspect`, one for the cleaning flow.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/metaclean/runner.rb', line 24

def inspect_paths(paths)
  files = expand_files(paths)
  if files.empty?
    Display.warning('No files to inspect.')
    exit 1
  end
  files.each do |file|
    Display.header "📄 #{file}"
    meta = Exiftool.read(file)
    Display.section "Metadata (#{Display.count_embedded(meta)} embedded tags)"
    Display.(meta)
  rescue Error, SystemCallError => e
    # One unreadable/odd file shouldn't abort inspecting the rest — mirrors
    # the per-file rescue in the clean batch.
    warn Display.error("#{file}: #{e.message}")
  end
end