This file is indexed.

/usr/bin/sup-recover-sources is in sup-mail 0.22.1-2.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
87
#!/usr/bin/ruby

$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])

require 'optparse'

$opts = {
  :unusual => false,
  :archive => false,
  :scan_num => 10,
}


OPTIONPARSERSUCKS = "\n" + " " * 38
OptionParser.new do |opts|
  opts.banner = <<EOS
Usage: sup-recover-sources [options] <source>+

Rebuilds a lost sources.yaml file by reading messages from a list of
sources and determining, for each source, the most prevalent
'source_id' field of messages from that source in the index.

The only non-deterministic component to this is that if the same
message appears in multiple sources, those sources may be
mis-diagnosed by this program.

If the first N messages (--scan-num below) all have the same source_id
in the index, the source will be added to sources.yaml. Otherwise, the
distribution will be printed, and you will have to add it by hand.

The offset pointer into the sources will be set to the end of the source,
so you will have to run sup-import --rebuild for each new source after
doing this.

Options include:
EOS

  opts.on("--unusual", "Mark sources as 'unusual'. Only usual#{OPTIONPARSERSUCKS}sources will be polled by hand. Default:#{OPTIONPARSERSUCKS}#{$opts[:unusual]}.") { $opts[:unusual] = true }

  opts.on("--archive", "Mark sources as 'archive'. New messages#{OPTIONPARSERSUCKS}from these sources will not appear in#{OPTIONPARSERSUCKS}the inbox. Default: #{$opts[:archive]}.") { $opts[:archive] = true }

  opts.on("--scan-num N", Integer, "Number of messages to scan per source.#{OPTIONPARSERSUCKS}Default: #{$opts[:scan_num]}.") do |n|
    $opts[:scan_num] = n
  end

  opts.on_tail("-h", "--help", "Show this message") do
    puts opts
    exit
  end
end.parse(ARGV)

require "sup"
Redwood::start
puts "loading index..."
index = Redwood::Index.init
index.load
puts "loaded index of #{index.size} messages"

ARGV.each do |fn|
  next if Redwood::SourceManager.source_for fn

  ## TODO: merge this code with the same snippet in import
  source = Redwood::MBox.new(fn, nil, !$opts[:unusual], $opts[:archive])

  source_ids = Hash.new 0
  count = 0
  source.each do |offset, labels|
    m = Redwood::Message.new :source => source, :source_info => offset
    m.load_from_source!
    source_id = Redwood::SourceManager.source_for_id m.id
    next unless source_id
    source_ids[source_id] += 1
    count += 1
    break if count == $opts[:scan_num]
  end

  if source_ids.size == 1
    id = source_ids.keys.first.to_i
    puts "assigned #{source} to #{source_ids.keys.first}"
    source.id = id
    Redwood::SourceManager.add_source source
  else
    puts ">> unable to determine #{source}: #{source_ids.inspect}"
  end
end

index.save