Mercurial > hg > xemacs-beta
comparison lisp/gnus/nnmh.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 |
---|---|
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) |
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)) |
115 (nnoo-change-server 'nnmh server defs) | 115 (nnoo-change-server 'nnmh server defs) |
116 (when (not (file-exists-p nnmh-directory)) | 116 (when (not (file-exists-p nnmh-directory)) |
117 (condition-case () | 117 (condition-case () |
118 (make-directory nnmh-directory t) | 118 (make-directory nnmh-directory t) |
119 (error t))) | 119 (error t))) |
120 (cond | 120 (cond |
121 ((not (file-exists-p nnmh-directory)) | 121 ((not (file-exists-p nnmh-directory)) |
122 (nnmh-close-server) | 122 (nnmh-close-server) |
123 (nnheader-report 'nnmh "Couldn't create directory: %s" nnmh-directory)) | 123 (nnheader-report 'nnmh "Couldn't create directory: %s" nnmh-directory)) |
124 ((not (file-directory-p (file-truename nnmh-directory))) | 124 ((not (file-directory-p (file-truename nnmh-directory))) |
125 (nnmh-close-server) | 125 (nnmh-close-server) |
142 (string-to-int (file-name-nondirectory file))))) | 142 (string-to-int (file-name-nondirectory file))))) |
143 | 143 |
144 (deffoo nnmh-request-group (group &optional server dont-check) | 144 (deffoo nnmh-request-group (group &optional server dont-check) |
145 (let ((pathname (nnmail-group-pathname group nnmh-directory)) | 145 (let ((pathname (nnmail-group-pathname group nnmh-directory)) |
146 dir) | 146 dir) |
147 (cond | 147 (cond |
148 ((not (file-directory-p pathname)) | 148 ((not (file-directory-p pathname)) |
149 (nnheader-report | 149 (nnheader-report |
150 'nnmh "Can't select group (no such directory): %s" group)) | 150 'nnmh "Can't select group (no such directory): %s" group)) |
151 (t | 151 (t |
152 (setq nnmh-current-directory pathname) | 152 (setq nnmh-current-directory pathname) |
153 (and nnmh-get-new-mail | 153 (and nnmh-get-new-mail |
154 nnmh-be-safe | 154 nnmh-be-safe |
155 (nnmh-update-gnus-unreads group)) | 155 (nnmh-update-gnus-unreads group)) |
156 (cond | 156 (cond |
157 (dont-check | 157 (dont-check |
158 (nnheader-report 'nnmh "Selected group %s" group) | 158 (nnheader-report 'nnmh "Selected group %s" group) |
159 t) | 159 t) |
160 (t | 160 (t |
161 ;; Re-scan the directory if it's on a foreign system. | 161 ;; Re-scan the directory if it's on a foreign system. |
162 (nnheader-re-read-dir pathname) | 162 (nnheader-re-read-dir pathname) |
163 (setq dir | 163 (setq dir |
164 (sort | 164 (sort |
165 (mapcar (lambda (name) (string-to-int name)) | 165 (mapcar (lambda (name) (string-to-int name)) |
166 (directory-files pathname nil "^[0-9]+$" t)) | 166 (directory-files pathname nil "^[0-9]+$" t)) |
167 '<)) | 167 '<)) |
168 (cond | 168 (cond |
169 (dir | 169 (dir |
170 (nnheader-report 'nnmh "Selected group %s" group) | 170 (nnheader-report 'nnmh "Selected group %s" group) |
171 (nnheader-insert | 171 (nnheader-insert |
172 "211 %d %d %d %s\n" (length dir) (car dir) | 172 "211 %d %d %d %s\n" (length dir) (car dir) |
173 (progn (while (cdr dir) (setq dir (cdr dir))) (car dir)) | 173 (progn (while (cdr dir) (setq dir (cdr dir))) (car dir)) |
208 (directory-files dir nil "^[0-9]+$" t)))) | 208 (directory-files dir nil "^[0-9]+$" t)))) |
209 (when files | 209 (when files |
210 (save-excursion | 210 (save-excursion |
211 (set-buffer nntp-server-buffer) | 211 (set-buffer nntp-server-buffer) |
212 (goto-char (point-max)) | 212 (goto-char (point-max)) |
213 (insert | 213 (insert |
214 (format | 214 (format |
215 "%s %d %d y\n" | 215 "%s %d %d y\n" |
216 (progn | 216 (progn |
217 (string-match | 217 (string-match |
218 (regexp-quote | 218 (regexp-quote |
219 (file-truename (file-name-as-directory | 219 (file-truename (file-name-as-directory |
220 (expand-file-name nnmh-toplev)))) | 220 (expand-file-name nnmh-toplev)))) |
221 dir) | 221 dir) |
222 (nnheader-replace-chars-in-string | 222 (nnheader-replace-chars-in-string |
223 (substring dir (match-end 0)) ?/ ?.)) | 223 (substring dir (match-end 0)) ?/ ?.)) |
224 (apply 'max files) | 224 (apply 'max files) |
229 (nnmh-request-list server)) | 229 (nnmh-request-list server)) |
230 | 230 |
231 (deffoo nnmh-request-expire-articles (articles newsgroup | 231 (deffoo nnmh-request-expire-articles (articles newsgroup |
232 &optional server force) | 232 &optional server force) |
233 (nnmh-possibly-change-directory newsgroup server) | 233 (nnmh-possibly-change-directory newsgroup server) |
234 (let* ((active-articles | 234 (let* ((active-articles |
235 (mapcar | 235 (mapcar |
236 (function | 236 (function |
237 (lambda (name) | 237 (lambda (name) |
238 (string-to-int name))) | 238 (string-to-int name))) |
239 (directory-files nnmh-current-directory nil "^[0-9]+$" t))) | 239 (directory-files nnmh-current-directory nil "^[0-9]+$" t))) |
240 (is-old t) | 240 (is-old t) |
241 article rest mod-time) | 241 article rest mod-time) |
242 (nnmail-activate 'nnmh) | 242 (nnmail-activate 'nnmh) |
243 | 243 |
244 (while (and articles is-old) | 244 (while (and articles is-old) |
245 (setq article (concat nnmh-current-directory | 245 (setq article (concat nnmh-current-directory |
246 (int-to-string (car articles)))) | 246 (int-to-string (car articles)))) |
247 (when (setq mod-time (nth 5 (file-attributes article))) | 247 (when (setq mod-time (nth 5 (file-attributes article))) |
248 (if (and (nnmh-deletable-article-p newsgroup (car articles)) | 248 (if (and (nnmh-deletable-article-p newsgroup (car articles)) |
249 (setq is-old | 249 (setq is-old |
250 (nnmail-expired-article-p newsgroup mod-time force))) | 250 (nnmail-expired-article-p newsgroup mod-time force))) |
251 (progn | 251 (progn |
252 (nnheader-message 5 "Deleting article %s in %s..." | 252 (nnheader-message 5 "Deleting article %s in %s..." |
253 article newsgroup) | 253 article newsgroup) |
254 (condition-case () | 254 (condition-case () |
255 (funcall nnmail-delete-file-function article) | 255 (funcall nnmail-delete-file-function article) |
256 (file-error | 256 (file-error |
257 (nnheader-message 1 "Couldn't delete article %s in %s" | 257 (nnheader-message 1 "Couldn't delete article %s in %s" |
263 (nconc rest articles))) | 263 (nconc rest articles))) |
264 | 264 |
265 (deffoo nnmh-close-group (group &optional server) | 265 (deffoo nnmh-close-group (group &optional server) |
266 t) | 266 t) |
267 | 267 |
268 (deffoo nnmh-request-move-article | 268 (deffoo nnmh-request-move-article |
269 (article group server accept-form &optional last) | 269 (article group server accept-form &optional last) |
270 (let ((buf (get-buffer-create " *nnmh move*")) | 270 (let ((buf (get-buffer-create " *nnmh move*")) |
271 result) | 271 result) |
272 (and | 272 (and |
273 (nnmh-deletable-article-p group article) | 273 (nnmh-deletable-article-p group article) |
274 (nnmh-request-article article group server) | 274 (nnmh-request-article article group server) |
275 (save-excursion | 275 (save-excursion |
276 (set-buffer buf) | 276 (set-buffer buf) |
277 (erase-buffer) | 277 (erase-buffer) |
288 result)) | 288 result)) |
289 | 289 |
290 (deffoo nnmh-request-accept-article (group &optional server last noinsert) | 290 (deffoo nnmh-request-accept-article (group &optional server last noinsert) |
291 (nnmh-possibly-change-directory group server) | 291 (nnmh-possibly-change-directory group server) |
292 (nnmail-check-syntax) | 292 (nnmail-check-syntax) |
293 (nnmail-cache-insert (nnmail-fetch-field "message-id")) | |
293 (if (stringp group) | 294 (if (stringp group) |
294 (and | 295 (and |
295 (nnmail-activate 'nnmh) | 296 (nnmail-activate 'nnmh) |
296 (car (nnmh-save-mail | 297 (car (nnmh-save-mail |
297 (list (cons group (nnmh-active-number group))) | 298 (list (cons group (nnmh-active-number group))) |
298 noinsert))) | 299 noinsert))) |
299 (and | 300 (and |
300 (nnmail-activate 'nnmh) | 301 (nnmail-activate 'nnmh) |
301 (car (nnmh-save-mail (nnmail-article-group 'nnmh-active-number) | 302 (car (nnmh-save-mail (nnmail-article-group 'nnmh-active-number) |
302 noinsert))))) | 303 noinsert)))) |
304 (when last | |
305 (nnmail-cache-close))) | |
303 | 306 |
304 (deffoo nnmh-request-replace-article (article group buffer) | 307 (deffoo nnmh-request-replace-article (article group buffer) |
305 (nnmh-possibly-change-directory group) | 308 (nnmh-possibly-change-directory group) |
306 (save-excursion | 309 (save-excursion |
307 (set-buffer buffer) | 310 (set-buffer buffer) |
308 (nnmh-possibly-create-directory group) | 311 (nnmh-possibly-create-directory group) |
309 (ignore-errors | 312 (ignore-errors |
310 (nnmail-write-region | 313 (nnmail-write-region |
311 (point-min) (point-max) | 314 (point-min) (point-max) |
312 (concat nnmh-current-directory (int-to-string article)) | 315 (concat nnmh-current-directory (int-to-string article)) |
313 nil (if (nnheader-be-verbose 5) nil 'nomesg)) | 316 nil (if (nnheader-be-verbose 5) nil 'nomesg)) |
314 t))) | 317 t))) |
315 | 318 |
322 (nnmh-possibly-create-directory group) | 325 (nnmh-possibly-create-directory group) |
323 (nnmh-possibly-change-directory group server) | 326 (nnmh-possibly-change-directory group server) |
324 (let ((articles (mapcar | 327 (let ((articles (mapcar |
325 (lambda (file) | 328 (lambda (file) |
326 (string-to-int file)) | 329 (string-to-int file)) |
327 (directory-files | 330 (directory-files |
328 nnmh-current-directory nil "^[0-9]+$")))) | 331 nnmh-current-directory nil "^[0-9]+$")))) |
329 (when articles | 332 (when articles |
330 (setcar active (apply 'min articles)) | 333 (setcar active (apply 'min articles)) |
331 (setcdr active (apply 'max articles)))))) | 334 (setcdr active (apply 'max articles)))))) |
332 t) | 335 t) |
335 (nnmh-possibly-change-directory group server) | 338 (nnmh-possibly-change-directory group server) |
336 ;; Delete all articles in GROUP. | 339 ;; Delete all articles in GROUP. |
337 (if (not force) | 340 (if (not force) |
338 () ; Don't delete the articles. | 341 () ; Don't delete the articles. |
339 (let ((articles (directory-files nnmh-current-directory t "^[0-9]+$"))) | 342 (let ((articles (directory-files nnmh-current-directory t "^[0-9]+$"))) |
340 (while articles | 343 (while articles |
341 (when (file-writable-p (car articles)) | 344 (when (file-writable-p (car articles)) |
342 (nnheader-message 5 "Deleting article %s in %s..." | 345 (nnheader-message 5 "Deleting article %s in %s..." |
343 (car articles) group) | 346 (car articles) group) |
344 (funcall nnmail-delete-file-function (car articles))) | 347 (funcall nnmail-delete-file-function (car articles))) |
345 (setq articles (cdr articles)))) | 348 (setq articles (cdr articles)))) |
346 ;; Try to delete the directory itself. | 349 ;; Try to delete the directory itself. |
347 (ignore-errors | 350 (ignore-errors |
348 (delete-directory nnmh-current-directory))) | 351 (delete-directory nnmh-current-directory))) |
349 ;; Remove the group from all structures. | 352 ;; Remove the group from all structures. |
350 (setq nnmh-group-alist | 353 (setq nnmh-group-alist |
351 (delq (assoc group nnmh-group-alist) nnmh-group-alist) | 354 (delq (assoc group nnmh-group-alist) nnmh-group-alist) |
352 nnmh-current-directory nil) | 355 nnmh-current-directory nil) |
353 t) | 356 t) |
354 | 357 |
355 (deffoo nnmh-request-rename-group (group new-name &optional server) | 358 (deffoo nnmh-request-rename-group (group new-name &optional server) |
362 ;; We move the articles file by file instead of renaming | 365 ;; We move the articles file by file instead of renaming |
363 ;; the directory -- there may be subgroups in this group. | 366 ;; the directory -- there may be subgroups in this group. |
364 ;; One might be more clever, I guess. | 367 ;; One might be more clever, I guess. |
365 (let ((files (nnheader-article-to-file-alist old-dir))) | 368 (let ((files (nnheader-article-to-file-alist old-dir))) |
366 (while files | 369 (while files |
367 (rename-file | 370 (rename-file |
368 (concat old-dir (cdar files)) | 371 (concat old-dir (cdar files)) |
369 (concat new-dir (cdar files))) | 372 (concat new-dir (cdar files))) |
370 (pop files))) | 373 (pop files))) |
371 (when (<= (length (directory-files old-dir)) 2) | 374 (when (<= (length (directory-files old-dir)) 2) |
372 (ignore-errors | 375 (ignore-errors |
382 | 385 |
383 | 386 |
384 ;;; Internal functions. | 387 ;;; Internal functions. |
385 | 388 |
386 (defun nnmh-possibly-change-directory (newsgroup &optional server) | 389 (defun nnmh-possibly-change-directory (newsgroup &optional server) |
387 (when (and server | 390 (when (and server |
388 (not (nnmh-server-opened server))) | 391 (not (nnmh-server-opened server))) |
389 (nnmh-open-server server)) | 392 (nnmh-open-server server)) |
390 (when newsgroup | 393 (when newsgroup |
391 (let ((pathname (nnmail-group-pathname newsgroup nnmh-directory))) | 394 (let ((pathname (nnmail-group-pathname newsgroup nnmh-directory))) |
392 (if (file-directory-p pathname) | 395 (if (file-directory-p pathname) |
402 (while dirs | 405 (while dirs |
403 (when (make-directory (directory-file-name (car dirs))) | 406 (when (make-directory (directory-file-name (car dirs))) |
404 (error "Could not create directory %s" (car dirs))) | 407 (error "Could not create directory %s" (car dirs))) |
405 (nnheader-message 5 "Creating mail directory %s" (car dirs)) | 408 (nnheader-message 5 "Creating mail directory %s" (car dirs)) |
406 (setq dirs (cdr dirs))))) | 409 (setq dirs (cdr dirs))))) |
407 | 410 |
408 (defun nnmh-save-mail (group-art &optional noinsert) | 411 (defun nnmh-save-mail (group-art &optional noinsert) |
409 "Called narrowed to an article." | 412 "Called narrowed to an article." |
410 (unless noinsert | 413 (unless noinsert |
411 (nnmail-insert-lines) | 414 (nnmail-insert-lines) |
412 (nnmail-insert-xref group-art)) | 415 (nnmail-insert-xref group-art)) |
419 ;; We save the article in all the newsgroups it belongs in. | 422 ;; We save the article in all the newsgroups it belongs in. |
420 (let ((ga group-art) | 423 (let ((ga group-art) |
421 first) | 424 first) |
422 (while ga | 425 (while ga |
423 (nnmh-possibly-create-directory (caar ga)) | 426 (nnmh-possibly-create-directory (caar ga)) |
424 (let ((file (concat (nnmail-group-pathname | 427 (let ((file (concat (nnmail-group-pathname |
425 (caar ga) nnmh-directory) | 428 (caar ga) nnmh-directory) |
426 (int-to-string (cdar ga))))) | 429 (int-to-string (cdar ga))))) |
427 (if first | 430 (if first |
428 ;; It was already saved, so we just make a hard link. | 431 ;; It was already saved, so we just make a hard link. |
429 (funcall nnmail-crosspost-link-function first file t) | 432 (funcall nnmail-crosspost-link-function first file t) |
436 (defun nnmh-active-number (group) | 439 (defun nnmh-active-number (group) |
437 "Compute the next article number in GROUP." | 440 "Compute the next article number in GROUP." |
438 (let ((active (cadr (assoc group nnmh-group-alist)))) | 441 (let ((active (cadr (assoc group nnmh-group-alist)))) |
439 (unless active | 442 (unless active |
440 ;; The group wasn't known to nnmh, so we just create an active | 443 ;; The group wasn't known to nnmh, so we just create an active |
441 ;; entry for it. | 444 ;; entry for it. |
442 (setq active (cons 1 0)) | 445 (setq active (cons 1 0)) |
443 (push (list group active) nnmh-group-alist) | 446 (push (list group active) nnmh-group-alist) |
444 ;; Find the highest number in the group. | 447 ;; Find the highest number in the group. |
445 (let ((files (sort | 448 (let ((files (sort |
446 (mapcar | 449 (mapcar |
463 ;; Go through the .nnmh-articles file and compare with the actual | 466 ;; Go through the .nnmh-articles file and compare with the actual |
464 ;; articles in this folder. The articles that are "new" will be | 467 ;; articles in this folder. The articles that are "new" will be |
465 ;; marked as unread by Gnus. | 468 ;; marked as unread by Gnus. |
466 (let* ((dir nnmh-current-directory) | 469 (let* ((dir nnmh-current-directory) |
467 (files (sort (mapcar (function (lambda (name) (string-to-int name))) | 470 (files (sort (mapcar (function (lambda (name) (string-to-int name))) |
468 (directory-files nnmh-current-directory | 471 (directory-files nnmh-current-directory |
469 nil "^[0-9]+$" t)) | 472 nil "^[0-9]+$" t)) |
470 '<)) | 473 '<)) |
471 (nnmh-file (concat dir ".nnmh-articles")) | 474 (nnmh-file (concat dir ".nnmh-articles")) |
472 new articles) | 475 new articles) |
473 ;; Load the .nnmh-articles file. | 476 ;; Load the .nnmh-articles file. |
474 (when (file-exists-p nnmh-file) | 477 (when (file-exists-p nnmh-file) |
475 (setq articles | 478 (setq articles |
476 (let (nnmh-newsgroup-articles) | 479 (let (nnmh-newsgroup-articles) |
477 (ignore-errors (load nnmh-file nil t t)) | 480 (ignore-errors (load nnmh-file nil t t)) |
478 nnmh-newsgroup-articles))) | 481 nnmh-newsgroup-articles))) |
479 ;; Add all new articles to the `new' list. | 482 ;; Add all new articles to the `new' list. |
480 (let ((art files)) | 483 (let ((art files)) |
492 ;; they are by looking at the time-stamps. | 495 ;; they are by looking at the time-stamps. |
493 (let ((arts articles) | 496 (let ((arts articles) |
494 art) | 497 art) |
495 (while (setq art (pop arts)) | 498 (while (setq art (pop arts)) |
496 (when (not (equal | 499 (when (not (equal |
497 (nth 5 (file-attributes | 500 (nth 5 (file-attributes |
498 (concat dir (int-to-string (car art))))) | 501 (concat dir (int-to-string (car art))))) |
499 (cdr art))) | 502 (cdr art))) |
500 (setq articles (delq art articles)) | 503 (setq articles (delq art articles)) |
501 (push (car art) new)))) | 504 (push (car art) new)))) |
502 ;; Go through all the new articles and add them, and their | 505 ;; Go through all the new articles and add them, and their |
509 (nth 5 (file-attributes | 512 (nth 5 (file-attributes |
510 (concat dir (int-to-string art)))))) | 513 (concat dir (int-to-string art)))))) |
511 new))) | 514 new))) |
512 ;; Make Gnus mark all new articles as unread. | 515 ;; Make Gnus mark all new articles as unread. |
513 (when new | 516 (when new |
514 (gnus-make-articles-unread | 517 (gnus-make-articles-unread |
515 (gnus-group-prefixed-name group (list 'nnmh "")) | 518 (gnus-group-prefixed-name group (list 'nnmh "")) |
516 (setq new (sort new '<)))) | 519 (setq new (sort new '<)))) |
517 ;; Sort the article list with highest numbers first. | 520 ;; Sort the article list with highest numbers first. |
518 (setq articles (sort articles (lambda (art1 art2) | 521 (setq articles (sort articles (lambda (art1 art2) |
519 (> (car art1) (car art2))))) | 522 (> (car art1) (car art2))))) |
526 | 529 |
527 (defun nnmh-deletable-article-p (group article) | 530 (defun nnmh-deletable-article-p (group article) |
528 "Say whether ARTICLE in GROUP can be deleted." | 531 "Say whether ARTICLE in GROUP can be deleted." |
529 (let ((path (concat nnmh-current-directory (int-to-string article)))) | 532 (let ((path (concat nnmh-current-directory (int-to-string article)))) |
530 ;; Writable. | 533 ;; Writable. |
531 (and (file-writable-p path) | 534 (and (file-writable-p path) |
532 ;; We can never delete the last article in the group. | 535 ;; We can never delete the last article in the group. |
533 (not (eq (cdr (nth 1 (assoc group nnmh-group-alist))) | 536 (not (eq (cdr (nth 1 (assoc group nnmh-group-alist))) |
534 article))))) | 537 article))))) |
535 | 538 |
536 (provide 'nnmh) | 539 (provide 'nnmh) |