From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.ciao.gmane.io!not-for-mail From: Wolfgang Scherer Newsgroups: gmane.emacs.bugs Subject: bug#37189: 25.4.1: vc-hg-ignore implementation is missing Date: Sat, 1 Feb 2020 02:20:08 +0100 Message-ID: <6145d6f6-37a8-7166-731b-57669086b145@gmx.de> References: <1ba53ae2-42a4-3ab3-d4f2-2ceae565d198@gmx.de> <52917e6f-2f00-25cf-4353-dfb40287d0ea@gmx.de> <83pnkrdpb3.fsf@gnu.org> <679942e8-abe9-b0fc-720d-75a54d8d0b5a@gmx.de> <95da41e8-7a55-a15c-cfa7-d70366f9ee6b@gmx.de> <412195c1-e196-12af-933b-0312f5075847@yandex.ru> <57825d73-27a4-d5f5-8198-a172796a558a@gmx.de> <1ebc6077-9175-65ba-4996-282bb2c8eca5@yandex.ru> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="ciao.gmane.io:159.69.161.202"; logging-data="75058"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.9.1 To: Dmitry Gutov , 37189@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sat Feb 01 02:33:31 2020 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1ixhf9-000JTI-LI for geb-bug-gnu-emacs@m.gmane-mx.org; Sat, 01 Feb 2020 02:33:31 +0100 Original-Received: from localhost ([::1]:34876 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ixhf8-00025r-Bn for geb-bug-gnu-emacs@m.gmane-mx.org; Fri, 31 Jan 2020 20:33:30 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:33703) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ixhT6-0003dp-LU for bug-gnu-emacs@gnu.org; Fri, 31 Jan 2020 20:21:07 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ixhT4-0008HO-N7 for bug-gnu-emacs@gnu.org; Fri, 31 Jan 2020 20:21:04 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:60499) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ixhT4-0008Eg-38 for bug-gnu-emacs@gnu.org; Fri, 31 Jan 2020 20:21:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1ixhT3-0003Ci-Tt for bug-gnu-emacs@gnu.org; Fri, 31 Jan 2020 20:21:01 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Wolfgang Scherer Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 01 Feb 2020 01:21:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 37189 X-GNU-PR-Package: emacs Original-Received: via spool by 37189-submit@debbugs.gnu.org id=B37189.158052001812245 (code B ref 37189); Sat, 01 Feb 2020 01:21:01 +0000 Original-Received: (at 37189) by debbugs.gnu.org; 1 Feb 2020 01:20:18 +0000 Original-Received: from localhost ([127.0.0.1]:38239 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ixhSM-0003BQ-7r for submit@debbugs.gnu.org; Fri, 31 Jan 2020 20:20:18 -0500 Original-Received: from mout.gmx.net ([212.227.15.18]:50027) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ixhSK-0003BB-0z for 37189@debbugs.gnu.org; Fri, 31 Jan 2020 20:20:16 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1580520009; bh=XsDnvo6jj0tOsHvJg8LrZm5gL1bnlFScAl6YDiD8YBE=; h=X-UI-Sender-Class:Subject:To:References:From:Date:In-Reply-To; b=YjA8p5WNzOqHL/sU/EE8FfTTKmYe++wnZ8XmjkhfLWKyemb5o3g52KWr6O2xO6+fi tf5mfH5AEwKa1Nu+L3i2HDTRDyLoXVY2Ozq4S2iBwlFRvk8zUs5iQSg6VD+jonyriL aR7P4b9jMaCnZwlBOXs4HpKeUcZO2C483a1vod4g= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Original-Received: from sheckley.simul.de ([87.160.210.52]) by mail.gmx.com (mrgmx004 [212.227.17.190]) with ESMTPSA (Nemesis) id 1MowGa-1jLEud2TYU-00qRcb; Sat, 01 Feb 2020 02:20:09 +0100 Original-Received: from [127.0.0.1] (sheckley.simul.de [127.0.0.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sheckley.simul.de (Postfix) with ESMTPSA id 725D619431B6; Sat, 1 Feb 2020 02:20:08 +0100 (CET) Openpgp: preference=signencrypt Autocrypt: addr=Wolfgang.Scherer@gmx.de; prefer-encrypt=mutual; keydata= xsDiBEb46IgRBACMHOAb1KNo1Ylk+ebri+4R+bG4tyKlqBlrpv8D9/ZwRdXSGt+0DyCHoaAd 7KW7noHapLe87DunABOjKG4nqTGv+dRiWuUBlp3I4aYRFDVa3Da+XnIYkMHKqhK59VEHQCdp Km42nuLS7TS+n99at9YwzTG6VBdOlBKTlRFngOjVLwCg1RGXJ6X3EjS1FKCQeXziURVpWlkD /2zY6Ayhxi62TS84VjikXrrmjXykAAaAmMVEyKKYb9L5pGlqiZz9g/K9xw1EUoZTYuaufquD v4rAGR58K/3V4CYfJLEeshMWiaXHvMmlxMznlG16/um4MvmR8B3r+cx0nOPK1JBdD2qrkNnF Mw8FB+zouLFB4Gt2IUC5IlOmZ8OQA/4qdU53CItzWsCr9Nux4L0qUlRweSmCnV8xGQ2wP5XI MawIQxxREvSrsYDG8cNnYETMg4iQFfIktwAoxCJvuFAwIB6ZxHGF4FcEZm64CXc2u7CmFLqt rVhXhIfMz9oEYC+HhGczGamn9ofbGTFd2hJEtPcQgWNR4f7+aKknmi2+OM0fV29sZmdhbmcg U2NoZXJlciA8d3NAc3ctYW10LndzPsJhBBMRAgAhBQJYmz3YAhsjBQsJCAcCBhUICQoLAgQW AgMBAh4BAheAAAoJEIUCr3Gr112VZZoAoLTBSTp1qGuNhLdXY04iaWCMYmHCAJ4kHPtQ6nTw kEq9qCHgVgXDaY7wjs7ATQRG+OiIEAQAhi0wjcxvA4tychg2NQuwBIf9LX/46l+74+QbewCn a4a+mw/9s5KY In-Reply-To: <1ebc6077-9175-65ba-4996-282bb2c8eca5@yandex.ru> Content-Language: de-DE X-Provags-ID: V03:K1:3gItFbRP+4LvtXFf1fk9jr3z9zxp5F/90+WAixFocvvddku4ugI jqTFtSPZWUgc6nKOWh3eLf9Xxsfsseun1PyJQPJ+r09sQCK+vaOeOTqrqb1AxOoJn1MdKIN ME027eERsNWSkeaZQwbk4D8RM5lV78BTwvPr5IyPYQCED+1obkt/UU6kBsk/looZLMDeTF8 VUZpE9mnFWXNG8IsOIh2Q== X-UI-Out-Filterresults: notjunk:1;V03:K0:TPsaQUUGq1Q=:oo9gkwrji0jeDp7WDDbD97 WJ8g1feWDpbu+7SGtXzXvkzXSPrhGj9Hf6Ws8A/jIN0vQ3VEldm4CJC73TvBG1y3v0SV8rGYM JgeBWQyw9BSGzK1vOXsBYqHy/hroHCS3rcADtJiDVxc80W/AT1ahw0+s8B+6Z4sOTkxkEFJHc ws93FVWBlmpCKzlnTZknKkcK4sTybXH7wv4rVpIIK2ctitiIiN40uxoRilf6FhnFAHMPF+zBx 7tz8ePyumIQ2CcmLsqteNPXd8j/cO/U0mTNsfeNHmWK+cVU8ym8DdS35o2zx2dcQgCXGTuVdI CIqtZjiHw+uwVfyHVp3ksD/cu2rkA0AdcN3oQnvVWHnr3QvI60gdmNESIkMRM98iBEq5ZViS2 CWXrUZgrFuwluPpc16qNAdXR79jDpFvh3fmooI23eErQiJ/9aVaKuybbotdV6UNUeqQSDlsd6 NLNWt606G6OSRM9YxrTaAiNy5JQo7tSmoOM59Ms+DFzo+9ZFin7ugKu+QWi2W55N20FqZbby6 Nm8CUxjMKOHGYLpftC8Y97KFZC8vYVBv+DpsWpD8/3CUhE5/WhfxWjWOaYPFRr4AhRJOry5Hw MW2tABuiRdgeOe0eyRlMijAHRAjLNb5Cb46Wpm8BfEQHXXTT/hKu6brZYad6Ac1cS3iD3IymI SCPiBiTCHtxywVUFC7pX2ea58Ry1OOmQomo8XSjwY86bnT9ZemltjVAFKBRoXGoydy/z1zx4r V4xxaGy2/0/ektZG+wkxK1DK8LCUAoJuU6aYCwLn/uYpVVMOsleWT6ZJdBBkHvnhUCBxe+/b X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:175538 Archived-At: Hi Dmitry, I don't think, that the problem with ignore specs can be solved in this (adhoc) manner. It should (finally) be properly designed. There is a fundamental difference between per-directory ignore specs and per-tree ignore specs. Let me try to outline, where I see the problem with the current implementation: 1. Per-tree VC support is (unecessarily) mapped onto per-directory =C2=A0=C2=A0 semantics. 2. `vc-ignore` is a quick and dirty afterthought, which does not =C2=A0=C2=A0 properly model per-tree use cases. 3. The rationale for my implementation of `vc-hg-ignore` covers =C2=A0=C2=A0 several use cases, which should be considered for a proper de= sign. Until the `vc-ignore` system is fully streamlined, the patches I provided can be used to deliver something other than nonsense for the `vc-dir-mode` cases. Per-directory vs. per-tree =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Originally, `vc` only supoprted SCCS, RCS, CVS, which all have per-directory semantics (see A. VC Backend History). It is not until 2004-03-15, when Arch is added, that per-tree semantics is mentioned. Starting 2007-07-30 GIT, HG, BZR, Mtn per-tree VCS are added. Finally 2014-11-20 SRC is added to the current list of supported backends: =C2=A0=C2=A0=C2=A0 (defcustom vc-handled-backends '(RCS CVS SVN SCCS SRC B= zr Git Hg Mtn) =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ;; RCS, CVS, SVN, SCCS, and SRC come first = because they are per-dir =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ;; rather than per-tree.=C2=A0 RCS comes fi= rst because of the multibackend However, the per-directory paradigm still bleeds through the UI. With changes as late as 2015, when `vc-root` became the default for `vc-dir`. And Bug#39380, which I just discovered. vc-ignore is a quick and dirty afterthought =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Since `vc` started out with RCS and SCCS support only, there was no need for ignore file support. Since `pcl-cvs` was more popular than `vc` for CVS, the ignore file support was obviously never missed enough. The first version of `cvs-ignore` in `vc` appeared in 2013 (see B. Initial revision of vc-ignore). It imported `cvs-append-to-ignore` from `pcl-cvs` and added some quick and dirty backend implementations for other VCS. Especially, ignoring files in `vc-dir-mode` is seriously broken. My standard use case for ignore files under per-tree VCS =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D My most frequent use case is ignoring a couple of marked files in `vc-dir-mode` under Mercurial.=C2=A0 I almost never add (or remove) patterns with `M-x vc-ignore`. The following use cases are implemented in `vc-ignore`, `vc-hg-ignore`: 1. `vc-dir-ignore` without a prefix argument shall call `vc-ignore` =C2=A0=C2=A0 with the result of (vc-dir-current-file), which is an absolut= e path =C2=A0=C2=A0 name. 2. `vc-dir-ignore` with a prefix argument shall call `vc-ignore` for =C2=A0=C2=A0 each marked file with the result of (vc-dir-fileinfo->name =C2=A0=C2=A0 filearg), which is a path relative to (vc-root). 3. The argument FILE of `vc-ignore` is either a pattern, an absolute =C2=A0=C2=A0 file path or a relative file path. 4. The argument FILE of `vc-hg-ignore` is either a pattern or a file name. =C2=A0=C2=A0 a. If FILE matches the regular expression =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 `vc-hg-ignore-detect-wildcard` ("[*^$]"), i= t is considered a =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pattern an is written unmodified into the i= gnore file, =C2=A0=C2=A0 b. Otherwise, FILE is expanded to an absolute file name, whic= h is =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 then made relative to the ignore file direc= tory. The relative =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 file path is then escaped according to the = active ignore syntax =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 and written into the ignore file. Examples (Mercurial repository): * `M-x vc-ignore` in sub directory "below1/below2": =C2=A0 "/home/repo/below1/below2/file.name" =3D> "^below1/below2/file\.nam= e$" * `M-x vc-ignore` in sub directory "below1/below2": =C2=A0 "file.name" =3D> "^below1/below2/file\.name$" * `M-x vc-ignore` in sub directory "some/where/in": =C2=A0 "\.ext$" =3D> "\.ext$" * `G` in `vc-dir-mode` on "below1/below2/file.name": =C2=A0 "/home/repo/below1/below2/file.name" =3D> "^below1/below2/file\.nam= e$" * `G` in `vc-dir-mode` marked "below1/below2/file.name": =C2=A0 "below1/below2/file.name" =3D> "^below1/below2/file\.name$" A. VC backend history =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 2015-01-19: (vc-root) instead of default-directory as default for `vc-dir` 2014-12-08: Arch removed -(defcustom vc-handled-backends '(RCS CVS SVN SCCS SRC Bzr Git Hg Mtn Arch= ) +(defcustom vc-handled-backends '(RCS CVS SVN SCCS SRC Bzr Git Hg Mtn) 2014-11-20: SRC added -(defcustom vc-handled-backends '(RCS CVS SVN SCCS Bzr Git Hg Mtn Arch) -=C2=A0 ;; RCS, CVS, SVN and SCCS come first because they are per-dir +(defcustom vc-handled-backends '(RCS CVS SVN SCCS SRC Bzr Git Hg Mtn Arch= ) +=C2=A0 ;; RCS, CVS, SVN, SCCS, and SRC come first because they are per-di= r 2008-05-07: MCVS removed -(defcustom vc-handled-backends '(RCS CVS SVN SCCS Bzr Git Hg Mtn Arch MCV= S) +(defcustom vc-handled-backends '(RCS CVS SVN SCCS Bzr Git Hg Mtn Arch) 2007-09-14: Mtn added -(defcustom vc-handled-backends '(RCS CVS SVN SCCS Bzr Git Hg Arch MCVS) +(defcustom vc-handled-backends '(RCS CVS SVN SCCS Bzr Git Hg Mtn Arch MCV= S) 2007-07-31: BZR added -(defcustom vc-handled-backends '(RCS CVS SVN SCCS GIT HG Arch MCVS) +(defcustom vc-handled-backends '(RCS CVS SVN SCCS GIT HG BZR Arch MCVS) 2007-07-30: GIT, HG added -(defcustom vc-handled-backends '(RCS CVS SVN SCCS Arch MCVS) +(defcustom vc-handled-backends '(RCS CVS SVN SCCS GIT HG Arch MCVS) 2004-03-15: Arch added, first mention of per-tree -(defcustom vc-handled-backends '(RCS CVS SVN MCVS SCCS) +(defcustom vc-handled-backends '(RCS CVS SVN SCCS Arch MCVS) +=C2=A0 ;; Arch and MCVS come last because they are per-tree rather than p= er-dir. 2003-05-07: SVN MCVS added -(defcustom vc-handled-backends '(RCS CVS SCCS) +(defcustom vc-handled-backends '(RCS CVS SVN MCVS SCCS) 2000-09-04: vc-handled-backends introduced +(defcustom vc-handled-backends '(RCS CVS SCCS) 1994 CVS support '(RCS SCCS CVS) 1992 first version of vc.el '(RCS SCCS) B. Initial revision of vc-ignore =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D Note: `cvs-append-to-ignore` imported from pcvs.el commit 7aa7fff0c8860b72a2c7cdc7d4d0845245754d43 Author: Xue Fuqiao Date:=C2=A0=C2=A0 Tue Jul 30 08:25:31 2013 +0800 =C2=A0=C2=A0=C2=A0 Add vc-ignore. =C2=A0=C2=A0=C2=A0 * lisp/vc/vc.el (vc-ignore): New function. =C2=A0=C2=A0=C2=A0 * lisp/vc/vc-svn.el (vc-svn-ignore): New function. =C2=A0=C2=A0=C2=A0 * lisp/vc/vc-hg.el (vc-hg-ignore): New function. =C2=A0=C2=A0=C2=A0 * lisp/vc/vc-git.el (vc-git-ignore): New function. =C2=A0=C2=A0=C2=A0 * lisp/vc/vc-dir.el (vc-dir-mode-map): Add key binding = for vc-dir-ignore =C2=A0=C2=A0=C2=A0 (vc-dir-ignore): New function. =C2=A0=C2=A0=C2=A0 * lisp/vc/vc-cvs.el (vc-cvs-ignore): New function. =C2=A0=C2=A0=C2=A0 (cvs-append-to-ignore): Moved from pcvs.el. =C2=A0=C2=A0=C2=A0 * lisp/vc/vc-bzr.el (vc-bzr-ignore): New function. =C2=A0=C2=A0=C2=A0 * lisp/vc/pcvs.el (vc-cvs): Require 'vc-cvs. +(defun vc-bzr-ignore (file) +=C2=A0 "Ignore FILE under Bazaar." +=C2=A0 (interactive) +=C2=A0 (vc-bzr-command "ignore" (get-buffer-create "*vc-ignore*") 0 +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 file)) +(defun vc-cvs-ignore (file) +=C2=A0 "Ignore FILE under CVS." +=C2=A0 (interactive) +=C2=A0 (cvs-append-to-ignore (file-name-directory file) file)) + +(defun cvs-append-to-ignore (dir str &optional old-dir) +=C2=A0 "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." +=C2=A0 (with-current-buffer +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (find-file-noselect (expand-file-name ".cv= signore" dir)) +=C2=A0=C2=A0=C2=A0 (when (ignore-errors +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (and buffer-= read-only +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0 (eq 'CVS (vc-backend buffer-file-name)) +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0 (not (vc-editable-p buffer-file-name)))) +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ;; CVSREAD=3Don special case +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (vc-checkout buffer-file-name t)) +=C2=A0=C2=A0=C2=A0 (goto-char (point-max)) +=C2=A0=C2=A0=C2=A0 (unless (bolp) (insert "\n")) +=C2=A0=C2=A0=C2=A0 (insert str (if old-dir "/\n" "\n")) +=C2=A0=C2=A0=C2=A0 (if cvs-sort-ignore-file (sort-lines nil (point-min) (= point-max))) +=C2=A0=C2=A0=C2=A0 (save-buffer))) +=C2=A0=C2=A0=C2=A0 (define-key map "I" 'vc-dir-ignore) +(defun vc-dir-ignore () +=C2=A0 "Ignore the current file." +=C2=A0 (interactive) +=C2=A0 (vc-ignore (vc-dir-current-file))) +(defun vc-git-ignore (file) +=C2=A0 "Ignore FILE under Git." +=C2=A0 (interactive) +=C2=A0 (with-temp-buffer +=C2=A0=C2=A0=C2=A0 (insert-file-contents +=C2=A0=C2=A0=C2=A0=C2=A0 (let (gitignore (concat (file-name-as-directory = (vc-git-root +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 default-directory)) ".gitignore")) +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (unless (search-forward file nil t) +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (goto-char (point-max)) +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (insert (concat "\n" file "\n"= )) +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (write-region 1 (point-max) gi= tignore)))))) +(defun vc-hg-ignore (file) +=C2=A0 "Ignore FILE under Mercurial." +=C2=A0 (interactive) +=C2=A0 (with-temp-buffer +=C2=A0=C2=A0=C2=A0 (insert-file-contents +=C2=A0=C2=A0=C2=A0=C2=A0 (let (hgignore (concat (file-name-as-directory (= vc-hg-root +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0 default-directory)) ".hgignore")) +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (unless (search-forward file nil t) +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (goto-char (point-max)) +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (insert (concat "\n" file "\n"= )) +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (write-region 1 (point-max) hg= ignore)))))) +(defun vc-svn-ignore (file) +=C2=A0 "Ignore FILE under Subversion." +=C2=A0 (interactive) +=C2=A0 (vc-svn-command (get-buffer-create "*vc-ignore*") 0 +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 file "propedit" "svn:ignore")) + +(defun vc-ignore (file) +=C2=A0 "Ignore FILE under the current VCS." +=C2=A0 (interactive "fIgnore file: ") +=C2=A0 (let ((backend (vc-backend file))) +=C2=A0=C2=A0=C2=A0 (vc-call-backend backend 'ignore file))) C. My personal experience with Emacs version control =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D I have been using `vc` for RCS and `pcl-cvs` (and later `vc`) for CVS since the very beginning in the 90's. `pcl-cvs` already had support for ignoring files (`cvs-mode-ignore`), which I always missed in `vc`. I stopped using CVS in favour of Mercurial for new projects around 2007.=C2=A0 Due to the lack of support for Mercurial in `vc`, I use= d the `dvc` package until recently. The `dvc` package always presents the entire repository tree and does not map the per-tree semantics into an inapplicable per-directory UI. Marking some files in the `*xhg-status*` buffer and invoking the ignore function properly escapes the filenames relative to the repository root and puts them into the `.hgignore` file at the repository root. Both, `pcl-cvs` and `dvc` work the same way, with `pcl-cvs` placing the ignored files into the appropriate per-directory ignore files and `dvc` adding them properly escaped to the per-tree ignore file. I recently started using `vc` again for Mercurial and Git. When trying to phase out `dvc` by covering all use cases, I stumbled over the `vc-ignore` problems. First Mercurial, then CVS and SVN.