sup 0.17.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +17 -0
  3. data/.travis.yml +12 -0
  4. data/Gemfile +3 -0
  5. data/HACKING +42 -0
  6. data/History.txt +8 -0
  7. data/Rakefile +12 -0
  8. data/ReleaseNotes +4 -0
  9. data/bin/sup-sync +1 -1
  10. data/bin/sup-tweak-labels +6 -1
  11. data/contrib/colorpicker.rb +100 -0
  12. data/contrib/completion/_sup.zsh +114 -0
  13. data/devel/console.sh +3 -0
  14. data/devel/count-loc.sh +3 -0
  15. data/devel/load-index.rb +9 -0
  16. data/devel/profile.rb +12 -0
  17. data/devel/start-console.rb +5 -0
  18. data/doc/FAQ.txt +119 -0
  19. data/doc/Hooks.txt +79 -0
  20. data/doc/Philosophy.txt +69 -0
  21. data/lib/sup/colormap.rb +6 -0
  22. data/lib/sup/modes/thread_index_mode.rb +12 -1
  23. data/lib/sup/modes/thread_view_mode.rb +20 -0
  24. data/lib/sup/version.rb +1 -1
  25. data/sup.gemspec +55 -0
  26. data/test/dummy_source.rb +61 -0
  27. data/test/gnupg_test_home/gpg.conf +1 -0
  28. data/test/gnupg_test_home/pubring.gpg +0 -0
  29. data/test/gnupg_test_home/receiver_pubring.gpg +0 -0
  30. data/test/gnupg_test_home/receiver_secring.gpg +0 -0
  31. data/test/gnupg_test_home/receiver_trustdb.gpg +0 -0
  32. data/test/gnupg_test_home/secring.gpg +0 -0
  33. data/test/gnupg_test_home/sup-test-2@foo.bar.asc +20 -0
  34. data/test/gnupg_test_home/trustdb.gpg +0 -0
  35. data/test/integration/test_label_service.rb +18 -0
  36. data/test/messages/bad-content-transfer-encoding-1.eml +8 -0
  37. data/test/messages/binary-content-transfer-encoding-2.eml +21 -0
  38. data/test/messages/missing-line.eml +9 -0
  39. data/test/test_crypto.rb +109 -0
  40. data/test/test_header_parsing.rb +168 -0
  41. data/test/test_helper.rb +7 -0
  42. data/test/test_message.rb +532 -0
  43. data/test/test_messages_dir.rb +147 -0
  44. data/test/test_yaml_migration.rb +85 -0
  45. data/test/test_yaml_regressions.rb +17 -0
  46. data/test/unit/service/test_label_service.rb +19 -0
  47. data/test/unit/test_horizontal_selector.rb +40 -0
  48. data/test/unit/util/test_query.rb +46 -0
  49. data/test/unit/util/test_string.rb +57 -0
  50. data/test/unit/util/test_uri.rb +19 -0
  51. metadata +81 -36
  52. checksums.yaml.gz.sig +0 -1
  53. data.tar.gz.sig +0 -0
  54. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e3a7c84961e495c61ffe169ec02add530f566ddd
4
- data.tar.gz: f47dc9295a1b1b76a8237243a9e043908f090727
3
+ metadata.gz: 0193b6fb21e5af566be86fe3e69f8ffc3c91f3cb
4
+ data.tar.gz: 83d09212502c49ed5eaf6a05a68f7be5d5f66b18
5
5
  SHA512:
