sup 0.11 → 0.12
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sup might be problematic. Click here for more details.
- data/CONTRIBUTORS +16 -5
- data/History.txt +9 -0
- data/ReleaseNotes +9 -0
- data/bin/sup +9 -24
- data/bin/sup-add +3 -3
- data/bin/sup-config +1 -1
- data/bin/sup-dump +22 -9
- data/bin/sup-recover-sources +1 -11
- data/bin/sup-sync +65 -130
- data/bin/sup-sync-back +6 -5
- data/bin/sup-tweak-labels +5 -6
- data/lib/sup.rb +89 -71
- data/lib/sup/account.rb +3 -2
- data/lib/sup/buffer.rb +28 -16
- data/lib/sup/client.rb +92 -0
- data/lib/sup/crypto.rb +91 -49
- data/lib/sup/draft.rb +14 -17
- data/lib/sup/hook.rb +10 -5
- data/lib/sup/index.rb +72 -28
- data/lib/sup/logger.rb +1 -1
- data/lib/sup/maildir.rb +55 -112
- data/lib/sup/mbox.rb +151 -6
- data/lib/sup/message-chunks.rb +20 -4
- data/lib/sup/message.rb +183 -76
- data/lib/sup/modes/compose-mode.rb +2 -1
- data/lib/sup/modes/console-mode.rb +4 -1
- data/lib/sup/modes/edit-message-mode.rb +50 -5
- data/lib/sup/modes/line-cursor-mode.rb +1 -0
- data/lib/sup/modes/reply-mode.rb +17 -11
- data/lib/sup/modes/thread-index-mode.rb +10 -9
- data/lib/sup/modes/thread-view-mode.rb +48 -2
- data/lib/sup/poll.rb +56 -60
- data/lib/sup/protocol.rb +161 -0
- data/lib/sup/sent.rb +8 -11
- data/lib/sup/server.rb +116 -0
- data/lib/sup/source.rb +15 -33
- data/lib/sup/thread.rb +6 -0
- data/lib/sup/util.rb +44 -39
- metadata +126 -88
- data/lib/sup/connection.rb +0 -63
- data/lib/sup/imap.rb +0 -349
- data/lib/sup/mbox/loader.rb +0 -180
- data/lib/sup/mbox/ssh-file.rb +0 -254
- data/lib/sup/mbox/ssh-loader.rb +0 -74
data/CONTRIBUTORS
CHANGED
@@ -3,6 +3,7 @@ Rich Lane <rlane at the club.cc.cmu dot edus>
|
|
3
3
|
Ismo Puustinen <ismo at the iki dot fis>
|
4
4
|
Nicolas Pouillard <nicolas.pouillard at the gmail dot coms>
|
5
5
|
Eric Sherman <hyperbolist at the gmail dot coms>
|
6
|
+
Michael Stapelberg <michael at the stapelberg dot des>
|
6
7
|
Ben Walton <bwalton at the artsci.utoronto dot cas>
|
7
8
|
Mike Stipicevic <stipim at the rpi dot edus>
|
8
9
|
Marcus Williams <marcus-sup at the bar-coded dot nets>
|
@@ -10,34 +11,44 @@ Lionel Ott <white.magic at the gmx dot des>
|
|
10
11
|
Tero Tilus <tero at the tilus dot nets>
|
11
12
|
Ingmar Vanhassel <ingmar at the exherbo dot orgs>
|
12
13
|
Mark Alexander <marka at the pobox dot coms>
|
14
|
+
Gaute Hope <eg at the gaute.vetsj dot coms>
|
13
15
|
Christopher Warrington <chrisw at the rice dot edus>
|
16
|
+
W. Trevor King <wking at the drexel dot edus>
|
17
|
+
Gaudenz Steinlin <gaudenz at the soziologie dot chs>
|
14
18
|
Richard Brown <rbrown at the exherbo dot orgs>
|
15
19
|
Marc Hartstein <marc.hartstein at the alum.vassar dot edus>
|
20
|
+
Sascha Silbe <sascha-pgp at the silbe dot orgs>
|
16
21
|
Israel Herraiz <israel.herraiz at the gmail dot coms>
|
17
22
|
Anthony Martinez <pi+sup at the pihost dot uss>
|
18
|
-
|
23
|
+
Hamish Downer <dmishd at the gmail dot coms>
|
19
24
|
Bo Borgerson <gigabo at the gmail dot coms>
|
20
25
|
William Erik Baxter <web at the superscript dot coms>
|
26
|
+
Michael Hamann <michael at the content-space dot des>
|
21
27
|
Grant Hollingworth <grant at the antiflux dot orgs>
|
22
28
|
Adeodato Simó <dato at the net.com.org dot ess>
|
23
29
|
Daniel Schoepe <daniel.schoepe at the googlemail dot coms>
|
30
|
+
Jason Petsod <jason at the petsod dot orgs>
|
24
31
|
Steve Goldman <sgoldman at the tower-research dot coms>
|
25
32
|
Edward Z. Yang <ezyang at the MIT dot EDUs>
|
26
33
|
Decklin Foster <decklin at the red-bean dot coms>
|
27
34
|
Cameron Matheson <cam+sup at the cammunism dot orgs>
|
28
35
|
Carl Worth <cworth at the cworth dot orgs>
|
36
|
+
Jeff Balogh <its.jeff.balogh at the gmail dot coms>
|
29
37
|
Andrew Pimlott <andrew at the pimlott dot nets>
|
30
38
|
Alex Vandiver <alexmv at the mit dot edus>
|
31
|
-
Jeff Balogh <its.jeff.balogh at the gmail dot coms>
|
32
39
|
Peter Harkins <ph at the malaprop dot orgs>
|
33
40
|
Kornilios Kourtis <kkourt at the cslab.ece.ntua dot grs>
|
34
|
-
Michael Hamann <michael at the content-space dot des>
|
35
41
|
Giorgio Lando <patroclo7 at the gmail dot coms>
|
42
|
+
Damien Leone <damien.leone at the fensalir dot frs>
|
36
43
|
Benoît PIERRE <benoit.pierre at the gmail dot coms>
|
44
|
+
Alvaro Herrera <alvherre at the alvh.no-ip dot orgs>
|
37
45
|
Jonah <Jonah at the GoodCoffee dot cas>
|
46
|
+
Adam Lloyd <adam at the alloy-d dot nets>
|
47
|
+
Todd Eisenberger <teisenbe at the andrew.cmu dot edus>
|
38
48
|
ian <ian at the lorf dot orgs>
|
39
49
|
Steven Walter <swalter at the monarch.(none)>
|
40
|
-
|
41
|
-
Stefan Lundström <lundst at the snabb.(none)>
|
50
|
+
ian <itaylor at the uark dot edus>
|
42
51
|
Jon M. Dugan <jdugan at the es dot nets>
|
52
|
+
Gregor Hoffleit <gregor at the sam.mediasupervision dot des>
|
53
|
+
Stefan Lundström <lundst at the snabb.(none)>
|
43
54
|
Kirill Smelkov <kirr at the landau.phys.spbu dot rus>
|
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 0.12 / 2011-01-13
|
2
|
+
* Remove deprecated IMAP, IMAPS, and mbox+ssh sources
|
3
|
+
* Inline GPG support
|
4
|
+
* Robust maildir support
|
5
|
+
* sup-dump compatibility between Sup versions
|
6
|
+
* New hook: sendmail
|
7
|
+
* Better Ruby 1.9/UTF8 support
|
8
|
+
* As always, many bugfixes and tweaks.
|
9
|
+
|
1
10
|
== 0.11 / 2010-03-07
|
2
11
|
* Remove deprecated Ferret backend.
|
3
12
|
* Add deprecation notices to IMAP, IMAPS, and mbox+ssh sources.
|
data/ReleaseNotes
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
Release 0.12:
|
2
|
+
|
3
|
+
Deprecated remote sources have been removed.
|
4
|
+
|
5
|
+
Maildir support has been improved to gracefully handle messages that
|
6
|
+
move or disappear. The "out of sync" errors should no longer occur.
|
7
|
+
|
8
|
+
Inline GPG is now supported.
|
9
|
+
|
1
10
|
Release 0.11:
|
2
11
|
|
3
12
|
The deprecated Ferret index has been removed.
|
data/bin/sup
CHANGED
@@ -12,7 +12,7 @@ end
|
|
12
12
|
|
13
13
|
require 'fileutils'
|
14
14
|
require 'trollop'
|
15
|
-
require "sup"; Redwood::check_library_version_against "0.
|
15
|
+
require "sup"; Redwood::check_library_version_against "0.12"
|
16
16
|
|
17
17
|
if ENV['SUP_PROFILE']
|
18
18
|
require 'ruby-prof'
|
@@ -49,7 +49,7 @@ No variables.
|
|
49
49
|
No return value.
|
50
50
|
EOS
|
51
51
|
|
52
|
-
Redwood::HookManager.register "shutdown", <<EOS
|
52
|
+
Redwood::HookManager.register "shutdown", <<EOS
|
53
53
|
Executes when sup is shutting down. May be run when sup is crashing,
|
54
54
|
so don\'t do anything too important. Run before the label, contacts,
|
55
55
|
and people are saved.
|
@@ -58,6 +58,7 @@ No return value.
|
|
58
58
|
EOS
|
59
59
|
|
60
60
|
if $opts[:list_hooks]
|
61
|
+
Redwood.start
|
61
62
|
Redwood::HookManager.print_hooks
|
62
63
|
exit
|
63
64
|
end
|
@@ -86,6 +87,7 @@ global_keymap = Keymap.new do |k|
|
|
86
87
|
k.add :nothing, "Do nothing", :ctrl_g
|
87
88
|
k.add :recall_draft, "Edit most recent draft message", 'R'
|
88
89
|
k.add :show_inbox, "Show the Inbox buffer", 'I'
|
90
|
+
k.add :clear_hooks, "Clear all hooks", 'H'
|
89
91
|
k.add :show_console, "Show the Console buffer", '~'
|
90
92
|
|
91
93
|
## Submap for less often used keybindings
|
@@ -94,8 +96,6 @@ global_keymap = Keymap.new do |k|
|
|
94
96
|
kk.add :run_keybindings_hook, "Rerun keybindings hook", 'k'
|
95
97
|
end
|
96
98
|
end
|
97
|
-
|
98
|
-
Redwood::Keymap.run_hook global_keymap
|
99
99
|
|
100
100
|
## the following magic enables wide characters when used with a ruby
|
101
101
|
## ncurses.so that's been compiled against libncursesw. (note the w.) why
|
@@ -154,26 +154,6 @@ begin
|
|
154
154
|
Index.load
|
155
155
|
Index.start_sync_worker unless $opts[:no_threads]
|
156
156
|
|
157
|
-
if Redwood::SourceManager.sources.any? { |x| x.is_a? Redwood::MBox::SSHLoader }
|
158
|
-
$stderr.puts <<EOS
|
159
|
-
mbox+ssh sources are deprecated and will be removed in the next release.
|
160
|
-
Running rsync in your before-poll hook is a good alternative.
|
161
|
-
|
162
|
-
Press enter to continue.
|
163
|
-
EOS
|
164
|
-
$stdin.gets
|
165
|
-
end
|
166
|
-
|
167
|
-
if Redwood::SourceManager.sources.any? { |x| x.is_a? Redwood::IMAP }
|
168
|
-
$stderr.puts <<EOS
|
169
|
-
IMAP sources are deprecated and will be removed in the next release.
|
170
|
-
Running offlineimap or fetchmail in your before-poll hook is a good alternative.
|
171
|
-
|
172
|
-
Press enter to continue.
|
173
|
-
EOS
|
174
|
-
$stdin.gets
|
175
|
-
end
|
176
|
-
|
177
157
|
$die = false
|
178
158
|
trap("TERM") { |x| $die = true }
|
179
159
|
trap("WINCH") { |x| BufferManager.sigwinch_happened! }
|
@@ -192,6 +172,7 @@ EOS
|
|
192
172
|
end
|
193
173
|
|
194
174
|
HookManager.run "startup"
|
175
|
+
Redwood::Keymap.run_hook global_keymap
|
195
176
|
|
196
177
|
debug "starting curses"
|
197
178
|
Redwood::Logger.remove_sink $stderr
|
@@ -318,6 +299,8 @@ EOS
|
|
318
299
|
SearchResultsMode.spawn_from_query "is:unread"
|
319
300
|
when :list_labels
|
320
301
|
labels = LabelManager.all_labels.map { |l| LabelManager.string_for l }
|
302
|
+
labels = labels.each { |l| l.force_encoding 'UTF-8' if l.methods.include?(:encoding) }
|
303
|
+
|
321
304
|
user_label = bm.ask_with_completions :label, "Show threads with label (enter for listing): ", labels
|
322
305
|
unless user_label.nil?
|
323
306
|
if user_label.empty?
|
@@ -350,6 +333,8 @@ EOS
|
|
350
333
|
end
|
351
334
|
when :show_inbox
|
352
335
|
BufferManager.raise_to_front ibuf
|
336
|
+
when :clear_hooks
|
337
|
+
HookManager.clear
|
353
338
|
when :show_console
|
354
339
|
b, new = bm.spawn_unless_exists("Console", :system => true) { ConsoleMode.new }
|
355
340
|
b.mode.run
|
data/bin/sup-add
CHANGED
@@ -4,7 +4,7 @@ require 'uri'
|
|
4
4
|
require 'rubygems'
|
5
5
|
require 'highline/import'
|
6
6
|
require 'trollop'
|
7
|
-
require "sup"; Redwood::check_library_version_against "0.
|
7
|
+
require "sup"; Redwood::check_library_version_against "0.12"
|
8
8
|
|
9
9
|
$opts = Trollop::options do
|
10
10
|
version "sup-add (sup #{Redwood::VERSION})"
|
@@ -97,9 +97,9 @@ begin
|
|
97
97
|
source =
|
98
98
|
case parsed_uri.scheme
|
99
99
|
when "maildir"
|
100
|
-
Redwood::Maildir.new uri,
|
100
|
+
Redwood::Maildir.new uri, !$opts[:unusual], $opts[:archive], nil, labels
|
101
101
|
when "mbox"
|
102
|
-
Redwood::MBox
|
102
|
+
Redwood::MBox.new uri, !$opts[:unusual], $opts[:archive], nil, labels
|
103
103
|
when nil
|
104
104
|
Trollop::die "Sources must be specified with an URI"
|
105
105
|
else
|
data/bin/sup-config
CHANGED
data/bin/sup-dump
CHANGED
@@ -1,17 +1,20 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
|
+
require 'xapian'
|
4
5
|
require 'trollop'
|
5
|
-
require
|
6
|
+
require 'set'
|
7
|
+
|
8
|
+
BASE_DIR = ENV["SUP_BASE"] || File.join(ENV["HOME"], ".sup")
|
6
9
|
|
7
10
|
$opts = Trollop::options do
|
8
|
-
version "sup-dump
|
11
|
+
version "sup-dump"
|
9
12
|
banner <<EOS
|
10
13
|
Dumps all message state from the sup index to standard out. You can
|
11
14
|
later use sup-sync --restored --restore <filename> to recover the index.
|
12
15
|
|
13
|
-
This tool is primarily useful in the event that a
|
14
|
-
|
16
|
+
This tool is primarily useful in the event that a Sup upgrade breaks index
|
17
|
+
format compatibility.
|
15
18
|
|
16
19
|
Usage:
|
17
20
|
sup-dump > <filename>
|
@@ -19,10 +22,20 @@ Usage:
|
|
19
22
|
EOS
|
20
23
|
end
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
+
xapian = Xapian::Database.new File.join(BASE_DIR, 'xapian')
|
26
|
+
version = xapian.get_metadata 'rescue-version'
|
27
|
+
version = '0' if version.empty?
|
25
28
|
|
26
|
-
|
27
|
-
|
29
|
+
case version
|
30
|
+
when '0'
|
31
|
+
xapian.postlist('Kmail').each do |x|
|
32
|
+
begin
|
33
|
+
entry = Marshal.load(xapian.document(x.docid).data)
|
34
|
+
puts "#{entry[:message_id]} (#{entry[:labels].sort_by { |l| l.to_s } * ' '})"
|
35
|
+
rescue
|
36
|
+
$stderr.puts "failed to dump document #{x.docid}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
else
|
40
|
+
abort "this sup-dump version doesn't understand your index"
|
28
41
|
end
|
data/bin/sup-recover-sources
CHANGED
@@ -58,17 +58,7 @@ ARGV.each do |fn|
|
|
58
58
|
next if Redwood::SourceManager.source_for fn
|
59
59
|
|
60
60
|
## TODO: merge this code with the same snippet in import
|
61
|
-
source =
|
62
|
-
case fn
|
63
|
-
when %r!^imaps?://!
|
64
|
-
print "Username for #{fn}: "
|
65
|
-
username = $stdin.gets.chomp
|
66
|
-
print "Password for #{fn} (warning: cleartext): "
|
67
|
-
password = $stdin.gets.chomp
|
68
|
-
Redwood::IMAP.new(fn, username, password, nil, !$opts[:unusual], $opts[:archive])
|
69
|
-
else
|
70
|
-
Redwood::MBox::Loader.new(fn, nil, !$opts[:unusual], $opts[:archive])
|
71
|
-
end
|
61
|
+
source = Redwood::MBox.new(fn, nil, !$opts[:unusual], $opts[:archive])
|
72
62
|
|
73
63
|
source_ids = Hash.new 0
|
74
64
|
count = 0
|
data/bin/sup-sync
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'uri'
|
4
4
|
require 'rubygems'
|
5
5
|
require 'trollop'
|
6
|
-
require "sup"; Redwood::check_library_version_against "0.
|
6
|
+
require "sup"; Redwood::check_library_version_against "0.12"
|
7
7
|
|
8
8
|
PROGRESS_UPDATE_INTERVAL = 15 # seconds
|
9
9
|
|
@@ -53,16 +53,6 @@ where <source>* is zero or more source URIs. If no sources are given,
|
|
53
53
|
sync from all usual sources. Supported source URI schemes can be seen
|
54
54
|
by running "sup-add --help".
|
55
55
|
|
56
|
-
Options controlling WHICH messages sup-sync operates on:
|
57
|
-
EOS
|
58
|
-
opt :new, "Operate on new messages only. Don't scan over the entire source. (Default.)", :short => :none
|
59
|
-
opt :changed, "Scan over the entire source for messages that have been deleted, altered, or moved from another source."
|
60
|
-
opt :restored, "Operate only on those messages included in a dump file as specified by --restore which have changed state."
|
61
|
-
opt :all, "Operate on all messages in the source, regardless of newness or changedness."
|
62
|
-
opt :start_at, "For --changed, --restored and --all, start at a particular offset.", :type => :int
|
63
|
-
|
64
|
-
text <<EOS
|
65
|
-
|
66
56
|
Options controlling HOW message state is altered:
|
67
57
|
EOS
|
68
58
|
opt :asis, "If the message is already in the index, preserve its state. Otherwise, use default source state. (Default.)", :short => :none
|
@@ -82,16 +72,9 @@ EOS
|
|
82
72
|
opt :dry_run, "Don't actually modify the index. Probably only useful with --verbose.", :short => "-n"
|
83
73
|
opt :version, "Show version information", :short => :none
|
84
74
|
|
85
|
-
conflicts :changed, :all, :new, :restored
|
86
75
|
conflicts :asis, :restore, :discard
|
87
76
|
end
|
88
|
-
Trollop::die :restored, "requires --restore" if opts[:restored] unless opts[:restore]
|
89
|
-
if opts[:start_at]
|
90
|
-
Trollop::die :start_at, "must be non-negative" if opts[:start_at] < 0
|
91
|
-
Trollop::die :start_at, "requires either --changed, --restored or --all" unless opts[:changed] || opts[:restored] || opts[:all]
|
92
|
-
end
|
93
77
|
|
94
|
-
target = [:new, :changed, :all, :restored].find { |x| opts[x] } || :new
|
95
78
|
op = [:asis, :restore, :discard].find { |x| opts[x] } || :asis
|
96
79
|
|
97
80
|
Redwood::start
|
@@ -116,6 +99,12 @@ index.lock_interactively or exit
|
|
116
99
|
begin
|
117
100
|
index.load
|
118
101
|
|
102
|
+
if(s = Redwood::SourceManager.source_for Redwood::SentManager.source_uri)
|
103
|
+
Redwood::SentManager.source = s
|
104
|
+
else
|
105
|
+
Redwood::SourceManager.add_source Redwood::SentManager.default_source
|
106
|
+
end
|
107
|
+
|
119
108
|
sources = if opts[:all_sources]
|
120
109
|
Redwood::SourceManager.sources
|
121
110
|
elsif ARGV.empty?
|
@@ -126,134 +115,80 @@ begin
|
|
126
115
|
end
|
127
116
|
end
|
128
117
|
|
129
|
-
## for all target specifications except for only-new messages, reset the
|
130
|
-
## source to the beginning (or to the user-specified starting point.)
|
131
|
-
unless target == :new
|
132
|
-
if opts[:start_at]
|
133
|
-
Trollop::die :start_at, "can only be used on one source" unless sources.size == 1
|
134
|
-
sources.first.seek_to! opts[:start_at]
|
135
|
-
sources.first.correct_offset! if sources.first.respond_to?(:correct_offset!)
|
136
|
-
else
|
137
|
-
sources.each { |s| s.reset! }
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
118
|
sources.each do |source|
|
142
119
|
puts "Scanning #{source}..."
|
143
120
|
num_added = num_updated = num_scanned = num_restored = 0
|
144
121
|
last_info_time = start_time = Time.now
|
145
122
|
|
146
|
-
Redwood::PollManager.
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
##
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
##
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
num_restored += 1
|
179
|
-
[:update_message_state, restored_state[m.id]]
|
180
|
-
elsif old_m.nil?
|
181
|
-
num_restored += 1
|
182
|
-
m.labels = restored_state[m.id]
|
183
|
-
:add_message
|
184
|
-
else
|
185
|
-
# labels are the same; don't do anything
|
186
|
-
end
|
187
|
-
when op == :discard
|
188
|
-
if old_m && (old_m.labels != m.labels)
|
189
|
-
[:update_message_state, m.labels]
|
190
|
-
else
|
191
|
-
# labels are the same; don't do anything
|
192
|
-
end
|
193
|
-
else
|
194
|
-
## duplicate behavior of poll mode: if index_state is non-nil, this is a newer
|
195
|
-
## version of an older message, so merge in any new labels except :unread and
|
196
|
-
## :inbox.
|
197
|
-
##
|
198
|
-
## TODO: refactor such that this isn't duplicated
|
199
|
-
if old_m
|
200
|
-
m.labels = old_m.labels + (m.labels - [:unread, :inbox])
|
201
|
-
:update_message
|
123
|
+
Redwood::PollManager.poll_from source do |action,m,old_m,progress|
|
124
|
+
if action == :delete
|
125
|
+
puts "Deleting #{m.id}"
|
126
|
+
elsif action == :add
|
127
|
+
num_scanned += 1
|
128
|
+
seen[m.id] = true
|
129
|
+
|
130
|
+
## tweak source labels according to commandline arguments if necessary
|
131
|
+
m.labels.delete :inbox if opts[:archive]
|
132
|
+
m.labels.delete :unread if opts[:read]
|
133
|
+
m.labels += opts[:extra_labels].to_set_of_symbols(",")
|
134
|
+
|
135
|
+
## decide what to do based on message labels and the operation we're performing
|
136
|
+
dothis = case
|
137
|
+
when (op == :restore) && restored_state[m.id]
|
138
|
+
if old_m && (old_m.labels != restored_state[m.id])
|
139
|
+
num_restored += 1
|
140
|
+
m.labels = restored_state[m.id]
|
141
|
+
:update_message_state
|
142
|
+
elsif old_m.nil?
|
143
|
+
num_restored += 1
|
144
|
+
m.labels = restored_state[m.id]
|
145
|
+
:add_message
|
146
|
+
else
|
147
|
+
# labels are the same; don't do anything
|
148
|
+
end
|
149
|
+
when op == :discard
|
150
|
+
if old_m && (old_m.labels != m.labels)
|
151
|
+
:update_message_state
|
152
|
+
else
|
153
|
+
# labels are the same; don't do anything
|
154
|
+
end
|
202
155
|
else
|
203
|
-
|
156
|
+
if old_m
|
157
|
+
:update_message
|
158
|
+
else
|
159
|
+
:add_message
|
160
|
+
end
|
204
161
|
end
|
205
|
-
end
|
206
162
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
m.labels = new_labels
|
220
|
-
index.update_message_state m unless opts[:dry_run]
|
221
|
-
num_updated += 1
|
222
|
-
end
|
163
|
+
## now, actually do the operation
|
164
|
+
case dothis
|
165
|
+
when :add_message
|
166
|
+
puts "Adding new message #{source}##{m.source_info} with labels #{m.labels}" if opts[:verbose]
|
167
|
+
num_added += 1
|
168
|
+
when :update_message
|
169
|
+
puts "Updating message #{source}##{m.source_info}; labels #{old_m.labels} => #{m.labels}; offset #{old_m.source_info} => #{m.source_info}" if opts[:verbose]
|
170
|
+
num_updated += 1
|
171
|
+
when :update_message_state
|
172
|
+
puts "Changing flags for #{source}##{m.source_info} from #{old_m.labels} to #{m.labels}" if opts[:verbose]
|
173
|
+
num_updated += 1
|
174
|
+
end
|
223
175
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
176
|
+
if Time.now - last_info_time > PROGRESS_UPDATE_INTERVAL
|
177
|
+
last_info_time = Time.now
|
178
|
+
elapsed = last_info_time - start_time
|
179
|
+
pctdone = progress * 100.0
|
180
|
+
remaining = (100.0 - pctdone) * (elapsed.to_f / pctdone)
|
181
|
+
printf "## read %dm (~%.0f%%) @ %.1fm/s. %s elapsed, ~%s remaining\n", num_scanned, pctdone, num_scanned / elapsed, elapsed.to_time_s, remaining.to_time_s
|
182
|
+
end
|
183
|
+
else fail
|
230
184
|
end
|
185
|
+
next if opts[:dry_run]
|
231
186
|
end
|
232
187
|
|
233
188
|
puts "Scanned #{num_scanned}, added #{num_added}, updated #{num_updated} messages from #{source}."
|
234
189
|
puts "Restored state on #{num_restored} (#{100.0 * num_restored / num_scanned}%) messages." if num_restored > 0
|
235
190
|
end
|
236
191
|
|
237
|
-
## delete any messages in the index that claim they're from one of
|
238
|
-
## these sources, but that we didn't see.
|
239
|
-
if (target == :all || target == :changed)
|
240
|
-
puts "Deleting missing messages from the index..."
|
241
|
-
num_del, num_scanned = 0, 0
|
242
|
-
sources.each do |source|
|
243
|
-
raise "no source id for #{source}" unless source.id
|
244
|
-
index.each_message :source_id => source.id, :load_spam => true, :load_deleted => true, :load_killed => true do |m|
|
245
|
-
num_scanned += 1
|
246
|
-
unless seen[m.id]
|
247
|
-
next unless m.source_info >= opts[:start_at] if opts[:start_at]
|
248
|
-
puts "Deleting #{m.id}" if opts[:verbose]
|
249
|
-
index.delete m.id unless opts[:dry_run]
|
250
|
-
num_del += 1
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
puts "Deleted #{num_del} / #{num_scanned} messages"
|
255
|
-
end
|
256
|
-
|
257
192
|
index.save
|
258
193
|
|
259
194
|
if opts[:optimize]
|