Browse Source

Revamp packaging to achieve more correct Lua style

Several changes regarding packaging, namespacing and handler API:

 *  Utility function module is now called 'imapdomo', not 'common'.

 *  The module behaves as one, instead of being just a global-modifying
    include.

 *  Lots of cleanups as advised by luacheck (local declarations,
    removal of unused variables...)

 *  Handlers now have to access utility API via `require` and provide
    accout configuration in new file mailboxes.lua, which has to return
    table.  Accessing mailboxes is via utility function.  (This sounds
    complicated but actually is not.  Believe me! :))
Alois Mahdal 4 years ago
parent
commit
b4ae749515
6 changed files with 55 additions and 39 deletions
  1. 1
    1
      mkit.ini
  2. 1
    1
      packaging/debian/install
  3. 1
    1
      packaging/template.spec
  4. 45
    32
      src/imapdomo.lua
  5. 5
    2
      src/imapdomo.skel
  6. 2
    2
      src/main.lua.skel

+ 1
- 1
mkit.ini View File

@@ -38,7 +38,7 @@
38 38
 
39 39
 [files]
40 40
     bin     = src/imapdomo
41
+    share   = src/imapdomo.lua
41 42
     share   = src/main.lua
42
-    share   = src/common.lua
43 43
 
44 44
 #mkit version=0.0.34

+ 1
- 1
packaging/debian/install View File

@@ -1,3 +1,3 @@
1 1
 /usr/bin/imapdomo
2
-/usr/share/imapdomo/common.lua
2
+/usr/share/imapdomo/imapdomo.lua
3 3
 /usr/share/imapdomo/main.lua

+ 1
- 1
packaging/template.spec View File

@@ -29,7 +29,7 @@ make %{?_smp_mflags}
29 29
 %files
30 30
 %dir %{_datadir}/%{name}
31 31
 %{_bindir}/%{name}
32
-%{_datadir}/%{name}/common.lua
32
+%{_datadir}/%{name}/imapdomo.lua
33 33
 %{_datadir}/%{name}/main.lua
34 34
 
35 35
 %changelog

src/common.lua → src/imapdomo.lua View File

@@ -1,9 +1,19 @@
1
+local pkg = {}
1 2
 
2 3
 ------------------------------------------------------------------------------
3 4
 -- config and handling                                                      --
4 5
 ------------------------------------------------------------------------------
5 6
 
6
-function file_exists(name)
7
+pkg.load_mailboxes = function()
8
+    --
9
+    -- Load mailboxes from $IMAPDOMO_CFGDIR/mailboxes.lua
10
+    --
11
+    local fname = os.getenv("IMAPDOMO_CFGDIR") .. '/mailboxes.lua'
12
+    assert(pkg.file_exists(fname))
13
+    return dofile(fname)
14
+end
15
+
16
+pkg.file_exists = function(name)
7 17
     --
8 18
     -- True if file *name* exists
9 19
     --
@@ -16,25 +26,25 @@ function file_exists(name)
16 26
     end
17 27
 end
18 28
 
19
-function do_if_exists(filename)
29
+pkg.do_if_exists = function (filename)
20 30
     --
21 31
     -- Do file from home, if exists
22 32
     --
23 33
     local file = os.getenv("IMAPFILTER_HOME") .. "/" .. filename
24
-    if file_exists(file) then
34
+    if pkg.file_exists(file) then
25 35
         dofile(file)
26 36
         return
27 37
     end
28 38
 end
29 39
 
30
-function handle()
40
+pkg.handle = function()
31 41
     --
32 42
     -- Handle action if it's valid
33 43
     --
34 44
     local action = os.getenv("IMAPDOMO_ACTION")
35 45
     local file = os.getenv("IMAPFILTER_HOME") .. "/handlers/" .. action .. ".lua"
36
-    if file_exists(file) then
37
-        do_if_exists("init.lua")
46
+    if pkg.file_exists(file) then
47
+        pkg.do_if_exists("init.lua")
38 48
         dofile(file)
39 49
     else
40 50
         error("no handler for action: " .. action)
@@ -47,21 +57,21 @@ end
47 57
 -- mail getters                                                             --
48 58
 ------------------------------------------------------------------------------
49 59
 
50
-function get_queue(acct, mbox)
60
+pkg.get_queue = function(acct, mbox)
51 61
     --
52 62
     -- Get queue from *mbox* from *acct* or nil (no messages)
53 63
     --
54 64
     -- If mbox is not specified, "FILTER_QUEUE" is used
55 65
     --