6
- metadata.gz: 34f77536b3f04ac960ee9f2fc835f41ac7ca0f818941d25d74b61007660e373fa6b830a038e68c10fd97eb8f437b2f4d5bd9d399f1a1ffddc3424432e327b9a8
7
- data.tar.gz: a501e2f21f8e76aa018deea70a0dd9a16014fa6546e996a0a1f7cca23a9993749d72737dec292f216806eb8888d900a343dd44d88f7bc0fa7f2b9d24000ca62a
6
+ metadata.gz: 9dbf5ff6caa5e68e6488cc035faee89062392b75cf8ca2ed35e00fd48154e491d4db1a465334c412759d27a54be6ec9b651ff5d8409fdcf945abae54b7123732
7
+ data.tar.gz: 961d4cf7a8798a757dd2edac9789179e6ca636d3e2ba49855af58f4f00b976faa4d6b05c19b87ef86c056d2039f3b5ee37aba2b04aa5d80e7dc603cc7ebc3bbb
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ # i use vi
2
+ *.swp
3
+ # i use emacs
4
+ *~
5
+ # artifact
6
+ pkg/
7
+ *.gem
8
+ # i have accidently added this one one too many times
9
+ sup-exception-log.txt
10
+
11
+ # bundler stuff
12
+ Gemfile.lock
13
+ .bundle
14
+
15
+ # generated file for gnupg test
16
+ test/gnupg_test_home/random_seed
17
+
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 2.1.1
5
+ - 2.0.0
6
+ - 1.9.3
7
+
8
+ before_install:
9
+ - sudo apt-get update -qq
10
+ - sudo apt-get install -qq uuid-dev uuid libncursesw5-dev libncursesw5 gnupg2
11
+
12
+ script: bundle exec rake travis
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org/'
2
+
3
+ gemspec
data/HACKING ADDED
@@ -0,0 +1,42 @@
1
+ Running Sup from your git checkout
2
+ ----------------------------------
3
+
4
+ Invoke it like this:
5
+
6
+ ruby -I lib -w bin/sup
7
+
8
+ You'll have to install all gems mentioned in the Rakefile (look for the line
9
+ setting p.extra_deps). If you're on a Debian or Debian-based system (e.g.
10
+ Ubuntu), you'll have to make sure you have a complete Ruby installation,
11
+ especially libssl-ruby. You will need libruby-devel, gcc, and rake installed
12
+ to build certain gems like Xapian. Gem install does not do a good job of
13
+ detecting when these things are missing and the build fails.
14
+
15
+ Rubygems also is particularly aggressive about picking up libraries from
16
+ installed gems. If you do have Sup installed as a gem, please examine
17
+ backtraces to make sure you're loading files from the repository and NOT from
18
+ the installed gem before submitting any bug reports.
19
+
20
+ Coding standards
21
+ ----------------
22
+
23
+ - Don't wrap code unless it really benefits from it.
24
+ - Do wrap comments at 72 characters.
25
+ - Old lisp-style comment differentiations:
26
+ # one for comments on the same line as a line of code
27
+ ## two for comments on their own line, except:
28
+ ### three for comments that demarcate large sections of code (rare)
29
+ - Use {} for one-liner blocks and do/end for multi-line blocks.
30
+ - I like poetry mode. Don't use parentheses unless you must.
31
+ - The one exception to poetry mode is if-statements that have an assignment in
32
+ the condition. To make it clear this is not a comparison, surround the
33
+ condition by parentheses. E.g.:
34
+ if a == b if(a = some.computation)
35
+ ... BUT ... something with a
36
+ end end
37
+ - and/or versus ||/&&. In Ruby, "and" and "or" bind very loosely---even
38
+ more loosely than function application. This makes them ideal for
39
+ end-of-line short-circuit control in poetry mode. So, use || and &&
40
+ for ordinary logical comparisons, and "and" and "or" for end-of-line
41
+ flow control. E.g.:
42
+ x = a || b or raise "neither is true"
data/History.txt CHANGED
@@ -1,3 +1,11 @@
1
+ == 0.18.0 / 2014-05-19
2
+
3
+ * new color option, :with_attachment for defining colors for the
4
+ attachment character.
5
+ * sup-tweak-labels works again (out of service since sync_back).
6
+ * gem building is done through bundler
7
+ * you can now kill a thread using & from thread_view
8
+
1
9
  == 0.17.0 / 2014-04-11
