Mercurial > hg > xemacs-beta
comparison lisp/gnus/nnmh.el @ 70:131b0175ea99 r20-0b30
Import from CVS: tag r20-0b30
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:02:59 +0200 |
parents | 8b8b7f3559a2 |
children | 0d2f883870bc |
comparison
equal
deleted
inserted
replaced
69:804d1389bcd6 | 70:131b0175ea99 |
---|---|
1 ;;; nnmh.el --- mhspool access for Gnus | 1 ;;; nnmh.el --- mhspool access for Gnus |
2 ;; Copyright (C) 1995,96,97 Free Software Foundation, Inc. | 2 ;; Copyright (C) 1995,96 Free Software Foundation, Inc. |
3 | 3 |
4 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no> | 4 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no> |
5 ;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet> | 5 ;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet> |
6 ;; Keywords: news, mail | 6 ;; Keywords: news, mail |
7 | 7 |
24 | 24 |
25 ;;; Commentary: | 25 ;;; Commentary: |
26 | 26 |
27 ;; Based on nnspool.el by Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>. | 27 ;; Based on nnspool.el by Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>. |
28 ;; For an overview of what the interface functions do, please see the | 28 ;; For an overview of what the interface functions do, please see the |
29 ;; Gnus sources. | 29 ;; Gnus sources. |
30 | 30 |
31 ;;; Code: | 31 ;;; Code: |
32 | 32 |
33 (require 'nnheader) | 33 (require 'nnheader) |
34 (require 'nnmail) | 34 (require 'nnmail) |
35 (require 'gnus-start) | 35 (require 'gnus) |
36 (require 'nnoo) | 36 (require 'nnoo) |
37 (require 'cl) | 37 (eval-and-compile (require 'cl)) |
38 | 38 |
39 (nnoo-declare nnmh) | 39 (nnoo-declare nnmh) |
40 | 40 |
41 (defvoo nnmh-directory message-directory | 41 (defvoo nnmh-directory message-directory |
42 "*Mail spool directory.") | 42 "*Mail spool directory.") |
80 (nnmh-possibly-change-directory newsgroup server) | 80 (nnmh-possibly-change-directory newsgroup server) |
81 ;; We don't support fetching by Message-ID. | 81 ;; We don't support fetching by Message-ID. |
82 (if (stringp (car articles)) | 82 (if (stringp (car articles)) |
83 'headers | 83 'headers |
84 (while articles | 84 (while articles |
85 (when (and (file-exists-p | 85 (when (and (file-exists-p |
86 (setq file (concat (file-name-as-directory | 86 (setq file (concat (file-name-as-directory |
87 nnmh-current-directory) | 87 nnmh-current-directory) |
88 (int-to-string | 88 (int-to-string |
89 (setq article (pop articles)))))) | 89 (setq article (pop articles)))))) |
90 (not (file-directory-p file))) | 90 (not (file-directory-p file))) |
91 (insert (format "221 %d Article retrieved.\n" article)) | 91 (insert (format "221 %d Article retrieved.\n" article)) |
103 (and large | 103 (and large |
104 (zerop (% count 20)) | 104 (zerop (% count 20)) |
105 (message "nnmh: Receiving headers... %d%%" | 105 (message "nnmh: Receiving headers... %d%%" |
106 (/ (* count 100) number)))) | 106 (/ (* count 100) number)))) |
107 | 107 |
108 (when large | 108 (and large (message "nnmh: Receiving headers...done")) |
109 (message "nnmh: Receiving headers...done")) | |
110 | 109 |
111 (nnheader-fold-continuation-lines) | 110 (nnheader-fold-continuation-lines) |
112 'headers)))) | 111 'headers)))) |
113 | 112 |
114 (deffoo nnmh-open-server (server &optional defs) | 113 (deffoo nnmh-open-server (server &optional defs) |
115 (nnoo-change-server 'nnmh server defs) | 114 (nnoo-change-server 'nnmh server defs) |
116 (when (not (file-exists-p nnmh-directory)) | 115 (when (not (file-exists-p nnmh-directory)) |
117 (condition-case () | 116 (condition-case () |
118 (make-directory nnmh-directory t) | 117 (make-directory nnmh-directory t) |
119 (error t))) | 118 (error t))) |
120 (cond | 119 (cond |
121 ((not (file-exists-p nnmh-directory)) | 120 ((not (file-exists-p nnmh-directory)) |
122 (nnmh-close-server) | 121 (nnmh-close-server) |
123 (nnheader-report 'nnmh "Couldn't create directory: %s" nnmh-directory)) | 122 (nnheader-report 'nnmh "Couldn't create directory: %s" nnmh-directory)) |
124 ((not (file-directory-p (file-truename nnmh-directory))) | 123 ((not (file-directory-p (file-truename nnmh-directory))) |
125 (nnmh-close-server) | 124 (nnmh-close-server) |
142 (string-to-int (file-name-nondirectory file))))) | 141 (string-to-int (file-name-nondirectory file))))) |
143 | 142 |
144 (deffoo nnmh-request-group (group &optional server dont-check) | 143 (deffoo nnmh-request-group (group &optional server dont-check) |
145 (let ((pathname (nnmail-group-pathname group nnmh-directory)) | 144 (let ((pathname (nnmail-group-pathname group nnmh-directory)) |
146 dir) | 145 dir) |
147 (cond | 146 (cond |
148 ((not (file-directory-p pathname)) | 147 ((not (file-directory-p pathname)) |
149 (nnheader-report | 148 (nnheader-report |
150 'nnmh "Can't select group (no such directory): %s" group)) | 149 'nnmh "Can't select group (no such directory): %s" group)) |
151 (t | 150 (t |
152 (setq nnmh-current-directory pathname) | 151 (setq nnmh-current-directory pathname) |
153 (and nnmh-get-new-mail | 152 (and nnmh-get-new-mail |
154 nnmh-be-safe | 153 nnmh-be-safe |
155 (nnmh-update-gnus-unreads group)) | 154 (nnmh-update-gnus-unreads group)) |
156 (cond | 155 (cond |
157 (dont-check | 156 (dont-check |
158 (nnheader-report 'nnmh "Selected group %s" group) | 157 (nnheader-report 'nnmh "Selected group %s" group) |
159 t) | 158 t) |
160 (t | 159 (t |
161 ;; Re-scan the directory if it's on a foreign system. | 160 ;; Re-scan the directory if it's on a foreign system. |
162 (nnheader-re-read-dir pathname) | 161 (nnheader-re-read-dir pathname) |
163 (setq dir | 162 (setq dir |
164 (sort | 163 (sort |
165 (mapcar (lambda (name) (string-to-int name)) | 164 (mapcar (lambda (name) (string-to-int name)) |
166 (directory-files pathname nil "^[0-9]+$" t)) | 165 (directory-files pathname nil "^[0-9]+$" t)) |
167 '<)) | 166 '<)) |
168 (cond | 167 (cond |
169 (dir | 168 (dir |
170 (nnheader-report 'nnmh "Selected group %s" group) | 169 (nnheader-report 'nnmh "Selected group %s" group) |
171 (nnheader-insert | 170 (nnheader-insert |
172 "211 %d %d %d %s\n" (length dir) (car dir) | 171 "211 %d %d %d %s\n" (length dir) (car dir) |
173 (progn (while (cdr dir) (setq dir (cdr dir))) (car dir)) | 172 (progn (while (cdr dir) (setq dir (cdr dir))) (car dir)) |
175 (t | 174 (t |
176 (nnheader-report 'nnmh "Empty group %s" group) | 175 (nnheader-report 'nnmh "Empty group %s" group) |
177 (nnheader-insert (format "211 0 1 0 %s\n" group)))))))))) | 176 (nnheader-insert (format "211 0 1 0 %s\n" group)))))))))) |
178 | 177 |
179 (deffoo nnmh-request-scan (&optional group server) | 178 (deffoo nnmh-request-scan (&optional group server) |
180 (nnmail-get-new-mail 'nnmh nil nnmh-directory group)) | 179 (nnmail-get-new-mail 'nnmh nil nnmh-directory group)) |
181 | 180 |
182 (deffoo nnmh-request-list (&optional server dir) | 181 (deffoo nnmh-request-list (&optional server dir) |
183 (nnheader-insert "") | 182 (nnheader-insert "") |
184 (let ((nnmh-toplev | 183 (let ((nnmh-toplev |
185 (or dir (file-truename (file-name-as-directory nnmh-directory))))) | 184 (or dir (file-truename (file-name-as-directory nnmh-directory))))) |
208 (directory-files dir nil "^[0-9]+$" t)))) | 207 (directory-files dir nil "^[0-9]+$" t)))) |
209 (when files | 208 (when files |
210 (save-excursion | 209 (save-excursion |
211 (set-buffer nntp-server-buffer) | 210 (set-buffer nntp-server-buffer) |
212 (goto-char (point-max)) | 211 (goto-char (point-max)) |
213 (insert | 212 (insert |
214 (format | 213 (format |
215 "%s %d %d y\n" | 214 "%s %d %d y\n" |
216 (progn | 215 (progn |
217 (string-match | 216 (string-match |
218 (regexp-quote | 217 (regexp-quote |
219 (file-truename (file-name-as-directory | 218 (file-truename (file-name-as-directory |
220 (expand-file-name nnmh-toplev)))) | 219 (expand-file-name nnmh-toplev)))) dir) |
221 dir) | |
222 (nnheader-replace-chars-in-string | 220 (nnheader-replace-chars-in-string |
223 (substring dir (match-end 0)) ?/ ?.)) | 221 (substring dir (match-end 0)) ?/ ?.)) |
224 (apply 'max files) | 222 (apply 'max files) |
225 (apply 'min files))))))) | 223 (apply 'min files))))))) |
226 t) | 224 t) |
227 | 225 |
228 (deffoo nnmh-request-newgroups (date &optional server) | 226 (deffoo nnmh-request-newgroups (date &optional server) |
229 (nnmh-request-list server)) | 227 (nnmh-request-list server)) |
230 | 228 |
231 (deffoo nnmh-request-expire-articles (articles newsgroup | 229 (deffoo nnmh-request-expire-articles (articles newsgroup &optional server force) |
232 &optional server force) | |
233 (nnmh-possibly-change-directory newsgroup server) | 230 (nnmh-possibly-change-directory newsgroup server) |
234 (let* ((active-articles | 231 (let* ((active-articles |
235 (mapcar | 232 (mapcar |
236 (function | 233 (function |
237 (lambda (name) | 234 (lambda (name) |
238 (string-to-int name))) | 235 (string-to-int name))) |
239 (directory-files nnmh-current-directory nil "^[0-9]+$" t))) | 236 (directory-files nnmh-current-directory nil "^[0-9]+$" t))) |
240 (is-old t) | 237 (is-old t) |
241 article rest mod-time) | 238 article rest mod-time) |
242 (nnmail-activate 'nnmh) | 239 (nnmail-activate 'nnmh) |
243 | 240 |
244 (while (and articles is-old) | 241 (while (and articles is-old) |
245 (setq article (concat nnmh-current-directory | 242 (setq article (concat nnmh-current-directory |
246 (int-to-string (car articles)))) | 243 (int-to-string (car articles)))) |
247 (when (setq mod-time (nth 5 (file-attributes article))) | 244 (if (setq mod-time (nth 5 (file-attributes article))) |
248 (if (and (nnmh-deletable-article-p newsgroup (car articles)) | 245 (if (and (nnmh-deletable-article-p newsgroup (car articles)) |
249 (setq is-old | 246 (setq is-old |
250 (nnmail-expired-article-p newsgroup mod-time force))) | 247 (nnmail-expired-article-p newsgroup mod-time force))) |
251 (progn | 248 (progn |
252 (nnheader-message 5 "Deleting article %s in %s..." | 249 (nnheader-message 5 "Deleting article %s in %s..." |
253 article newsgroup) | 250 article newsgroup) |
254 (condition-case () | 251 (condition-case () |
255 (funcall nnmail-delete-file-function article) | 252 (funcall nnmail-delete-file-function article) |
256 (file-error | 253 (file-error |
257 (nnheader-message 1 "Couldn't delete article %s in %s" | 254 (nnheader-message 1 "Couldn't delete article %s in %s" |
258 article newsgroup) | 255 article newsgroup) |
259 (push (car articles) rest)))) | 256 (setq rest (cons (car articles) rest))))) |
260 (push (car articles) rest))) | 257 (setq rest (cons (car articles) rest)))) |
261 (setq articles (cdr articles))) | 258 (setq articles (cdr articles))) |
262 (message "") | 259 (message "") |
263 (nconc rest articles))) | 260 (nconc rest articles))) |
264 | 261 |
265 (deffoo nnmh-close-group (group &optional server) | 262 (deffoo nnmh-close-group (group &optional server) |
266 t) | 263 t) |
267 | 264 |
268 (deffoo nnmh-request-move-article | 265 (deffoo nnmh-request-move-article |
269 (article group server accept-form &optional last) | 266 (article group server accept-form &optional last) |
270 (let ((buf (get-buffer-create " *nnmh move*")) | 267 (let ((buf (get-buffer-create " *nnmh move*")) |
271 result) | 268 result) |
272 (and | 269 (and |
273 (nnmh-deletable-article-p group article) | 270 (nnmh-deletable-article-p group article) |
274 (nnmh-request-article article group server) | 271 (nnmh-request-article article group server) |
275 (save-excursion | 272 (save-excursion |
276 (set-buffer buf) | 273 (set-buffer buf) |
277 (erase-buffer) | |
278 (insert-buffer-substring nntp-server-buffer) | 274 (insert-buffer-substring nntp-server-buffer) |
279 (setq result (eval accept-form)) | 275 (setq result (eval accept-form)) |
280 (kill-buffer (current-buffer)) | 276 (kill-buffer (current-buffer)) |
281 result) | 277 result) |
282 (progn | 278 (progn |
288 result)) | 284 result)) |
289 | 285 |
290 (deffoo nnmh-request-accept-article (group &optional server last noinsert) | 286 (deffoo nnmh-request-accept-article (group &optional server last noinsert) |
291 (nnmh-possibly-change-directory group server) | 287 (nnmh-possibly-change-directory group server) |
292 (nnmail-check-syntax) | 288 (nnmail-check-syntax) |
293 (when nnmail-cache-accepted-message-ids | 289 (if (stringp group) |
294 (nnmail-cache-insert (nnmail-fetch-field "message-id"))) | 290 (and |
295 (prog1 | 291 (nnmail-activate 'nnmh) |
296 (if (stringp group) | 292 ;; We trick the choosing function into believing that only one |
297 (and | 293 ;; group is available. |
298 (nnmail-activate 'nnmh) | 294 (let ((nnmail-split-methods (list (list group "")))) |
299 (car (nnmh-save-mail | 295 (car (nnmh-save-mail noinsert)))) |
300 (list (cons group (nnmh-active-number group))) | 296 (and |
301 noinsert))) | 297 (nnmail-activate 'nnmh) |
302 (and | 298 (car (nnmh-save-mail noinsert))))) |
303 (nnmail-activate 'nnmh) | |
304 (let ((resu|t (nnmail-article-group 'nnmh-active-number))) | |
305 (if (not result) | |
306 'junk | |
307 (car (nnmh-save-mail result noinsert)))))) | |
308 (when (and last nnmail-cache-accepted-message-ids) | |
309 (nnmail-cache-close)))) | |
310 | 299 |
311 (deffoo nnmh-request-replace-article (article group buffer) | 300 (deffoo nnmh-request-replace-article (article group buffer) |
312 (nnmh-possibly-change-directory group) | 301 (nnmh-possibly-change-directory group) |
313 (save-excursion | 302 (save-excursion |
314 (set-buffer buffer) | 303 (set-buffer buffer) |
315 (nnmh-possibly-create-directory group) | 304 (nnmh-possibly-create-directory group) |
316 (ignore-errors | 305 (condition-case () |
317 (nnmail-write-region | 306 (progn |
318 (point-min) (point-max) | 307 (write-region |
319 (concat nnmh-current-directory (int-to-string article)) | 308 (point-min) (point-max) |
320 nil (if (nnheader-be-verbose 5) nil 'nomesg)) | 309 (concat nnmh-current-directory (int-to-string article)) |
321 t))) | 310 nil (if (nnheader-be-verbose 5) nil 'nomesg)) |
322 | 311 t) |
323 (deffoo nnmh-request-create-group (group &optional server args) | 312 (error nil)))) |
313 | |
314 (deffoo nnmh-request-create-group (group &optional server) | |
324 (nnmail-activate 'nnmh) | 315 (nnmail-activate 'nnmh) |
325 (unless (assoc group nnmh-group-alist) | 316 (or (assoc group nnmh-group-alist) |
326 (let (active) | 317 (let (active) |
327 (push (list group (setq active (cons 1 0))) | 318 (setq nnmh-group-alist (cons (list group (setq active (cons 1 0))) |
328 nnmh-group-alist) | 319 nnmh-group-alist)) |
329 (nnmh-possibly-create-directory group) | 320 (nnmh-possibly-create-directory group) |
330 (nnmh-possibly-change-directory group server) | 321 (nnmh-possibly-change-directory group server) |
331 (let ((articles (mapcar | 322 (let ((articles (mapcar |
332 (lambda (file) | 323 (lambda (file) |
333 (string-to-int file)) | 324 (string-to-int file)) |
334 (directory-files | 325 (directory-files |
335 nnmh-current-directory nil "^[0-9]+$")))) | 326 nnmh-current-directory nil "^[0-9]+$")))) |
336 (when articles | 327 (and articles |
337 (setcar active (apply 'min articles)) | 328 (progn |
338 (setcdr active (apply 'max articles)))))) | 329 (setcar active (apply 'min articles)) |
330 (setcdr active (apply 'max articles))))))) | |
339 t) | 331 t) |
340 | 332 |
341 (deffoo nnmh-request-delete-group (group &optional force server) | 333 (deffoo nnmh-request-delete-group (group &optional force server) |
342 (nnmh-possibly-change-directory group server) | 334 (nnmh-possibly-change-directory group server) |
343 ;; Delete all articles in GROUP. | 335 ;; Delete all articles in GROUP. |
344 (if (not force) | 336 (if (not force) |
345 () ; Don't delete the articles. | 337 () ; Don't delete the articles. |
346 (let ((articles (directory-files nnmh-current-directory t "^[0-9]+$"))) | 338 (let ((articles (directory-files nnmh-current-directory t "^[0-9]+$"))) |
347 (while articles | 339 (while articles |
348 (when (file-writable-p (car articles)) | 340 (and (file-writable-p (car articles)) |
349 (nnheader-message 5 "Deleting article %s in %s..." | 341 (progn |
350 (car articles) group) | 342 (nnheader-message 5 "Deleting article %s in %s..." |
351 (funcall nnmail-delete-file-function (car articles))) | 343 (car articles) group) |
344 (funcall nnmail-delete-file-function (car articles)))) | |
352 (setq articles (cdr articles)))) | 345 (setq articles (cdr articles)))) |
353 ;; Try to delete the directory itself. | 346 ;; Try to delete the directory itself. |
354 (ignore-errors | 347 (condition-case () |
355 (delete-directory nnmh-current-directory))) | 348 (delete-directory nnmh-current-directory) |
349 (error nil))) | |
356 ;; Remove the group from all structures. | 350 ;; Remove the group from all structures. |
357 (setq nnmh-group-alist | 351 (setq nnmh-group-alist |
358 (delq (assoc group nnmh-group-alist) nnmh-group-alist) | 352 (delq (assoc group nnmh-group-alist) nnmh-group-alist) |
359 nnmh-current-directory nil) | 353 nnmh-current-directory nil) |
360 t) | 354 t) |
361 | 355 |
362 (deffoo nnmh-request-rename-group (group new-name &optional server) | 356 (deffoo nnmh-request-rename-group (group new-name &optional server) |
363 (nnmh-possibly-change-directory group server) | 357 (nnmh-possibly-change-directory group server) |
364 (let ((new-dir (nnmail-group-pathname new-name nnmh-directory)) | 358 ;; Rename directory. |
365 (old-dir (nnmail-group-pathname group nnmh-directory))) | 359 (and (file-writable-p nnmh-current-directory) |
366 (when (ignore-errors | 360 (condition-case () |
367 (make-directory new-dir t) | 361 (progn |
368 t) | 362 (rename-file |
369 ;; We move the articles file by file instead of renaming | 363 (directory-file-name nnmh-current-directory) |
370 ;; the directory -- there may be subgroups in this group. | 364 (directory-file-name |
371 ;; One might be more clever, I guess. | 365 (nnmail-group-pathname new-name nnmh-directory))) |
372 (let ((files (nnheader-article-to-file-alist old-dir))) | 366 t) |
373 (while files | 367 (error nil)) |
374 (rename-file | 368 ;; That went ok, so we change the internal structures. |
375 (concat old-dir (cdar files)) | 369 (let ((entry (assoc group nnmh-group-alist))) |
376 (concat new-dir (cdar files))) | 370 (and entry (setcar entry new-name)) |
377 (pop files))) | 371 (setq nnmh-current-directory nil) |
378 (when (<= (length (directory-files old-dir)) 2) | 372 t))) |
379 (ignore-errors | |
380 (delete-directory old-dir))) | |
381 ;; That went ok, so we change the internal structures. | |
382 (let ((entry (assoc group nnmh-group-alist))) | |
383 (when entry | |
384 (setcar entry new-name)) | |
385 (setq nnmh-current-directory nil) | |
386 t)))) | |
387 | |
388 (nnoo-define-skeleton nnmh) | |
389 | 373 |
390 | 374 |
391 ;;; Internal functions. | 375 ;;; Internal functions. |
392 | 376 |
393 (defun nnmh-possibly-change-directory (newsgroup &optional server) | 377 (defun nnmh-possibly-change-directory (newsgroup &optional server) |
394 (when (and server | 378 (when (and server |
395 (not (nnmh-server-opened server))) | 379 (not (nnmh-server-opened server))) |
396 (nnmh-open-server server)) | 380 (nnmh-open-server server)) |
397 (when newsgroup | 381 (if newsgroup |
398 (let ((pathname (nnmail-group-pathname newsgroup nnmh-directory))) | 382 (let ((pathname (nnmail-group-pathname newsgroup nnmh-directory))) |
399 (if (file-directory-p pathname) | 383 (if (file-directory-p pathname) |
400 (setq nnmh-current-directory pathname) | 384 (setq nnmh-current-directory pathname) |
401 (error "No such newsgroup: %s" newsgroup))))) | 385 (error "No such newsgroup: %s" newsgroup))))) |
402 | 386 |
403 (defun nnmh-possibly-create-directory (group) | 387 (defun nnmh-possibly-create-directory (group) |
404 (let (dir dirs) | 388 (let (dir dirs) |
405 (setq dir (nnmail-group-pathname group nnmh-directory)) | 389 (setq dir (nnmail-group-pathname group nnmh-directory)) |
406 (while (not (file-directory-p dir)) | 390 (while (not (file-directory-p dir)) |
407 (push dir dirs) | 391 (setq dirs (cons dir dirs)) |
408 (setq dir (file-name-directory (directory-file-name dir)))) | 392 (setq dir (file-name-directory (directory-file-name dir)))) |
409 (while dirs | 393 (while dirs |
410 (when (make-directory (directory-file-name (car dirs))) | 394 (if (make-directory (directory-file-name (car dirs))) |
411 (error "Could not create directory %s" (car dirs))) | 395 (error "Could not create directory %s" (car dirs))) |
412 (nnheader-message 5 "Creating mail directory %s" (car dirs)) | 396 (nnheader-message 5 "Creating mail directory %s" (car dirs)) |
413 (setq dirs (cdr dirs))))) | 397 (setq dirs (cdr dirs))))) |
414 | 398 |
415 (defun nnmh-save-mail (group-art &optional noinsert) | 399 (defun nnmh-save-mail (&optional noinsert) |
416 "Called narrowed to an article." | 400 "Called narrowed to an article." |
417 (unless noinsert | 401 (let ((group-art (nreverse (nnmail-article-group 'nnmh-active-number)))) |
418 (nnmail-insert-lines) | 402 (unless noinsert |
419 (nnmail-insert-xref group-art)) | 403 (nnmail-insert-lines) |
420 (run-hooks 'nnmail-prepare-save-mail-hook) | 404 (nnmail-insert-xref group-art)) |
421 (run-hooks 'nnmh-prepare-save-mail-hook) | 405 (run-hooks 'nnmail-prepare-save-mail-hook) |
422 (goto-char (point-min)) | 406 (run-hooks 'nnmh-prepare-save-mail-hook) |
423 (while (looking-at "From ") | 407 (goto-char (point-min)) |
424 (replace-match "X-From-Line: ") | 408 (while (looking-at "From ") |
425 (forward-line 1)) | 409 (replace-match "X-From-Line: ") |
426 ;; We save the article in all the newsgroups it belongs in. | 410 (forward-line 1)) |
427 (let ((ga group-art) | 411 ;; We save the article in all the newsgroups it belongs in. |
428 first) | 412 (let ((ga group-art) |
429 (while ga | 413 first) |
430 (nnmh-possibly-create-directory (caar ga)) | 414 (while ga |
431 (let ((file (concat (nnmail-group-pathname | 415 (nnmh-possibly-create-directory (caar ga)) |
432 (caar ga) nnmh-directory) | 416 (let ((file (concat (nnmail-group-pathname |
433 (int-to-string (cdar ga))))) | 417 (caar ga) nnmh-directory) |
434 (if first | 418 (int-to-string (cdar ga))))) |
435 ;; It was already saved, so we just make a hard link. | 419 (if first |
436 (funcall nnmail-crosspost-link-function first file t) | 420 ;; It was already saved, so we just make a hard link. |
437 ;; Save the article. | 421 (funcall nnmail-crosspost-link-function first file t) |
438 (nnmail-write-region (point-min) (point-max) file nil nil) | 422 ;; Save the article. |
439 (setq first file))) | 423 (write-region (point-min) (point-max) file nil nil) |
440 (setq ga (cdr ga)))) | 424 (setq first file))) |
441 group-art) | 425 (setq ga (cdr ga)))) |
426 group-art)) | |
442 | 427 |
443 (defun nnmh-active-number (group) | 428 (defun nnmh-active-number (group) |
444 "Compute the next article number in GROUP." | 429 "Compute the next article number in GROUP." |
445 (let ((active (cadr (assoc group nnmh-group-alist)))) | 430 (let ((active (cadr (assoc group nnmh-group-alist)))) |
446 (unless active | 431 ;; The group wasn't known to nnmh, so we just create an active |
447 ;; The group wasn't known to nnmh, so we just create an active | 432 ;; entry for it. |
448 ;; entry for it. | 433 (or active |
449 (setq active (cons 1 0)) | 434 (progn |
450 (push (list group active) nnmh-group-alist) | 435 (setq active (cons 1 0)) |
451 ;; Find the highest number in the group. | 436 (setq nnmh-group-alist (cons (list group active) nnmh-group-alist)))) |
452 (let ((files (sort | |
453 (mapcar | |
454 (lambda (f) | |
455 (string-to-int f)) | |
456 (directory-files | |
457 (nnmail-group-pathname group nnmh-directory) | |
458 nil "^[0-9]+$")) | |
459 '>))) | |
460 (when files | |
461 (setcdr active (car files))))) | |
462 (setcdr active (1+ (cdr active))) | 437 (setcdr active (1+ (cdr active))) |
463 (while (file-exists-p | 438 (while (file-exists-p |
464 (concat (nnmail-group-pathname group nnmh-directory) | 439 (concat (nnmail-group-pathname group nnmh-directory) |
465 (int-to-string (cdr active)))) | 440 (int-to-string (cdr active)))) |
466 (setcdr active (1+ (cdr active)))) | 441 (setcdr active (1+ (cdr active)))) |
467 (cdr active))) | 442 (cdr active))) |
468 | 443 |
469 (defun nnmh-update-gnus-unreads (group) | 444 (defun nnmh-update-gnus-unreads (group) |
470 ;; Go through the .nnmh-articles file and compare with the actual | 445 ;; Go through the .nnmh-articles file and compare with the actual |
471 ;; articles in this folder. The articles that are "new" will be | 446 ;; articles in this folder. The articles that are "new" will be |
472 ;; marked as unread by Gnus. | 447 ;; marked as unread by Gnus. |
473 (let* ((dir nnmh-current-directory) | 448 (let* ((dir nnmh-current-directory) |
474 (files (sort (mapcar (function (lambda (name) (string-to-int name))) | 449 (files (sort (mapcar (function (lambda (name) (string-to-int name))) |
475 (directory-files nnmh-current-directory | 450 (directory-files nnmh-current-directory |
476 nil "^[0-9]+$" t)) | 451 nil "^[0-9]+$" t)) '<)) |
477 '<)) | |
478 (nnmh-file (concat dir ".nnmh-articles")) | 452 (nnmh-file (concat dir ".nnmh-articles")) |
479 new articles) | 453 new articles) |
480 ;; Load the .nnmh-articles file. | 454 ;; Load the .nnmh-articles file. |
481 (when (file-exists-p nnmh-file) | 455 (if (file-exists-p nnmh-file) |
482 (setq articles | 456 (setq articles |
483 (let (nnmh-newsgroup-articles) | 457 (let (nnmh-newsgroup-articles) |
484 (ignore-errors (load nnmh-file nil t t)) | 458 (condition-case nil (load nnmh-file nil t t) (error nil)) |
485 nnmh-newsgroup-articles))) | 459 nnmh-newsgroup-articles))) |
486 ;; Add all new articles to the `new' list. | 460 ;; Add all new articles to the `new' list. |
487 (let ((art files)) | 461 (let ((art files)) |
488 (while art | 462 (while art |
489 (unless (assq (car art) articles) | 463 (if (not (assq (car art) articles)) (setq new (cons (car art) new))) |
490 (push (car art) new)) | |
491 (setq art (cdr art)))) | 464 (setq art (cdr art)))) |
492 ;; Remove all deleted articles. | 465 ;; Remove all deleted articles. |
493 (let ((art articles)) | 466 (let ((art articles)) |
494 (while art | 467 (while art |
495 (unless (memq (caar art) files) | 468 (if (not (memq (caar art) files)) |
496 (setq articles (delq (car art) articles))) | 469 (setq articles (delq (car art) articles))) |
497 (setq art (cdr art)))) | 470 (setq art (cdr art)))) |
498 ;; Check whether the articles really are the ones that Gnus thinks | 471 ;; Check whether the highest-numbered articles really are the ones |
499 ;; they are by looking at the time-stamps. | 472 ;; that Gnus thinks they are by looking at the time-stamps. |
500 (let ((arts articles) | 473 (let ((art articles)) |
501 art) | 474 (while (and art |
502 (while (setq art (pop arts)) | 475 (not (equal |
503 (when (not (equal | 476 (nth 5 (file-attributes |
504 (nth 5 (file-attributes | 477 (concat dir (int-to-string (caar art))))) |
505 (concat dir (int-to-string (car art))))) | 478 (cdar art)))) |
506 (cdr art))) | 479 (setq articles (delq (car art) articles)) |
507 (setq articles (delq art articles)) | 480 (setq new (cons (caar art) new)) |
508 (push (car art) new)))) | 481 (setq art (cdr art)))) |
509 ;; Go through all the new articles and add them, and their | 482 ;; Go through all the new articles and add them, and their |
510 ;; time-stamps, to the list. | 483 ;; time-stamps to the list. |
511 (setq articles | 484 (let ((n new)) |
512 (nconc articles | 485 (while n |
513 (mapcar | 486 (setq articles |
514 (lambda (art) | 487 (cons (cons |
515 (cons art | 488 (car n) |
516 (nth 5 (file-attributes | 489 (nth 5 (file-attributes |
517 (concat dir (int-to-string art)))))) | 490 (concat dir (int-to-string (car n)))))) |
518 new))) | 491 articles)) |
492 (setq n (cdr n)))) | |
519 ;; Make Gnus mark all new articles as unread. | 493 ;; Make Gnus mark all new articles as unread. |
520 (when new | 494 (or (zerop (length new)) |
521 (gnus-make-articles-unread | 495 (gnus-make-articles-unread |
522 (gnus-group-prefixed-name group (list 'nnmh "")) | 496 (gnus-group-prefixed-name group (list 'nnmh "")) |
523 (setq new (sort new '<)))) | 497 (setq new (sort new '<)))) |
524 ;; Sort the article list with highest numbers first. | 498 ;; Sort the article list with highest numbers first. |
525 (setq articles (sort articles (lambda (art1 art2) | 499 (setq articles (sort articles (lambda (art1 art2) |
526 (> (car art1) (car art2))))) | 500 (> (car art1) (car art2))))) |
527 ;; Finally write this list back to the .nnmh-articles file. | 501 ;; Finally write this list back to the .nnmh-articles file. |
528 (nnheader-temp-write nnmh-file | 502 (save-excursion |
503 (set-buffer (get-buffer-create "*nnmh out*")) | |
529 (insert ";; Gnus article active file for " group "\n\n") | 504 (insert ";; Gnus article active file for " group "\n\n") |
530 (insert "(setq nnmh-newsgroup-articles '") | 505 (insert "(setq nnmh-newsgroup-articles '") |
531 (gnus-prin1 articles) | 506 (insert (prin1-to-string articles) ")\n") |
532 (insert ")\n")))) | 507 (write-region (point-min) (point-max) nnmh-file nil 'nomesg) |
508 (kill-buffer (current-buffer))))) | |
533 | 509 |
534 (defun nnmh-deletable-article-p (group article) | 510 (defun nnmh-deletable-article-p (group article) |
535 "Say whether ARTICLE in GROUP can be deleted." | 511 "Say whether ARTICLE in GROUP can be deleted." |
536 (let ((path (concat nnmh-current-directory (int-to-string article)))) | 512 (let ((path (concat nnmh-current-directory (int-to-string article)))) |
537 ;; Writable. | |
538 (and (file-writable-p path) | 513 (and (file-writable-p path) |
539 ;; We can never delete the last article in the group. | 514 (or (not nnmail-keep-last-article) |
540 (not (eq (cdr (nth 1 (assoc group nnmh-group-alist))) | 515 (not (eq (cdr (nth 1 (assoc group nnmh-group-alist))) |
541 article))))) | 516 article)))))) |
542 | 517 |
543 (provide 'nnmh) | 518 (provide 'nnmh) |
544 | 519 |
545 ;;; nnmh.el ends here | 520 ;;; nnmh.el ends here |