56 66
     mbox = mbox or "FILTER_QUEUE"
57
-    local exist, unread, unseen, uidnext = acct[mbox]:check_status()
67
+    local exist = acct[mbox]:check_status()
58 68
     if exist > 0 then
59 69
         return acct[mbox]:select_all()
60 70
     end
61 71
     return nil
62 72
 end
63 73
 
64
-function _notifirc1(subj, from, body)
74
+pkg._notifirc1 = function(subj, from, body)
65 75
     --
66 76
     -- notify about message using (pre-configured) notifirc
67 77
     --
@@ -71,40 +81,41 @@ function _notifirc1(subj, from, body)
71 81
     fd:close()
72 82
 end
73 83
 
74
-function notifirc_all(seq)
84
+pkg.notifirc_all = function(seq)
75 85
     --
76 86
     -- Send notifications about all messages in *seq*
77 87
     --
78 88
     for _, mesg in ipairs(seq) do
89
+        local mbox, uid, subj, from, body
79 90
         mbox, uid = table.unpack(mesg)
80 91
         subj = mbox[uid]:fetch_field('Subject')
81 92
         from = mbox[uid]:fetch_field('From')
82 93
         body = mbox[uid]:fetch_body()
83
-        _notifirc1(subj, from, body)
94
+        pkg._notifirc1(subj, from, body)
84 95
     end
85 96
 end
86 97
 
87
-function hook_all(seq, hname, ...)
98
+pkg.hook_all = function(seq, hname, ...)
88 99
     --
89 100
     -- Call hook hname for all messages in seq
90 101
     --
91 102
     local hfile = os.getenv("IMAPFILTER_HOME") .. "/hooks/" .. hname
92 103
     local hargs = {...}
93
-    local harg
94 104
     local hcmd = hfile
95 105
     local fmt = ' %q'
96
-    if file_exists(hfile) then
106
+    if pkg.file_exists(hfile) then
97 107
         for _, harg in pairs(hargs) do
98 108
             hcmd = hcmd .. fmt:format(harg)
99 109
         end
100 110
         for _, mesg in ipairs(seq) do
111
+            local mbox, uid, subj, body, from, to, date
101 112
             mbox, uid = table.unpack(mesg)
102 113
             subj = mbox[uid]:fetch_field('Subject')
103 114
             from = mbox[uid]:fetch_field('From')
104 115
             to = mbox[uid]:fetch_field('To')
105 116
             date = mbox[uid]:fetch_field('Date')
106 117
             body = mbox[uid]:fetch_body()
107
-            _hook1(hcmd, subj, from, to, date, body)
118
+            pkg._hook1(hcmd, subj, from, to, date, body)
108 119
         end
109 120
     else
110 121
         error("no such hook: " .. hname)
@@ -112,7 +123,7 @@ function hook_all(seq, hname, ...)
112 123
     end
113 124
 end
114 125
 
115
-function _hook1(hcmd, subj, from, to, date, body)
126
+pkg._hook1 = function(hcmd, subj, from, to, date, body)
116 127
     --
117 128
     -- push message through hook script
118 129
     --
@@ -122,7 +133,7 @@ function _hook1(hcmd, subj, from, to, date, body)
122 133
     fd:close()
123 134
 end
124 135
 
125
-function _partinf_compare(a, b)
136
+pkg._partinf_compare = function(a, b)
126 137
     if not type(a) == type(b) then
127 138
         return false
128 139
     end
@@ -133,7 +144,7 @@ function _partinf_compare(a, b)
133 144
     end
134 145
 end
135 146
 
136
-function has_part_like(query, structure)
147
+pkg.has_part_like = function(query, structure)
137 148
     --
138 149
     -- True if structure has MIME part matching *query*
139 150
     --
@@ -144,8 +155,8 @@ function has_part_like(query, structure)
144 155
         local part_answer = true
145 156
         -- check all query parts
146 157
         for qkey, qvalue in pairs(query) do
147
-            value = partinf[qkey]
148
-            if not _partinf_compare(value, qvalue) then
158
+            local value = partinf[qkey]
159
+            if not pkg._partinf_compare(value, qvalue) then
149 160
                 part_answer = false
150 161
                 break
151 162
             end
@@ -157,7 +168,7 @@ function has_part_like(query, structure)
157 168
     return false
158 169
 end
159 170
 
160
-function save_header(mesg, name)
171
+pkg.save_header = function(mesg, name)
161 172
     --
162 173
     -- Append header from *mesg* to file named *name*
163 174
     --