2
10
 
3
11
  * add continuous scrolling to thread view
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'rake/testtask'
3
+ require "bundler/gem_tasks"
4
+
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'test'
7
+ test.test_files = FileList.new('test/**/test_*.rb')
8
+ test.verbose = true
9
+ end
10
+ task :default => :test
11
+
12
+ task :travis => [:test, :build]
data/ReleaseNotes CHANGED
@@ -1,3 +1,7 @@
1
+ Release 0.18.0:
2
+
3
+ sup-tweak-labels works again. new color options and some bug fixes.
4
+
1
5
  Release 0.17.0:
2
6
 
3
7
  Bugfixes and new option for continous scrolling as well as an option for
data/bin/sup-sync CHANGED
@@ -175,7 +175,7 @@ begin
175
175
  puts "Changing flags for #{source}##{m.source_info} from #{old_m.labels} to #{m.labels}" if opts[:verbose]
176
176
  num_updated += 1
177
177
  end
178
- else fail
178
+ else fail "sup-sync cannot handle :update's"
179
179
  end
180
180
 
181
181
  if Time.now - last_info_time > PROGRESS_UPDATE_INTERVAL
data/bin/sup-tweak-labels CHANGED
@@ -51,6 +51,7 @@ EOS
51
51
  opt :very_verbose, "Print message names and subjects as they're processed."
52
52
  opt :all_sources, "Scan over all sources.", :short => :none
53
53
  opt :dry_run, "Don't actually modify the index. Probably only useful with --verbose.", :short => "-n"
54
+ opt :no_sync_back, "Do not sync back to the original Maildir."
54
55
  opt :version, "Show version information", :short => :none
55
56
  end
56
57
  opts[:verbose] = true if opts[:very_verbose]
@@ -63,6 +64,7 @@ Trollop::die "nothing to do: no labels to add or remove" if add_labels.empty? &&
63
64
  Redwood::start
64
65
  index = Redwood::Index.init
65
66
  index.lock_interactively or exit
67
+
66
68
  begin
67
69
  index.load
68
70
 
@@ -106,7 +108,10 @@ begin
106
108
  puts "From #{m.from}, subject: #{m.subj}" if opts[:very_verbose]
107
109
  puts "#{m.id}: {#{old_labels.to_a.join ','}} => {#{m.labels.to_a.join ','}}" if opts[:verbose]
108
110
  puts if opts[:very_verbose]
109
- index.update_message_state m unless opts[:dry_run]
111
+ unless opts[:dry_run]
112
+ index.update_message_state [m, false]
113
+ m.sync_back unless opts[:no_sync_back]
114
+ end
110
115
  end
111
116
 
112
117
  if Time.now - last_info_time > 60
