1 ;;; elmo-localdir.el --- Localdir Interface for ELMO.
3 ;; Copyright (C) 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
4 ;; Copyright (C) 1998,1999,2000 Masahiro MURATA <muse@ba2.so-net.ne.jp>
5 ;; Copyright (C) 1999,2000 Kenichi OKADA <okada@opaopa.org>
7 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
8 ;; Masahiro MURATA <muse@ba2.so-net.ne.jp>
9 ;; Kenichi OKADA <okada@opaopa.org>
10 ;; Keywords: mail, net news
12 ;; This file is part of ELMO (Elisp Library for Message Orchestration).
14 ;; This program is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation; either version 2, or (at your option)
19 ;; This program is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ;; GNU General Public License for more details.
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with GNU Emacs; see the file COPYING. If not, write to the
26 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27 ;; Boston, MA 02111-1307, USA.
35 (eval-when-compile (require 'cl
))
40 (defcustom elmo-localdir-folder-path
"~/Mail"
41 "*Local mail directory (MH format) path."
45 (defvar elmo-localdir-lockfile-list nil
)
47 ;;; ELMO Local directory folder
49 (luna-define-class elmo-localdir-folder
(elmo-folder elmo-file-tag
)
51 (luna-define-internal-accessors 'elmo-localdir-folder
))
53 ;;; elmo-localdir specific methods.
54 (luna-define-generic elmo-localdir-folder-path
(folder)
55 "Return local directory path of the FOLDER.")
57 (luna-define-generic elmo-localdir-folder-name
(folder name
)
58 "Return directory NAME for FOLDER.")
60 (luna-define-method elmo-localdir-folder-path
((folder elmo-localdir-folder
))
61 elmo-localdir-folder-path
)
63 (luna-define-method elmo-localdir-folder-name
((folder elmo-localdir-folder
)
67 (luna-define-method elmo-folder-initialize
((folder
70 (elmo-localdir-folder-set-dir-name-internal folder name
)
71 (if (file-name-absolute-p name
)
72 (elmo-localdir-folder-set-directory-internal
74 (expand-file-name name
))
75 (elmo-localdir-folder-set-directory-internal
78 (elmo-localdir-folder-name folder name
)
79 (elmo-localdir-folder-path folder
))))
82 ;; open, check, commit, and close are generic.
84 (luna-define-method elmo-folder-exists-p
((folder elmo-localdir-folder
))
85 (file-directory-p (elmo-localdir-folder-directory-internal folder
)))
87 (luna-define-method elmo-folder-expand-msgdb-path
((folder
88 elmo-localdir-folder
))
89 (let* ((dir-name (elmo-localdir-folder-dir-name-internal folder
))
94 'elmo-replace-string-as-filename
96 (if (file-name-absolute-p dir-name
)
97 (expand-file-name dir-name
)
103 (expand-file-name ;;"localdir" or "localdir-abs"
105 (symbol-name (elmo-folder-type-internal folder
))
106 (when (file-name-absolute-p dir-name
) "-abs"))
107 elmo-msgdb-directory
))))
109 (luna-define-method elmo-message-file-name
((folder
110 elmo-localdir-folder
)
112 (expand-file-name (int-to-string number
)
113 (elmo-localdir-folder-directory-internal folder
)))
115 (luna-define-method elmo-folder-message-file-number-p
((folder
116 elmo-localdir-folder
))
119 (luna-define-method elmo-folder-message-file-directory
((folder
120 elmo-localdir-folder
))
121 (elmo-localdir-folder-directory-internal folder
))
123 (luna-define-method elmo-folder-message-make-temp-file-p
124 ((folder elmo-localdir-folder
))
127 (luna-define-method elmo-folder-message-make-temp-files
((folder
128 elmo-localdir-folder
)
132 (let ((temp-dir (elmo-folder-make-temporary-directory folder
))
133 (cur-number (or start-number
0)))
134 (dolist (number numbers
)
137 (int-to-string number
)
138 (elmo-localdir-folder-directory-internal folder
))
140 (int-to-string (if start-number cur-number number
))
145 (defun elmo-localdir-msgdb-create-entity (msgdb dir number
)
146 (elmo-msgdb-create-message-entity-from-file
147 (elmo-msgdb-message-entity-handler msgdb
)
148 number
(expand-file-name (int-to-string number
) dir
)))
150 (luna-define-method elmo-folder-msgdb-create
((folder elmo-localdir-folder
)
154 (let ((dir (elmo-localdir-folder-directory-internal folder
))
155 (new-msgdb (elmo-make-msgdb))
156 entity message-id flags
)
157 (elmo-with-progress-display (elmo-folder-msgdb-create (length numbers
))
159 (dolist (number numbers
)
160 (setq entity
(elmo-localdir-msgdb-create-entity
161 new-msgdb dir number
))
163 (setq message-id
(elmo-message-entity-field entity
'message-id
)
164 flags
(elmo-flag-table-get flag-table message-id
))
165 (elmo-global-flags-set flags folder number message-id
)
166 (elmo-msgdb-append-entity new-msgdb entity flags
))
167 (elmo-progress-notify 'elmo-folder-msgdb-create
)))
170 (luna-define-method elmo-folder-list-subfolders
((folder elmo-localdir-folder
)
172 (elmo-mapcar-list-of-list
173 (lambda (x) (concat (elmo-folder-prefix-internal folder
) x
))
174 (elmo-list-subdirectories
175 (elmo-localdir-folder-path folder
)
176 (or (elmo-localdir-folder-dir-name-internal folder
) "")
179 (defsubst elmo-localdir-list-subr
(folder &optional nonsort
)
180 (let ((flist (mapcar 'string-to-number
182 (elmo-localdir-folder-directory-internal folder
)
184 (killed (elmo-msgdb-killed-list-load (elmo-folder-msgdb-path folder
))))
186 (cons (or (elmo-max-of-list flist
) 0)
189 (elmo-msgdb-killed-list-length killed
))
193 (luna-define-method elmo-folder-append-buffer
((folder elmo-localdir-folder
)
194 &optional flags number
)
195 (let ((filename (elmo-message-file-name
198 (1+ (car (elmo-folder-status folder
)))))))
199 (when (and (file-writable-p filename
)
200 (not (file-exists-p filename
)))
201 (write-region-as-binary
202 (point-min) (point-max) filename nil
'no-msg
)
203 (elmo-folder-preserve-flags
204 folder
(elmo-msgdb-get-message-id-from-buffer) flags
)
207 (defun elmo-folder-append-messages-*-localdir
(folder
211 (let ((src-msgdb-exists (not (zerop (elmo-folder-length src-folder
))))
212 (dir (elmo-localdir-folder-directory-internal folder
))
213 (table (elmo-folder-flag-table folder
))
215 (next-num (1+ (car (elmo-folder-status folder
))))
218 (setq flags
(elmo-message-flags src-folder
(car numbers
)))
220 (elmo-message-file-name src-folder
(car numbers
))
223 (if same-number
(car numbers
) next-num
))
225 ;; save flag-table only when src folder's msgdb is loaded.
226 (when (setq id
(and src-msgdb-exists
227 (elmo-message-field src-folder
(car numbers
)
229 (elmo-flag-table-set table id flags
))
230 (elmo-progress-notify 'elmo-folder-move-messages
)
231 (if (and (setq numbers
(cdr numbers
))
234 (if (elmo-localdir-locked-p)
236 (1+ (car (elmo-folder-status folder
)))
238 (when (elmo-folder-persistent-p folder
)
239 (elmo-folder-close-flag-table folder
))
242 (luna-define-method elmo-folder-delete-messages-internal
243 ((folder elmo-localdir-folder
) numbers
)
244 (dolist (number numbers
)
245 (elmo-localdir-delete-message folder number
))
248 (defun elmo-localdir-delete-message (folder number
)
249 "Delete message in the FOLDER with NUMBER."
250 (let ((filename (elmo-message-file-name folder number
)))
251 (when (and (string-match "[0-9]+" filename
) ; for safety.
252 (file-exists-p filename
)
253 (file-writable-p filename
)
254 (not (file-directory-p filename
)))
255 (delete-file filename
)
258 (luna-define-method elmo-message-fetch-internal
((folder elmo-localdir-folder
)
260 &optional section unread
)
261 (let ((filename (elmo-message-file-name folder number
)))
262 (when (file-exists-p filename
)
263 (insert-file-contents-as-raw-text filename
))))
265 (luna-define-method elmo-folder-list-messages-internal
266 ((folder elmo-localdir-folder
) &optional nohide
)
267 (elmo-localdir-list-subr folder
))
269 (luna-define-method elmo-folder-status
((folder elmo-localdir-folder
))
270 (elmo-localdir-list-subr folder t
))
272 (luna-define-method elmo-folder-creatable-p
((folder elmo-localdir-folder
))
275 (luna-define-method elmo-folder-writable-p
((folder elmo-localdir-folder
))
278 (luna-define-method elmo-folder-create
((folder elmo-localdir-folder
))
279 (let ((dir (elmo-localdir-folder-directory-internal folder
)))
280 (if (file-directory-p dir
)
282 (if (file-exists-p dir
)
283 (error "Create folder failed")
284 (elmo-make-directory dir
))
287 (luna-define-method elmo-folder-delete
((folder elmo-localdir-folder
))
288 (let ((msgs (and (elmo-folder-exists-p folder
)
289 (elmo-folder-list-messages folder
))))
290 (when (yes-or-no-p (format "%sDelete msgdb and substance of \"%s\"? "
291 (if (> (length msgs
) 0)
292 (format "%d msg(s) exists. " (length msgs
))
294 (elmo-folder-name-internal folder
)))
295 (let ((dir (elmo-localdir-folder-directory-internal folder
)))
296 (if (not (file-directory-p dir
))
297 (error "No such directory: %s" dir
)
298 (elmo-delete-match-files dir
"[0-9]+" t
)))
299 (elmo-msgdb-delete-path folder
)
302 (luna-define-method elmo-folder-rename-internal
((folder elmo-localdir-folder
)
304 (let* ((old (elmo-localdir-folder-directory-internal folder
))
305 (new (elmo-localdir-folder-directory-internal new-folder
))
306 (new-dir (directory-file-name (file-name-directory new
))))
307 (unless (file-directory-p old
)
308 (error "No such directory: %s" old
))
309 (when (file-exists-p new
)
310 (error "Already exists directory: %s" new
))
311 (unless (file-directory-p new-dir
)
312 (elmo-make-directory new-dir
))
313 (rename-file old new
)
316 (luna-define-method elmo-folder-pack-numbers
((folder elmo-localdir-folder
))
317 (let* ((dir (elmo-localdir-folder-directory-internal folder
))
318 (msgdb (elmo-folder-msgdb folder
))
319 (new-msgdb (elmo-make-msgdb (elmo-folder-msgdb-path folder
)))
320 (numbers (sort (elmo-folder-list-messages
323 (not elmo-pack-number-check-strict
))
325 (new-number 1) ; first ordinal position in localdir
327 (elmo-with-progress-display (elmo-folder-pack-numbers (length numbers
))
329 (dolist (old-number numbers
)
330 (setq entity
(elmo-msgdb-message-entity msgdb old-number
))
331 (when (not (eq old-number new-number
)) ; why \=() is wrong..
335 (rename-file (int-to-string old-number
)
336 (int-to-string new-number
) t
))
337 (elmo-message-entity-set-number entity new-number
))
338 (elmo-msgdb-append-entity new-msgdb entity
339 (elmo-msgdb-flags msgdb old-number
))
340 (elmo-emit-signal 'message-number-changed folder old-number new-number
)
341 (setq new-number
(1+ new-number
))))
342 (message "Packing...done")
343 (elmo-folder-set-msgdb-internal folder new-msgdb
)))
345 (luna-define-method elmo-folder-message-file-p
((folder elmo-localdir-folder
))
348 (defun elmo-localdir-locked-p ()
349 (if elmo-localdir-lockfile-list
350 (let ((lock elmo-localdir-lockfile-list
))
353 (if (file-exists-p (car lock
))
355 (setq lock
(cdr lock
)))))))
357 (autoload 'elmo-global-flags-set
"elmo-flag")
360 (product-provide (provide 'elmo-localdir
) (require 'elmo-version
))
362 ;;; elmo-localdir.el ends here