comparison lisp/gnus/nnfolder.el @ 108:360340f9fd5f r20-1b6

Import from CVS: tag r20-1b6
author cvs
date Mon, 13 Aug 2007 09:18:39 +0200
parents cf808b4c4290
children fe104dbd9147
comparison
equal deleted inserted replaced
107:523141596bda 108:360340f9fd5f
37 (nnoo-declare nnfolder) 37 (nnoo-declare nnfolder)
38 38
39 (defvoo nnfolder-directory (expand-file-name message-directory) 39 (defvoo nnfolder-directory (expand-file-name message-directory)
40 "The name of the nnfolder directory.") 40 "The name of the nnfolder directory.")
41 41
42 (defvoo nnfolder-active-file 42 (defvoo nnfolder-active-file
43 (nnheader-concat nnfolder-directory "active") 43 (nnheader-concat nnfolder-directory "active")
44 "The name of the active file.") 44 "The name of the active file.")
45 45
46 ;; I renamed this variable to something more in keeping with the general GNU 46 ;; I renamed this variable to something more in keeping with the general GNU
47 ;; style. -SLB 47 ;; style. -SLB
48 48
49 (defvoo nnfolder-ignore-active-file nil 49 (defvoo nnfolder-ignore-active-file nil
50 "If non-nil, causes nnfolder to do some extra work in order to determine 50 "If non-nil, causes nnfolder to do some extra work in order to determine
51 the true active ranges of an mbox file. Note that the active file is still 51 the true active ranges of an mbox file. Note that the active file is still
52 saved, but it's values are not used. This costs some extra time when 52 saved, but it's values are not used. This costs some extra time when
53 scanning an mbox when opening it.") 53 scanning an mbox when opening it.")
54 54
55 (defvoo nnfolder-distrust-mbox nil 55 (defvoo nnfolder-distrust-mbox nil
56 "If non-nil, causes nnfolder to not trust the user with respect to 56 "If non-nil, causes nnfolder to not trust the user with respect to
57 inserting unaccounted for mail in the middle of an mbox file. This can greatly 57 inserting unaccounted for mail in the middle of an mbox file. This can greatly
58 slow down scans, which now must scan the entire file for unmarked messages. 58 slow down scans, which now must scan the entire file for unmarked messages.
59 When nil, scans occur forward from the last marked message, a huge 59 When nil, scans occur forward from the last marked message, a huge
60 time saver for large mailboxes.") 60 time saver for large mailboxes.")
61 61
62 (defvoo nnfolder-newsgroups-file 62 (defvoo nnfolder-newsgroups-file
63 (concat (file-name-as-directory nnfolder-directory) "newsgroups") 63 (concat (file-name-as-directory nnfolder-directory) "newsgroups")
64 "Mail newsgroups description file.") 64 "Mail newsgroups description file.")
65 65
66 (defvoo nnfolder-get-new-mail t 66 (defvoo nnfolder-get-new-mail t
67 "If non-nil, nnfolder will check the incoming mail file and split the mail.") 67 "If non-nil, nnfolder will check the incoming mail file and split the mail.")
87 (defvoo nnfolder-current-buffer nil) 87 (defvoo nnfolder-current-buffer nil)
88 (defvoo nnfolder-status-string "") 88 (defvoo nnfolder-status-string "")
89 (defvoo nnfolder-group-alist nil) 89 (defvoo nnfolder-group-alist nil)
90 (defvoo nnfolder-buffer-alist nil) 90 (defvoo nnfolder-buffer-alist nil)
91 (defvoo nnfolder-scantime-alist nil) 91 (defvoo nnfolder-scantime-alist nil)
92 (defvoo nnfolder-active-timestamp nil)
92 93
93 94
94 95
95 ;;; Interface functions 96 ;;; Interface functions
96 97
132 (nnheader-fold-continuation-lines) 133 (nnheader-fold-continuation-lines)
133 'headers))))) 134 'headers)))))
134 135
135 (deffoo nnfolder-open-server (server &optional defs) 136 (deffoo nnfolder-open-server (server &optional defs)
136 (nnoo-change-server 'nnfolder server defs) 137 (nnoo-change-server 'nnfolder server defs)
137 (when (not (file-exists-p nnfolder-directory)) 138 (nnmail-activate 'nnfolder t)
138 (gnus-make-directory nnfolder-directory)) 139 (gnus-make-directory nnfolder-directory)
139 (cond 140 (cond
140 ((not (file-exists-p nnfolder-directory)) 141 ((not (file-exists-p nnfolder-directory))
141 (nnfolder-close-server) 142 (nnfolder-close-server)
142 (nnheader-report 'nnfolder "Couldn't create directory: %s" 143 (nnheader-report 'nnfolder "Couldn't create directory: %s"
143 nnfolder-directory)) 144 nnfolder-directory))
144 ((not (file-directory-p (file-truename nnfolder-directory))) 145 ((not (file-directory-p (file-truename nnfolder-directory)))
145 (nnfolder-close-server) 146 (nnfolder-close-server)
146 (nnheader-report 'nnfolder "Not a directory: %s" nnfolder-directory)) 147 (nnheader-report 'nnfolder "Not a directory: %s" nnfolder-directory))
147 (t 148 (t
149 (nnmail-activate 'nnfolder)
148 (nnheader-report 'nnfolder "Opened server %s using directory %s" 150 (nnheader-report 'nnfolder "Opened server %s using directory %s"
149 server nnfolder-directory) 151 server nnfolder-directory)
150 t))) 152 t)))
151 153
152 (deffoo nnfolder-request-close () 154 (deffoo nnfolder-request-close ()
184 (if (numberp article) 186 (if (numberp article)
185 (cons nnfolder-current-group article) 187 (cons nnfolder-current-group article)
186 (goto-char (point-min)) 188 (goto-char (point-min))
187 (search-forward (concat "\n" nnfolder-article-marker)) 189 (search-forward (concat "\n" nnfolder-article-marker))
188 (cons nnfolder-current-group 190 (cons nnfolder-current-group
189 (string-to-int 191 (string-to-int
190 (buffer-substring 192 (buffer-substring
191 (point) (progn (end-of-line) (point))))))))))) 193 (point) (progn (end-of-line) (point)))))))))))
192 194
193 (deffoo nnfolder-request-group (group &optional server dont-check) 195 (deffoo nnfolder-request-group (group &optional server dont-check)
196 (nnfolder-possibly-change-group group server)
194 (save-excursion 197 (save-excursion
195 (nnmail-activate 'nnfolder) 198 (nnmail-activate 'nnfolder)
196 (if (not (assoc group nnfolder-group-alist)) 199 (if (not (assoc group nnfolder-group-alist))
197 (nnheader-report 'nnfolder "No such group: %s" group) 200 (nnheader-report 'nnfolder "No such group: %s" group)
198 (nnfolder-possibly-change-group group server)
199 (if dont-check 201 (if dont-check
200 (progn 202 (progn
201 (nnheader-report 'nnfolder "Selected group %s" group) 203 (nnheader-report 'nnfolder "Selected group %s" group)
202 t) 204 t)
203 (let* ((active (assoc group nnfolder-group-alist)) 205 (let* ((active (assoc group nnfolder-group-alist))
204 (group (car active)) 206 (group (car active))
205 (range (cadr active))) 207 (range (cadr active)))
206 (cond 208 (cond
207 ((null active) 209 ((null active)
208 (nnheader-report 'nnfolder "No such group: %s" group)) 210 (nnheader-report 'nnfolder "No such group: %s" group))
209 ((null nnfolder-current-group) 211 ((null nnfolder-current-group)
210 (nnheader-report 'nnfolder "Empty group: %s" group)) 212 (nnheader-report 'nnfolder "Empty group: %s" group))
211 (t 213 (t
212 (nnheader-report 'nnfolder "Selected group %s" group) 214 (nnheader-report 'nnfolder "Selected group %s" group)
213 (nnheader-insert "211 %d %d %d %s\n" 215 (nnheader-insert "211 %d %d %d %s\n"
214 (1+ (- (cdr range) (car range))) 216 (1+ (- (cdr range) (car range)))
215 (car range) (cdr range) group)))))))) 217 (car range) (cdr range) group))))))))
216 218
217 (deffoo nnfolder-request-scan (&optional group server) 219 (deffoo nnfolder-request-scan (&optional group server)
218 (nnfolder-possibly-change-group group server t) 220 (nnfolder-possibly-change-group group server t)
219 (nnmail-get-new-mail 221 (nnmail-get-new-mail
220 'nnfolder 222 'nnfolder
221 (lambda () 223 (lambda ()
222 (let ((bufs nnfolder-buffer-alist)) 224 (let ((bufs nnfolder-buffer-alist))
223 (save-excursion 225 (save-excursion
224 (while bufs 226 (while bufs
225 (if (not (buffer-name (nth 1 (car bufs)))) 227 (if (not (buffer-name (nth 1 (car bufs))))
226 (setq nnfolder-buffer-alist 228 (setq nnfolder-buffer-alist
227 (delq (car bufs) nnfolder-buffer-alist)) 229 (delq (car bufs) nnfolder-buffer-alist))
228 (set-buffer (nth 1 (car bufs))) 230 (set-buffer (nth 1 (car bufs)))
229 (nnfolder-save-buffer) 231 (nnfolder-save-buffer)
230 (kill-buffer (current-buffer))) 232 (kill-buffer (current-buffer)))
231 (setq bufs (cdr bufs)))))) 233 (setq bufs (cdr bufs))))))
267 t) 269 t)
268 270
269 (deffoo nnfolder-request-create-group (group &optional server args) 271 (deffoo nnfolder-request-create-group (group &optional server args)
270 (nnfolder-possibly-change-group nil server) 272 (nnfolder-possibly-change-group nil server)
271 (nnmail-activate 'nnfolder) 273 (nnmail-activate 'nnfolder)
272 (when group 274 (when group
273 (unless (assoc group nnfolder-group-alist) 275 (unless (assoc group nnfolder-group-alist)
274 (push (list group (cons 1 0)) nnfolder-group-alist) 276 (push (list group (cons 1 0)) nnfolder-group-alist)
275 (nnmail-save-active nnfolder-group-alist nnfolder-active-file))) 277 (nnmail-save-active nnfolder-group-alist nnfolder-active-file)))
276 t) 278 t)
277 279
289 (deffoo nnfolder-request-list-newsgroups (&optional server) 291 (deffoo nnfolder-request-list-newsgroups (&optional server)
290 (nnfolder-possibly-change-group nil server) 292 (nnfolder-possibly-change-group nil server)
291 (save-excursion 293 (save-excursion
292 (nnmail-find-file nnfolder-newsgroups-file))) 294 (nnmail-find-file nnfolder-newsgroups-file)))
293 295
294 (deffoo nnfolder-request-expire-articles 296 (deffoo nnfolder-request-expire-articles
295 (articles newsgroup &optional server force) 297 (articles newsgroup &optional server force)
296 (nnfolder-possibly-change-group newsgroup server) 298 (nnfolder-possibly-change-group newsgroup server)
297 (let* ((is-old t) 299 (let* ((is-old t)
298 rest) 300 rest)
299 (nnmail-activate 'nnfolder) 301 (nnmail-activate 'nnfolder)
300 302
301 (save-excursion 303 (save-excursion
302 (set-buffer nnfolder-current-buffer) 304 (set-buffer nnfolder-current-buffer)
303 (while (and articles is-old) 305 (while (and articles is-old)
304 (goto-char (point-min)) 306 (goto-char (point-min))
305 (when (search-forward (nnfolder-article-string (car articles)) nil t) 307 (when (search-forward (nnfolder-article-string (car articles)) nil t)
306 (if (setq is-old 308 (if (setq is-old
307 (nnmail-expired-article-p 309 (nnmail-expired-article-p
308 newsgroup 310 newsgroup
309 (buffer-substring 311 (buffer-substring
310 (point) (progn (end-of-line) (point))) 312 (point) (progn (end-of-line) (point)))
311 force nnfolder-inhibit-expiry)) 313 force nnfolder-inhibit-expiry))
312 (progn 314 (progn
313 (nnheader-message 5 "Deleting article %d..." 315 (nnheader-message 5 "Deleting article %d..."
314 (car articles) newsgroup) 316 (car articles) newsgroup)
315 (nnfolder-delete-mail)) 317 (nnfolder-delete-mail))
316 (push (car articles) rest))) 318 (push (car articles) rest)))
317 (setq articles (cdr articles))) 319 (setq articles (cdr articles)))
318 (unless nnfolder-inhibit-expiry 320 (unless nnfolder-inhibit-expiry
336 338
337 (deffoo nnfolder-request-move-article 339 (deffoo nnfolder-request-move-article
338 (article group server accept-form &optional last) 340 (article group server accept-form &optional last)
339 (let ((buf (get-buffer-create " *nnfolder move*")) 341 (let ((buf (get-buffer-create " *nnfolder move*"))
340 result) 342 result)
341 (and 343 (and
342 (nnfolder-request-article article group server) 344 (nnfolder-request-article article group server)
343 (save-excursion 345 (save-excursion
344 (set-buffer buf) 346 (set-buffer buf)
345 (buffer-disable-undo (current-buffer)) 347 (buffer-disable-undo (current-buffer))
346 (erase-buffer) 348 (erase-buffer)
347 (insert-buffer-substring nntp-server-buffer) 349 (insert-buffer-substring nntp-server-buffer)
348 (goto-char (point-min)) 350 (goto-char (point-min))
349 (while (re-search-forward 351 (while (re-search-forward
350 (concat "^" nnfolder-article-marker) 352 (concat "^" nnfolder-article-marker)
351 (save-excursion (search-forward "\n\n" nil t) (point)) t) 353 (save-excursion (search-forward "\n\n" nil t) (point)) t)
352 (delete-region (progn (beginning-of-line) (point)) 354 (delete-region (progn (beginning-of-line) (point))
353 (progn (forward-line 1) (point)))) 355 (progn (forward-line 1) (point))))
354 (setq result (eval accept-form)) 356 (setq result (eval accept-form))
365 367
366 (deffoo nnfolder-request-accept-article (group &optional server last) 368 (deffoo nnfolder-request-accept-article (group &optional server last)
367 (nnfolder-possibly-change-group group server) 369 (nnfolder-possibly-change-group group server)
368 (nnmail-check-syntax) 370 (nnmail-check-syntax)
369 (let ((buf (current-buffer)) 371 (let ((buf (current-buffer))
370 result) 372 result art-group)
371 (goto-char (point-min)) 373 (goto-char (point-min))
372 (when (looking-at "X-From-Line: ") 374 (when (looking-at "X-From-Line: ")
373 (replace-match "From ")) 375 (replace-match "From "))
374 (and 376 (and
375 (nnfolder-request-list) 377 (nnfolder-request-list)
376 (save-excursion 378 (save-excursion
377 (set-buffer buf) 379 (set-buffer buf)
378 (goto-char (point-min)) 380 (goto-char (point-min))
379 (search-forward "\n\n" nil t) 381 (search-forward "\n\n" nil t)
380 (forward-line -1) 382 (forward-line -1)
381 (while (re-search-backward (concat "^" nnfolder-article-marker) nil t) 383 (while (re-search-backward (concat "^" nnfolder-article-marker) nil t)
382 (delete-region (point) (progn (forward-line 1) (point)))) 384 (delete-region (point) (progn (forward-line 1) (point))))
385 (nnmail-cache-insert (nnmail-fetch-field "message-id"))
383 (setq result 386 (setq result
384 (car (nnfolder-save-mail 387 (car (nnfolder-save-mail
385 (if (stringp group) 388 (if (stringp group)
386 (list (cons group (nnfolder-active-number group))) 389 (list (cons group (nnfolder-active-number group)))
387 (nnmail-article-group 'nnfolder-active-number)))))) 390 (setq art-group
388 (save-excursion 391 (nnmail-article-group 'nnfolder-active-number)))))))
389 (set-buffer nnfolder-current-buffer) 392 (when last
390 (and last (nnfolder-save-buffer)))) 393 (save-excursion
394 (nnfolder-possibly-change-folder (or (caar art-group) group))
395 (nnfolder-save-buffer)
396 (nnmail-cache-close))))
391 (nnmail-save-active nnfolder-group-alist nnfolder-active-file) 397 (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
392 (unless result 398 (unless result
393 (nnheader-report 'nnfolder "Couldn't store article")) 399 (nnheader-report 'nnfolder "Couldn't store article"))
394 result)) 400 result))
395 401
412 () ; Don't delete the articles. 418 () ; Don't delete the articles.
413 ;; Delete the file that holds the group. 419 ;; Delete the file that holds the group.
414 (ignore-errors 420 (ignore-errors
415 (delete-file (nnfolder-group-pathname group)))) 421 (delete-file (nnfolder-group-pathname group))))
416 ;; Remove the group from all structures. 422 ;; Remove the group from all structures.
417 (setq nnfolder-group-alist 423 (setq nnfolder-group-alist
418 (delq (assoc group nnfolder-group-alist) nnfolder-group-alist) 424 (delq (assoc group nnfolder-group-alist) nnfolder-group-alist)
419 nnfolder-current-group nil 425 nnfolder-current-group nil
420 nnfolder-current-buffer nil) 426 nnfolder-current-buffer nil)
421 ;; Save the active file. 427 ;; Save the active file.
422 (nnmail-save-active nnfolder-group-alist nnfolder-active-file) 428 (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
426 (nnfolder-possibly-change-group group server) 432 (nnfolder-possibly-change-group group server)
427 (save-excursion 433 (save-excursion
428 (set-buffer nnfolder-current-buffer) 434 (set-buffer nnfolder-current-buffer)
429 (and (file-writable-p buffer-file-name) 435 (and (file-writable-p buffer-file-name)
430 (ignore-errors 436 (ignore-errors
431 (rename-file 437 (rename-file
432 buffer-file-name 438 buffer-file-name
433 (nnfolder-group-pathname new-name)) 439 (nnfolder-group-pathname new-name))
434 t) 440 t)
435 ;; That went ok, so we change the internal structures. 441 ;; That went ok, so we change the internal structures.
436 (let ((entry (assoc group nnfolder-group-alist))) 442 (let ((entry (assoc group nnfolder-group-alist)))
465 (if (and (not (bobp)) leave-delim) 471 (if (and (not (bobp)) leave-delim)
466 (progn (forward-line -2) (point)) 472 (progn (forward-line -2) (point))
467 (point)) 473 (point))
468 (point-max)))))) 474 (point-max))))))
469 475
470 ;; When scanning, we're not looking t immediately switch into the group - if
471 ;; we know our information is up to date, don't even bother reading the file.
472 (defun nnfolder-possibly-change-group (group &optional server scanning) 476 (defun nnfolder-possibly-change-group (group &optional server scanning)
477 ;; Change servers.
473 (when (and server 478 (when (and server
474 (not (nnfolder-server-opened server))) 479 (not (nnfolder-server-opened server)))
475 (nnfolder-open-server server)) 480 (nnfolder-open-server server))
476 (when (and group (or nnfolder-current-buffer 481 ;; Change group.
477 (not (equal group nnfolder-current-group)))) 482 (when (and group
478 (gnus-make-directory (directory-file-name nnfolder-directory)) 483 (not (equal group nnfolder-current-group)))
479 (nnfolder-possibly-activate-groups nil) 484 (nnmail-activate 'nnfolder)
480 (or (assoc group nnfolder-group-alist) 485 (when (and (not (assoc group nnfolder-group-alist))
481 (not (file-exists-p 486 (not (file-exists-p
482 (nnfolder-group-pathname group))) 487 (nnfolder-group-pathname group))))
483 (progn 488 ;; The group doesn't exist, so we create a new entry for it.
484 (push (list group (cons 1 0)) nnfolder-group-alist) 489 (push (list group (cons 1 0)) nnfolder-group-alist)
485 (nnmail-save-active nnfolder-group-alist nnfolder-active-file))) 490 (nnmail-save-active nnfolder-group-alist nnfolder-active-file))
491
486 (let (inf file) 492 (let (inf file)
487 (if (and (equal group nnfolder-current-group) 493 ;; If we have to change groups, see if we don't already have the
488 nnfolder-current-buffer 494 ;; folder in memory. If we do, verify the modtime and destroy
489 (buffer-name nnfolder-current-buffer)) 495 ;; the folder if needed so we can rescan it.
490 () 496 (when (setq inf (assoc group nnfolder-buffer-alist))
491 (setq nnfolder-current-group group) 497 (setq nnfolder-current-buffer (nth 1 inf)))
492 498
493 ;; If we have to change groups, see if we don't already have the mbox 499 ;; If the buffer is not live, make sure it isn't in the alist. If it
494 ;; in memory. If we do, verify the modtime and destroy the mbox if 500 ;; is live, verify that nobody else has touched the file since last
495 ;; needed so we can rescan it. 501 ;; time.
496 (when (setq inf (assoc group nnfolder-buffer-alist)) 502 (when (and nnfolder-current-buffer
497 (setq nnfolder-current-buffer (nth 1 inf))) 503 (not (gnus-buffer-live-p nnfolder-current-buffer)))
498 504 (setq nnfolder-buffer-alist (delq inf nnfolder-buffer-alist)
499 ;; If the buffer is not live, make sure it isn't in the alist. If it 505 nnfolder-current-buffer nil))
500 ;; is live, verify that nobody else has touched the file since last 506
501 ;; time. 507 (setq nnfolder-current-group group)
502 (when (or (not (and nnfolder-current-buffer 508
503 (buffer-name nnfolder-current-buffer))) 509 (when (or (not nnfolder-current-buffer)
504 (not (and (bufferp nnfolder-current-buffer) 510 (not (verify-visited-file-modtime nnfolder-current-buffer)))
505 (verify-visited-file-modtime 511 (save-excursion
506 nnfolder-current-buffer)))) 512 (setq file (nnfolder-group-pathname group))
507 (when (and nnfolder-current-buffer 513 ;; See whether we need to create the new file.
508 (buffer-name nnfolder-current-buffer) 514 (unless (file-exists-p file)
509 (bufferp nnfolder-current-buffer)) 515 (gnus-make-directory (file-name-directory file))
510 (kill-buffer nnfolder-current-buffer)) 516 (nnmail-write-region 1 1 file t 'nomesg))
511 (setq nnfolder-buffer-alist (delq inf nnfolder-buffer-alist)) 517 (when (setq nnfolder-current-buffer (nnfolder-read-folder group))
512 (setq inf nil)) 518 (set-buffer nnfolder-current-buffer)
513 519 (push (list group nnfolder-current-buffer)
514 (unless inf 520 nnfolder-buffer-alist)))))))
515 (save-excursion
516 (setq file (nnfolder-group-pathname group))
517 (unless (file-directory-p (file-truename file))
518 (unless (file-exists-p file)
519 (gnus-make-directory (file-name-directory file))
520 (nnmail-write-region 1 1 file t 'nomesg))
521 (setq nnfolder-current-group group)
522 (setq nnfolder-current-buffer
523 (nnfolder-read-folder file scanning))
524 (when nnfolder-current-buffer
525 (set-buffer nnfolder-current-buffer)
526 (push (list group nnfolder-current-buffer)
527 nnfolder-buffer-alist)))))))
528 (setq nnfolder-current-group group)))
529 521
530 (defun nnfolder-save-mail (group-art-list) 522 (defun nnfolder-save-mail (group-art-list)
531 "Called narrowed to an article." 523 "Called narrowed to an article."
532 (let* (save-list group-art) 524 (let* (save-list group-art)
533 (goto-char (point-min)) 525 (goto-char (point-min))
534 ;; The From line may have been quoted by movemail. 526 ;; The From line may have been quoted by movemail.
535 (when (looking-at (concat ">" message-unix-mail-delimiter)) 527 (when (looking-at (concat ">" message-unix-mail-delimiter))
536 (delete-char 1)) 528 (delete-char 1))
537 ;; This might come from somewhere else. 529 ;; This might come from somewhere else.
538 (unless (looking-at message-unix-mail-delimiter) 530 (unless (looking-at message-unix-mail-delimiter)
539 (insert "From nobody " (current-time-string) "\n") 531 (insert "From nobody " (current-time-string) "\n")
540 (goto-char (point-min))) 532 (goto-char (point-min)))
541 ;; Quote all "From " lines in the article. 533 ;; Quote all "From " lines in the article.
542 (forward-line 1) 534 (forward-line 1)
548 (nnmail-insert-xref group-art-list) 540 (nnmail-insert-xref group-art-list)
549 (run-hooks 'nnmail-prepare-save-mail-hook) 541 (run-hooks 'nnmail-prepare-save-mail-hook)
550 (run-hooks 'nnfolder-prepare-save-mail-hook) 542 (run-hooks 'nnfolder-prepare-save-mail-hook)
551 543
552 ;; Insert the mail into each of the destination groups. 544 ;; Insert the mail into each of the destination groups.
553 (while group-art-list 545 (while (setq group-art (pop group-art-list))
554 (setq group-art (car group-art-list) 546 ;; Kill any previous newsgroup markers.
555 group-art-list (cdr group-art-list))
556
557 ;; Kill the previous newsgroup markers.
558 (goto-char (point-min)) 547 (goto-char (point-min))
559 (search-forward "\n\n" nil t) 548 (search-forward "\n\n" nil t)
560 (forward-line -1) 549 (forward-line -1)
561 (while (search-backward (concat "\n" nnfolder-article-marker) nil t) 550 (while (search-backward (concat "\n" nnfolder-article-marker) nil t)
562 (delete-region (1+ (point)) (progn (forward-line 2) (point)))) 551 (delete-region (1+ (point)) (progn (forward-line 2) (point))))
563 552
564 (nnfolder-possibly-change-group (car group-art))
565 ;; Insert the new newsgroup marker. 553 ;; Insert the new newsgroup marker.
566 (nnfolder-insert-newsgroup-line group-art) 554 (nnfolder-insert-newsgroup-line group-art)
567 (unless nnfolder-current-buffer 555
568 (nnfolder-close-group (car group-art)) 556 (save-excursion
569 (nnfolder-request-create-group (car group-art)) 557 (let ((beg (point-min))
570 (nnfolder-possibly-change-group (car group-art))) 558 (end (point-max))
571 (let ((beg (point-min)) 559 (obuf (current-buffer)))
572 (end (point-max)) 560 (nnfolder-possibly-change-folder (car group-art))
573 (obuf (current-buffer))) 561 (goto-char (point-max))
574 (set-buffer nnfolder-current-buffer) 562 (unless (eolp)
575 (goto-char (point-max)) 563 (insert "\n"))
576 (unless (eolp) 564 (unless (bobp)
577 (insert "\n")) 565 (insert "\n"))
578 (unless (bobp) 566 (insert-buffer-substring obuf beg end))))
579 (insert "\n"))
580 (insert-buffer-substring obuf beg end)
581 (set-buffer obuf)))
582 567
583 ;; Did we save it anywhere? 568 ;; Did we save it anywhere?
584 save-list)) 569 save-list))
585 570
586 (defun nnfolder-insert-newsgroup-line (group-art) 571 (defun nnfolder-insert-newsgroup-line (group-art)
588 (goto-char (point-min)) 573 (goto-char (point-min))
589 (when (search-forward "\n\n" nil t) 574 (when (search-forward "\n\n" nil t)
590 (forward-char -1) 575 (forward-char -1)
591 (insert (format (concat nnfolder-article-marker "%d %s\n") 576 (insert (format (concat nnfolder-article-marker "%d %s\n")
592 (cdr group-art) (current-time-string)))))) 577 (cdr group-art) (current-time-string))))))
593
594 (defun nnfolder-possibly-activate-groups (&optional group)
595 (save-excursion
596 ;; If we're looking for the activation of a specific group, find out
597 ;; its real name and switch to it.
598 (when group
599 (nnfolder-possibly-change-group group))
600 ;; If the group alist isn't active, activate it now.
601 (nnmail-activate 'nnfolder)))
602 578
603 (defun nnfolder-active-number (group) 579 (defun nnfolder-active-number (group)
604 ;; Find the next article number in GROUP. 580 ;; Find the next article number in GROUP.
605 (let ((active (cadr (assoc group nnfolder-group-alist)))) 581 (let ((active (cadr (assoc group nnfolder-group-alist))))
606 (if active 582 (if active
610 ;; a hat, but I don't know... 586 ;; a hat, but I don't know...
611 (push (list group (setq active (cons 1 1))) 587 (push (list group (setq active (cons 1 1)))
612 nnfolder-group-alist)) 588 nnfolder-group-alist))
613 (cdr active))) 589 (cdr active)))
614 590
591 (defun nnfolder-possibly-change-folder (group)
592 (let ((inf (assoc group nnfolder-buffer-alist)))
593 (if (and inf
594 (gnus-buffer-live-p (cadr inf)))
595 (set-buffer (cadr inf))
596 (when inf
597 (setq nnfolder-buffer-alist (delq inf nnfolder-buffer-alist)))
598 (when nnfolder-group-alist
599 (nnmail-save-active nnfolder-group-alist nnfolder-active-file))
600 (push (list group (nnfolder-read-folder group))
601 nnfolder-buffer-alist))))
615 602
616 ;; This method has a problem if you've accidentally let the active list get 603 ;; This method has a problem if you've accidentally let the active list get
617 ;; out of sync with the files. This could happen, say, if you've 604 ;; out of sync with the files. This could happen, say, if you've
618 ;; accidentally gotten new mail with something other than Gnus (but why 605 ;; accidentally gotten new mail with something other than Gnus (but why
619 ;; would _that_ ever happen? :-). In that case, we will be in the middle of 606 ;; would _that_ ever happen? :-). In that case, we will be in the middle of
626 ;; rest of the message looking for any more, possibly higher IDs. We'll 613 ;; rest of the message looking for any more, possibly higher IDs. We'll
627 ;; assume the maximum that we find is the highest active. Note that this 614 ;; assume the maximum that we find is the highest active. Note that this
628 ;; shouldn't cost us much extra time at all, but will be a lot less 615 ;; shouldn't cost us much extra time at all, but will be a lot less
629 ;; vulnerable to glitches between the mbox and the active file. 616 ;; vulnerable to glitches between the mbox and the active file.
630 617
631 (defun nnfolder-read-folder (file &optional scanning) 618 (defun nnfolder-read-folder (group)
632 ;; This is an attempt at a serious shortcut - don't even read in the file 619 (let* ((file (nnfolder-group-pathname group))
633 ;; if we know we've seen it since the last time it was touched. 620 (buffer (set-buffer (nnheader-find-file-noselect file))))
634 (let ((scantime (cadr (assoc nnfolder-current-group 621 (if (equal (cadr (assoc group nnfolder-scantime-alist))
635 nnfolder-scantime-alist))) 622 (nth 5 (file-attributes file)))
636 (modtime (nth 5 (file-attributes file)))) 623 ;; This looks up-to-date, so we don't do any scanning.
637 (if (and scanning scantime 624 buffer
638 (eq (car scantime) (car modtime)) 625 ;; Parse the damn thing.
639 (eq (cdr scantime) (cadr modtime)))
640 nil
641 (save-excursion 626 (save-excursion
642 (nnfolder-possibly-activate-groups nil) 627 (nnmail-activate 'nnfolder)
643 ;; Read in the file. 628 ;; Read in the file.
644 (set-buffer (setq nnfolder-current-buffer
645 (nnheader-find-file-noselect file)))
646 (buffer-disable-undo (current-buffer))
647 (setq buffer-read-only nil)
648 ;; If the file hasn't been touched since the last time we scanned it,
649 ;; don't bother doing anything with it.
650 (let ((delim (concat "^" message-unix-mail-delimiter)) 629 (let ((delim (concat "^" message-unix-mail-delimiter))
651 (marker (concat "\n" nnfolder-article-marker)) 630 (marker (concat "\n" nnfolder-article-marker))
652 (number "[0-9]+") 631 (number "[0-9]+")
653 (active (or (cadr (assoc nnfolder-current-group 632 (active (cadr (assoc group nnfolder-group-alist)))
654 nnfolder-group-alist)) 633 (scantime (assoc group nnfolder-scantime-alist))
655 (cons 1 0)))
656 (scantime (assoc nnfolder-current-group nnfolder-scantime-alist))
657 (minid (lsh -1 -1)) 634 (minid (lsh -1 -1))
658 maxid start end newscantime) 635 maxid start end newscantime
659 636 buffer-read-only)
660 (setq maxid (or (cdr active) 0)) 637 (buffer-disable-undo (current-buffer))
638 (setq maxid (cdr active))
661 (goto-char (point-min)) 639 (goto-char (point-min))
662 640
663 ;; Anytime the active number is 1 or 0, it is suspect. In that 641 ;; Anytime the active number is 1 or 0, it is suspect. In that
664 ;; case, search the file manually to find the active number. Or, 642 ;; case, search the file manually to find the active number. Or,
665 ;; of course, if we're being paranoid. (This would also be the 643 ;; of course, if we're being paranoid. (This would also be the
690 (goto-char (point-min))))) 668 (goto-char (point-min)))))
691 669
692 ;; Keep track of the active number on our own, and insert it back 670 ;; Keep track of the active number on our own, and insert it back
693 ;; into the active list when we're done. Also, prime the pump to 671 ;; into the active list when we're done. Also, prime the pump to
694 ;; cut down on the number of searches we do. 672 ;; cut down on the number of searches we do.
673 (unless (nnmail-search-unix-mail-delim)
674 (goto-char (point-max)))
695 (setq end (point-marker)) 675 (setq end (point-marker))
696 (set-marker end (or (and (nnmail-search-unix-mail-delim)
697 (point))
698 (point-max)))
699 (while (not (= end (point-max))) 676 (while (not (= end (point-max)))
700 (setq start (marker-position end)) 677 (setq start (marker-position end))
701 (goto-char end) 678 (goto-char end)
702 ;; There may be more than one "From " line, so we skip past 679 ;; There may be more than one "From " line, so we skip past
703 ;; them. 680 ;; them.
704 (while (looking-at delim) 681 (while (looking-at delim)
705 (forward-line 1)) 682 (forward-line 1))
706 (set-marker end (or (and (nnmail-search-unix-mail-delim) 683 (set-marker end (if (nnmail-search-unix-mail-delim)
707 (point)) 684 (point)
708 (point-max))) 685 (point-max)))
709 (goto-char start) 686 (goto-char start)
710 (when (not (search-forward marker end t)) 687 (when (not (search-forward marker end t))
711 (narrow-to-region start end) 688 (narrow-to-region start end)
712 (nnmail-insert-lines) 689 (nnmail-insert-lines)
713 (nnfolder-insert-newsgroup-line 690 (nnfolder-insert-newsgroup-line
714 (cons nil (nnfolder-active-number nnfolder-current-group))) 691 (cons nil (nnfolder-active-number nnfolder-current-group)))
715 (widen))) 692 (widen)))
716 693
694 (set-marker end nil)
717 ;; Make absolutely sure that the active list reflects reality! 695 ;; Make absolutely sure that the active list reflects reality!
718 (nnmail-save-active nnfolder-group-alist nnfolder-active-file) 696 (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
719 ;; Set the scantime for this group. 697 ;; Set the scantime for this group.
720 (setq newscantime (visited-file-modtime)) 698 (setq newscantime (visited-file-modtime))
721 (if scantime 699 (if scantime
731 (nnmail-activate 'nnfolder) 709 (nnmail-activate 'nnfolder)
732 (let ((files (directory-files nnfolder-directory)) 710 (let ((files (directory-files nnfolder-directory))
733 file) 711 file)
734 (while (setq file (pop files)) 712 (while (setq file (pop files))
735 (when (and (not (backup-file-name-p file)) 713 (when (and (not (backup-file-name-p file))
736 (nnheader-mail-file-mbox-p 714 (message-mail-file-mbox-p
737 (concat nnfolder-directory file))) 715 (concat nnfolder-directory file)))
738 (nnheader-message 5 "Adding group %s..." file) 716 (nnheader-message 5 "Adding group %s..." file)
739 (push (list file (cons 1 0)) nnfolder-group-alist) 717 (push (list file (cons 1 0)) nnfolder-group-alist)
740 (nnfolder-possibly-change-group file) 718 (nnfolder-possibly-change-group file)
741 (nnfolder-close-group file)) 719 (nnfolder-close-group file))
743 721
744 (defun nnfolder-group-pathname (group) 722 (defun nnfolder-group-pathname (group)
745 "Make pathname for GROUP." 723 "Make pathname for GROUP."
746 (let ((dir (file-name-as-directory (expand-file-name nnfolder-directory)))) 724 (let ((dir (file-name-as-directory (expand-file-name nnfolder-directory))))
747 ;; If this file exists, we use it directly. 725 ;; If this file exists, we use it directly.
748 (if (or nnmail-use-long-file-names 726 (if (or nnmail-use-long-file-names
749 (file-exists-p (concat dir group))) 727 (file-exists-p (concat dir group)))
750 (concat dir group) 728 (concat dir group)
751 ;; If not, we translate dots into slashes. 729 ;; If not, we translate dots into slashes.
752 (concat dir (nnheader-replace-chars-in-string group ?. ?/))))) 730 (concat dir (nnheader-replace-chars-in-string group ?. ?/)))))
753 731