From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.devel Subject: Re: Don't complain about changed file when it hasn't changed Date: Fri, 02 Sep 2016 11:22:15 -0400 Message-ID: References: <83oa4bbq5b.fsf@gnu.org> <83a8funuqw.fsf@gnu.org> <83twe2mdpu.fsf@gnu.org> <83h9a2mabl.fsf@gnu.org> <83k2evg26c.fsf@gnu.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: blaine.gmane.org 1472829622 6514 195.159.176.226 (2 Sep 2016 15:20:22 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Fri, 2 Sep 2016 15:20:22 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.1.50 (gnu/linux) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Fri Sep 02 17:20:15 2016 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bfqGL-0000qA-K5 for ged-emacs-devel@m.gmane.org; Fri, 02 Sep 2016 17:20:13 +0200 Original-Received: from localhost ([::1]:42665 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bfqGJ-0003z9-Da for ged-emacs-devel@m.gmane.org; Fri, 02 Sep 2016 11:20:11 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:38655) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bfqFj-0003ys-VQ for emacs-devel@gnu.org; Fri, 02 Sep 2016 11:19:37 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bfqFf-0001sj-Mo for emacs-devel@gnu.org; Fri, 02 Sep 2016 11:19:34 -0400 Original-Received: from [195.159.176.226] (port=34714 helo=blaine.gmane.org) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bfqFf-0001rv-FZ for emacs-devel@gnu.org; Fri, 02 Sep 2016 11:19:31 -0400 Original-Received: from list by blaine.gmane.org with local (Exim 4.84_2) (envelope-from ) id 1bfqFR-00046i-2N for emacs-devel@gnu.org; Fri, 02 Sep 2016 17:19:17 +0200 X-Injected-Via-Gmane: http://gmane.org/ Original-Lines: 101 Original-X-Complaints-To: usenet@blaine.gmane.org Cancel-Lock: sha1:elJpMtc55DsNlAjMr8JEgYTbCc0= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 195.159.176.226 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:207133 Archived-At: > My preference would be to have the test in the caller, because I doubt > that anyone who replaces that function would want to lose the test. > But that preference is not very strong. How 'bout the patch below, then, Stefan diff --git a/doc/lispref/buffers.texi b/doc/lispref/buffers.texi index 740d7cf..e4ef4d5 100644 --- a/doc/lispref/buffers.texi +++ b/doc/lispref/buffers.texi @@ -669,8 +669,9 @@ Modification Time This function is used to ask a user how to proceed after an attempt to modify an buffer visiting file @var{filename} when the file is newer than the buffer text. Emacs detects this because the modification -time of the file on disk is newer than the last save-time of the -buffer. This means some other program has probably altered the file. +time of the file on disk is newer than the last save-time and its contents +have changed. +This means some other program has probably altered the file. @kindex file-supersession Depending on the user's answer, the function may return normally, in diff --git a/etc/NEWS b/etc/NEWS index 1290fa4..cdabeda 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -213,6 +213,10 @@ In modes where form feed was treated as a whitespace character, It now deletes whitespace after the last form feed thus behaving the same as in modes where the character is not whitespace. +** No more prompt about changed file when the file's content is unchanged. +Instead of only checking the modification time, Emacs now also checks +the file's actual content before prompting the user. + * Changes in Specialized Modes and Packages in Emacs 25.2 diff --git a/lisp/userlock.el b/lisp/userlock.el index a0c55fd..1cfc3b9 100644 --- a/lisp/userlock.el +++ b/lisp/userlock.el @@ -97,6 +97,41 @@ ask-user-about-lock-help (define-error 'file-supersession nil 'file-error) +(defun userlock--check-content-unchanged (fn) + (with-demoted-errors "Unchanged content check: %S" + ;; Even tho we receive `fn', we know that `fn' refers to the current + ;; buffer's file. + (cl-assert (equal fn (expand-file-name buffer-file-truename))) + ;; Note: rather than read the file and compare to the buffer, we could save + ;; the buffer and compare to the file, but for encrypted data this + ;; wouldn't work well (and would risk exposing the data). + (save-restriction + (widen) + (let ((buf (current-buffer)) + (cs buffer-file-coding-system) + (start (point-min)) + (end (point-max))) + ;; FIXME: To avoid a slow `insert-file-contents' on large or + ;; remote files, it'd be good to include file size in the + ;; "visited-modtime" check. + (when (with-temp-buffer + (let ((coding-system-for-read cs) + (non-essential t)) + (insert-file-contents fn)) + (when (= (buffer-size) (- end start)) ;Minor optimization. + (= 0 (let ((case-fold-search nil)) + (compare-buffer-substrings + buf start end + (current-buffer) (point-min) (point-max)))))) + (set-visited-file-modtime) + 'unchanged))))) + +;;;###autoload +(defun userlock--ask-user-about-supersession-threat (fn) + ;; Called from filelock.c. + (unless (userlock--check-content-unchanged fn) + (ask-user-about-supersession-threat fn))) + ;;;###autoload (defun ask-user-about-supersession-threat (fn) "Ask a user who is about to modify an obsolete buffer what to do. diff --git a/src/filelock.c b/src/filelock.c index 2f92e0f..bde34e2 100644 --- a/src/filelock.c +++ b/src/filelock.c @@ -684,7 +684,7 @@ lock_file (Lisp_Object fn) if (!NILP (subject_buf) && NILP (Fverify_visited_file_modtime (subject_buf)) && !NILP (Ffile_exists_p (fn))) - call1 (intern ("ask-user-about-supersession-threat"), fn); + call1 (intern ("userlock--ask-user-about-supersession-threat"), fn); }