Subject: Re: bug#37215: [PATCH] vc-cvs-ignore writes absolute filenames and duplicate strings

From: Wolfgang Scherer <[email-masked]>
Date: Thu, 20 Feb 2020 00:06:11 +0100

Am 15.02.20 um 08:44 schrieb Eli Zaretskii:
>
> I'd like to install your patch, and I'd like to do it soon, so it
> makes it into Emacs 27.  Can you please propose a modified patch which
> adds some minimal information about what's going on to the doc string
> and/or the comments around the code?

Here is the revised patch. I have cleared the FIXME issue mentioned by Lars and added commentary to what is going on.

From 375bdad57a2b56c63722e1d93c1e1de13566e8a2 Mon Sep 17 00:00:00 2001
From: Wolfgang Scherer <[email-masked]>
Date: Wed, 19 Feb 2020 23:53:10 +0100
Subject: [PATCH] Do not write absolute filenames and duplicate strings into
 .cvsignore
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* lisp/vc/vc-cvs.el: (vc-cvs-ignore) Expand filename correctly
and pass on basename only.
(vc-cvs-append-to-ignore) Do not write duplicate strings to
.cvsignore.  Addtional optional parameter SORT.
(lisp/vc/pcvs.el) Call ‘vc-cvs-append-to-ignore’ with SORT argument.
---
 lisp/vc/pcvs.el   |  4 ++--
 lisp/vc/vc-cvs.el | 40 +++++++++++++++++++++++++++-------------
 2 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/lisp/vc/pcvs.el b/lisp/vc/pcvs.el
index dcba504..cb0494e 100644
--- a/lisp/vc/pcvs.el
+++ b/lisp/vc/pcvs.el
@@ -106,7 +106,6 @@
 ;; 	right now, it's killed without further ado.
 ;; - make `cvs-mode-ignore' allow manually entering a pattern.
 ;; 	to which dir should it apply ?
-;; - cvs-mode-ignore should try to remove duplicate entries.
 ;; - maybe poll/check CVS/Entries files to react to external `cvs' commands ?
 ;; - some kind of `cvs annotate' support ?
 ;; 	but vc-annotate can be used instead.
@@ -1972,7 +1971,8 @@ This command ignores files that are not flagged as `Unknown'."
   (interactive)
   (dolist (fi (cvs-mode-marked 'ignore))
     (vc-cvs-append-to-ignore (cvs-fileinfo->dir fi) (cvs-fileinfo->file fi)
-			  (eq (cvs-fileinfo->subtype fi) 'NEW-DIR))
+			  (eq (cvs-fileinfo->subtype fi) 'NEW-DIR)
+                          cvs-sort-ignore-file)
     (setf (cvs-fileinfo->type fi) 'DEAD))
   (cvs-cleanup-collection cvs-cookies nil nil nil))

diff --git a/lisp/vc/vc-cvs.el b/lisp/vc/vc-cvs.el
index 16566a8..00459e8 100644
--- a/lisp/vc/vc-cvs.el
+++ b/lisp/vc/vc-cvs.el
@@ -1220,14 +1220,27 @@ is non-nil."
   "Return the administrative directory of FILE."
   (vc-find-root file "CVS"))

-(defun vc-cvs-ignore (file &optional _directory _remove)
-  "Ignore FILE under CVS."
-  (vc-cvs-append-to-ignore (file-name-directory file) file))
-
-(defun vc-cvs-append-to-ignore (dir str &optional old-dir)
+(defun vc-cvs-ignore (file &optional directory _remove)
+  "Ignore FILE under CVS.
+FILE is either absolute or relative to DIRECTORY.
+
+There is a CVS ignore file in each subdirectory.  Patterns only
+match files in the same directory.  Since FILE can be a relative
+filename with leading diretories, FILE is expanded against
+DIRECTORY to determine the correct absolute filename.  This path
+is then used to determine the directory and the pattern for the
+ignore file.
+
+Patterns follow glob(7) syntax.  Special characters \"?*[\\\" are
+escaped with a backslash."
+  (setq file (directory-file-name (expand-file-name file directory)))
+  (vc-cvs-append-to-ignore (file-name-directory file) (file-name-nondirectory file)))
+
+(defun vc-cvs-append-to-ignore (dir str &optional old-dir sort)
   "In DIR, add STR to the .cvsignore file.
 If OLD-DIR is non-nil, then this is a directory that we don't want
-to hear about anymore."
+to hear about anymore.  If SORT is non-nil, sort the ines of the
+ignore file."
   (with-current-buffer
       (find-file-noselect (expand-file-name ".cvsignore" dir))
     (when (ignore-errors
@@ -1236,13 +1249,14 @@ to hear about anymore."
 		 (not (vc-editable-p buffer-file-name))))
       ;; CVSREAD=on special case
       (vc-checkout buffer-file-name t))
-    (goto-char (point-max))
-    (unless (bolp) (insert "\n"))
-    (insert str (if old-dir "/\n" "\n"))
-    ;; FIXME this is a pcvs variable.
-    (if (bound-and-true-p cvs-sort-ignore-file)
-        (sort-lines nil (point-min) (point-max)))
-    (save-buffer)))
+    (goto-char (point-min))
+    (save-match-data
+      (unless (re-search-forward (concat "^" (regexp-quote str) "$") nil t)
+        (goto-char (point-max))
+        (unless (bolp) (insert "\n"))
+        (insert str (if old-dir "/\n" "\n"))
+        (if sort (sort-lines nil (point-min) (point-max)))
+        (save-buffer)))))

 (provide 'vc-cvs)

--
2.7.4