* WL-ELS (ELMO-MODULES): Added elmo-signal.
[elisp/wanderlust.git] / elmo / elmo-pipe.el
1 ;;; elmo-pipe.el --- PIPE Interface for ELMO.
2
3 ;; Copyright (C) 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
4
5 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Keywords: mail, net news
7
8 ;; This file is part of ELMO (Elisp Library for Message Orchestration).
9
10 ;; This program is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14 ;;
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
19 ;;
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24 ;;
25
26 ;;; Commentary:
27 ;;
28
29 ;;; Code:
30 ;;
31
32 (require 'elmo)
33 (require 'elmo-signal)
34
35 (defvar elmo-pipe-folder-copied-filename "copied"
36   "Copied messages number set.")
37
38 ;;; ELMO pipe folder
39 (eval-and-compile
40   (luna-define-class elmo-pipe-folder (elmo-folder)
41                      (src dst copy))
42   (luna-define-internal-accessors 'elmo-pipe-folder))
43
44 (luna-define-method elmo-folder-initialize ((folder elmo-pipe-folder)
45                                             name)
46   (when (string-match "^\\([^|]*\\)|\\(:?\\)\\(.*\\)$" name)
47     (elmo-pipe-folder-set-src-internal folder
48                                        (elmo-make-folder
49                                         (elmo-match-string 1 name)))
50     (elmo-pipe-folder-set-dst-internal folder
51                                        (elmo-make-folder
52                                         (elmo-match-string 3 name)))
53     (elmo-pipe-folder-set-copy-internal folder
54                                         (string= ":"
55                                                  (elmo-match-string 2 name))))
56   (elmo-pipe-connect-signals folder (elmo-pipe-folder-dst-internal folder))
57   folder)
58
59 (defun elmo-pipe-connect-signals (folder destination)
60   (elmo-connect-signal
61    destination 'flag-changing folder
62    (elmo-define-signal-handler (folder dst number old-flags new-flags)
63      (elmo-emit-signal 'flag-changing folder number old-flags new-flags)))
64   (elmo-connect-signal
65    destination 'flag-changed folder
66    (elmo-define-signal-handler (folder dst numbers)
67      (elmo-emit-signal 'flag-changed folder numbers)))
68   (elmo-connect-signal
69    destination 'cache-changed folder
70    (elmo-define-signal-handler (folder dst number)
71      (elmo-emit-signal 'cache-changed folder number))))
72
73 (luna-define-method elmo-folder-get-primitive-list ((folder elmo-pipe-folder))
74   (nconc
75    (elmo-folder-get-primitive-list (elmo-pipe-folder-src-internal folder))
76    (elmo-folder-get-primitive-list (elmo-pipe-folder-dst-internal folder))))
77
78 (luna-define-method elmo-folder-contains-type ((folder elmo-pipe-folder)
79                                                type)
80   (or (elmo-folder-contains-type (elmo-pipe-folder-src-internal folder) type)
81       (elmo-folder-contains-type (elmo-pipe-folder-dst-internal folder) type)))
82
83 (luna-define-method elmo-folder-append-messages ((folder elmo-pipe-folder)
84                                                  src-folder numbers
85                                                  &optional same-number)
86   (elmo-folder-append-messages (elmo-pipe-folder-dst-internal folder)
87                                src-folder numbers
88                                same-number))
89
90 (luna-define-method elmo-folder-append-buffer ((folder elmo-pipe-folder)
91                                                &optional flag number)
92   (elmo-folder-append-buffer (elmo-pipe-folder-dst-internal folder)
93                              flag number))
94
95 (luna-define-method elmo-message-fetch ((folder elmo-pipe-folder)
96                                         number strategy
97                                         &optional unseen section)
98   (elmo-message-fetch (elmo-pipe-folder-dst-internal folder)
99                       number strategy unseen section))
100
101 (luna-define-method elmo-folder-clear :after ((folder elmo-pipe-folder)
102                                               &optional keep-killed)
103   (unless keep-killed
104     (elmo-pipe-folder-copied-list-save folder nil)))
105
106 (luna-define-method elmo-folder-delete-messages ((folder elmo-pipe-folder)
107                                                  numbers)
108   (elmo-folder-delete-messages (elmo-pipe-folder-dst-internal folder)
109                                numbers))
110
111 (luna-define-method elmo-folder-detach-messages ((folder elmo-pipe-folder)
112                                                  numbers)
113   (elmo-folder-detach-messages (elmo-pipe-folder-dst-internal folder)
114                                numbers))
115
116 (defvar elmo-pipe-drained-hook nil "A hook called when the pipe is flushed.")
117
118 (defsubst elmo-pipe-folder-list-target-messages (src &optional ignore-list)
119   (unwind-protect
120       (progn
121         (elmo-folder-set-killed-list-internal src ignore-list)
122         (elmo-folder-list-messages src t))
123     (elmo-folder-set-killed-list-internal src nil)))
124
125 (defun elmo-pipe-drain (src dst &optional copy ignore-list)
126   "Move or copy all messages of SRC to DST."
127   (let ((elmo-inhibit-number-mapping (and (eq (elmo-folder-type-internal
128                                                src) 'pop3)
129                                           (not copy))) ; No need to use UIDL
130         msgs len)
131     (message "Checking %s..." (elmo-folder-name-internal src))
132     ;; Warnnig: some function requires msgdb
133     ;; but elmo-folder-open-internal do not load msgdb.
134     (elmo-folder-open-internal src)
135     (setq msgs (elmo-pipe-folder-list-target-messages src ignore-list)
136           len (length msgs))
137     (when (> len elmo-display-progress-threshold)
138       (elmo-progress-set 'elmo-folder-move-messages
139                          len
140                          (if copy
141                              "Copying messages..."
142                            "Moving messages...")))
143     (unwind-protect
144         (elmo-folder-move-messages src msgs dst copy)
145       (elmo-progress-clear 'elmo-folder-move-messages))
146     (when (and copy msgs)
147       (setq ignore-list (elmo-number-set-append-list ignore-list
148                                                      msgs)))
149     (elmo-folder-close-internal src)
150     (run-hooks 'elmo-pipe-drained-hook)
151     ignore-list))
152
153 (defun elmo-pipe-folder-copied-list-load (folder)
154   (elmo-object-load
155    (expand-file-name elmo-pipe-folder-copied-filename
156                      (expand-file-name
157                       (elmo-replace-string-as-filename
158                        (elmo-folder-name-internal folder))
159                       (expand-file-name "pipe" elmo-msgdb-directory)))
160    nil t))
161
162 (defun elmo-pipe-folder-copied-list-save (folder copied-list)
163   (elmo-object-save
164    (expand-file-name elmo-pipe-folder-copied-filename
165                      (expand-file-name
166                       (elmo-replace-string-as-filename
167                        (elmo-folder-name-internal folder))
168                       (expand-file-name "pipe" elmo-msgdb-directory)))
169    copied-list))
170
171 (luna-define-method elmo-folder-msgdb ((folder elmo-pipe-folder))
172   (elmo-folder-msgdb (elmo-pipe-folder-dst-internal folder)))
173
174 (luna-define-method elmo-folder-open-internal ((folder elmo-pipe-folder))
175   (elmo-folder-open-internal (elmo-pipe-folder-dst-internal folder)))
176
177 (luna-define-method elmo-folder-close-internal ((folder elmo-pipe-folder))
178   (elmo-folder-close-internal(elmo-pipe-folder-dst-internal folder)))
179
180 (luna-define-method elmo-folder-list-messages ((folder elmo-pipe-folder)
181                                                &optional visible-only in-msgdb)
182   ;; Use target folder's killed-list in the pipe folder.
183   (elmo-folder-list-messages (elmo-pipe-folder-dst-internal
184                               folder) visible-only in-msgdb))
185
186 (luna-define-method elmo-folder-diff ((folder elmo-pipe-folder))
187   (elmo-folder-open-internal (elmo-pipe-folder-src-internal folder))
188   (elmo-folder-open-internal (elmo-pipe-folder-dst-internal folder))
189   (let* ((elmo-inhibit-number-mapping
190           (not (elmo-pipe-folder-copy-internal folder)))
191          (src-length (length (elmo-pipe-folder-list-target-messages
192                               (elmo-pipe-folder-src-internal folder)
193                               (elmo-pipe-folder-copied-list-load folder))))
194          (dst-diff (elmo-folder-diff (elmo-pipe-folder-dst-internal folder))))
195     (prog1
196         (cond
197          ((consp (cdr dst-diff)) ; new unread all
198           (mapcar (lambda (number) (+ number src-length)) dst-diff))
199          (t
200           (cons (+ (or (car dst-diff) 0) src-length)
201                 (+ (or (cdr dst-diff) 0) src-length))))
202       ;; No save.
203       (elmo-folder-close-internal (elmo-pipe-folder-src-internal folder))
204       (elmo-folder-close-internal (elmo-pipe-folder-dst-internal folder)))))
205
206 (luna-define-method elmo-folder-exists-p ((folder elmo-pipe-folder))
207   (and (elmo-folder-exists-p (elmo-pipe-folder-src-internal folder))
208        (elmo-folder-exists-p (elmo-pipe-folder-dst-internal folder))))
209
210 (luna-define-method elmo-folder-expand-msgdb-path ((folder
211                                                     elmo-pipe-folder))
212   ;; Share with destination...OK?
213   (elmo-folder-expand-msgdb-path (elmo-pipe-folder-dst-internal folder)))
214
215 (luna-define-method elmo-folder-newsgroups ((folder elmo-pipe-folder))
216   (elmo-folder-newsgroups (elmo-pipe-folder-src-internal folder)))
217
218 (luna-define-method elmo-folder-creatable-p ((folder elmo-pipe-folder))
219   (and (or
220         (elmo-folder-exists-p (elmo-pipe-folder-src-internal folder))
221         (elmo-folder-creatable-p (elmo-pipe-folder-src-internal folder)))
222        (or
223         (elmo-folder-exists-p (elmo-pipe-folder-dst-internal folder))
224         (elmo-folder-creatable-p (elmo-pipe-folder-dst-internal folder)))))
225
226 (luna-define-method elmo-folder-writable-p ((folder elmo-pipe-folder))
227   (elmo-folder-writable-p (elmo-pipe-folder-dst-internal folder)))
228
229 (luna-define-method elmo-folder-create ((folder elmo-pipe-folder))
230   (if (and (not (elmo-folder-exists-p (elmo-pipe-folder-src-internal folder)))
231            (elmo-folder-creatable-p (elmo-pipe-folder-src-internal folder)))
232       (elmo-folder-create (elmo-pipe-folder-src-internal folder)))
233   (if (and (not (elmo-folder-exists-p (elmo-pipe-folder-dst-internal folder)))
234            (elmo-folder-creatable-p (elmo-pipe-folder-dst-internal folder)))
235       (elmo-folder-create (elmo-pipe-folder-dst-internal folder))))
236
237 (luna-define-method elmo-folder-search ((folder elmo-pipe-folder)
238                                         condition &optional numlist)
239   (elmo-folder-search (elmo-pipe-folder-dst-internal folder)
240                       condition numlist))
241
242 (luna-define-method elmo-message-use-cache-p ((folder elmo-pipe-folder) number)
243   (elmo-message-use-cache-p (elmo-pipe-folder-dst-internal folder) number))
244
245 (luna-define-method elmo-folder-check ((folder elmo-pipe-folder))
246   (elmo-folder-check (elmo-pipe-folder-dst-internal folder)))
247
248 (luna-define-method elmo-folder-plugged-p ((folder elmo-pipe-folder))
249   (and (elmo-folder-plugged-p (elmo-pipe-folder-src-internal folder))
250        (elmo-folder-plugged-p (elmo-pipe-folder-dst-internal folder))))
251
252 (luna-define-method elmo-folder-message-file-p ((folder elmo-pipe-folder))
253   (elmo-folder-message-file-p (elmo-pipe-folder-dst-internal folder)))
254
255 (luna-define-method elmo-message-file-p ((folder elmo-pipe-folder) number)
256   (elmo-message-file-p (elmo-pipe-folder-dst-internal folder) number))
257
258 (luna-define-method elmo-message-file-name ((folder elmo-pipe-folder) number)
259   (elmo-message-file-name (elmo-pipe-folder-dst-internal folder) number))
260
261 (luna-define-method elmo-folder-message-file-number-p ((folder
262                                                         elmo-pipe-folder))
263   (elmo-folder-message-file-number-p (elmo-pipe-folder-dst-internal folder)))
264
265 (luna-define-method elmo-folder-message-file-directory ((folder
266                                                          elmo-pipe-folder))
267   (elmo-folder-message-file-directory
268    (elmo-pipe-folder-dst-internal folder)))
269
270 (luna-define-method elmo-folder-message-make-temp-file-p
271   ((folder elmo-pipe-folder))
272   (elmo-folder-message-make-temp-file-p
273    (elmo-pipe-folder-dst-internal folder)))
274
275 (luna-define-method elmo-folder-message-make-temp-files ((folder
276                                                           elmo-pipe-folder)
277                                                          numbers
278                                                          &optional
279                                                          start-number)
280   (elmo-folder-message-make-temp-files
281    (elmo-pipe-folder-dst-internal folder) numbers start-number))
282
283 (luna-define-method elmo-folder-set-flag ((folder elmo-pipe-folder)
284                                           numbers
285                                           flag
286                                           &optional is-local)
287   (elmo-folder-set-flag (elmo-pipe-folder-dst-internal folder)
288                         numbers flag is-local))
289
290 (luna-define-method elmo-folder-unset-flag ((folder elmo-pipe-folder)
291                                             numbers
292                                             flag
293                                             &optional is-local)
294   (elmo-folder-unset-flag (elmo-pipe-folder-dst-internal folder)
295                           numbers flag is-local))
296
297 (luna-define-method elmo-folder-pack-numbers ((folder elmo-pipe-folder))
298   (elmo-folder-pack-numbers (elmo-pipe-folder-dst-internal folder)))
299
300 (luna-define-method elmo-folder-rename ((folder elmo-pipe-folder) new-name)
301   (let* ((new-folder (elmo-make-folder new-name)))
302     (unless (string= (elmo-folder-name-internal
303                       (elmo-pipe-folder-src-internal folder))
304                      (elmo-folder-name-internal
305                       (elmo-pipe-folder-src-internal new-folder)))
306       (error "Source folder differ"))
307     (unless (eq (elmo-folder-type-internal
308                  (elmo-pipe-folder-dst-internal folder))
309                 (elmo-folder-type-internal
310                  (elmo-pipe-folder-dst-internal new-folder)))
311       (error "Not same folder type"))
312     (if (or (file-exists-p (elmo-folder-msgdb-path
313                             (elmo-pipe-folder-dst-internal new-folder)))
314             (elmo-folder-exists-p
315              (elmo-pipe-folder-dst-internal new-folder)))
316         (error "Already exists folder: %s" new-name))
317     (elmo-folder-send (elmo-pipe-folder-dst-internal folder)
318                       'elmo-folder-rename-internal
319                       (elmo-pipe-folder-dst-internal new-folder))
320     (elmo-msgdb-rename-path folder new-folder)))
321
322 (luna-define-method elmo-folder-synchronize ((folder elmo-pipe-folder)
323                                              &optional
324                                              disable-killed
325                                              ignore-msgdb
326                                              no-check
327                                              mask)
328   (let ((src-folder (elmo-pipe-folder-src-internal folder))
329         (dst-folder (elmo-pipe-folder-dst-internal folder)))
330     (when (and (elmo-folder-plugged-p src-folder)
331                (elmo-folder-plugged-p dst-folder))
332       (if (elmo-pipe-folder-copy-internal folder)
333           (elmo-pipe-folder-copied-list-save
334            folder
335            (elmo-pipe-drain src-folder
336                             dst-folder
337                             'copy
338                             (elmo-pipe-folder-copied-list-load folder)))
339         (elmo-pipe-drain src-folder dst-folder))))
340   (elmo-folder-synchronize
341    (elmo-pipe-folder-dst-internal folder)
342    disable-killed ignore-msgdb no-check mask))
343
344 (luna-define-method elmo-folder-list-flagged ((folder elmo-pipe-folder)
345                                               flag
346                                               &optional in-msgdb)
347   (elmo-folder-list-flagged
348    (elmo-pipe-folder-dst-internal folder) flag in-msgdb))
349
350 (luna-define-method elmo-folder-commit ((folder elmo-pipe-folder))
351   (elmo-folder-commit (elmo-pipe-folder-dst-internal folder)))
352
353 (luna-define-method elmo-folder-length ((folder elmo-pipe-folder))
354   (elmo-folder-length (elmo-pipe-folder-dst-internal folder)))
355
356 (luna-define-method elmo-message-flag-available-p ((folder elmo-pipe-folder)
357                                                    number flag)
358   (elmo-message-flag-available-p
359    (elmo-pipe-folder-dst-internal folder)
360    number flag))
361
362 (luna-define-method elmo-folder-count-flags ((folder elmo-pipe-folder))
363   (elmo-folder-count-flags (elmo-pipe-folder-dst-internal folder)))
364
365 (luna-define-method elmo-message-flags ((folder elmo-pipe-folder) number)
366   (elmo-message-flags (elmo-pipe-folder-dst-internal folder) number))
367
368 (luna-define-method elmo-message-field ((folder elmo-pipe-folder)
369                                         number field)
370   (elmo-message-field (elmo-pipe-folder-dst-internal folder)
371                       number
372                       field))
373
374 (luna-define-method elmo-message-set-cached ((folder elmo-pipe-folder)
375                                              number cached)
376   (elmo-message-set-cached (elmo-pipe-folder-dst-internal folder)
377                            number cached))
378
379 (luna-define-method elmo-find-fetch-strategy ((folder elmo-pipe-folder)
380                                               number
381                                               &optional
382                                               ignore-cache
383                                               require-entireness)
384   (elmo-find-fetch-strategy (elmo-pipe-folder-dst-internal folder)
385                             number
386                             ignore-cache
387                             require-entireness))
388
389 (luna-define-method elmo-message-number ((folder elmo-pipe-folder)
390                                          message-id)
391   (elmo-message-number (elmo-pipe-folder-dst-internal folder)
392                        message-id))
393
394 (luna-define-method elmo-message-entity ((folder elmo-pipe-folder) key)
395   (elmo-message-entity (elmo-pipe-folder-dst-internal folder) key))
396
397 (luna-define-method elmo-message-folder ((folder elmo-pipe-folder)
398                                          number)
399   (elmo-message-folder (elmo-pipe-folder-dst-internal folder) number))
400
401 (require 'product)
402 (product-provide (provide 'elmo-pipe) (require 'elmo-version))
403
404 ;;; elmo-pipe.el ends here