@@ -0,0 +1,100 @@
1
+ require 'rubygems'
2
+
3
+ require 'ncursesw'
4
+
5
+ Ncurses.initscr
6
+ Ncurses.noecho
7
+ Ncurses.cbreak
8
+ Ncurses.start_color
9
+
10
+ Ncurses.curs_set 0
11
+ Ncurses.move 0, 0
12
+ Ncurses.clear
13
+ Ncurses.refresh
14
+ cc = Ncurses.COLORS
15
+
16
+ Ncurses::keypad(Ncurses::stdscr, 1)
17
+ Ncurses::mousemask(Ncurses::ALL_MOUSE_EVENTS | Ncurses::REPORT_MOUSE_POSITION, [])
18
+
19
+ fail "color count is #{cc}, expected 256" unless cc == 256
20
+
21
+ 1.upto(255) do |c|
22
+ Ncurses.init_pair(c, 0, c)
23
+ end
24
+
25
+ def cell y, x, c
26
+ @map[[y,x]] = c
27
+ Ncurses.attron(Ncurses.COLOR_PAIR(c))
28
+ Ncurses.mvaddstr(y, x, " ")
29
+ Ncurses.attroff(Ncurses.COLOR_PAIR(c))
30
+ end
31
+
32
+ def handle_click y, x
33
+ c = @map[[y,x]] or return
34
+ name = case c
35
+ when 0...16
36
+ c.to_s
37
+ when 16...232
38
+ 'c' + (c-16).to_s(6).rjust(3,'0')
39
+ when 232...256
40
+ 'g' + (c-232).to_s
41
+ end
42
+
43
+ Ncurses.mvaddstr 11, 0, "#{name} "
44
+
45
+ Ncurses.attron(Ncurses.COLOR_PAIR(c))
46
+ 10.times do |i|
47
+ 20.times do |j|
48
+ y = 13 + i
49
+ x = j
50
+ Ncurses.mvaddstr(y, x, " ")
51
+ end
52
+ end
53
+ Ncurses.attroff(Ncurses.COLOR_PAIR(c))
54
+ end
55
+
56
+ @map = {}
57
+ @fg = @bg = 0
58
+
59
+ begin
60
+ 16.times do |i|
61
+ cell 0, i, i
62
+ end
63
+
64
+ 6.times do |i|
65
+ 6.times do |j|
66
+ 6.times do |k|
67
+ c = 16 + 6*6*i + 6*j + k
68
+ y = 2 + j
69
+ x = 7*i + k
70
+ cell y, x, c
71
+ end
72
+ end
73
+ end
74
+
75
+ 16.times do |i|
76
+ c = 16 + 6*6*6 + i
77
+ cell 9, i, c
78
+ end
79
+
80
+ handle_click 0, 0
81
+ Ncurses.refresh
82
+
83
+ while (c = Ncurses.getch)
84
+ case c
85
+ when 113 #q
86
+ break
87
+ when Ncurses::KEY_MOUSE
88
+ mev = Ncurses::MEVENT.new
89
+ Ncurses.getmouse(mev)
90
+ case(mev.bstate)
91
+ when Ncurses::BUTTON1_CLICKED
92
+ handle_click mev.y, mev.x
93
+ end
94
+ end
95
+ Ncurses.refresh
96
+ end
97
+
98
+ ensure
99
+ Ncurses.endwin
100
+ end
@@ -0,0 +1,114 @@
1
+ #compdef sup sup-add sup-config sup-dump sup-sync sup-tweak-labels sup-recover-sources
2
+ # vim: set et sw=2 sts=2 ts=2 ft=zsh :
3
+
4
+ # TODO: sources completion: maildir://some/dir, mbox://some/file, ...
5
+ # for sup-add, sup-sync, sup-tweak-labels
6
+
7
+ (( ${+functions[_sup_cmd]} )) ||
8
+ _sup_cmd()
9
+ {
10
+ _arguments -s : \
11
+ "(--list-hooks -l)"{--list-hooks,-l}"[list all hooks and descriptions, and quit]" \
12
+ "(--no-threads -n)"{--no-threads,-n}"[turn off threading]" \
13
+ "(--no-initial-poll -o)"{--no-initial-poll,-o}"[Don't poll for new messages when starting]" \
14
+ "(--search -s)"{--search,-s}"[search for this query upon startup]:Query: " \
15
+ "(--compose -c)"{--compose,-c}"[compose message to this recipient upon startup]:Email: " \
16
+ "--version[show version information]" \
17
+ "(--help -h)"{--help,-h}"[show help]"
18
+ }
19
+
20
+ (( ${+functions[_sup_add_cmd]} )) ||
21
+ _sup_add_cmd()
22
+ {
23
+ _arguments -s : \
24
+ "(--archive -a)"{--archive,-a}"[automatically archive all new messages from this source]" \
25
+ "(--unusual -u)"{--unusual,-u}"[do not automatically poll for new messages from this source]" \
26
+ "(--labels -l)"{--labels,-l}"[set of labels to apply to all messages from this source]:Labels: " \
27
+ "(--force-new -f)"{--force-new,-f}"[create a new account for this source, even if one already exists]" \
28
+ "--version[show version information]" \
29
+ "(--help -h)"{--help,-h}"[show help]"
30
+ }
31
+
32
+ (( ${+functions[_sup_config_cmd]} )) ||
33
+ _sup_config_cmd()
34
+ {
35
+ _arguments -s : \
36
+ "--version[show version information]" \
37
+ "(--help -h)"{--help,-h}"[show help]"
38
+ }
39
+
40
+ (( ${+functions[_sup_dump_cmd]} )) ||
41
+ _sup_dump_cmd()
42
+ {
43
+ _arguments -s : \
44
+ "--version[show version information]" \
45
+ "(--help -h)"{--help,-h}"[show help]"
46
+ }
47
+
48
+ (( ${+functions[_sup_recover_sources_cmd]} )) ||
49
+ _sup_recover_sources_cmd()
50
+ {
51
+ _arguments -s : \
52
+ "--archive[automatically archive all new messages from this source]" \
53
+ "--scan-num[number of messages to scan per source]:" \
54
+ "--unusual[do not automatically poll for new messages from this source]" \
55
+ "(--help -h)"{--help,-h}"[show help]"
56
+ }
57
+
58
+ (( ${+functions[_sup_sync_cmd]} )) ||
59
+ _sup_sync_cmd()
60
+ {
61
+ # XXX Add only when --restore is given: (--restored -r)
62
+ # Add only when --changed or--all are given: (--start-at -s)
63
+ _arguments -s : \
64
+ "--new[operate on new messages only]" \
65
+ "(--changed -c)"{--changed,-c}"[scan over the entire source for messages that have been deleted, altered, or moved from another source]" \
66
+ "(--restored -r)"{--restored,-r}"[operate only on those messages included in a dump file as specified by --restore which have changed state]" \
67
+ "(--all -a)"{--all,-a}"[operate on all messages in the source, regardless of newness or changedness]" \
68
+ "(--start-at -s)"{--start-at,-s}"[start at a particular offset]:Offset: " \
69
+ "--asis[if the message is already in the index, preserve its state, otherwise, use default source state]" \
70
+ "--restore[restore message state from a dump file created with sup-dump]:File:_file" \
71
+ "--discard[discard any message state in the index and use the default source state]" \
72
+ "(--archive -x)"{--archive,-x}"[mark messages as archived when using the default source state]" \
73
+ "(--read -e)"{--read,-e}"[mark messages as read when using the default source state]" \
74
+ "--extra-labels[apply these labels when using the default source state]:Labels: " \
75
+ "(--verbose -v)"{--verbose,-v}"[print message ids as they're processed]" \
76
+ "(--optimize -o)"{--optimize,-o}"[as the final operation, optimize the index]" \
77
+ "--all-sources[scan over all sources]" \
78
+ "(--dry-run -n)"{--dry-run,-n}"[don't actually modify the index]" \
79
+ "--version[show version information]" \
80
+ "(--help -h)"{--help,-h}"[show help]"
81
+ }
82
+
83
+ (( ${+functions[_sup_sync_back_cmd]} )) ||
84
+ _sup_sync_back_cmd()
85
+ {
86
+ _arguments -s : \
87
+ "(--drop-deleted -d)"{--drop-deleted,-d}"[drop deleted messages]" \
88
+ "--move-deleted[move deleted messages to a local mbox file]:File:_file" \
89
+ "(--drop-spam -s)"{--drop-spam,-s}"[drop spam messages]" \
90
+ "--move-spam[move spam messages to a local mbox file]:File:_file" \
91
+ "--with-dotlockfile[specific dotlockfile location (mbox files only)]:File:_file" \
92
+ "--dont-use-dotlockfile[don't use dotlockfile to lock mbox files]" \
93
+ "(--verbose -v)"{--verbose,-v}"[print message ids as they're processed]" \
94
+ "(--dry-run -n)"{--dry-run,-n}"[don't actually modify the index]" \
95
+ "--version[show version information]" \
96
+ "(--help -h)"{--help,-h}"[show help]"
97
+ }
98
+
99
+ (( ${+functions[_sup_tweak_labels_cmd]} )) ||
100
+ _sup_tweak_labels_cmd()
101
+ {
102
+ _arguments -s : \
103
+ "(--add -a)"{--add,-a}"[which labels to add to every message from the specified sources]:Labels: " \
104
+ "(--remove -r)"{--remove,-r}"[which labels to remove from every message from the specified sources]:Labels: " \
105
+ "--all-sources[scan over all sources]" \
106
+ "(--verbose -v)"{--verbose,-v}"[print message ids as they're processed]" \
107
+ "(--dry-run -n)"{--dry-run,-n}"[don't actually modify the index]" \
108
+ "--version[show version information]" \
109
+ "(--help -h)"{--help,-h}"[show help]"
110
+ }
111
+
112
+ _call_function ret _${words[1]//-/_}_cmd
113
+ return ret
114
+
data/devel/console.sh ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ irb -I lib -r ./devel/start-console.rb
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ egrep ".rb$" Manifest.txt | xargs cat | grep -v "^ *$"|grep -v "^ *#"|grep -v "^ *end *$"|wc -l
@@ -0,0 +1,9 @@
1
+ require 'sup'
2
+
3
+ puts "loading index..."
4
+ @index = Redwood::Index.new
5
+ @index.load
6
+ @i = @index.index
7
+ puts "loaded index of #{@i.size} messages"
8
+
9
+
data/devel/profile.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'ruby-prof'
3
+ require "redwood"
4
+
5
+ result = RubyProf.profile do
6
+ Redwood::ThreadSet.new(ARGV.map { |fn| Redwood::MBox::Scanner.new fn }).load_n_threads 100
7
+ end
8
+
9
+ printer = RubyProf::GraphHtmlPrinter.new(result)
10
+ File.open("profile.html", "w") { |f| printer.print(f, 1) }
11
+ puts "report in profile.html"
12
+
@@ -0,0 +1,5 @@
1
+ require 'sup'
2
+ include Redwood
3
+ start
4
+ Index.init
5
+ Index.load
data/doc/FAQ.txt ADDED
@@ -0,0 +1,119 @@
1
+ Sup FAQ
2
+ -------
3
+
4
+ Q: What is Sup?
5
+ A: A console-based email client for people with a lot of email.
6
+
7
+ Q: What does Sup stand for?
8
+ A: "What's up?"
9
+
10
+ Q: Sup looks like a text-based Gmail.
11
+ A: First I stole their ideas. Then I improved them.
12
+
13
+ Q: Why not just use Gmail?
14
+ A: I hate ads, I hate using a mouse, and I hate non-programmability and
15
+ non-extensibility.
16
+
17
+ Also, Gmail doesn't let you use a monospace font, which is just
18
+ lame.
19
+
20
+ Also, Gmail encourages top-posting. THIS CANNOT BE TOLERATED!
21
+
22
+ Q: Why the console?
23
+ A: Because a keystroke is worth a hundred mouse clicks, as any Unix
24
+ user knows. Because you don't need a web browser. Because you get
25
+ an instantaneous response and a simple interface.
26
+
27
+ Q: How does Sup deal with spam?
28
+ A: You can manually mark messages as spam, which prevents them from
29
+ showing up in future searches. Later, you can run a batch process to
30
+ remove such messages from your sources. That's as far as Sup goes.
31
+ Spam filtering should be done by a dedicated tool like SpamAssassin.
32
+
33
+ Q: How do I delete a message?
34
+ A: Why delete? Unless it's spam, you might as well just archive it.
35
+
36
+ Q: C'mon, really now!
37
+ A: Ok, press the 'd' key.
38
+
39
+ Q: But I want to delete it for real, not just add a 'deleted' flag in
40
+ the index. I want it gone from disk!
41
+ A: Currently, for mbox sources, there is a batch deletion tool that
42
+ will strip out all messages marked as spam or deleted.
43
+
44
+ Q: How well does Sup play with other mail clients?
45
+ A: Not well at all. If messages have been moved, deleted, or altered
46
+ due to some other client, Sup will have to rebuild its index for
47
+ that message source. For example, for mbox files, reading a single
48
+ unread message changes the offsets of every file on disk. Rather
49
+ than rescanning every time, Sup assumes sources don't change except
50
+ by having new messages added. If that assumption is violated,
51
+ you'll have to sync the index.
52
+
53
+ Q: How do I back up my index?
54
+ A: Since the contents of the messages are recoverable from their
55
+ sources using sup-sync, all you need to back up is the message
56
+ state. To do this, simply run:
57
+ sup-dump > <dumpfile>
58
+ This will save all message state in a big text file, which you
59
+ should probably compress.
60
+
61
+ Q: How do I restore the message state I saved in my state dump?
62
+ A: Run:
63
+ sup-sync [<source>+] --restored --restore <dumpfile>
64
+ where <dumpfile> was created as above.
65
+
66
+ Q: Xapian crashed and I can't read my index. Luckily I made a state
67
+ dump. What should I do?
68
+ Q: How do I rebuild the index completely?
69
+ A: Run:
70
+ rm -rf ~/.sup/xapian # omg wtf
71
+ sup-sync --all-sources --all --restore <dumpfile>
72
+ Voila! A brand new index.
73
+
74
+ Q: I want to move messages from one source to another. (E.g., my
75
+ primary inbox is an mbox file, and I want to move some of those
76
+ messages to a Maildir.) How do I do that while preserving message
77
+ state?
78
+ A: Move the messages from the source to the target using whatever tool
79
+ you'd like. Mutt's a good one. :) Then run:
80
+ sup-sync --changed <source1> <source2>
81
+
82
+ Note that if you sup-sync only one source at a time, depending on
83
+ the order in which you do it, the messages may be treated as
84
+ missing and then deleted from the index, which means that their
85
+ states will be lost when you sync the other source. So do them both
86
+ in one go.
87
+
88
+ Q: What are all these "Redwood" references I see in the code?
89
+ A: That was Sup's original name. (Think pine, elm. Although I was a
90
+ Mutt user, I couldn't think of a good progression there.) But it was
91
+ taken by another project on RubyForge, and wasn't that original, and
92
+ was too long to type anyways.
93
+
94
+ Common Problems
95
+ ---------------
96
+
97
+ P: I get some error message from Rubymail about frozen strings when
98
+ importing messages with attachments.
99
+ S: The current solution is to directly modify RubyMail. Change line 159 of
100
+ multipart.rb to:
101
+ chunk = chunk[0..start]
102
+ This is because RubyMail hasn't been updated since like Ruby 1.8.2.
103
+ Please bug Matt Armstrong.
104
+
105
+ P: I see this error:
106
+ /usr/local/lib/ruby/1.8/yaml.rb:133:in `transfer': allocator undefined for Bignum (TypeError)
107
+ S: You need to upgrade to Ruby 1.8.5. YAML in earlier versions can't
108
+ parse BigNums, but Sup relies on that for Maildir.
109
+
110
+ P: When I run Sup remotely and view an HTML attachment, an existing
111
+ Firefox on the *local* machine is redirected to the attachment
112
+ file, which it can't find (since it's on the remote machine). How do
113
+ I view HTML attachments in this environment?
114
+ S: Put this in your ~/.mailcap on the machine you run Sup on:
115
+ text/html; /usr/bin/firefox -a sup %s; description=HTML Text; test=test -n "$DISPLAY"; nametemplate=%s.html
116
+
117
+ Please read
118
+ https://github.com/sup-heliotrope/sup/wiki/Viewing-Attachments for
119
+ some security concerns on opening attachments.