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 5 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
 
38
 
39
 [files]
39
 [files]
40
     bin     = src/imapdomo
40
     bin     = src/imapdomo
41
+    share   = src/imapdomo.lua
41
     share   = src/main.lua
42
     share   = src/main.lua
42
-    share   = src/common.lua
43
 
43
 
44
 #mkit version=0.0.34
44
 #mkit version=0.0.34

+ 1
- 1
packaging/debian/install View File

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

+ 1
- 1
packaging/template.spec View File

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

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

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

+ 5
- 2
src/imapdomo.skel View File

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

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

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