sup 0.17.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +17 -0
- data/.travis.yml +12 -0
- data/Gemfile +3 -0
- data/HACKING +42 -0
- data/History.txt +8 -0
- data/Rakefile +12 -0
- data/ReleaseNotes +4 -0
- data/bin/sup-sync +1 -1
- data/bin/sup-tweak-labels +6 -1
- data/contrib/colorpicker.rb +100 -0
- data/contrib/completion/_sup.zsh +114 -0
- data/devel/console.sh +3 -0
- data/devel/count-loc.sh +3 -0
- data/devel/load-index.rb +9 -0
- data/devel/profile.rb +12 -0
- data/devel/start-console.rb +5 -0
- data/doc/FAQ.txt +119 -0
- data/doc/Hooks.txt +79 -0
- data/doc/Philosophy.txt +69 -0
- data/lib/sup/colormap.rb +6 -0
- data/lib/sup/modes/thread_index_mode.rb +12 -1
- data/lib/sup/modes/thread_view_mode.rb +20 -0
- data/lib/sup/version.rb +1 -1
- data/sup.gemspec +55 -0
- data/test/dummy_source.rb +61 -0
- data/test/gnupg_test_home/gpg.conf +1 -0
- data/test/gnupg_test_home/pubring.gpg +0 -0
- data/test/gnupg_test_home/receiver_pubring.gpg +0 -0
- data/test/gnupg_test_home/receiver_secring.gpg +0 -0
- data/test/gnupg_test_home/receiver_trustdb.gpg +0 -0
- data/test/gnupg_test_home/secring.gpg +0 -0
- data/test/gnupg_test_home/sup-test-2@foo.bar.asc +20 -0
- data/test/gnupg_test_home/trustdb.gpg +0 -0
- data/test/integration/test_label_service.rb +18 -0
- data/test/messages/bad-content-transfer-encoding-1.eml +8 -0
- data/test/messages/binary-content-transfer-encoding-2.eml +21 -0
- data/test/messages/missing-line.eml +9 -0
- data/test/test_crypto.rb +109 -0
- data/test/test_header_parsing.rb +168 -0
- data/test/test_helper.rb +7 -0
- data/test/test_message.rb +532 -0
- data/test/test_messages_dir.rb +147 -0
- data/test/test_yaml_migration.rb +85 -0
- data/test/test_yaml_regressions.rb +17 -0
- data/test/unit/service/test_label_service.rb +19 -0
- data/test/unit/test_horizontal_selector.rb +40 -0
- data/test/unit/util/test_query.rb +46 -0
- data/test/unit/util/test_string.rb +57 -0
- data/test/unit/util/test_uri.rb +19 -0
- metadata +81 -36
- checksums.yaml.gz.sig +0 -1
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
data/doc/Hooks.txt
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
Sup's Hook System
|
2
|
+
-----------------
|
3
|
+
|
4
|
+
Sup can be easily customized via its hook system, which allows custom
|
5
|
+
user code to be injected into Sup's execution path by "hooking" the
|
6
|
+
code onto pre-defined events. When those events occur, the code is
|
7
|
+
executed.
|
8
|
+
|
9
|
+
To see which hooks are available, simply run sup -l. Each hook sits in
|
10
|
+
a file in ~/.sup/hooks/. Hooks are written in Ruby, and require no
|
11
|
+
class or method definitions, just the executable code itself.
|
12
|
+
|
13
|
+
Information passes from Sup to the hook code via Ruby variables
|
14
|
+
(actually method calls), and from the hook code back to Sup via a
|
15
|
+
return value. The values of variables persists across calls to the
|
16
|
+
same hook, but is NOT available to other hooks. To make the value of a
|
17
|
+
variable available to other hooks, use the get and set methods. Each
|
18
|
+
hook description lists the variables and return value expected, if
|
19
|
+
any.
|
20
|
+
|
21
|
+
The following special functions are available to hooks:
|
22
|
+
* say msg
|
23
|
+
Displays the string msg to the user at the bottom of the screen.
|
24
|
+
* log msg
|
25
|
+
Adds the string msg to the log, which the user can access via the
|
26
|
+
buffer list.
|
27
|
+
* ask_yes_or_no question
|
28
|
+
Prompts the user with the string question for a yes or no
|
29
|
+
response. Returns true if the user answered yes, false otherwise.
|
30
|
+
* get key
|
31
|
+
Gets the cross-hook value associated with key (which is typically a
|
32
|
+
string). If there is no value for a given key, nil is returned.
|
33
|
+
* set key value
|
34
|
+
Sets the cross-hook value associated with key to value. key is
|
35
|
+
typically a string, while value can be whatever type it needs to be,
|
36
|
+
including nil.
|
37
|
+
|
38
|
+
Some example hooks:
|
39
|
+
|
40
|
+
before-poll:
|
41
|
+
## runs fetchmail before polling
|
42
|
+
if (@last_fetchmail_time || Time.now) < Time.now - 60
|
43
|
+
say "Running fetchmail..."
|
44
|
+
system "fetchmail >& /dev/null"
|
45
|
+
say "Done running fetchmail."
|
46
|
+
end
|
47
|
+
@last_fetchmail_time = Time.now
|
48
|
+
|
49
|
+
|
50
|
+
mime-decode:
|
51
|
+
## Please read:
|
52
|
+
https://github.com/sup-heliotrope/sup/wiki/Viewing-Attachments for
|
53
|
+
some security concerns on opening attachments.
|
54
|
+
|
55
|
+
## turn text/html attachments into plain text, unless they are part
|
56
|
+
## of a multipart/alternative pair
|
57
|
+
require 'shellwords'
|
58
|
+
unless sibling_types.member? "text/plain"
|
59
|
+
case content_type
|
60
|
+
when "text/html"
|
61
|
+
`/usr/bin/w3m -dump -T #{content_type} #{Shellwords.escape filename}`
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
startup:
|
66
|
+
## runs a background task
|
67
|
+
@bgtask_pid = fork
|
68
|
+
if @bgtask_pid
|
69
|
+
set 'bgtask_pid' @bgtask_pid
|
70
|
+
Process.detach(@bgtask_pid) # so we don't have to wait on it when we go to kill it
|
71
|
+
else
|
72
|
+
exec "background-task args 2&>1 >> /tmp/logfile"
|
73
|
+
end
|
74
|
+
|
75
|
+
after-poll:
|
76
|
+
## kills the background task after the first poll
|
77
|
+
@bgtask_pid = get 'bgtask_pid'
|
78
|
+
Process.kill("TERM", @bgtask_pid) unless @bgtask_pid == nil
|
79
|
+
set 'bgtask_pid' nil
|
data/doc/Philosophy.txt
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
Should an email client have a philosophy? For many people, email is
|
2
|
+
one of our primary means of communication, and email archives are an
|
3
|
+
integral part of our long-term memory. Something so important ought to
|
4
|
+
warrant a little thought.
|
5
|
+
|
6
|
+
Here's Sup's philosophy.
|
7
|
+
|
8
|
+
Using "traditional" email clients today is increasingly problematic.
|
9
|
+
Anyone who's on a high-traffic mailing list knows this. My ruby-talk
|
10
|
+
folder is 430 megs and Mutt sits there for 60 seconds while it opens
|
11
|
+
it. Keeping up with the all the new traffic is impossible, even with
|
12
|
+
Mutt's excellent threading features, simply because there's so much of
|
13
|
+
it. A single thread can span several pages in the folder index view
|
14
|
+
alone! And Mutt is probably the fastest, most mailing-list aware email
|
15
|
+
client out there. God help me if I try and use Thunderbird.
|
16
|
+
|
17
|
+
The problem with traditional clients like Mutt is that they deal with
|
18
|
+
individual pieces of email. This places a high mental cost on the user
|
19
|
+
for each incoming email, by forcing them to ask: Should I keep this
|
20
|
+
email, or delete it? If I keep it, where should I file it? I've spent
|
21
|
+
the last 10 years of my life laboriously hand-filing every email
|
22
|
+
message I received and feeling a mild sense of panic every time an
|
23
|
+
email was both "from Mom" and "about school". The massive amounts of
|
24
|
+
email that many people receive, and the cheap cost of storage, have
|
25
|
+
made these questions both more costly and less useful to answer.
|
26
|
+
|
27
|
+
Contrast that with using Gmail. As a long-time Mutt user, I was blown
|
28
|
+
away when I first saw someone use Gmail. They treated their email
|
29
|
+
differently from how I ever had. They never filed email and they never
|
30
|
+
deleted it. They relied on an immediate, global, full-text search, and
|
31
|
+
thread-level tagging, to do everything I'd ever done with Mutt, but
|
32
|
+
with a trivial cost to the user at message receipt time.
|
33
|
+
|
34
|
+
From Gmail I learned that making certain operations quantitatively
|
35
|
+
easier (namely, search) resulted in a qualitative improvement in
|
36
|
+
usage. I also learned how thread-centrism was advantageous over
|
37
|
+
message-centrism when message volume was high: most of the time, a
|
38
|
+
message and its context deserve the same treatment. I think it's to
|
39
|
+
the Gmail designers' credit that they started with a somewhat ad-hoc
|
40
|
+
idea (hey, we're really good at search engines, so maybe we can build
|
41
|
+
an email client on top of one) and managed to build something that was
|
42
|
+
actually better than everything else out there. At least, that's how I
|
43
|
+
imagine in happened. Maybe they knew what they were doing from the
|
44
|
+
start.
|
45
|
+
|
46
|
+
Unfortunately, there's a lot to Gmail I can't tolerate (top posting,
|
47
|
+
HTML mail, one-level threads, and ads come to mind, never mind the
|
48
|
+
fact that it's not FOSS). Thus Sup was born.
|
49
|
+
|
50
|
+
Sup is based on the following principles, which I stole directly from
|
51
|
+
Gmail:
|
52
|
+
|
53
|
+
- An immediately accessible and fast search capability over the entire
|
54
|
+
email archive eliminates most of the need for folders, and most of
|
55
|
+
the necessity of deleting email.
|
56
|
+
|
57
|
+
- Labels eliminate what little need for folders search doesn't cover.
|
58
|
+
|
59
|
+
- A thread-centric approach to the UI is much more in line with how
|
60
|
+
people operate than dealing with individual messages is. In the vast
|
61
|
+
majority of cases, a message and its context should be subject to
|
62
|
+
the same treatment.
|
63
|
+
|
64
|
+
Sup is also based on many ideas from mutt and Emacs and vi, having to
|
65
|
+
do with the fantastic productivity of a console- and keyboard-based
|
66
|
+
application, the usefulness of multiple buffers, the necessity of
|
67
|
+
handling multiple email accounts, etc. But those are just details!
|
68
|
+
|
69
|
+
Try it and let me know what you think.
|
data/lib/sup/colormap.rb
CHANGED
@@ -50,6 +50,7 @@ class Colormap
|
|
50
50
|
:quote => { :fg => "yellow", :bg => "default" },
|
51
51
|
:sig => { :fg => "yellow", :bg => "default" },
|
52
52
|
:to_me => { :fg => "green", :bg => "default" },
|
53
|
+
:with_attachment => { :fg => "green", :bg => "default" },
|
53
54
|
:starred => { :fg => "yellow", :bg => "default", :attrs => ["bold"] },
|
54
55
|
:starred_patina => { :fg => "yellow", :bg => "green", :attrs => ["bold"] },
|
55
56
|
:alternate_starred_patina => { :fg => "yellow", :bg => "blue", :attrs => ["bold"] },
|
@@ -190,6 +191,11 @@ class Colormap
|
|
190
191
|
Redwood::load_yaml_obj Redwood::COLOR_FN
|
191
192
|
end
|
192
193
|
|
194
|
+
## Set attachment sybmol to sane default for existing colorschemes
|
195
|
+
if user_colors and user_colors.has_key? :to_me
|
196
|
+
user_colors[:with_attachment] = user_colors[:to_me] unless user_colors.has_key? :with_attachment
|
197
|
+
end
|
198
|
+
|
193
199
|
Colormap::DEFAULT_COLORS.merge(user_colors||{}).each_pair do |k, v|
|
194
200
|
fg = begin
|
195
201
|
Ncurses.const_get "COLOR_#{v[:fg].to_s.upcase}"
|
@@ -236,6 +236,13 @@ EOS
|
|
236
236
|
update
|
237
237
|
end
|
238
238
|
|
239
|
+
def handle_killed_update sender, m
|
240
|
+
t = @ts_mutex.synchronize { @ts.thread_for m }
|
241
|
+
return unless t
|
242
|
+
hide_thread t
|
243
|
+
update
|
244
|
+
end
|
245
|
+
|
239
246
|
def handle_spammed_update sender, m
|
240
247
|
t = @ts_mutex.synchronize { @ts.thread_for m }
|
241
248
|
return unless t
|
@@ -247,6 +254,10 @@ EOS
|
|
247
254
|
add_or_unhide m
|
248
255
|
end
|
249
256
|
|
257
|
+
def handle_unkilled_update sender, m
|
258
|
+
add_or_unhide m
|
259
|
+
end
|
260
|
+
|
250
261
|
def undo
|
251
262
|
UndoManager.undo
|
252
263
|
end
|
@@ -979,7 +990,7 @@ protected
|
|
979
990
|
from +
|
980
991
|
[
|
981
992
|
[:size_widget_color, size_widget_text],
|
982
|
-
[:
|
993
|
+
[:with_attachment_color , t.labels.member?(:attachment) ? "@" : " "],
|
983
994
|
[:to_me_color, directly_participated ? ">" : (participated ? '+' : " ")],
|
984
995
|
] +
|
985
996
|
(t.labels - @hidden_labels).sort_by {|x| x.to_s}.map {
|
@@ -78,11 +78,13 @@ EOS
|
|
78
78
|
|
79
79
|
k.add :archive_and_next, "Archive this thread, kill buffer, and view next", 'a'
|
80
80
|
k.add :delete_and_next, "Delete this thread, kill buffer, and view next", 'd'
|
81
|
+
k.add :kill_and_next, "Kill this thread, kill buffer, and view next", '&'
|
81
82
|
k.add :toggle_wrap, "Toggle wrapping of text", 'w'
|
82
83
|
|
83
84
|
k.add_multi "(a)rchive/(d)elete/mark as (s)pam/mark as u(N)read:", '.' do |kk|
|
84
85
|
kk.add :archive_and_kill, "Archive this thread and kill buffer", 'a'
|
85
86
|
kk.add :delete_and_kill, "Delete this thread and kill buffer", 'd'
|
87
|
+
kk.add :kill_and_kill, "Kill this thread and kill buffer", '&'
|
86
88
|
kk.add :spam_and_kill, "Mark this thread as spam and kill buffer", 's'
|
87
89
|
kk.add :unread_and_kill, "Mark this thread as unread and kill buffer", 'N'
|
88
90
|
kk.add :do_nothing_and_kill, "Just kill this buffer", '.'
|
@@ -91,6 +93,7 @@ EOS
|
|
91
93
|
k.add_multi "(a)rchive/(d)elete/mark as (s)pam/mark as u(N)read/do (n)othing:", ',' do |kk|
|
92
94
|
kk.add :archive_and_next, "Archive this thread, kill buffer, and view next", 'a'
|
93
95
|
kk.add :delete_and_next, "Delete this thread, kill buffer, and view next", 'd'
|
96
|
+
kk.add :kill_and_next, "Kill this thread, kill buffer, and view next", '&'
|
94
97
|
kk.add :spam_and_next, "Mark this thread as spam, kill buffer, and view next", 's'
|
95
98
|
kk.add :unread_and_next, "Mark this thread as unread, kill buffer, and view next", 'N'
|
96
99
|
kk.add :do_nothing_and_next, "Kill buffer, and view next", 'n', ','
|
@@ -99,6 +102,7 @@ EOS
|
|
99
102
|
k.add_multi "(a)rchive/(d)elete/mark as (s)pam/mark as u(N)read/do (n)othing:", ']' do |kk|
|
100
103
|
kk.add :archive_and_prev, "Archive this thread, kill buffer, and view previous", 'a'
|
101
104
|
kk.add :delete_and_prev, "Delete this thread, kill buffer, and view previous", 'd'
|
105
|
+
kk.add :kill_and_prev, "Kill this thread, kill buffer, and view previous", '&'
|
102
106
|
kk.add :spam_and_prev, "Mark this thread as spam, kill buffer, and view previous", 's'
|
103
107
|
kk.add :unread_and_prev, "Mark this thread as unread, kill buffer, and view previous", 'N'
|
104
108
|
kk.add :do_nothing_and_prev, "Kill buffer, and view previous", 'n', ']'
|
@@ -581,18 +585,21 @@ EOS
|
|
581
585
|
def archive_and_kill; archive_and_then :kill end
|
582
586
|
def spam_and_kill; spam_and_then :kill end
|
583
587
|
def delete_and_kill; delete_and_then :kill end
|
588
|
+
def kill_and_kill; kill_and_then :kill end
|
584
589
|
def unread_and_kill; unread_and_then :kill end
|
585
590
|
def do_nothing_and_kill; do_nothing_and_then :kill end
|
586
591
|
|
587
592
|
def archive_and_next; archive_and_then :next end
|
588
593
|
def spam_and_next; spam_and_then :next end
|
589
594
|
def delete_and_next; delete_and_then :next end
|
595
|
+
def kill_and_next; kill_and_then :next end
|
590
596
|
def unread_and_next; unread_and_then :next end
|
591
597
|
def do_nothing_and_next; do_nothing_and_then :next end
|
592
598
|
|
593
599
|
def archive_and_prev; archive_and_then :prev end
|
594
600
|
def spam_and_prev; spam_and_then :prev end
|
595
601
|
def delete_and_prev; delete_and_then :prev end
|
602
|
+
def kill_and_prev; kill_and_then :prev end
|
596
603
|
def unread_and_prev; unread_and_then :prev end
|
597
604
|
def do_nothing_and_prev; do_nothing_and_then :prev end
|
598
605
|
|
@@ -635,6 +642,19 @@ EOS
|
|
635
642
|
end
|
636
643
|
end
|
637
644
|
|
645
|
+
def kill_and_then op
|
646
|
+
dispatch op do
|
647
|
+
@thread.apply_label :killed
|
648
|
+
UpdateManager.relay self, :killed, @thread.first
|
649
|
+
Index.save_thread @thread
|
650
|
+
UndoManager.register "killed 1 thread" do
|
651
|
+
@thread.remove_label :killed
|
652
|
+
Index.save_thread @thread
|
653
|
+
UpdateManager.relay self, :unkilled, @thread.first
|
654
|
+
end
|
655
|
+
end
|
656
|
+
end
|
657
|
+
|
638
658
|
def unread_and_then op
|
639
659
|
dispatch op do
|
640
660
|
@thread.apply_label :unread
|
data/lib/sup/version.rb
CHANGED
data/sup.gemspec
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
require 'sup/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "sup"
|
7
|
+
s.version = ENV["REL"] || (::Redwood::VERSION == "git" ? "999" : ::Redwood::VERSION)
|
8
|
+
s.date = Time.now.strftime "%Y-%m-%d"
|
9
|
+
s.authors = ["William Morgan", "Gaute Hope", "Hamish Downer", "Matthieu Rakotojaona"]
|
10
|
+
s.email = "sup-talk@rubyforge.org"
|
11
|
+
s.summary = "A console-based email client with the best features of GMail, mutt and Emacs"
|
12
|
+
s.homepage = "http://supmua.org"
|
13
|
+
s.license = 'GPL-2'
|
14
|
+
s.description = <<-DESC
|
15
|
+
Sup is a console-based email client for people with a lot of email.
|
16
|
+
|
17
|
+
* GMail-like thread-centered archiving, tagging and muting
|
18
|
+
* Handling mail from multiple mbox and Maildir sources
|
19
|
+
* Blazing fast full-text search with a rich query language
|
20
|
+
* Multiple accounts - pick the right one when sending mail
|
21
|
+
* Ruby-programmable hooks
|
22
|
+
* Automatically tracking recent contacts
|
23
|
+
DESC
|
24
|
+
s.post_install_message = <<-EOF
|
25
|
+
SUP: If you are upgrading Sup from before version 0.14.0: Please
|
26
|
+
run `sup-psych-ify-config-files` to migrate from 0.13.
|
27
|
+
|
28
|
+
Check https://github.com/sup-heliotrope/sup/wiki/Migration-0.13-to-0.14
|
29
|
+
for more detailed and up-to-date instructions.
|
30
|
+
EOF
|
31
|
+
|
32
|
+
s.files = `git ls-files -z`.split("\x0")
|
33
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
34
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
35
|
+
s.require_paths = ["lib"]
|
36
|
+
|
37
|
+
s.required_ruby_version = '>= 1.9.3'
|
38
|
+
|
39
|
+
s.add_runtime_dependency "xapian-ruby", "~> 1.2.15"
|
40
|
+
s.add_runtime_dependency "ncursesw", "~> 1.4.0"
|
41
|
+
s.add_runtime_dependency "rmail-sup", "~> 1.0.1"
|
42
|
+
s.add_runtime_dependency "highline"
|
43
|
+
s.add_runtime_dependency "trollop", ">= 1.12"
|
44
|
+
s.add_runtime_dependency "lockfile"
|
45
|
+
s.add_runtime_dependency "mime-types", "~> 1.0"
|
46
|
+
s.add_runtime_dependency "locale", "~> 2.0"
|
47
|
+
s.add_runtime_dependency "chronic", "~> 0.9.1"
|
48
|
+
s.add_runtime_dependency "unicode", "~> 0.4.4"
|
49
|
+
|
50
|
+
s.add_development_dependency "bundler", "~> 1.3"
|
51
|
+
s.add_development_dependency "rake"
|
52
|
+
s.add_development_dependency "minitest", "~> 4.7"
|
53
|
+
s.add_development_dependency "rr", "~> 1.0.5"
|
54
|
+
s.add_development_dependency "gpgme", ">= 2.0.2"
|
55
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'sup'
|
4
|
+
require 'stringio'
|
5
|
+
require 'rmail'
|
6
|
+
require 'uri'
|
7
|
+
|
8
|
+
module Redwood
|
9
|
+
|
10
|
+
class DummySource < Source
|
11
|
+
|
12
|
+
attr_accessor :messages
|
13
|
+
|
14
|
+
def initialize uri, last_date=nil, usual=true, archived=false, id=nil, labels=[]
|
15
|
+
super uri, usual, archived, id
|
16
|
+
@messages = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def start_offset
|
20
|
+
0
|
21
|
+
end
|
22
|
+
|
23
|
+
def end_offset
|
24
|
+
# should contain the number of test messages -1
|
25
|
+
return @messages ? @messages.length - 1 : 0
|
26
|
+
end
|
27
|
+
|
28
|
+
def load_header offset
|
29
|
+
Source.parse_raw_email_header StringIO.new(raw_header(offset))
|
30
|
+
end
|
31
|
+
|
32
|
+
def load_message offset
|
33
|
+
RMail::Parser.read raw_message(offset)
|
34
|
+
end
|
35
|
+
|
36
|
+
def raw_header offset
|
37
|
+
ret = ""
|
38
|
+
f = StringIO.new(@messages[offset])
|
39
|
+
until f.eof? || (l = f.gets) =~ /^$/
|
40
|
+
ret += l
|
41
|
+
end
|
42
|
+
ret
|
43
|
+
end
|
44
|
+
|
45
|
+
def raw_message offset
|
46
|
+
@messages[offset]
|
47
|
+
end
|
48
|
+
|
49
|
+
def each_raw_message_line offset
|
50
|
+
ret = ""
|
51
|
+
f = StringIO.new(@messages[offset])
|
52
|
+
until f.eof?
|
53
|
+
yield f.gets
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
# vim:noai:ts=2:sw=2:
|
61
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
default-key 789E7011
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,20 @@
|
|
1
|
+
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
2
|
+
Version: GnuPG v2.0.20 (GNU/Linux)
|
3
|
+
|
4
|
+
mI0EUgi0fAEEAOLAcQW96NEUSB7YE/la8X56jGW5BMX3aAixOF8LvOwMBbUK1T+U
|
5
|
+
0H2PGIrXVcYyHcPqWRpRahbsIAldBqzffPlzMa+aqJaB1xKkNruxSoIzwPdidZMe
|
6
|
+
l0Dxz2FDsoXD0KPyWnAYhGmQyz2MFpZxu2tlYqvwWVW//XGnk/KHvIXbABEBAAG0
|
7
|
+
PlN1cCBUZXN0IFJlY2VpdmVyIChUZXN0IHJlY2VpdmVyIGZvciBTdXApIDxzdXAt
|
8
|
+
dGVzdC0yQGZvby5iYXI+iL8EEwECACkFAlIItHwCGwMFCQHhM4AHCwkIBwMCAQYV
|
9
|
+
CAIJCgsEFgIDAQIeAQIXgAAKCRAsABl+cWpykMMVBADHkQPgTz0CqKKp3k+z3dbm
|
10
|
+
ocmI4tYNn1dOkDQqyfoBTfs6L3g4j5OE2UrguntRYyg5oon+uO5d18CQ5dY0sCw/
|
11
|
+
o5IwyzTrxI8IocbtZvBdSb+XjLndynGuIQoqaJq9i6n1V4klFHVOna8Q9JstLfRX
|
12
|
+
H1d4xPhnvKcaDDx/NV3X/biNBFIItHwBBADBpb43MpkrUWlg7HWJ1ZfOlxnOxrJ3
|
13
|
+
Gz9WFNV06UbcZEuFKA/vHRjM6gWzUn5903FLuCWu3eBrq5xQfWipbp187PmocpoG
|
14
|
+
skJ6gosLs1fMYRBjv2VbG9xJVKdKJMjqZw5FUpXKAaHr8P9jN6g2STQrbeQ8CVUK
|
15
|
+
h7zOWRXAXSKUgwARAQABiKUEGAECAA8FAlIItHwCGwwFCQHhM4AACgkQLAAZfnFq
|
16
|
+
cpDV1QQAzcxFXznEX92DjWxWRC7gRHgIsQk9WJnDzjtnDjSWCp3H85qeTZGZrn9W
|
17
|
+
NoneV/S5Y7K3Mkceh4rFaANQ3zx4b05y1LFt5N/lPwIe5VB0vcPumtZum2fSGfpK
|
18
|
+
nTXvzelcWcm2aGyUSaWvOkntWKEEt1kB5Oq6EtZoRZLMzAxLd7s=
|
19
|
+
=aKsV
|
20
|
+
-----END PGP PUBLIC KEY BLOCK-----
|
Binary file
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
require "sup/service/label_service"
|
4
|
+
|
5
|
+
require "tmpdir"
|
6
|
+
|
7
|
+
describe Redwood::LabelService do
|
8
|
+
let(:tmpdir) { Dir.mktmpdir }
|
9
|
+
after do
|
10
|
+
require "fileutils"
|
11
|
+
FileUtils.remove_entry_secure @tmpdir unless @tmpdir.nil?
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#add_labels" do
|
15
|
+
# Integration tests are hard to write at this moment :(
|
16
|
+
it "add labels to all messages matching the query"
|
17
|
+
end
|
18
|
+
end
|