From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Wolfgang Scherer Newsgroups: gmane.emacs.bugs Subject: bug#37189: 25.4.1: vc-hg-ignore implementation is missing Date: Sun, 5 Jan 2020 04:46:33 +0100 Message-ID: <57825d73-27a4-d5f5-8198-a172796a558a@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> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------731B6E72D1AAA2423C792EAD" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="144062"; mail-complaints-to="usenet@blaine.gmane.org" 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.org@gnu.org Sun Jan 05 04:47:34 2020 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1inwt4-000bIW-01 for geb-bug-gnu-emacs@m.gmane.org; Sun, 05 Jan 2020 04:47:34 +0100 Original-Received: from localhost ([::1]:38880 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1inwt1-0004OF-Vm for geb-bug-gnu-emacs@m.gmane.org; Sat, 04 Jan 2020 22:47:32 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:44596) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1inwse-0004O9-IB for bug-gnu-emacs@gnu.org; Sat, 04 Jan 2020 22:47:11 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1inwsb-0006ef-MB for bug-gnu-emacs@gnu.org; Sat, 04 Jan 2020 22:47:08 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:37605) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1inwsb-0006aY-AO for bug-gnu-emacs@gnu.org; Sat, 04 Jan 2020 22:47:05 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1inwsY-0002ah-9C for bug-gnu-emacs@gnu.org; Sat, 04 Jan 2020 22:47:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Wolfgang Scherer Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 05 Jan 2020 03:47:02 +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.15781960059937 (code B ref 37189); Sun, 05 Jan 2020 03:47:02 +0000 Original-Received: (at 37189) by debbugs.gnu.org; 5 Jan 2020 03:46:45 +0000 Original-Received: from localhost ([127.0.0.1]:43578 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1inwsG-0002aC-45 for submit@debbugs.gnu.org; Sat, 04 Jan 2020 22:46:44 -0500 Original-Received: from mout.gmx.net ([212.227.17.22]:36875) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1inwsD-0002Zy-WF for 37189@debbugs.gnu.org; Sat, 04 Jan 2020 22:46:43 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1578195995; bh=RKMroODgtv5ohlGfEBmqNQxOCmF6ZvtmBVZAT/2BoVQ=; h=X-UI-Sender-Class:Subject:To:References:From:Date:In-Reply-To; b=HRfGxCx21jtCImOZTItWaJfHMqEThT02AznO4k5ZL6qs2W7GO3t6AGAUhyEsxdssW UOuhc044SS4rJnBEj1DTh14B4wD6Wbww4VxFZNw+bttelGTIibnZ5b5QjSdyn/hUiS Ehu8JhdQoFEHbv7Uftuxm1eO65i0StsOLDcgdy1E= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Original-Received: from sheckley.simul.de ([87.160.210.52]) by mail.gmx.com (mrgmx105 [212.227.17.168]) with ESMTPSA (Nemesis) id 1MK3Vu-1j9Jm10Es2-00LUDZ; Sun, 05 Jan 2020 04:46:35 +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 3C5821940579; Sun, 5 Jan 2020 04:46:34 +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: <412195c1-e196-12af-933b-0312f5075847@yandex.ru> Content-Language: de-DE X-Provags-ID: V03:K1:JA/1+6LxYVLxlGxhpdbvfXE35OvSI4u84QSqzw9ef9jBAC6YEIB /rKZux4Q8Nl0eH5uWMcAkgIzl5JlwYK0L4HJNo/sEfPrrHxR4bvqX19P/7bKlLGTPJseTX4 y/SP0dPTC6G+oMXUK1/5/IVHed/BObsfmRLd624aUJImtHZR9X1CtR4e14Bs33+uFGt9sF7 ACtbnrJXpXepu/uARldFw== X-UI-Out-Filterresults: notjunk:1;V03:K0:4xvwuhjIyxE=:g1f9TWId01k/kTvorj7FEj fIhlVtTKd5Pne/8uEmCjV/7pYlq1DKbC9n5vjNrUrKIQW+mkJfNVo7Lxn8cTQI5EeMw21+/nk D39fXx3xffMG33YXbsgjTKK/hv6J2MaAvXqO9/pYH3tlIRfwy4IE9kx1IZXyU5JplXTDUpk91 LJ0kMlaRtqqMSnqwkrgzFlYfaj94r6dsZpbOULgc+xQJYGi2GPrL4Er6tqlIDJS/66KXXRa6U 3nTKknFGNhqsW+pq4HuEUvAQRyGBnjgHmpsbMPaC+STM/5hl8HSq3djoUcxNEPeBNLRuGq66s o6XUjABixW9Ix1zTaKWCUH7baIY2ibJ+PJ3u2eZX0Zle8809QvPFisq+9iEJeC1hi6aTYHIhD g0udqAxHw1ZCGEUCZB66i2ck12HoG8viPo9EFgasssmuRW/SGEC577LE8iTDmsca5FTdAgrtv NNC0L+DH6VcqrbL6znvxl5hoDztTO9UVtjStMnmuvIANgNEk9kOLzl1gL/04P79mWublUnShr Us4EFNKFJJvfz39vHL2SCX9/0KlhXtrkSgy2ROrdi5B2c/fkuKdVa5HugDgS9G72ByC98d587 dAWCSHjP7xNCUyAqC4DjVipKLIA1tJaMBw+LLgcZQdylFfPsZ1wX7CKHPVe/ISKU6F0Q2eskv INTO0k/of7EdHwLROnb5nbOJZ0BSn+S1ZOnpVrjgQE/Mo/A6jpk7QBmAiMjlwe02AOl2jG+5+ Tpm2weF24/KanWe/F6RFmFpiEftuLt8rJxmQzEiJ2ye9wyTWHGZBWog9IL+op+siJBQApQlY 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.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:174186 Archived-At: This is a multi-part message in MIME format. --------------731B6E72D1AAA2423C792EAD Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Hi Dmitry, Am 25.12.19 um 01:16 schrieb Dmitry Gutov: > On 29.08.2019 18:52, Wolfgang Scherer wrote: >> +=C2=A0 "Ignore FILE of DIRECTORY (default is `default-directory'). > > IF this function needs a docstring at all (which is not obvious since it= should be following vc-ignore), I think I'd rather this followed the latt= er's docstring. Where the clarification about the default is not in the fi= rst sentence. vc-hg-ignore needs a docstring, since it exhibits specific behavior for th= e backend (e.g. glob/regex syntax), which is not and cannot be covered by = the rather generic vc-ignore docstring. Most of the description in=C2=A0 vc-ignore is not even applicable to the b= ackend specific functions, e.g. there is no interactive functionality in t= he backend function and no backend is determined. If a backend does not provide a vc-BACKEND-ignore function, vc-default-ign= ore is invoked. This function has a docstring of its own (which contains t= he clarification about the default in the first sentence). According to yo= ur argument, this function should also have no docstring of its own. Howev= er, I cannot see how both docstrings are equivalent. vc-hg-ignore is modeled after vc-default-ignore, the docstring was copied = from vc-default-ignore and modified to fit the implementation. I have modi= fied the docstring further to match other backend specific ignore function= s. > > Also, I think saying "Ignore FILE under DIRECTORY" would be better, if y= ou intend to add this particular semantics to relative names. All other ignore functions say "Ignore FILE under VCS". I have modified th= e docstring accordingly. > >> +Otherwise, FILE is either relative to DIRECTORY or absolute. FILE >> +is converted to a path relative to the project root of DIRECTORY. > > Isn't it a bit odd that vc-ignore's docstring doesn't specify this disti= nction, and yet we're trying to implement it in vc-hg-ignore? No. vc-ignore's semantic roots stem from SCCS/RCS/CVS/subversion with sing= le directory ignore files. The ignore files for those VCS only contain fil= e patterns. For a VCS with subdirectories and a single ignore file at the root of the = repository (Git, Mercurial), rooted and non-rooted expressions are handled= differently and the single directory ignore file paradigm fails. > > Do you have a particular reason for that? Yes. It is the standard use case for ignoring something from vc-dir mode. = As mentioned, the vc-default-ignore produces utterly useless results for G= it and Mercurial in vc-dir mode. > >> +=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 (concat pattern (and (file-directory-p file-path) "*= ")))))) > > I think it needs to asterisks for the glob to become recursive. At least= according to https://stackoverflow.com/a/255094/615245. No, according to https://stackoverflow.com/a/255094/2127439, all of "bin/"= , "bin/*", "bin/**" are equivalent under glob syntax. I also tested this s= pecifically and extensivlely. > >> +=C2=A0=C2=A0=C2=A0 (lambda (_c) >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (cons _c (concat "\\" (char-to-string _= c))))) > > Our convention says that an argument whose name starts with underscore i= s unused. That's not the case here, so it shouldn't be named like that. OK. > >> +=C2=A0=C2=A0=C2=A0 (lambda (_c) >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (or (cdr (assq _c vc-hg--py-regexp-spec= ial-chars)) >> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (char-to-string= _c)))) > > Same. OK. New patch attached. --------------731B6E72D1AAA2423C792EAD Content-Type: text/x-patch; name="0001-Provide-vc-hg-ignore-to-make-vc-ignore-work-correctl.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename*0="0001-Provide-vc-hg-ignore-to-make-vc-ignore-work-correctl.pa"; filename*1="tch" =46rom 81672e2909bca4ea4299301bbf4450e392b3a4f8 Mon Sep 17 00:00:00 2001 From: Wolfgang Scherer Date: Sun, 5 Jan 2020 04:29:28 +0100 Subject: [PATCH] Provide vc-hg-ignore to make vc-ignore work correctly * lisp/vc/vc-hg.el: (vc-hg-ignore) Ignore file of directory. Add filepath relative to directory of Mercurial .hgignore file. The filepath is quoted according to the active ignore syntax (Bug#37189). (vc-hg--py-regexp-quote) Quote string as regexp to match exactly string. =2D-- lisp/vc/vc-hg.el | 229 +++++++++++++++++++++++++++++++++++---------------= ----- 1 file changed, 145 insertions(+), 84 deletions(-) diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el index eac9a6f..db84a28 100644 =2D-- a/lisp/vc/vc-hg.el +++ b/lisp/vc/vc-hg.el @@ -142,9 +142,9 @@ If nil, use the value of `vc-diff-switches'. If t, us= e no switches." If nil, use the value of `vc-annotate-switches'. If t, use no switches." :type '(choice (const :tag "Unspecified" nil) - (const :tag "None" t) - (string :tag "Argument String") - (repeat :tag "Argument List" :value ("") string)) + (const :tag "None" t) + (string :tag "Argument String") + (repeat :tag "Argument List" :value ("") string)) :version "25.1" :group 'vc-hg) @@ -152,8 +152,8 @@ switches." "String or list of strings specifying switches for hg revert under VC." :type '(choice (const :tag "None" nil) - (string :tag "Argument String") - (repeat :tag "Argument List" :value ("") string)) + (string :tag "Argument String") + (repeat :tag "Argument List" :value ("") string)) :version "27.1" :group 'vc-hg) @@ -233,35 +233,35 @@ highlighting the Log View buffer." (setq status (condition-case nil ;; Ignore all errors. - (let ((process-environment - ;; Avoid localization of messages so we - ;; can parse the output. Disable pager. - (append - (list "TERM=3Ddumb" "LANGUAGE=3DC" "HGPLAIN=3D1") - process-environment))) - (process-file - vc-hg-program nil t nil + (let ((process-environment + ;; Avoid localization of messages so we + ;; can parse the output. Disable pager. + (append + (list "TERM=3Ddumb" "LANGUAGE=3DC" "HGPLAIN= =3D1") + process-environment))) + (process-file + vc-hg-program nil t nil "--config" "ui.report_untrusted=3D0" - "--config" "alias.status=3Dstatus" - "--config" "defaults.status=3D" - "status" "-A" (file-relative-name file))) + "--config" "alias.status=3Dstatus" + "--config" "defaults.status=3D" + "status" "-A" (file-relative-name file))) ;; Some problem happened. E.g. We can't find an `hg' ;; executable. (error nil))))))) (when (and (eq 0 status) - (> (length out) 0) - (null (string-match ".*: No such file or directory$" out))) + (> (length out) 0) + (null (string-match ".*: No such file or directory$" out))= ) (let ((state (aref out 0))) - (cond - ((eq state ?=3D) 'up-to-date) - ((eq state ?A) 'added) - ((eq state ?M) 'edited) - ((eq state ?I) 'ignored) - ((eq state ?R) 'removed) - ((eq state ?!) 'missing) - ((eq state ??) 'unregistered) - ((eq state ?C) 'up-to-date) ;; Older mercurial versions use this. - (t 'up-to-date)))))) + (cond + ((eq state ?=3D) 'up-to-date) + ((eq state ?A) 'added) + ((eq state ?M) 'edited) + ((eq state ?I) 'ignored) + ((eq state ?R) 'removed) + ((eq state ?!) 'missing) + ((eq state ??) 'unregistered) + ((eq state ?C) 'up-to-date) ;; Older mercurial versions use this= . + (t 'up-to-date)))))) (defun vc-hg-working-revision (file) "Hg-specific version of `vc-working-revision'." @@ -429,19 +429,19 @@ If LIMIT is non-nil, show no more than this many ent= ries." ;; read-only. (let ((inhibit-read-only t)) (with-current-buffer - buffer + buffer (apply 'vc-hg-command buffer 'async files "log" - (nconc - (when start-revision (list (format "-r%s:0" start-revision))) - (when limit (list "-l" (format "%s" limit))) + (nconc + (when start-revision (list (format "-r%s:0" start-revision)= )) + (when limit (list "-l" (format "%s" limit))) (when (eq vc-log-view-type 'with-diff) (list "-p")) - (if shortlog + (if shortlog `(,@(if vc-hg-log-graph '("--graph")) "--template" ,(car vc-hg-root-log-format)) `("--template" ,vc-hg-log-format)) - vc-hg-log-switches))))) + vc-hg-log-switches))))) (defvar log-view-message-re) (defvar log-view-file-re) @@ -455,35 +455,35 @@ If LIMIT is non-nil, show no more than this many ent= ries." (set (make-local-variable 'log-view-per-file-logs) nil) (set (make-local-variable 'log-view-message-re) (if (eq vc-log-view-type 'short) - (cadr vc-hg-root-log-format) + (cadr vc-hg-root-log-format) "^changeset:[ \t]*\\([0-9]+\\):\\(.+\\)")) (set (make-local-variable 'tab-width) 2) ;; Allow expanding short log entries (when (eq vc-log-view-type 'short) (setq truncate-lines t) (set (make-local-variable 'log-view-expanded-log-entry-function) - 'vc-hg-expanded-log-entry)) + 'vc-hg-expanded-log-entry)) (set (make-local-variable 'log-view-font-lock-keywords) (if (eq vc-log-view-type 'short) - (list (cons (nth 1 vc-hg-root-log-format) - (nth 2 vc-hg-root-log-format))) - (append - log-view-font-lock-keywords - '( - ;; Handle the case: - ;; user: FirstName LastName - ("^user:[ \t]+\\([^<(]+?\\)[ \t]*[(<]\\([A-Za-z0-9_.+-]+@[A-Za-z0-9_= .-]+\\)[>)]" - (1 'change-log-name) - (2 'change-log-email)) - ;; Handle the cases: - ;; user: foo@bar - ;; and - ;; user: foo - ("^user:[ \t]+\\([A-Za-z0-9_.+-]+\\(?:@[A-Za-z0-9_.-]+\\)?\\)" - (1 'change-log-email)) - ("^date: \\(.+\\)" (1 'change-log-date)) - ("^tag: +\\([^ ]+\\)$" (1 'highlight)) - ("^summary:[ \t]+\\(.+\\)" (1 'log-view-message))))))) + (list (cons (nth 1 vc-hg-root-log-format) + (nth 2 vc-hg-root-log-format))) + (append + log-view-font-lock-keywords + '( + ;; Handle the case: + ;; user: FirstName LastName + ("^user:[ \t]+\\([^<(]+?\\)[ \t]*[(<]\\([A-Za-z0-9_.+-]+@[A-Z= a-z0-9_.-]+\\)[>)]" + (1 'change-log-name) + (2 'change-log-email)) + ;; Handle the cases: + ;; user: foo@bar + ;; and + ;; user: foo + ("^user:[ \t]+\\([A-Za-z0-9_.+-]+\\(?:@[A-Za-z0-9_.-]+\\)?\\)= " + (1 'change-log-email)) + ("^date: \\(.+\\)" (1 'change-log-date)) + ("^tag: +\\([^ ]+\\)$" (1 'highlight)) + ("^summary:[ \t]+\\(.+\\)" (1 'log-view-message))))))) (autoload 'vc-switches "vc") @@ -545,7 +545,7 @@ This requires hg 4.4 or later, for the \"-L\" option o= f \"hg log\"." (when (and (not oldvers) newvers) (setq oldvers working)) (apply #'vc-hg-command - (or buffer "*vc-diff*") + (or buffer "*vc-diff*") nil ; bug#21969 files "diff" (append @@ -584,7 +584,7 @@ This requires hg 4.4 or later, for the \"-L\" option o= f \"hg log\"." "Execute \"hg annotate\" on FILE, inserting the contents in BUFFER. Optional arg REVISION is a revision to annotate from." (apply #'vc-hg-command buffer 0 file "annotate" "-dq" "-n" - (append (vc-switches 'hg 'annotate) + (append (vc-switches 'hg 'annotate) (if revision (list (concat "-r" revision)))))) (declare-function vc-annotate-convert-time "vc-annotate" (&optional time)= ) @@ -1102,9 +1102,9 @@ hg binary." (let ((vc-hg-size (nth 2 dirstate-entry)) (vc-hg-mtime (nth 3 dirstate-entry)) (fs-size (file-attribute-size stat)) - (fs-mtime (time-convert - (file-attribute-modification-time stat) - 'integer))) + (fs-mtime (time-convert + (file-attribute-modification-time stat) + 'integer))) (if (and (eql vc-hg-size fs-size) (eql vc-hg-mtime fs-mt= ime)) 'up-to-date 'edited))) @@ -1210,7 +1210,51 @@ REV is ignored." (defun vc-hg-find-ignore-file (file) "Return the root directory of the repository of FILE." (expand-file-name ".hgignore" - (vc-hg-root file))) + (vc-hg-root file))) + +(defvar vc-hg-ignore-detect-wildcard "[*^$]" + "Regular expresssion to detect wildcards in an ignored file + specification.") + +(defun vc-hg-ignore (file &optional directory remove) + "Ignore FILE under Mercurial. +FILE is either absolute or relative to DIRECTORY (default is +`default-directory'). +If FILE matches the regular expression +`vc-hg-ignore-detect-wildcard', it is processed unmodified. +Otherwise, FILE is converted to a path relative to the project +root of DIRECTORY. It is then further escaped/expanded according +to the active syntax in .hgignore. If the syntax is `regexp', +FILE is quoted as anchored literal Python regexp and if FILE is a +directory, the trailing `$' is omitted. Otherwise, if the syntax +is `glob', FILE is used unquoted and if FILE is a directory, a +`*' is appended. +If REMOVE is non-nil, remove the pattern derived from FILE from +ignored files." + (let ((ignore (vc-hg-find-ignore-file (or directory default-directory))= ) + (pattern file) + root-dir file-path syntax) + (unless (string-match vc-hg-ignore-detect-wildcard pattern) + (setq file-path (expand-file-name file directory)) + (setq root-dir (file-name-directory ignore)) + (when (not (string=3D (substring file-path 0 (length root-dir)) roo= t-dir)) + (error "Ignore spec %s is not below project root %s" file-path ro= ot-dir)) + (setq pattern (substring file-path (length root-dir))) + (save-match-data + (with-current-buffer (find-file-noselect ignore) + (goto-char (point-max)) + (setq syntax + (if (re-search-backward "^ *syntax: *\\(regexp\\|glob\\)$= " nil t) + (match-string 1) + "regexp"))) + (setq pattern + (if (string=3D syntax "regexp") + (concat "^" (vc-hg--py-regexp-quote pattern) + (and (not (file-directory-p file-path)) "$")) + (concat pattern (and (file-directory-p file-path) "*"))))= )) + (if remove + (vc--remove-regexp (concat "^" (regexp-quote pattern ) "\\(\n\\|$= \\)") ignore) + (vc--add-line pattern ignore)))) ;; Modeled after the similar function in vc-bzr.el (defun vc-hg-checkout (file &optional rev) @@ -1250,7 +1294,6 @@ REV is the revision to check out into WORKFILE." (add-hook 'after-save-hook 'vc-hg-resolve-when-done nil t) (vc-message-unresolved-conflicts buffer-file-name))) - ;; Modeled after the similar function in vc-bzr.el (defun vc-hg-revert (file &optional contents-done) (unless contents-done @@ -1386,12 +1429,12 @@ REV is the revision to check out into WORKFILE." (defun vc-hg-log-incoming (buffer remote-location) (vc-setup-buffer buffer) (vc-hg-command buffer 1 nil "incoming" "-n" (unless (string=3D remote-l= ocation "") - remote-location))) + remote-location))) (defun vc-hg-log-outgoing (buffer remote-location) (vc-setup-buffer buffer) (vc-hg-command buffer 1 nil "outgoing" "-n" (unless (string=3D remote-l= ocation "") - remote-location))) + remote-location))) (defvar vc-hg-error-regexp-alist '(("^M \\(.+\\)" 1 nil nil 0)) @@ -1413,30 +1456,30 @@ commands, which only operated on marked files." ;; `pull'/`push' VC actions were implemented. ;; The following is for backwards compatibility. (if (and obsolete (setq marked-list (log-view-get-marked))) - (apply #'vc-hg-command - nil 0 nil - command - (apply 'nconc - (mapcar (lambda (arg) (list "-r" arg)) marked-list))) + (apply #'vc-hg-command + nil 0 nil + command + (apply 'nconc + (mapcar (lambda (arg) (list "-r" arg)) marked-list)= )) (let* ((root (vc-hg-root default-directory)) - (buffer (format "*vc-hg : %s*" (expand-file-name root))) - ;; Disable pager. + (buffer (format "*vc-hg : %s*" (expand-file-name root))) + ;; Disable pager. (process-environment (cons "HGPLAIN=3D1" process-environment= )) - (hg-program vc-hg-program) - args) - ;; If necessary, prompt for the exact command. + (hg-program vc-hg-program) + args) + ;; If necessary, prompt for the exact command. ;; TODO if pushing, prompt if no default push location - cf bzr. - (when prompt - (setq args (split-string - (read-shell-command + (when prompt + (setq args (split-string + (read-shell-command (format "Hg %s command: " command) (format "%s %s" hg-program command) 'vc-hg-history) - " " t)) - (setq hg-program (car args) - command (cadr args) - args (cddr args))) - (apply 'vc-do-async-command buffer root hg-program command args) + " " t)) + (setq hg-program (car args) + command (cadr args) + args (cddr args))) + (apply 'vc-do-async-command buffer root hg-program command args) (with-current-buffer buffer (vc-run-delayed (dolist (cmd post-processing) @@ -1458,7 +1501,7 @@ commands, which only operated on marked files." (list compile-command nil (lambda (_name-of-mode) buffer) nil)))) - (vc-set-async-update buffer))))) + (vc-set-async-update buffer))))) (defun vc-hg-pull (prompt) "Issue a Mercurial pull command. @@ -1494,7 +1537,7 @@ call \"hg push -r REVS\" to push the specified revis= ions REVS." "Prompt for revision and merge it into working directory. This runs the command \"hg merge\"." (let* ((root (vc-hg-root default-directory)) - (buffer (format "*vc-hg : %s*" (expand-file-name root))) + (buffer (format "*vc-hg : %s*" (expand-file-name root))) ;; Disable pager. (process-environment (cons "HGPLAIN=3D1" process-environment)) (branch (vc-read-revision "Revision to merge: "))) @@ -1522,6 +1565,24 @@ This function differs from vc-do-command in that it= invokes (defun vc-hg-root (file) (vc-find-root file ".hg")) +(defvar vc-hg--py-regexp-special-chars + (mapcar + (function + (lambda (ch) + (cons ch (concat "\\" (char-to-string ch))))) + (append "()[]{}?*+-|^$\\.&~# \t\n\r\v\f" nil)) + "Characters that have special meaning in Python regular expressions.") + +(defun vc-hg--py-regexp-quote (string) + "Return a Python regexp string which matches exactly STRING and nothing= else. +Ported from Python v3.7" + (mapconcat + (function + (lambda (ch) + (or (cdr (assq ch vc-hg--py-regexp-special-chars)) + (char-to-string ch)))) + string "")) + (provide 'vc-hg) ;;; vc-hg.el ends here =2D- 2.7.4 --------------731B6E72D1AAA2423C792EAD--