@@ -166,16 +177,16 @@ function save_header(mesg, name)
166 177
     --
167 178
     local dest = os.getenv("IMAPDOMO_HEADERS") .. '/' .. name
168 179
     local cmd = ('cat >>"%q"'):format(dest)
169
-    mbox, uid = table.unpack(mesg)
170
-    header = mbox[uid]:fetch_header()
171
-    if pipe_to(cmd, header) == 0 then
180
+    local mbox, uid = table.unpack(mesg)
181
+    local header = mbox[uid]:fetch_header()
182
+    if pkg.pipe_to(cmd, header) == 0 then
172 183
         return true
173 184
     else
174 185
         return false
175 186
     end
176 187
 end
177 188
 
178
-function filter_header_saved(seq, name)
189
+pkg.filter_header_saved = function(seq, name)
179 190
     --
180 191
     -- Save headers from sequence
181 192
     --
@@ -183,26 +194,28 @@ function filter_header_saved(seq, name)
183 194
     -- *name* and return new sequence with those messages where save was
184 195
     -- successful.
185 196
     --
186
-    result = Set {}
197
+    local result = {}
187 198
     for _, mesg in ipairs(seq) do
188
-        if save_header(mesg, name) then
199
+        if pkg.save_header(mesg, name) then
189 200
             table.insert(result, mesg)
190 201
         end
191 202
     end
192 203
     return result
193 204
 end
194 205
 
195
-function filter_part_like(query, seq)
206
+pkg.filter_part_like = function(query, seq)
196 207
     --
197 208
     -- Run MIME part query on *seq* sequence of messages
198 209
     --
199
-    result = Set {}
210
+    local result = {}
200 211
     for _, mesg in ipairs(seq) do
201
-        mbox, uid = table.unpack(mesg)
202
-        structure = mbox[uid]:fetch_structure()
203
-        if has_part_like(query, structure) then
212
+        local mbox, uid = table.unpack(mesg)
213
+        local structure = mbox[uid]:fetch_structure()
214
+        if pkg.has_part_like(query, structure) then
204 215
             table.insert(result, mesg)
205 216
         end
206 217
     end
207 218
     return result
208 219
 end
220
+
221
+return pkg

+ 5
- 2
src/imapdomo.skel View File

@@ -24,7 +24,7 @@ usage() {
24 24
        "configuration directory."                                             \
25 25
        ""                                                                     \
26 26
        "See imapfilter_config(5)) for guide and API reference.  Few functions"\
27
-       "are also available in .imapdomo/common.lua"                           \
27
+       "are also available in .imapdomo/imapdomo.lua"                         \
28 28
        ""                                                                     \
29 29
        "NOTE: Be aware that it's your responsibility to ensure that filters"  \
30 30
        "don't cause performance problems. (Trust me, it's not so hard to"     \
@@ -46,6 +46,8 @@ mkcmd() {
46 46
     # Compose imapfilter command
47 47
     #
48 48
     echo -n "IMAPDOMO_ACTION=$Action"
49
+    echo -n "  LUA_PATH=$IMAPDOMO_HOME/?.lua"
50
+    echo -n "  IMAPDOMO_CFGDIR=$CfgDir"
49 51
     echo -n "  IMAPDOMO_HEADERS=$HeaderDir"
50 52
     echo -n "  IMAPFILTER_HOME=$CfgDir"
51 53
     echo -n "  imapfilter"
@@ -76,7 +78,7 @@ lshandlers() {
76 78
     #
77 79
     # List recognized handlers
78 80
     #
79
-    find "$CfgDir/handlers" -name "*.lua" -printf "%f\n" \
81
+    find "$CfgDir/handlers" -name "*.lua" -printf '%f\n' \
80 82
       | sed 's/.lua$//'
81 83
 }
82 84
 
@@ -172,6 +174,7 @@ main() {
172 174
     esac done
173 175
     Action="$1"; shift
174 176
     test -n "$Action" || usage -w "no action specified"
177
+    test -f "$CfgDir/mailboxes.lua" || die "no mailboxes defined"
175 178
     debug -v Action CfgDir LogDir HeaderDir Debug CdTo NoLock
176 179
     is_locked && return 1
177 180
     lock

+ 2
- 2
src/main.lua.skel View File

@@ -1,5 +1,5 @@
1 1
 #!/bin/lua
2 2
 
3
-dofile "__IMAPDOMO_SHARE__/common.lua"
3
+local imapdomo = require "imapdomo"
4 4
 
5
-handle()
5
+imapdomo.handle()