/[meta-cvs]/meta-cvs/F-FFF16CA4956A36F19290AC9E1EBAFFD8
ViewVC logotype

Diff of /meta-cvs/F-FFF16CA4956A36F19290AC9E1EBAFFD8

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.40 by kaz, Mon Aug 5 19:19:58 2002 UTC revision 1.40.2.4 by kaz, Tue Aug 27 03:19:05 2002 UTC
# Line 76  Line 76 
76              (symbol-macrolet ((sandbox-down-path ,downpath-sym))              (symbol-macrolet ((sandbox-down-path ,downpath-sym))
77                ,@forms)))))))                ,@forms)))))))
78    
79  (defun mapping-generate-name (suffix &key no-dir)  (defstruct mapping-entry
80    (let* ((suffix (if (or (null suffix)    (kind :file)
81                           (string= "" suffix))    (id "")
82                     ""    (path "")
83                     (format nil ".~a" suffix)))    (target ""))
84           (name (format nil "F-~32,'0X~a" (guid-gen) suffix)))  
85      (if no-dir  (defun equal-mapping-entries (left right)
86        name    (and (eq (mapping-entry-kind left) (mapping-entry-kind right))
87        (path-cat *mcvs-dir* name))))         (string= (mapping-entry-id left) (mapping-entry-id right))
88           (path-equal (mapping-entry-path left) (mapping-entry-path right))
89           (equal (mapping-entry-target left) (mapping-entry-target right))))
90    
91    (defun equal-filemaps (left right)
92      (let ((same nil))
93        (mapc #'(lambda (le re)
94                  (setf same (and same (equal-mapping-entries le re))))
95                left right)))
96    
97    (defun mapping-generate-id (&key no-dir (suffix "") (prefix "F-"))
98      (format nil "~a~a~32,'0X~a"
99              (if no-dir "" (concatenate 'string *mcvs-dir* *path-sep*))
100              prefix
101              (guid-gen)
102              (if (or (null suffix) (string= "" suffix))
103                ""
104                (concatenate 'string "." suffix))))
105    
106    (defun mapping-extract-kind (filemap kind)
107      (remove-if-not #'(lambda (entry-kind)
108                         (eq entry-kind kind))
109                     filemap
110                     :key #'mapping-entry-kind))
111    
112  (defun mapping-extract-paths (filemap)  (defun mapping-extract-paths (filemap)
113    (mapcar #'second filemap))    (mapcar #'mapping-entry-path filemap))
114  (declaim (inline mapping-extract-paths))  (declaim (inline mapping-extract-paths))
115    
116  (defun mapping-lookup (filemap path)  (defun mapping-lookup (filemap path)
117    (find path filemap :test #'path-equal :key #'second))    (find path filemap :test #'path-equal :key #'mapping-entry-path))
118    
119  (defun mapping-prefix-lookup (filemap prefix)  (defun mapping-prefix-lookup (filemap prefix)
120    (if (path-equal *this-dir* prefix)    (if (path-equal *this-dir* prefix)
121      (first filemap)      (first filemap)
122      (find prefix filemap :test #'path-prefix-equal :key #'second)))      (find prefix filemap :test #'path-prefix-equal :key #'mapping-entry-path)))
123    
124  (defun mapping-prefix-matches (filemap path)  (defun mapping-prefix-matches (filemap path)
125    (if (path-equal *this-dir* path)    (if (path-equal *this-dir* path)
126      filemap      filemap
127      (remove-if-not #'(lambda (entry)      (remove-if-not #'(lambda (entry)
128                         (path-prefix-equal path (second entry))) filemap)))                         (path-prefix-equal path (mapping-entry-path entry)))
129                       filemap)))
130    
131  (defun mapping-object-lookup (filemap object)  (defun mapping-same-id-p (entry-one entry-two)
132    (find object filemap :test #'string= :key #'first))    (string= (mapping-entry-id entry-one) (mapping-entry-id entry-two)))
   
 (defun mapping-same-object-p (entry-one entry-two)  
   (string= (first entry-one) (first entry-two)))  
133    
134  (defun mapping-same-path-p (entry-one entry-two)  (defun mapping-same-path-p (entry-one entry-two)
135    (path-equal (second entry-one) (second entry-two)))    (path-equal (mapping-entry-path entry-one) (mapping-entry-path entry-two)))
   
 (defun mapping-moved-p (entry-one entry-two)  
   (and (string= (first entry-one) (first entry-two))  
        (not (path-equal (second entry-one) (second entry-two)))))  
136    
137  (defun mapping-rename-files (filemap file-list old-prefix new-prefix)  (defun mapping-rename-files (filemap file-list old-prefix new-prefix)
138  "Returns a new filemap, in which the pathames in the list file-list are edited  "Returns a new filemap, in which the pathames in the list file-list are edited
# Line 128  of the map is not preserved." Line 145  of the map is not preserved."
145               (canonicalize-path (path-cat prefix path)))))               (canonicalize-path (path-cat prefix path)))))
146      (let* ((op-len (length old-prefix))      (let* ((op-len (length old-prefix))
147             (delete-map (mapcan #'(lambda (entry)             (delete-map (mapcan #'(lambda (entry)
148                                     (let ((path (second entry)))                                     (with-slots (path) entry
149                                       (if (and (member path file-list                                       (if (and (member path file-list
150                                                        :test #'path-equal)                                                        :test #'path-equal)
151                                                (path-prefix-equal old-prefix                                                (path-prefix-equal old-prefix
152                                                                   path))                                                                   path))
153                                         (list entry)))) filemap))                                         (list entry)))) filemap))
154             (replace-map (mapcan #'(lambda (entry)             (replace-map (mapcan #'(lambda (entry)
155                                      (destructuring-bind (object path) entry                                      (with-slots (path) entry
156                                        (list (list object                                        (let ((new-entry (copy-mapping-entry
157                                                    (combine new-prefix                                                           entry)))
158                                                             (subseq path                                          (setf (mapping-entry-path new-entry)
159                                                                     op-len))))))                                                (combine new-prefix
160                                                           (subseq path op-len)))
161                                            (list new-entry))))
162                                   delete-map)))                                   delete-map)))
163      (append      (append
164        (set-difference        (set-difference
# Line 153  of the map is not preserved." Line 172  of the map is not preserved."
172  (defun mapping-dupe-check (filemap)  (defun mapping-dupe-check (filemap)
173  "Signals an error condition if the filemap contains duplicate paths or  "Signals an error condition if the filemap contains duplicate paths or
174  duplicate objects. Otherwise returns the filemap, sorted by path."  duplicate objects. Otherwise returns the filemap, sorted by path."
175    (dolist (entry filemap)    (let ((dupes)
176      (when (or (not (consp entry))          (id-hash (make-hash-table :test #'equal))
177                (not (and (stringp (first entry))          (path-hash (make-hash-table :test #'equal)))
178                          (stringp (second entry)))))      (dolist (entry filemap)
179        (malformed-map)))        (if (gethash (mapping-entry-id entry) id-hash)
180            (push entry dupes)
181    (let (dupes          (setf (gethash (mapping-entry-id entry) id-hash) entry))
182          (sorted-map (sort (copy-list filemap) #'string< :key #'first)))        (if (gethash (mapping-entry-path entry) path-hash)
183      (let ((iter (rest filemap)) (current-item (first (first filemap))))          (push entry dupes)
184        (loop          (setf (gethash (mapping-entry-path entry) path-hash) entry)))
         (when (endp iter)  
           (return))  
         (if (string= (first (first iter)) current-item)  
           (push (first iter) dupes)  
           (setf current-item (first (first iter))))  
         (setf iter (rest iter))))  
   
     (setf sorted-map (sort sorted-map #'string< :key #'second))  
   
     (let ((iter (rest filemap)) (current-item (second (first filemap))))  
       (loop  
         (when (endp iter)  
           (return))  
         (if (path-equal (second (first iter)) current-item)  
           (push (first iter) dupes)  
           (setf current-item (second (first iter))))  
         (setf iter (rest iter))))  
   
185      (when dupes      (when dupes
186        (dolist (dupe dupes)        (dolist (dupe dupes)
187          (chatter-terse "duplicate ~a -> ~a~%" (first dupe) (second dupe)))          (chatter-terse "duplicate ~a -> ~a~%"
188                           (mapping-entry-id dupe) (mapping-entry-path dupe)))
189        (error "mcvs: duplicates in map: correct and run mcvs update.")))        (error "mcvs: duplicates in map: correct and run mcvs update.")))
190    filemap)    filemap)
191    
192    (defun mapping-convert-old-style-in (raw-filemap)
193    "Converts old-style Meta-CVS file mapping to a list of mapping-entry
194    structures."
195      (mapcar #'(lambda (item)
196                  (when (or (not (consp item))
197                            (not (and (stringp (first item))
198                                      (stringp (second item)))))
199                    (malformed-map))
200                  (make-mapping-entry :kind :file
201                                      :id (first item)
202                                      :path (second item)))
203              raw-filemap))
204    
205    (defun mapping-convert-in (raw-filemap)
206    "Converts a Meta-CVS filemap as read from a file into its internal
207    representation---a list of mapping-entry structures."
208      (mapcar #'(lambda (item)
209                  (when (or (not (consp item))
210                            (not (and (keywordp (first item))
211                                      (stringp (second item)))))
212                    (malformed-map))
213                  (case (first item)
214                    ((:file)
215                       (make-mapping-entry :kind :file
216                                           :id (second item)
217                                           :path (third item)))
218                    ((:symlink)
219                       (when (not (third item))
220                         (error "mcvs: bad map: symlink ~a has no target."
221                                (second item)))
222                       (make-mapping-entry :kind :symlink
223                                           :id (second item)
224                                           :path (third item)
225                                           :target (fourth item)))
226                    (otherwise (error "mcvs: bad type keyword ~s in map."
227                                      (first item)))))
228              raw-filemap))
229    
230    (defun mapping-convert-out (filemap)
231    "Converts the internal representation of a Meta-CVS mapping to
232    the external form that is written out to files."
233      (mapcar #'(lambda (entry)
234                  (with-slots (kind id path target) entry
235                    (case kind
236                      ((:file) (list kind id path))
237                      ((:symlink) (list kind id path target))
238                      (otherwise (error "unknown mapping entry type ~s." kind)))))
239              filemap))
240    
241  (defun mapping-read (filename &key sanity-check)  (defun mapping-read (filename &key sanity-check)
242    "Reads a Meta-CVS from a file, optionally performing a check
243    for duplicate entries"
244    (let (filemap)    (let (filemap)
245        ;;
246        ;; Read the raw data, ensure that the file contains
247        ;; a Lisp object and that it's a list, or at least a cons.
248        ;;
249      (with-open-file (file filename :direction :input)      (with-open-file (file filename :direction :input)
250        (setf filemap (read file nil :error))        (setf filemap (read file nil :error))
251        (when (or (eq filemap :error)        (when (or (eq filemap :error)
252                  (and (not (consp filemap)) (not (null filemap))))                  (and (not (consp filemap)) (not (null filemap))))
253          (malformed-map)))          (malformed-map)))
254        ;;
255        ;; Distinguish between the old-style Meta-CVS map and
256        ;; the new one. The old one is a list of lists of strings.
257        ;; The new one is a list of lists having a keyword in
258        ;; the first position.
259        ;;
260        (setf filemap (if (or (null filemap) (keywordp (first (first filemap))))
261                        (mapping-convert-in filemap)
262                        (mapping-convert-old-style-in filemap)))
263    
264      (if sanity-check      (if sanity-check
265        (mapping-dupe-check filemap)        (mapping-dupe-check filemap)
266        filemap)))        filemap)))
267    
268  (defun mapping-write (filemap filename &key sort-map)  (defun mapping-write (filemap filename &key sort-map)
269    (with-open-file (file filename :direction :output)    (when sort-map
270      (let ((*print-right-margin* 1))      (setf filemap (sort (copy-list filemap)
271        (prin1 (if sort-map                          #'string< :key #'mapping-entry-id)))
272                 (sort (copy-list filemap) #'string< :key #'first)    (let ((raw-filemap (mapping-convert-out filemap)))
273                 filemap) file)      (with-open-file (file filename :direction :output)
274        (terpri file))))        (let ((*print-right-margin* 1))
275            (prin1 raw-filemap file)
276            (terpri file)))))
277    
278  (defun mapping-synchronize ()  (defun mapping-synchronize ()
279  "Synchronizes the contents of files in the sandbox, and their corresponding  "Synchronizes the contents of files in the sandbox, and their corresponding
# Line 215  to ensure that the newly incorporated ch Line 284  to ensure that the newly incorporated ch
284    (let ((filemap (mapping-read *mcvs-map-local*)))    (let ((filemap (mapping-read *mcvs-map-local*)))
285      (dolist (item filemap)      (dolist (item filemap)
286        (can-restart-here ("Continue synchronizing files.")        (can-restart-here ("Continue synchronizing files.")
287          (destructuring-bind (left right) item          (with-slots (kind id path target) item
288            (when (real-path-exists right)            (when (real-path-exists path)
289              (setf right (abstract-to-real-path right))              (case kind
290              (case (synchronize-files left right)                ((:file)
291                ((:left)                   (let ((left id) (right (abstract-to-real-path path)))
292                  (chatter-info "sync ~a -> ~a~%" left right))                     (case (synchronize-files left right)
293                ((:right)                       ((:left)
294                  (chatter-info "sync ~a <- ~a~%" left right))                         (chatter-info "sync ~a -> ~a~%" left right))
295                ((:same))                       ((:right)
296                ((:dir)                         (chatter-info "sync ~a <- ~a~%" left right))
297                  (error "mcvs-sync: cannot sync, either ~a or ~a is a directory."                       ((:same))
298                         left right))                       ((:dir)
299                ((nil)                         (error "mcvs-sync: cannot sync, either ~a or ~a is a directory."
300                  (error "mcvs-sync: neither ~a nor ~a exists."                                left right))
301                         left right)))))))))                       ((nil)
302                           (error "mcvs-sync: neither ~a nor ~a exists."
303                                  left right)))))
304                  ((:symlink)
305                     (let* ((symlink (abstract-to-real-path path))
306                            (linkdata (no-existence-error (readlink symlink))))
307                       (when (or (not linkdata)
308                                 (not (string= linkdata target)))
309                         (no-existence-error (unlink symlink))
310                         (ensure-directories-exist symlink)
311                         (symlink target symlink)
312                         (chatter-info "linking: ~a -> ~a~%"
313                                       symlink target)))))))))))
314    
315  (defun mapping-difference (old-mapping new-mapping)  (defun mapping-difference (old-mapping new-mapping)
316  "Compute the difference between two mappings. Returns three values:  "Compute the difference between two mappings. Returns three values:
# Line 240  to ensure that the newly incorporated ch Line 321  to ensure that the newly incorporated ch
321    (multiple-value-bind (moved-pairs added-items removed-items)    (multiple-value-bind (moved-pairs added-items removed-items)
322                         (intersection-difference                         (intersection-difference
323                           new-mapping old-mapping                           new-mapping old-mapping
324                           :key #'first :test #'equal                           :key #'mapping-entry-id :test #'equal
325                           :combine #'(lambda (new old)                           :combine #'(lambda (new old)
326                                        (unless (string= (second new)                                        (unless (string= (mapping-entry-path new)
327                                                         (second old))                                                         (mapping-entry-path old))
328                                          (list old new)))                                          (list old new)))
329                           :squash-nil t)                           :squash-nil t)
330      (values added-items removed-items moved-pairs)))      (values added-items removed-items moved-pairs)))
# Line 268  whether they came from the CVS repositor Line 349  whether they came from the CVS repositor
349          ;; do sanity checks, we won't complain about clobbering things          ;; do sanity checks, we won't complain about clobbering things
350          ;; that are slated to disappear.          ;; that are slated to disappear.
351          (dolist (item removed-items)          (dolist (item removed-items)
352            (when (real-path-exists (second item))            (when (real-path-exists (mapping-entry-path item))
353              (let ((real (abstract-to-real-path (second item))))              (let ((real (abstract-to-real-path (mapping-entry-path item))))
354                (chatter-terse "removing ~a~%" real)                (chatter-terse "removing ~a~%" real)
355                (unless no-delete-removed                (unless no-delete-removed
356                  (restart-case                  (restart-case
# Line 279  whether they came from the CVS repositor Line 360  whether they came from the CVS repositor
360    
361          (dolist (pair moved-pairs)          (dolist (pair moved-pairs)
362            (let ((old-item (first pair)))            (let ((old-item (first pair)))
363              (when (real-path-exists (second old-item))              (with-slots (path) old-item
364                (ensure-directories-gone (abstract-to-real-path (second old-item)))                (when (real-path-exists path)
365                (push old-item rollback-restore-items))))                  (ensure-directories-gone (abstract-to-real-path path))
366                    (push old-item rollback-restore-items)))))
367    
368          ;; Now check sanity of adds and moves, to verify they don't          ;; Now check sanity of adds and moves, to verify they don't
369          ;; clobber any local files.          ;; clobber any local files.
370          (let (clobber-add-items clobber-move-pairs)          (let (clobber-add-items clobber-move-pairs)
371            (dolist (item added-items)            (dolist (item added-items)
372              (when (real-path-exists (second item))              (with-slots (kind id path target) item
373                (let ((file-info (exists (abstract-to-real-path (second item)))))                (when (real-path-exists path)
374                  (when (and file-info                  (let* ((real-path (abstract-to-real-path path))
375                             (not (same-file-p file-info (stat (first item))))                         (file-info (exists real-path)))
376                             (not (mapping-lookup old-filemap (second item))))                    (when (and file-info
377                    (push item clobber-add-items)))))                               (case kind
378                                   ((:file)
379                                      (not (same-file-p file-info (stat id))))
380                                   ((:symlink)
381                                      (not (string= (readlink real-path)
382                                                    target)))
383                                   (otherwise t))
384                                 (not (mapping-lookup old-filemap path)))
385                        (push item clobber-add-items))))))
386    
387            (dolist (item moved-pairs)            (dolist (item moved-pairs)
388              (destructuring-bind (old-item new-item) item              (destructuring-bind (old-item new-item) item
389                (declare (ignore old-item))                (declare (ignore old-item))
390                (when (real-path-exists (second new-item))                (with-slots (path) new-item
391                  (let ((file-info (exists (abstract-to-real-path (second new-item)))))                  (when (real-path-exists path)
392                    (when (and file-info                    (let ((file-info (exists (abstract-to-real-path path))))
393                               (not (mapping-lookup old-filemap (second new-item))))                      (when (and file-info
394                                   (not (mapping-lookup old-filemap path)))
395                      (push item clobber-move-pairs))))))                        (push item clobber-move-pairs)))))))
396    
397            (when (or clobber-add-items clobber-move-pairs)            (when (or clobber-add-items clobber-move-pairs)
398              (block nil              (block nil
# Line 311  whether they came from the CVS repositor Line 401  whether they came from the CVS repositor
401                     #'(lambda ()                     #'(lambda ()
402                         (dolist (item clobber-add-items)                         (dolist (item clobber-add-items)
403                           (format t "add: ~a~%"                           (format t "add: ~a~%"
404                                   (abstract-to-real-path (second item))))                                   (abstract-to-real-path (mapping-entry-path item))))
405                         (dolist (pair clobber-move-pairs)                         (dolist (pair clobber-move-pairs)
406                           (format t "move ~a -> ~a~%"                           (format t "move ~a -> ~a~%"
407                                   (second (abstract-to-real-path (first pair)))                                   (abstract-to-real-path (mapping-entry-path
408                                   (second (abstract-to-real-path (second pair))))))                                                            (first pair)))
409                                     (abstract-to-real-path (mapping-entry-path
410                                                              (second pair))))))
411                    :report-function                    :report-function
412                    #'(lambda (stream)                    #'(lambda (stream)
413                        (write-string "Print list of adds or moves which want to overwrite."                        (write-string "Print list of adds or moves which want to overwrite."
# Line 332  whether they came from the CVS repositor Line 424  whether they came from the CVS repositor
424          ;; Sanity check passed, complete moves and adds.          ;; Sanity check passed, complete moves and adds.
425          (dolist (item moved-pairs)          (dolist (item moved-pairs)
426            (destructuring-bind (old-item new-item) item            (destructuring-bind (old-item new-item) item
427              (let ((real-old-exists (real-path-exists (second old-item)))              (with-slots ((old-path path) (old-id id)) old-item
428                    (real-new-exists (real-path-exists (second new-item))))                (with-slots ((new-path path) (new-id id) kind target) new-item
429                (let ((real-old (and real-old-exists                  (let ((real-old-exists (real-path-exists old-path))
430                                     (abstract-to-real-path (second old-item))))                        (real-new-exists (real-path-exists new-path)))
431                      (real-new (and real-new-exists                    (let ((real-old (and real-old-exists
432                                     (abstract-to-real-path (second new-item)))))                                         (abstract-to-real-path old-path)))
433                  (cond                          (real-new (and real-new-exists
434                    ((and real-old-exists real-new-exists)                                         (abstract-to-real-path new-path))))
435                       (chatter-terse "moving ~a -> ~a~%" real-old real-new))                      (cond
436                    (real-new-exists                        ((and real-old-exists real-new-exists)
437                       (chatter-terse "moving (out-of-sandbox) -> ~a~%" real-new))                           (chatter-terse "moving ~a -> ~a~%" real-old real-new))
438                    (real-old-exists                        (real-new-exists
439                       (chatter-terse "moving ~a -> (out-of-sandbox)~%" real-old)))                           (chatter-terse "moving (out-of-sandbox) -> ~a~%" real-new))
440                          (real-old-exists
441                  (when real-new-exists                           (chatter-terse "moving ~a -> (out-of-sandbox)~%" real-old)))
442                    (no-existence-error (unlink real-new))  
443                    (synchronize-files (first new-item) real-new))                      (when real-new-exists
444                    (push new-item rollback-remove-items)))))                        (no-existence-error (unlink real-new))
445                          (case kind
446                            ((:file)
447                               (synchronize-files new-id real-new))
448                            ((:symlink)
449                               (ensure-directories-exist real-new)
450                               (symlink target real-new)))
451                          (push new-item rollback-remove-items))))))))
452    
453          (dolist (item added-items)          (dolist (item added-items)
454            (when (real-path-exists (second item))            (with-slots (kind id path target) item
455              (let ((real (abstract-to-real-path (second item))))              (when (real-path-exists path)
456                (can-restart-here ("Continue updating file structure.")                (let ((real (abstract-to-real-path path)))
457                  (chatter-terse "adding ~a~%" real)                  (can-restart-here ("Continue updating file structure.")
458                  (synchronize-files (first item) real)                    (case kind
459                  (push item rollback-remove-items))))))                      ((:file)
460                           (chatter-terse "adding ~a~%" real)
461                           (synchronize-files id real))
462                        ((:symlink)
463                           (chatter-terse "linking ~a -> ~a~%" real target)
464                           (no-existence-error (unlink real))
465                           (ensure-directories-exist real)
466                           (symlink target real)))
467                      (push item rollback-remove-items)))))))
468        (continue ()        (continue ()
469          :report "Restore all restructuring done so far."          :report "Restore all restructuring done so far."
470          (chatter-debug "Restoring.~%")          (chatter-debug "Restoring.~%")
471          (dolist (item rollback-remove-items)          (dolist (item rollback-remove-items)
472            (let ((real (abstract-to-real-path (second item))))            (let ((real (abstract-to-real-path (mapping-entry-path item))))
473              (chatter-terse "removing ~a~%" real)              (chatter-terse "removing ~a~%" real)
474              (ensure-directories-gone real)))              (ensure-directories-gone real)))
475          (dolist (item rollback-restore-items)          (dolist (item rollback-restore-items)
476            (let ((real (abstract-to-real-path (second item))))            (with-slots (kind path id target) item
477              (chatter-terse "restoring ~a~%" real)              (let ((real (abstract-to-real-path path)))
478              (synchronize-files (first item) real)))                (chatter-terse "restoring ~a~%" real)
479                  (case kind
480                    ((:file)
481                       (synchronize-files id real))
482                    ((:symlink)
483                       (ensure-directories-exist real)
484                       (symlink target real))))))
485          (return-from mapping-update nil)))          (return-from mapping-update nil)))
486    
487      (mapping-write new-filemap *mcvs-map-local*))      (mapping-write new-filemap *mcvs-map-local*))
# Line 378  whether they came from the CVS repositor Line 491  whether they came from the CVS repositor
491    (let ((to-be-removed ())    (let ((to-be-removed ())
492          (f-hash (make-hash-table :test #'equal)))          (f-hash (make-hash-table :test #'equal)))
493      (dolist (entry filemap)      (dolist (entry filemap)
494        (setf (gethash (first entry) f-hash) entry))        (setf (gethash (mapping-entry-id entry) f-hash) entry))
495      (for-each-file-info (fi *mcvs-dir*)      (for-each-file-info (fi *mcvs-dir*)
496        (let ((base (basename (file-name fi))))        (let ((base (basename (file-name fi))))
497          (multiple-value-bind (suffix name) (suffix base)          (multiple-value-bind (suffix name) (suffix base)

Legend:
Removed from v.1.40  
changed lines
  Added in v.1.40.2.4

  ViewVC Help
Powered by ViewVC 1.1.5