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: Mon, 29 Aug 2016 09:17:06 -0400 Message-ID: References: <031d3e59-eaa3-df7a-492d-2a2d3c726094@gmail.com> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: blaine.gmane.org 1472547299 30424 195.159.176.226 (30 Aug 2016 08:54:59 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Tue, 30 Aug 2016 08:54:59 +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 Tue Aug 30 10:54:55 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 1beeoo-0007R1-BX for ged-emacs-devel@m.gmane.org; Tue, 30 Aug 2016 10:54:54 +0200 Original-Received: from localhost ([::1]:47846 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1beeop-0006bU-8e for ged-emacs-devel@m.gmane.org; Tue, 30 Aug 2016 04:54:55 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:53222) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1beelT-0003Ep-Ct for emacs-devel@gnu.org; Tue, 30 Aug 2016 04:51:29 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1beelM-0000on-8n for emacs-devel@gnu.org; Tue, 30 Aug 2016 04:51:26 -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 1beelL-0000oB-Ug for emacs-devel@gnu.org; Tue, 30 Aug 2016 04:51:20 -0400 Original-Received: from list by blaine.gmane.org with local (Exim 4.84_2) (envelope-from ) id 1beMR7-0005nT-S3 for emacs-devel@gnu.org; Mon, 29 Aug 2016 15:17:13 +0200 X-Injected-Via-Gmane: http://gmane.org/ Original-Lines: 127 Original-X-Complaints-To: usenet@blaine.gmane.org Cancel-Lock: sha1:zlNHV1E1sIbrmBKkl9g7BQQ6/5Y= 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:206921 Archived-At: >> The patch below is supposed to change Emacs such that if the file's >> timestamp has changed, but the contents is still the same, it doesn't >> prompt the user about a supersession-threat. >> Any objection? > This sounds like a neat feature! Are you sure you want (point-min) and > (point-max) rather than 1 and (buffer-size), though? I hate this assumption that point-min is 1 (so much so that my own local Emacs has point-min set to 12345678). I dreamed of changing this long-standing wart so that point-min starts at 0 but it would require changes in the redisplay code which I was not able to figure out. [ For the curious, the error of using 1 became blindly obvious when I did some work on src/intervals.c where we have things like interval_start_pos (that's right: 15 lines to decide if it starts with 0 or with 1). ] > Also, maybe this should be predicated on a test for small-enough files? > For large-ish files, it could make things slow. Presumably, this code is not run often and is normally followed by a prompt to the user, so its acceptable time scale is fairly large. If we want to speed it up, I think a more promising approach would be for "visited-modtime" to keep not just the modtime but also the file size, so we would only perform the (potentially slow) insert-file-contents with the new file has the same size as the old. Michael added: > Same concern here, for remote files. For large remote files I would > prefer a cksum call, if possible. But maybe we shall profile this, first. Of course we can't cksum the buffer without first encoding it. Also, this would require a cksum on files. Is there a reliably-available cksum operation we could run on files? Stefan PS: I just noticed a problem with the patch. I need to set coding-system-for-read around the insert-file-contents call, otherwise we might fail to notice when the only change to the file is that it uses another coding system. >> diff --git a/lisp/userlock.el b/lisp/userlock.el >> index a0c55fd..9b45ef4 100644 >> --- a/lisp/userlock.el >> +++ b/lisp/userlock.el >> @@ -97,6 +97,20 @@ ask-user-about-lock-help >> >> (define-error 'file-supersession nil 'file-error) >> >> +(defun userlock--check-content-unchanged (fn) >> + (save-restriction >> + (widen) >> + (let ((buf (current-buffer)) >> + (start (point-min)) >> + (end (point-max))) >> + (when (with-temp-buffer >> + (insert-file-contents fn) >> + (= 0 (compare-buffer-substrings >> + buf start end >> + (current-buffer) (point-min) (point-max)))) >> + (set-visited-file-modtime) >> + 'unchanged)))) >> + >> ;;;###autoload >> (defun ask-user-about-supersession-threat (fn) >> "Ask a user who is about to modify an obsolete buffer what to do. >> @@ -106,30 +120,30 @@ ask-user-about-supersession-threat >> >> You can rewrite this to use any criterion you like to choose which one to do. >> The buffer in question is current when this function is called." >> - (discard-input) >> - (save-window-excursion >> - (let ((prompt >> - (format "%s changed on disk; \ >> + (unless (userlock--check-content-unchanged fn) >> + (discard-input) >> + (save-window-excursion >> + (let ((prompt >> + (format "%s changed on disk; \ >> really edit the buffer? (y, n, r or C-h) " >> - (file-name-nondirectory fn))) >> - (choices '(?y ?n ?r ?? ?\C-h)) >> - answer) >> - (while (null answer) >> - (setq answer (read-char-choice prompt choices)) >> - (cond ((memq answer '(?? ?\C-h)) >> - (ask-user-about-supersession-help) >> - (setq answer nil)) >> - ((eq answer ?r) >> - ;; Ask for confirmation if buffer modified >> - (revert-buffer nil (not (buffer-modified-p))) >> - (signal 'file-supersession >> - (list "File reverted" fn))) >> - ((eq answer ?n) >> - (signal 'file-supersession >> - (list "File changed on disk" fn))))) >> - (message >> - "File on disk now will become a backup file if you save these changes.") >> - (setq buffer-backed-up nil)))) >> + (file-name-nondirectory fn)))) >> + (while >> + (let ((answer (read-char-choice prompt '(?y ?n ?r ?? ?\C-h)))) >> + (cond ((memq answer '(?? ?\C-h)) >> + (ask-user-about-supersession-help) >> + 'repeat) >> + ((eq answer ?r) >> + ;; Ask for confirmation if buffer modified >> + (revert-buffer nil (not (buffer-modified-p))) >> + (signal 'file-supersession >> + (list "File reverted" fn))) >> + ((eq answer ?n) >> + (signal 'file-supersession >> + (list "File changed on disk" fn))) >> + (t (null answer))))) >> + (message >> + "File on disk now will become a backup file if you save these changes.") >> + (setq buffer-backed-up nil))))) >> >> (defun ask-user-about-supersession-help () >> (with-output-to-temp-buffer "*Help*" >> >>