sup 0.7 → 0.8
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 +8 -3
- data/History.txt +19 -0
- data/README.txt +45 -44
- data/ReleaseNotes +6 -0
- data/bin/sup +36 -5
- data/bin/sup-add +0 -0
- data/bin/sup-config +0 -0
- data/bin/sup-dump +0 -0
- data/bin/sup-recover-sources +8 -12
- data/bin/sup-sync +22 -16
- data/bin/sup-sync-back +1 -1
- data/bin/sup-tweak-labels +8 -8
- data/lib/sup.rb +3 -17
- data/lib/sup/account.rb +2 -3
- data/lib/sup/buffer.rb +21 -10
- data/lib/sup/colormap.rb +30 -27
- data/lib/sup/contact.rb +1 -1
- data/lib/sup/draft.rb +1 -3
- data/lib/sup/imap.rb +1 -1
- data/lib/sup/index.rb +70 -48
- data/lib/sup/label.rb +12 -10
- data/lib/sup/logger.rb +1 -1
- data/lib/sup/maildir.rb +1 -1
- data/lib/sup/mbox.rb +13 -70
- data/lib/sup/mbox/loader.rb +26 -15
- data/lib/sup/message-chunks.rb +18 -6
- data/lib/sup/message.rb +56 -67
- data/lib/sup/mode.rb +2 -1
- data/lib/sup/modes/buffer-list-mode.rb +6 -2
- data/lib/sup/modes/compose-mode.rb +0 -1
- data/lib/sup/modes/contact-list-mode.rb +1 -1
- data/lib/sup/modes/edit-message-mode.rb +37 -9
- data/lib/sup/modes/inbox-mode.rb +34 -0
- data/lib/sup/modes/label-list-mode.rb +10 -3
- data/lib/sup/modes/reply-mode.rb +24 -13
- data/lib/sup/modes/resume-mode.rb +2 -0
- data/lib/sup/modes/scroll-mode.rb +10 -9
- data/lib/sup/modes/search-results-mode.rb +2 -2
- data/lib/sup/modes/thread-index-mode.rb +157 -38
- data/lib/sup/modes/thread-view-mode.rb +27 -11
- data/lib/sup/person.rb +22 -73
- data/lib/sup/poll.rb +18 -20
- data/lib/sup/source.rb +44 -0
- data/lib/sup/undo.rb +39 -0
- data/lib/sup/util.rb +25 -16
- metadata +46 -45
data/CONTRIBUTORS
CHANGED
@@ -1,17 +1,22 @@
|
|
1
|
-
William Morgan <wmorgan-sup at the masanjin dot nets>
|
2
|
-
Ismo Puustinen <ismo at the iki dot fis>
|
3
1
|
Nicolas Pouillard <nicolas.pouillard at the gmail dot coms>
|
2
|
+
Mike Stipicevic <stipim at the rpi dot edus>
|
4
3
|
Marcus Williams <marcus-sup at the bar-coded dot nets>
|
5
4
|
Lionel Ott <white.magic at the gmx dot des>
|
5
|
+
Ingmar Vanhassel <ingmar at the exherbo dot orgs>
|
6
6
|
Mark Alexander <marka at the pobox dot coms>
|
7
7
|
Christopher Warrington <chrisw at the rice dot edus>
|
8
|
-
|
8
|
+
Richard Brown <rbrown at the exherbo dot orgs>
|
9
9
|
Ben Walton <bwalton at the artsci.utoronto dot cas>
|
10
|
+
Marc Hartstein <marc.hartstein at the alum.vassar dot edus>
|
10
11
|
Grant Hollingworth <grant at the antiflux dot orgs>
|
11
12
|
Steve Goldman <sgoldman at the tower-research dot coms>
|
12
13
|
Decklin Foster <decklin at the red-bean dot coms>
|
14
|
+
Ismo Puustinen <ismo at the iki dot fis>
|
13
15
|
Jeff Balogh <its.jeff.balogh at the gmail dot coms>
|
16
|
+
Alex Vandiver <alexmv at the mit dot edus>
|
14
17
|
Giorgio Lando <patroclo7 at the gmail dot coms>
|
15
18
|
Israel Herraiz <israel.herraiz at the gmail dot coms>
|
16
19
|
Ian Taylor <ian at the lorf dot orgs>
|
20
|
+
Stefan Lundström <lundst at the snabb.(none)>
|
17
21
|
Rich Lane <rlane at the club.cc.cmu dot edus>
|
22
|
+
Kirill Smelkov <kirr at the landau.phys.spbu dot rus>
|
data/History.txt
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
== 0.8 / 2009-06-05
|
2
|
+
* Undo support on many operations. Yay!
|
3
|
+
* Mbox splitting fixes. No more "From "-line problems.
|
4
|
+
* Mail parsing speedups.
|
5
|
+
* Many utf8 and widechar fixes. Display of crazy characters should be pretty
|
6
|
+
close.
|
7
|
+
* Outgoing email with non-ASCII headers is now properly encoded.
|
8
|
+
* Email addresses are no longer permanently attached to names. This was
|
9
|
+
causing problems with automated email systems that used different names
|
10
|
+
with the same address.
|
11
|
+
* Curses background now retains the terminal default color. This also makes
|
12
|
+
Sup work better on transparent terminals.
|
13
|
+
* Improve dynamic loading of setlocale for Cygwin and BSD systems.
|
14
|
+
* Labels can now be removed from multiple tagged threads.
|
15
|
+
* Applying operations to tagged threads is now invoked with '='.
|
16
|
+
* Buffer list is betterified and is now invoked with ';'.
|
17
|
+
* Zsh autocompletion support.
|
18
|
+
* As always, many bugfixes and tweaks.
|
19
|
+
|
1
20
|
== 0.7 / 2009-03-16
|
2
21
|
* Ferret index corruption issues fixed (hopefully!)
|
3
22
|
* Text entry now scrolls to the right on overflow, i.e. is actually usable
|
data/README.txt
CHANGED
@@ -13,22 +13,20 @@ Sup makes it easy to:
|
|
13
13
|
- Handle massive amounts of email.
|
14
14
|
|
15
15
|
- Mix email from different sources: mbox files (even across different
|
16
|
-
machines), Maildir directories, IMAP folders,
|
17
|
-
GMail accounts.
|
16
|
+
machines), Maildir directories, IMAP folders, and GMail accounts.
|
18
17
|
|
19
|
-
- Instantaneously search over your entire email collection. Search
|
20
|
-
|
21
|
-
|
18
|
+
- Instantaneously search over your entire email collection. Search over
|
19
|
+
body text, or use a query language to combine search predicates in any
|
20
|
+
way.
|
22
21
|
|
23
22
|
- Handle multiple accounts. Replying to email sent to a particular
|
24
|
-
account will use the correct SMTP server, signature, and from
|
25
|
-
address.
|
23
|
+
account will use the correct SMTP server, signature, and from address.
|
26
24
|
|
27
|
-
- Add custom code to
|
28
|
-
|
25
|
+
- Add custom code to customize Sup to whatever particular and bizarre
|
26
|
+
needs you may have.
|
29
27
|
|
30
|
-
- Organize email with user-defined labels, automatically track
|
31
|
-
|
28
|
+
- Organize email with user-defined labels, automatically track recent
|
29
|
+
contacts, and much more!
|
32
30
|
|
33
31
|
The goal of Sup is to become the email client of choice for nerds
|
34
32
|
everywhere.
|
@@ -48,40 +46,41 @@ Features:
|
|
48
46
|
message level. Entire threads are manipulated and viewed (with
|
49
47
|
redundancies removed) at a time.
|
50
48
|
|
51
|
-
- Labels instead of folders. Drop that tired old metaphor and you'll
|
52
|
-
|
49
|
+
- Labels instead of folders. Drop that tired old metaphor and you'll see
|
50
|
+
how much easier it is to organize email.
|
53
51
|
|
54
|
-
- GMail-style thread management
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
52
|
+
- GMail-style thread management. Archive a thread, and it will disappear
|
53
|
+
from your inbox until someone replies. Kill a thread, and it will
|
54
|
+
never come back to your inbox (but will still show up in searches.)
|
55
|
+
Mark a thread as spam and you'll never again see it unless explicitly
|
56
|
+
searching for spam.
|
59
57
|
|
60
58
|
- Console based interface. No mouse clicking required!
|
61
59
|
|
62
|
-
- Programmability. It's in Ruby. The code is good. It
|
63
|
-
extend.
|
60
|
+
- Programmability. It's in Ruby. The code is good. It has an extensive
|
61
|
+
hook system that makes it easy to extend and customize.
|
64
62
|
|
65
|
-
- Multiple buffer support. Why be limited to viewing one
|
63
|
+
- Multiple buffer support. Why be limited to viewing one thing at a
|
66
64
|
time?
|
67
65
|
|
68
|
-
- Tons of other little features, like automatic context-sensitive
|
69
|
-
|
70
|
-
|
66
|
+
- Tons of other little features, like automatic context-sensitive help,
|
67
|
+
multi-message operations, MIME attachment viewing, recent contact list
|
68
|
+
generation, etc.
|
71
69
|
|
72
70
|
Current limitations which will be fixed:
|
73
71
|
|
74
|
-
-
|
75
|
-
|
72
|
+
- Sup doesn't play nicely with other mail clients. If you alter a mail
|
73
|
+
source (read, move, delete, etc) with another client Sup will punish
|
74
|
+
you with a lengthy reindexing process.
|
76
75
|
|
77
|
-
-
|
78
|
-
|
76
|
+
- Support for mbox, Maildir, and IMAP only at this point. No support for
|
77
|
+
POP or mh.
|
79
78
|
|
80
|
-
-
|
81
|
-
|
79
|
+
- IMAP support is very slow due mostly to Ruby's IMAP library. You may
|
80
|
+
consider something like offlineimap to mirror your IMAP folders with
|
81
|
+
local Maildir ones.
|
82
82
|
|
83
|
-
-
|
84
|
-
searches, message annotations, etc.
|
83
|
+
- Unix-centrism in MIME attachment handling and in sendmail invocation.
|
85
84
|
|
86
85
|
== SYNOPSYS:
|
87
86
|
|
@@ -90,21 +89,23 @@ Current limitations which will be fixed:
|
|
90
89
|
|
91
90
|
Note that Sup never changes the contents of any mailboxes; it only
|
92
91
|
indexes in to them. So it shouldn't ever corrupt your mail. The flip
|
93
|
-
side is that if you change a mailbox (e.g. delete messages, or, in
|
94
|
-
|
95
|
-
|
96
|
-
|
92
|
+
side is that if you change a mailbox (e.g. delete messages, or, in the
|
93
|
+
case of mbox files, read an unread message) then Sup will be unable to
|
94
|
+
load messages from that source and will ask you to run sup-sync
|
95
|
+
--changed.
|
97
96
|
|
98
97
|
== REQUIREMENTS:
|
99
98
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
99
|
+
- ferret >= 0.11.6
|
100
|
+
- ncurses >= 0.9.1
|
101
|
+
- rmail >= 0.17
|
102
|
+
- highline
|
103
|
+
- net-ssh
|
104
|
+
- trollop >= 1.12
|
105
|
+
- lockfile
|
106
|
+
- mime-types
|
107
|
+
- gettext
|
108
|
+
- fastthread
|
108
109
|
|
109
110
|
== INSTALL:
|
110
111
|
|
data/ReleaseNotes
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
Release 0.8:
|
2
|
+
|
3
|
+
The big wins are undo support, mbox splitting fixes, and the various UI
|
4
|
+
speedups and bugfixes. Parsing new email should also be faster, although
|
5
|
+
IMAP remains tragically slow, as usual.
|
6
|
+
|
1
7
|
Release 0.7:
|
2
8
|
|
3
9
|
The big win in this release is that Ferret index corruption issues should now
|
data/bin/sup
CHANGED
@@ -8,7 +8,7 @@ require 'trollop'
|
|
8
8
|
require 'fastthread'
|
9
9
|
require "sup"
|
10
10
|
|
11
|
-
BIN_VERSION = "0.
|
11
|
+
BIN_VERSION = "0.8"
|
12
12
|
|
13
13
|
unless Redwood::VERSION == BIN_VERSION
|
14
14
|
$stderr.puts <<EOS
|
@@ -67,9 +67,9 @@ global_keymap = Keymap.new do |k|
|
|
67
67
|
k.add :quit_now, "Quit Sup immediately", 'Q'
|
68
68
|
k.add :help, "Show help", '?'
|
69
69
|
k.add :roll_buffers, "Switch to next buffer", 'b'
|
70
|
-
|
70
|
+
k.add :roll_buffers_backwards, "Switch to previous buffer", 'B'
|
71
71
|
k.add :kill_buffer, "Kill the current buffer", 'x'
|
72
|
-
k.add :list_buffers, "List all buffers", '
|
72
|
+
k.add :list_buffers, "List all buffers", ';'
|
73
73
|
k.add :list_contacts, "List contacts", 'C'
|
74
74
|
k.add :redraw, "Redraw screen", :ctrl_l
|
75
75
|
k.add :search, "Search all messages", '\\', 'F'
|
@@ -81,11 +81,42 @@ global_keymap = Keymap.new do |k|
|
|
81
81
|
k.add :recall_draft, "Edit most recent draft message", 'R'
|
82
82
|
end
|
83
83
|
|
84
|
+
## the following magic enables wide characters when used with a ruby
|
85
|
+
## ncurses.so that's been compiled against libncursesw. (note the w.) why
|
86
|
+
## this works, i have no idea. much like pretty much every aspect of
|
87
|
+
## dealing with curses. cargo cult programming at its best.
|
88
|
+
##
|
89
|
+
## BSD users: if libc.so.6 is not found, try installing compat6x.
|
90
|
+
require 'dl/import'
|
91
|
+
module LibC
|
92
|
+
extend DL::Importable
|
93
|
+
setlocale_lib = case Config::CONFIG['arch']
|
94
|
+
when /darwin/; "libc.dylib"
|
95
|
+
when /cygwin/; "cygwin1.dll"
|
96
|
+
else; "libc.so.6"
|
97
|
+
end
|
98
|
+
|
99
|
+
Redwood::log "dynamically loading setlocale() from #{setlocale_lib}"
|
100
|
+
begin
|
101
|
+
dlload setlocale_lib
|
102
|
+
extern "void setlocale(int, const char *)"
|
103
|
+
Redwood::log "setting locale..."
|
104
|
+
LibC.setlocale(6, "") # LC_ALL == 6
|
105
|
+
rescue RuntimeError => e
|
106
|
+
Redwood::log "cannot dlload setlocale(); ncurses wide character support probably broken."
|
107
|
+
Redwood::log "dlload error was #{e.class}: #{e.message}"
|
108
|
+
if Config::CONFIG['arch'] =~ /bsd/
|
109
|
+
Redwood::log "BSD variant detected. You may have to install a compat6x package to acquire libc."
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
84
114
|
def start_cursing
|
85
115
|
Ncurses.initscr
|
86
116
|
Ncurses.noecho
|
87
117
|
Ncurses.cbreak
|
88
118
|
Ncurses.stdscr.keypad 1
|
119
|
+
Ncurses.use_default_colors
|
89
120
|
Ncurses.curs_set 0
|
90
121
|
Ncurses.start_color
|
91
122
|
$cursing = true
|
@@ -229,7 +260,7 @@ begin
|
|
229
260
|
when :kill_buffer
|
230
261
|
bm.kill_buffer_safely bm.focus_buf
|
231
262
|
when :list_buffers
|
232
|
-
bm.spawn_unless_exists("
|
263
|
+
bm.spawn_unless_exists("buffer list", :system => true) { BufferListMode.new }
|
233
264
|
when :list_contacts
|
234
265
|
b, new = bm.spawn_unless_exists("Contact List") { ContactListMode.new }
|
235
266
|
b.mode.load_in_background if new
|
@@ -240,7 +271,7 @@ begin
|
|
240
271
|
when :search_unread
|
241
272
|
SearchResultsMode.spawn_from_query "is:unread"
|
242
273
|
when :list_labels
|
243
|
-
labels = LabelManager.
|
274
|
+
labels = LabelManager.all_labels.map { |l| LabelManager.string_for l }
|
244
275
|
user_label = bm.ask_with_completions :label, "Show threads with label (enter for listing): ", labels
|
245
276
|
unless user_label.nil?
|
246
277
|
if user_label.empty?
|
data/bin/sup-add
CHANGED
File without changes
|
data/bin/sup-config
CHANGED
File without changes
|
data/bin/sup-dump
CHANGED
File without changes
|
data/bin/sup-recover-sources
CHANGED
@@ -72,18 +72,14 @@ ARGV.each do |fn|
|
|
72
72
|
source_ids = {}
|
73
73
|
count = 0
|
74
74
|
source.each do |offset, labels|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
break if count == $opts[:scan_num]
|
84
|
-
rescue Redwood::MessageFormatError => e
|
85
|
-
puts "# #{e.message}"
|
86
|
-
end
|
75
|
+
m = Redwood::Message.new :source => source, :source_info => offset
|
76
|
+
docid, entry = index.load_entry_for_id m.id
|
77
|
+
next unless entry
|
78
|
+
#puts "# #{source} #{offset} #{entry[:source_id]}"
|
79
|
+
|
80
|
+
source_ids[entry[:source_id]] = (source_ids[entry[:source_id]] || 0) + 1
|
81
|
+
count += 1
|
82
|
+
break if count == $opts[:scan_num]
|
87
83
|
end
|
88
84
|
|
89
85
|
if source_ids.size == 1
|
data/bin/sup-sync
CHANGED
@@ -5,6 +5,8 @@ require 'rubygems'
|
|
5
5
|
require 'trollop'
|
6
6
|
require "sup"
|
7
7
|
|
8
|
+
PROGRESS_UPDATE_INTERVAL = 15 # seconds
|
9
|
+
|
8
10
|
class Float
|
9
11
|
def to_s; sprintf '%.2f', self; end
|
10
12
|
def to_time_s
|
@@ -100,7 +102,7 @@ restored_state =
|
|
100
102
|
IO.foreach opts[:restore] do |l|
|
101
103
|
l =~ /^(\S+) \((.*?)\)$/ or raise "Can't read dump line: #{l.inspect}"
|
102
104
|
mid, labels = $1, $2
|
103
|
-
dump[mid] = labels.
|
105
|
+
dump[mid] = labels.symbolistize
|
104
106
|
end
|
105
107
|
$stderr.puts "Read #{dump.size} entries from dump file."
|
106
108
|
dump
|
@@ -122,7 +124,9 @@ begin
|
|
122
124
|
|
123
125
|
unless target == :new
|
124
126
|
if opts[:start_at]
|
125
|
-
|
127
|
+
Trollop::die :start_at, "can only be used on one source" unless sources.size == 1
|
128
|
+
sources.first.seek_to! opts[:start_at]
|
129
|
+
sources.first.correct_offset! if sources.first.respond_to?(:correct_offset!)
|
126
130
|
else
|
127
131
|
sources.each { |s| s.reset! }
|
128
132
|
end
|
@@ -137,18 +141,22 @@ begin
|
|
137
141
|
num_scanned += 1
|
138
142
|
seen[m.id] = true
|
139
143
|
|
144
|
+
if Time.now - last_info_time > PROGRESS_UPDATE_INTERVAL
|
145
|
+
last_info_time = Time.now
|
146
|
+
elapsed = last_info_time - start_time
|
147
|
+
start = opts[:start_at] || source.start_offset
|
148
|
+
pctdone = 100.0 * (source.cur_offset - start).to_f / (source.end_offset - start).to_f
|
149
|
+
remaining = (100.0 - pctdone) * (elapsed.to_f / pctdone)
|
150
|
+
$stderr.printf "## read %dm (about %.0f%%) @ %.1fm/s. %s elapsed, about %s remaining\n", num_scanned, pctdone, num_scanned / elapsed, elapsed.to_time_s, remaining.to_time_s
|
151
|
+
end
|
152
|
+
|
140
153
|
## skip if we're operating only on changed messages, the message
|
141
154
|
## is in the index, and it's unchanged from what the source is
|
142
155
|
## reporting.
|
143
156
|
next if target == :changed && entry && entry[:source_id].to_i == source.id && entry[:source_info].to_i == offset
|
144
157
|
|
145
158
|
## get the state currently in the index
|
146
|
-
index_state =
|
147
|
-
if entry
|
148
|
-
entry[:label].split(/\s+/).map { |x| x.intern }
|
149
|
-
else
|
150
|
-
nil
|
151
|
-
end
|
159
|
+
index_state = entry[:label].symbolistize if entry
|
152
160
|
|
153
161
|
## skip if we're operating on restored messages, and this one
|
154
162
|
## ain't.
|
@@ -158,12 +166,12 @@ begin
|
|
158
166
|
## to default source state modification flags.
|
159
167
|
m.labels -= [:inbox] if opts[:archive]
|
160
168
|
m.labels -= [:unread] if opts[:read]
|
161
|
-
m.labels += opts[:extra_labels].split(/\s*,\s*/).map { |x| x.intern } if opts[:extra_labels]
|
169
|
+
m.labels += opts[:extra_labels].strip.split(/\s*,\s*/).map { |x| x.intern } if opts[:extra_labels]
|
162
170
|
|
163
171
|
## assign message labels based on the operation we're performing
|
164
172
|
case op
|
165
173
|
when :asis
|
166
|
-
m.labels = index_state if index_state
|
174
|
+
m.labels = ((m.labels - [:unread, :inbox]) + index_state).uniq if index_state
|
167
175
|
when :restore
|
168
176
|
## if the entry exists on disk
|
169
177
|
if restored_state[m.id]
|
@@ -176,16 +184,16 @@ begin
|
|
176
184
|
## nothin! use default source labels
|
177
185
|
end
|
178
186
|
|
179
|
-
if Time.now - last_info_time >
|
187
|
+
if Time.now - last_info_time > PROGRESS_UPDATE_INTERVAL
|
180
188
|
last_info_time = Time.now
|
181
189
|
elapsed = last_info_time - start_time
|
182
190
|
pctdone = source.respond_to?(:pct_done) ? source.pct_done : 100.0 * (source.cur_offset.to_f - source.start_offset).to_f / (source.end_offset - source.start_offset).to_f
|
183
191
|
remaining = (100.0 - pctdone) * (elapsed.to_f / pctdone)
|
184
|
-
$stderr.
|
192
|
+
$stderr.printf "## read %dm (about %.0f%%) @ %.1fm/s. %s elapsed, about %s remaining\n", num_scanned, pctdone, num_scanned / elapsed, elapsed.to_time_s, remaining.to_time_s
|
185
193
|
end
|
186
194
|
|
187
195
|
if index_state.nil?
|
188
|
-
puts "Adding message #{source}##{offset} with state {#{m.labels * ', '}}" if opts[:verbose]
|
196
|
+
puts "Adding message #{source}##{offset} from #{m.from} with state {#{m.labels * ', '}}" if opts[:verbose]
|
189
197
|
num_added += 1
|
190
198
|
else
|
191
199
|
puts "Updating message #{source}##{offset}, source #{entry[:source_id]} => #{source.id}, offset #{entry[:source_info]} => #{offset}, state {#{index_state * ', '}} => {#{m.labels * ', '}}" if opts[:verbose]
|
@@ -205,9 +213,7 @@ begin
|
|
205
213
|
## API.
|
206
214
|
##
|
207
215
|
## TODO: move this to Index, i suppose.
|
208
|
-
|
209
|
-
|
210
|
-
if target == :all || target == :changed
|
216
|
+
if (target == :all || target == :changed) && !opts[:start_at]
|
211
217
|
$stderr.puts "Deleting missing messages from the index..."
|
212
218
|
num_del, num_scanned = 0, 0
|
213
219
|
sources.each do |source|
|
data/bin/sup-sync-back
CHANGED
data/bin/sup-tweak-labels
CHANGED
@@ -46,10 +46,12 @@ EOS
|
|
46
46
|
Other options:
|
47
47
|
EOS
|
48
48
|
opt :verbose, "Print message ids as they're processed."
|
49
|
+
opt :very_verbose, "Print message names and subjects as they're processed."
|
49
50
|
opt :all_sources, "Scan over all sources.", :short => :none
|
50
51
|
opt :dry_run, "Don't actually modify the index. Probably only useful with --verbose.", :short => "-n"
|
51
52
|
opt :version, "Show version information", :short => :none
|
52
53
|
end
|
54
|
+
opts[:verbose] = true if opts[:very_verbose]
|
53
55
|
|
54
56
|
add_labels = (opts[:add] || "").split(",").map { |l| l.intern }.uniq
|
55
57
|
remove_labels = (opts[:remove] || "").split(",").map { |l| l.intern }.uniq
|
@@ -71,7 +73,7 @@ begin
|
|
71
73
|
end.map { |s| s.id }
|
72
74
|
Trollop::die "nothing to do: no sources" if source_ids.empty?
|
73
75
|
|
74
|
-
query = "+(" + source_ids.map { |id| "source_id:#{id}" }.join(" ") + ")"
|
76
|
+
query = "+(" + source_ids.map { |id| "source_id:#{id}" }.join(" OR ") + ")"
|
75
77
|
if add_labels.empty?
|
76
78
|
## if all we're doing is removing labels, we can further restrict the
|
77
79
|
## query to only messages with those labels
|
@@ -79,19 +81,15 @@ begin
|
|
79
81
|
end
|
80
82
|
query += ' ' + opts[:query] if opts[:query]
|
81
83
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
results = index.ferret.search query, :limit => :all
|
86
|
-
num_total = results.total_hits
|
84
|
+
docs = Redwood::Index.run_query query
|
85
|
+
num_total = docs.size
|
87
86
|
|
88
87
|
$stderr.puts "Found #{num_total} documents across #{source_ids.length} sources. Scanning..."
|
89
88
|
|
90
89
|
num_changed = num_scanned = 0
|
91
90
|
last_info_time = start_time = Time.now
|
92
|
-
|
91
|
+
docs.each do |id|
|
93
92
|
num_scanned += 1
|
94
|
-
id = hit.doc
|
95
93
|
|
96
94
|
m = index.build_message id
|
97
95
|
old_labels = m.labels.clone
|
@@ -102,7 +100,9 @@ begin
|
|
102
100
|
|
103
101
|
unless m.labels.sort_by { |s| s.to_s } == old_labels.sort_by { |s| s.to_s }
|
104
102
|
num_changed += 1
|
103
|
+
puts "From #{m.from}, subject: #{m.subj}" if opts[:very_verbose]
|
105
104
|
puts "#{m.id}: {#{old_labels.join ','}} => {#{m.labels.join ','}}" if opts[:verbose]
|
105
|
+
puts if opts[:very_verbose]
|
106
106
|
index.sync_message m unless opts[:dry_run]
|
107
107
|
end
|
108
108
|
|