* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory @ 2022-10-31 8:54 Thierry Volpiatto 2022-10-31 13:01 ` Eli Zaretskii 0 siblings, 1 reply; 17+ messages in thread From: Thierry Volpiatto @ 2022-10-31 8:54 UTC (permalink / raw) To: 58919 This is a followup of this report on reddit: https://www.reddit.com/r/emacs/comments/yha104/merging_directories_in_dired_am_i_doing_it_wrong/ When using dired-copy to copy a directory to another directory containing a directory with the same name overwriting fails. e.g. copy ~/tmp/test/foo/ to ~/tmp/test1/ fails when test1 contain foo/ The bug is IMHO in copy-directory 3th clause of this cond: (cond ((not (directory-name-p newname)) ;; If NEWNAME is not a directory name, create it; ;; that is where we will copy the files of DIRECTORY. (make-directory newname parents)) ;; NEWNAME is a directory name. If COPY-CONTENTS is non-nil, ;; create NEWNAME if it is not already a directory; ;; otherwise, create NEWNAME/[DIRECTORY-BASENAME]. ((if copy-contents (or parents (not (file-directory-p newname))) (setq newname (concat newname (file-name-nondirectory directory)))) (make-directory (directory-file-name newname) parents)) (t (setq follow t))) This change was introduced here: commit 047f02f00f602b9aef63ae8938e12f3f0ab481eb Author: Paul Eggert <eggert@cs.ucla.edu> Date: Wed Sep 20 11:49:12 2017 -0700 Fix new copy-directory bug with empty dirs Problem reported by Afdam Plaice (Bug#28520) and by Eli Zaretskii (Bug#28483#34). This is another bug that I introduced in my recent copy-directory changes. * lisp/files.el (copy-directory): Work with empty subdirectories, too. * test/lisp/files-tests.el (files-tests--copy-directory): Test for this bug. Reverting this change fix the bug. Using this should also fix the bug (based on my 2012 changes), not sure though if it fix the bug described in the above commit. (cond ((not (directory-name-p newname)) ;; If NEWNAME is not a directory name, create it; ;; that is where we will copy the files of DIRECTORY. (make-directory newname parents)) ;; NEWNAME is a directory name. If COPY-CONTENTS is non-nil, ;; create NEWNAME if it is not already a directory; ;; otherwise, create NEWNAME/[DIRECTORY-BASENAME]. ((and copy-contents (or parents (not (file-directory-p newname)))) (make-directory (directory-file-name newname) parents)) ((not copy-contents) (setq newname (concat newname (file-name-nondirectory directory))) (and (file-exists-p newname) (not (file-directory-p newname)) (error "Cannot overwrite non-directory %s with a directory" newname)) (make-directory newname t)) (t (setq follow t))) It also make readable the clauses handling copy-contents... In GNU Emacs 28.2 (build 1, x86_64-pc-linux-gnu, Motif Version 2.3.8, cairo version 1.16.0) of 2022-09-12 built on IPad-S340 Windowing system distributor 'The X.Org Foundation', version 11.0.12013000 System Description: Linux Mint 20.3 Configured using: 'configure CFLAGS=-O8 --with-mailutils --with-cairo --without-dbus --without-gconf --without-gsettings --with-x-toolkit=motif' Configured features: ACL CAIRO FREETYPE GIF GLIB GMP GNUTLS GPM HARFBUZZ JPEG JSON LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND THREADS TIFF TOOLKIT_SCROLL_BARS X11 XDBE XIM XPM MOTIF ZLIB Important settings: value of $LANG: fr_FR.UTF-8 locale-coding-system: utf-8-unix Major mode: ƐĽ Minor modes in effect: bug-reference-prog-mode: t global-undo-tree-mode: t undo-tree-mode: t psession-mode: t psession-savehist-mode: t global-git-gutter-mode: t git-gutter-mode: t display-time-mode: t winner-mode: t helm-epa-mode: t helm-descbinds-mode: t helm-adaptive-mode: t helm-mode: t helm-minibuffer-history-mode: t helm-ff-icon-mode: t shell-dirtrack-mode: t helm-popup-tip-mode: t async-bytecomp-package-mode: t minibuffer-depth-indicate-mode: t override-global-mode: t tooltip-mode: t global-eldoc-mode: t eldoc-mode: t show-paren-mode: t mouse-wheel-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t column-number-mode: t line-number-mode: t auto-fill-function: do-auto-fill transient-mark-mode: t Load-path shadows: None found. Features: (shadow epa-mail face-remap emacsbug vc-annotate sort gnus-cite w3m-form w3m-symbol w3m doc-view jka-compr timezone w3m-hist w3m-fb bookmark-w3m w3m-ems w3m-favicon w3m-image tab-line w3m-proc w3m-util mm-archive qp smiley mail-extr addressbook-bookmark tv-mu4e-config mu4e-contrib eshell esh-cmd esh-ext esh-opt esh-proc esh-io esh-arg esh-module esh-groups esh-util mu4e-patch mu4e mu4e-org mu4e-main mu4e-view gnus-art mm-uu mml2015 mm-view mml-smime smime dig gnus-sum gnus-group gnus-undo gnus-start gnus-dbus gnus-cloud nnimap nnmail mail-source utf7 netrc nnoo gnus-spec gnus-int gnus-range gnus-win mu4e-headers mu4e-compose mu4e-draft mu4e-actions smtpmail sendmail mu4e-search mu4e-lists mu4e-bookmarks mu4e-mark mu4e-message shr kinsoku svg flow-fill hl-line mu4e-contacts mu4e-update mu4e-folders mu4e-server mu4e-context mu4e-obsolete mu4e-vars mu4e-helpers mu4e-config ido helm-firefox helm-dabbrev help-fns radix-tree debug cl-print cus-start helm-command helm-x-files helm-for-files dired-x image-file image-converter char-fold tramp-archive tramp-gvfs dbus bug-reference naquadah-theme view solar cal-dst holidays hol-loaddefs tv-utils osm dom yaml-mode undo-tree diff queue psession frameset log-view pcvs-util bash-completion cl-indent pcase ffap thingatpt autocrypt-message message rmc puny rfc822 mml mml-sec mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader autocrypt-gnus gnus nnheader gnus-util rmail rmail-loaddefs rfc2047 rfc2045 mail-utils mm-util mail-prsvr autocrypt-mu4e autocrypt ietf-drums config-w3m git-gutter mule-util appt diary-lib diary-loaddefs gud wdired dired-extension org-config ob-gnuplot org-crypt net-utils time winner autotest-mode autoconf-mode woman man ediff ediff-merg ediff-mult ediff-wind ediff-diff ediff-help ediff-init ediff-util init-helm helm-ls-git vc-git diff-mode vc vc-dispatcher helm-fd epa derived epg rfc6068 epg-config helm-epa helm-imenu imenu helm-elisp-package helm-find helm-org org ob ob-tangle ob-ref ob-lob ob-table ob-exp org-macro org-footnote org-src ob-comint org-pcomplete org-list org-faces org-entities noutline outline org-version ob-emacs-lisp ob-core ob-eval org-table oc-basic bibtex ol rx org-keys oc org-compat advice org-macs org-loaddefs cal-menu calendar cal-loaddefs helm-external isl helm-descbinds helm-wikipedia all-the-icons all-the-icons-faces data-material data-weathericons data-octicons data-fileicons data-faicons data-alltheicons wfnames cus-edit wid-edit helm-ipython helm-elisp helm-eval edebug backtrace find-func python tramp-sh popup helm-bookmark helm-net xml helm-info bookmark pp helm-adaptive helm-mode helm-misc helm-files image-dired image-mode exif filenotify tramp tramp-loaddefs trampver tramp-integration files-x tramp-compat shell pcomplete parse-time iso8601 time-date ls-lisp helm-buffers helm-occur helm-tags helm-locate helm-grep wgrep-helm wgrep grep compile text-property-search comint ring helm-regexp format-spec ansi-color helm-utils helm-help helm-types helm-extensions-autoloads helm-config helm-autoloads helm helm-global-bindings helm-easymenu helm-core async-bytecomp helm-source helm-multi-match helm-lib dired-async dired-aux dired dired-loaddefs async diminish cl-extra help-mode mb-depth server edmacro kmacro avoid cus-load use-package use-package-ensure use-package-delight use-package-diminish use-package-bind-key bind-key easy-mmode use-package-core finder-inf package browse-url url url-proxy url-privacy url-expand url-methods url-history url-cookie url-domsuf url-util mailcap url-handlers url-parse auth-source cl-seq eieio eieio-core cl-macs eieio-loaddefs password-cache json subr-x map url-vars seq byte-opt gv bytecomp byte-compile cconv cl-loaddefs cl-lib info w3m-load iso-transl tooltip eldoc paren electric uniquify ediff-hook vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe tabulated-list replace newcomment text-mode lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow isearch easymenu timer select scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors frame minibuffer cl-generic cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese composite emoji-zwj charscript charprop case-table epa-hook jka-cmpr-hook help simple abbrev obarray cl-preloaded nadvice button loaddefs faces cus-face macroexp files window text-properties overlay sha1 md5 base64 format env code-pages mule custom widget hashtable-print-readable backquote threads inotify lcms2 dynamic-setting font-render-setting cairo motif x-toolkit x multi-tty make-network-process emacs) Memory information: ((conses 16 824596 90080) (symbols 48 43448 5) (strings 32 266727 16954) (string-bytes 1 8033636) (vectors 16 86864) (vector-slots 8 1908060 113478) (floats 8 2769 951) (intervals 56 23817 13089) (buffers 992 107)) <#secure method=pgpmime mode=sign> -- Thierry ^ permalink raw reply [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-10-31 8:54 bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory Thierry Volpiatto @ 2022-10-31 13:01 ` Eli Zaretskii 2022-11-01 17:34 ` Thierry Volpiatto 2022-11-01 18:04 ` Paul Eggert 0 siblings, 2 replies; 17+ messages in thread From: Eli Zaretskii @ 2022-10-31 13:01 UTC (permalink / raw) To: Thierry Volpiatto, Paul Eggert; +Cc: 58919 merge 58919 58918 thanks > From: Thierry Volpiatto <thievol@posteo.net> > Date: Mon, 31 Oct 2022 08:54:28 +0000 > > > This is a followup of this report on reddit: > https://www.reddit.com/r/emacs/comments/yha104/merging_directories_in_dired_am_i_doing_it_wrong/ Which was already reported as bug#58918... > When using dired-copy to copy a directory to another directory > containing a directory with the same name overwriting fails. > e.g. copy ~/tmp/test/foo/ to ~/tmp/test1/ fails when test1 contain foo/ > > The bug is IMHO in copy-directory 3th clause of this cond: > > (cond ((not (directory-name-p newname)) > ;; If NEWNAME is not a directory name, create it; > ;; that is where we will copy the files of DIRECTORY. > (make-directory newname parents)) > ;; NEWNAME is a directory name. If COPY-CONTENTS is non-nil, > ;; create NEWNAME if it is not already a directory; > ;; otherwise, create NEWNAME/[DIRECTORY-BASENAME]. > ((if copy-contents > (or parents (not (file-directory-p newname))) > (setq newname (concat newname > (file-name-nondirectory directory)))) > (make-directory (directory-file-name newname) parents)) > (t (setq follow t))) > > This change was introduced here: > > commit 047f02f00f602b9aef63ae8938e12f3f0ab481eb > Author: Paul Eggert <eggert@cs.ucla.edu> > Date: Wed Sep 20 11:49:12 2017 -0700 > > Fix new copy-directory bug with empty dirs > > Problem reported by Afdam Plaice (Bug#28520) and by Eli Zaretskii > (Bug#28483#34). This is another bug that I introduced in my > recent copy-directory changes. > * lisp/files.el (copy-directory): Work with empty subdirectories, too. > * test/lisp/files-tests.el (files-tests--copy-directory): > Test for this bug. > > Reverting this change fix the bug. Paul, could you please look into this? I think this also affects bug#58721. Thanks. ^ permalink raw reply [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-10-31 13:01 ` Eli Zaretskii @ 2022-11-01 17:34 ` Thierry Volpiatto 2022-11-01 18:04 ` Paul Eggert 1 sibling, 0 replies; 17+ messages in thread From: Thierry Volpiatto @ 2022-11-01 17:34 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 58919, Paul Eggert [-- Attachment #1: Type: text/plain, Size: 2276 bytes --] For people using dired-async.el (from emacs-async package) here how to fix this bug temporarily until fixed: https://github.com/jwiegley/emacs-async/issues/158 Eli Zaretskii <eliz@gnu.org> writes: > merge 58919 58918 > thanks > >> From: Thierry Volpiatto <thievol@posteo.net> >> Date: Mon, 31 Oct 2022 08:54:28 +0000 >> >> >> This is a followup of this report on reddit: >> https://www.reddit.com/r/emacs/comments/yha104/merging_directories_in_dired_am_i_doing_it_wrong/ > > Which was already reported as bug#58918... > >> When using dired-copy to copy a directory to another directory >> containing a directory with the same name overwriting fails. >> e.g. copy ~/tmp/test/foo/ to ~/tmp/test1/ fails when test1 contain foo/ >> >> The bug is IMHO in copy-directory 3th clause of this cond: >> >> (cond ((not (directory-name-p newname)) >> ;; If NEWNAME is not a directory name, create it; >> ;; that is where we will copy the files of DIRECTORY. >> (make-directory newname parents)) >> ;; NEWNAME is a directory name. If COPY-CONTENTS is non-nil, >> ;; create NEWNAME if it is not already a directory; >> ;; otherwise, create NEWNAME/[DIRECTORY-BASENAME]. >> ((if copy-contents >> (or parents (not (file-directory-p newname))) >> (setq newname (concat newname >> (file-name-nondirectory directory)))) >> (make-directory (directory-file-name newname) parents)) >> (t (setq follow t))) >> >> This change was introduced here: >> >> commit 047f02f00f602b9aef63ae8938e12f3f0ab481eb >> Author: Paul Eggert <eggert@cs.ucla.edu> >> Date: Wed Sep 20 11:49:12 2017 -0700 >> >> Fix new copy-directory bug with empty dirs >> >> Problem reported by Afdam Plaice (Bug#28520) and by Eli Zaretskii >> (Bug#28483#34). This is another bug that I introduced in my >> recent copy-directory changes. >> * lisp/files.el (copy-directory): Work with empty subdirectories, too. >> * test/lisp/files-tests.el (files-tests--copy-directory): >> Test for this bug. >> >> Reverting this change fix the bug. > > Paul, could you please look into this? > > I think this also affects bug#58721. > > Thanks. -- Thierry [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 686 bytes --] ^ permalink raw reply [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-10-31 13:01 ` Eli Zaretskii 2022-11-01 17:34 ` Thierry Volpiatto @ 2022-11-01 18:04 ` Paul Eggert 2022-11-01 18:09 ` Eli Zaretskii 2022-11-01 19:21 ` Michael Albinus 1 sibling, 2 replies; 17+ messages in thread From: Paul Eggert @ 2022-11-01 18:04 UTC (permalink / raw) To: Eli Zaretskii, Thierry Volpiatto; +Cc: 58919 On 2022-10-31 06:01, Eli Zaretskii wrote: > Paul, could you please look into this? I am taking a look. Sigh, what a mess this code is; even the proposed fix has a TOCTOU bug. The simplest fix I can see is to enhance make-directory so that it returns t if the directory already existed and PARENTS was given, nil on any other successful return. This would require changes to Tramp to avoid races there. I plan to post a proposed patch for comment. ^ permalink raw reply [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-11-01 18:04 ` Paul Eggert @ 2022-11-01 18:09 ` Eli Zaretskii 2022-11-01 19:21 ` Michael Albinus 1 sibling, 0 replies; 17+ messages in thread From: Eli Zaretskii @ 2022-11-01 18:09 UTC (permalink / raw) To: Paul Eggert; +Cc: thievol, 58919 > Date: Tue, 1 Nov 2022 11:04:22 -0700 > Cc: 58919@debbugs.gnu.org > From: Paul Eggert <eggert@cs.ucla.edu> > > The simplest fix I can see is to enhance make-directory so that it > returns t if the directory already existed and PARENTS was given, nil on > any other successful return. This would require changes to Tramp to > avoid races there. I plan to post a proposed patch for comment. SGTM: make-directory didn't return any meaningful value until now, so this change should be safe, I think. Thanks. ^ permalink raw reply [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-11-01 18:04 ` Paul Eggert 2022-11-01 18:09 ` Eli Zaretskii @ 2022-11-01 19:21 ` Michael Albinus 2022-12-11 10:46 ` Eli Zaretskii 1 sibling, 1 reply; 17+ messages in thread From: Michael Albinus @ 2022-11-01 19:21 UTC (permalink / raw) To: Paul Eggert; +Cc: Thierry Volpiatto, 58919, Eli Zaretskii Paul Eggert <eggert@cs.ucla.edu> writes: Hi Paul, > The simplest fix I can see is to enhance make-directory so that it > returns t if the directory already existed and PARENTS was given, nil > on any other successful return. This would require changes to Tramp to > avoid races there. I plan to post a proposed patch for comment. To make it more fun, there are several Tramp implementations of that function, and also other ones. Xref, running in the lisp/ tree for "defun.*make-directory", returns --8<---------------cut here---------------start------------->8--- lisp/dired.el 1911: (defun dired--make-directory-clickable () lisp/files.el 6203: (defun make-directory (dir &optional parents) lisp/gnus/gnus-group.el 3120: (defun gnus-group-make-directory-group (dir) lisp/gnus/gnus-util.el 726: (defun gnus-make-directory (directory) lisp/htmlfontify.el 1844: (defun hfy-make-directory (dir) lisp/ido.el 2994: (defun ido-make-directory (&optional dir) lisp/net/ange-ftp.el 4125: (defun ange-ftp-make-directory (dir &optional parents) 4530: (defun ange-ftp-real-make-directory (&rest args) lisp/net/tramp-adb.el 411: (defun tramp-adb-handle-make-directory (dir &optional parents) lisp/net/tramp-crypt.el 800: (defun tramp-crypt-handle-make-directory (dir &optional parents) lisp/net/tramp-fuse.el 128: (defun tramp-fuse-handle-make-directory (dir &optional parents) lisp/net/tramp-gvfs.el 1560: (defun tramp-gvfs-handle-make-directory (dir &optional parents) lisp/net/tramp-sh.el 2559: (defun tramp-sh-handle-make-directory (dir &optional parents) lisp/net/tramp-smb.el 1172: (defun tramp-smb-handle-make-directory (dir &optional parents) 1192: (defun tramp-smb-handle-make-directory-internal (directory) lisp/net/tramp-sudoedit.el 626: (defun tramp-sudoedit-handle-make-directory (dir &optional parents) lisp/obsolete/autoload.el 725: (defun make-directory-autoloads (dir output-file) lisp/url/url-dav.el 761: (defun url-dav-make-directory (url &optional _parents) --8<---------------cut here---------------end--------------->8--- Best regards, Michael. ^ permalink raw reply [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-11-01 19:21 ` Michael Albinus @ 2022-12-11 10:46 ` Eli Zaretskii 2022-12-16 23:22 ` Paul Eggert 0 siblings, 1 reply; 17+ messages in thread From: Eli Zaretskii @ 2022-12-11 10:46 UTC (permalink / raw) To: Michael Albinus; +Cc: thievol, 58919, eggert Ping! Paul, did you have an opportunity to come up with the patch you mentioned in this discussion? I'd like to solve this bug for Emacs 29, please. > From: Michael Albinus <michael.albinus@gmx.de> > Date: Tue, 01 Nov 2022 20:21:32 +0100 > Cc: Thierry Volpiatto <thievol@posteo.net>, 58919@debbugs.gnu.org, > Eli Zaretskii <eliz@gnu.org> > > Paul Eggert <eggert@cs.ucla.edu> writes: > > Hi Paul, > > > The simplest fix I can see is to enhance make-directory so that it > > returns t if the directory already existed and PARENTS was given, nil > > on any other successful return. This would require changes to Tramp to > > avoid races there. I plan to post a proposed patch for comment. > > To make it more fun, there are several Tramp implementations of that > function, and also other ones. Xref, running in the lisp/ tree for > "defun.*make-directory", returns > > --8<---------------cut here---------------start------------->8--- > lisp/dired.el > 1911: (defun dired--make-directory-clickable () > lisp/files.el > 6203: (defun make-directory (dir &optional parents) > lisp/gnus/gnus-group.el > 3120: (defun gnus-group-make-directory-group (dir) > lisp/gnus/gnus-util.el > 726: (defun gnus-make-directory (directory) > lisp/htmlfontify.el > 1844: (defun hfy-make-directory (dir) > lisp/ido.el > 2994: (defun ido-make-directory (&optional dir) > lisp/net/ange-ftp.el > 4125: (defun ange-ftp-make-directory (dir &optional parents) > 4530: (defun ange-ftp-real-make-directory (&rest args) > lisp/net/tramp-adb.el > 411: (defun tramp-adb-handle-make-directory (dir &optional parents) > lisp/net/tramp-crypt.el > 800: (defun tramp-crypt-handle-make-directory (dir &optional parents) > lisp/net/tramp-fuse.el > 128: (defun tramp-fuse-handle-make-directory (dir &optional parents) > lisp/net/tramp-gvfs.el > 1560: (defun tramp-gvfs-handle-make-directory (dir &optional parents) > lisp/net/tramp-sh.el > 2559: (defun tramp-sh-handle-make-directory (dir &optional parents) > lisp/net/tramp-smb.el > 1172: (defun tramp-smb-handle-make-directory (dir &optional parents) > 1192: (defun tramp-smb-handle-make-directory-internal (directory) > lisp/net/tramp-sudoedit.el > 626: (defun tramp-sudoedit-handle-make-directory (dir &optional parents) > lisp/obsolete/autoload.el > 725: (defun make-directory-autoloads (dir output-file) > lisp/url/url-dav.el > 761: (defun url-dav-make-directory (url &optional _parents) > --8<---------------cut here---------------end--------------->8--- > > Best regards, Michael. > > > > ^ permalink raw reply [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-12-11 10:46 ` Eli Zaretskii @ 2022-12-16 23:22 ` Paul Eggert 2022-12-17 8:04 ` Eli Zaretskii 0 siblings, 1 reply; 17+ messages in thread From: Paul Eggert @ 2022-12-16 23:22 UTC (permalink / raw) To: Eli Zaretskii, Michael Albinus; +Cc: thievol, 58919 [-- Attachment #1: Type: text/plain, Size: 630 bytes --] On 12/11/22 02:46, Eli Zaretskii wrote: > Paul, did you have an opportunity to come up with the patch you > mentioned in this discussion? I'd like to solve this bug for Emacs > 29, please. I hacked on it for a bit and came up with the attached proposed patches to the emacs-29 branch. I have not installed them. These patches address the issues raised by Michael by passing only single arguments to make-directory handlers. That way, we don't need to worry about whether the handlers follow the new convention. At our leisure, perhaps in Emacs 30, we can upgrade the make-directory handlers to support the new convention. [-- Attachment #2: 0001-Use-make-directory-handlers-uniformly.patch --] [-- Type: text/x-patch, Size: 6565 bytes --] From bfbb463c6e1b74c96211e454c80d8588f187dcfb Mon Sep 17 00:00:00 2001 From: Paul Eggert <eggert@cs.ucla.edu> Date: Fri, 16 Dec 2022 14:55:47 -0800 Subject: [PATCH 1/3] Use make-directory handlers uniformly Formerly, the code supported both make-directory and make-directory-internal handlers. This led to confusion and meant than in a few cases (nnmaildir, ido) remote directories could not be used in some cases. Fix this by using only make-directory handlers. Perhaps there used to be a reason for why there were both make-directory and make-directory-internal handlers, but whatever that reason was, it seems to have vanished even before now. There is no longer any need for make-directory-internal handlers, as the few remaining callers that use make-directory-internal do so only when there are no handlers. However, this change keeps the existing make-directory-internal handlers for now, in case this code is ever used in older Emacs versions that still call those handlers. * lisp/gnus/nnmaildir.el (nnmaildir--mkdir): * lisp/ido.el (ido-file-internal): * lisp/net/tramp-smb.el (tramp-smb-handle-make-directory): Use make-directory, not make-directory-internal. * lisp/net/tramp-smb.el (tramp-smb-handle-make-directory-internal): Now obsolete. * src/fileio.c (Fmake_directory_internal): Do not look for or use a make-directory-internal handler. * test/lisp/files-tests.el: (files-tests-file-name-non-special-make-directory-internal): Remove, as this test incorrectly assumes that make-directory-internal must support handlers. --- doc/lispref/files.texi | 2 -- etc/NEWS | 4 ++++ lisp/gnus/nnmaildir.el | 2 +- lisp/ido.el | 2 +- lisp/net/tramp-smb.el | 3 ++- src/fileio.c | 5 ----- test/lisp/files-tests.el | 11 ----------- 7 files changed, 8 insertions(+), 21 deletions(-) diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 4b45d89f9d0..5bcbac6ceb8 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -3378,7 +3378,6 @@ Magic File Names @code{load}, @code{lock-file}, @code{make-auto-save-file-name}, @code{make-directory}, -@code{make-directory-internal}, @code{make-lock-file-name}, @code{make-nearby-temp-file}, @code{make-process}, @@ -3440,7 +3439,6 @@ Magic File Names @code{load}, @code{lock-file}, @code{make-auto-save-file-name}, @code{make-direc@discretionary{}{}{}tory}, -@code{make-direc@discretionary{}{}{}tory-internal}, @code{make-lock-file-name}, @code{make-nearby-temp-file}, @code{make-process}, diff --git a/etc/NEWS b/etc/NEWS index 157fe98c983..dbf1642206b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -4477,6 +4477,10 @@ set is too big to transfer to Emacs every time a completion is needed. The table uses new 'external' completion style exclusively and cannot work with regular styles such as 'basic' or 'flex'. ++++ +** Magic file handlers for make-directory-internal are no longer needed. +Instead, Emacs uses the already-existing make-directory handlers. + \f * Changes in Emacs 29.1 on Non-Free Operating Systems diff --git a/lisp/gnus/nnmaildir.el b/lisp/gnus/nnmaildir.el index faa288934d1..3fb87f3a712 100644 --- a/lisp/gnus/nnmaildir.el +++ b/lisp/gnus/nnmaildir.el @@ -296,7 +296,7 @@ nnmaildir--unlink (if (file-attributes file) (delete-file file)))) (defun nnmaildir--mkdir (dir) (or (file-exists-p (file-name-as-directory dir)) - (make-directory-internal (directory-file-name dir)))) + (make-directory (directory-file-name dir)))) (defun nnmaildir--mkfile (file) (write-region "" nil file nil 'no-message)) (defun nnmaildir--delete-dir-files (dir ls) diff --git a/lisp/ido.el b/lisp/ido.el index 77e4dd447d8..92b4370cb45 100644 --- a/lisp/ido.el +++ b/lisp/ido.el @@ -2435,7 +2435,7 @@ ido-file-internal filename)) (ido-record-command method dirname) (ido-record-work-directory dirname) - (make-directory-internal dirname) + (make-directory dirname) (funcall method dirname)) (t ;; put make-directory command on history diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index c720b33b5f2..24fff9bb495 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -1186,12 +1186,13 @@ tramp-smb-handle-make-directory (make-directory ldir parents)) ;; Just do it. (when (file-directory-p ldir) - (make-directory-internal dir)) + (make-directory dir)) (unless (file-directory-p dir) (tramp-error v 'file-error "Couldn't make directory %s" dir))))) (defun tramp-smb-handle-make-directory-internal (directory) "Like `make-directory-internal' for Tramp files." + (declare (obsolete nil "29.1")) (setq directory (directory-file-name (expand-file-name directory))) (unless (file-name-absolute-p directory) (setq directory (expand-file-name directory default-directory))) diff --git a/src/fileio.c b/src/fileio.c index 92335b639cd..835c42cc0a4 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -2427,16 +2427,11 @@ DEFUN ("make-directory-internal", Fmake_directory_internal, (Lisp_Object directory) { const char *dir; - Lisp_Object handler; Lisp_Object encoded_dir; CHECK_STRING (directory); directory = Fexpand_file_name (directory, Qnil); - handler = Ffind_file_name_handler (directory, Qmake_directory_internal); - if (!NILP (handler)) - return call2 (handler, Qmake_directory_internal, directory); - encoded_dir = ENCODE_FILE (directory); dir = SSDATA (encoded_dir); diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el index 682b5cdb449..efafb5583ac 100644 --- a/test/lisp/files-tests.el +++ b/test/lisp/files-tests.el @@ -1038,17 +1038,6 @@ files-tests-file-name-non-special-make-directory (let ((default-directory nospecial-dir)) (should-error (make-directory "dir"))))) -(ert-deftest files-tests-file-name-non-special-make-directory-internal () - (files-tests--with-temp-non-special (tmpdir nospecial-dir t) - (let ((default-directory nospecial-dir)) - (make-directory-internal "dir") - (should (file-directory-p "dir")) - (delete-directory "dir"))) - (files-tests--with-temp-non-special-and-file-name-handler - (tmpdir nospecial-dir t) - (let ((default-directory nospecial-dir)) - (should-error (make-directory-internal "dir"))))) - (ert-deftest files-tests-file-name-non-special-make-nearby-temp-file () (let* ((default-directory (file-name-quote temporary-file-directory)) (near-tmpfile (make-nearby-temp-file "file"))) -- 2.38.1 [-- Attachment #3: 0002-make-directory-now-returns-t-if-dir-already-exists.patch --] [-- Type: text/x-patch, Size: 6734 bytes --] From b671e175372825c077ab4a1810e353845626c26a Mon Sep 17 00:00:00 2001 From: Paul Eggert <eggert@cs.ucla.edu> Date: Fri, 16 Dec 2022 14:55:48 -0800 Subject: [PATCH 2/3] make-directory now returns t if dir already exists This new feature will help fix a copy-directory bug (Bug#58919). Its implementation does not rely on make-directory handlers supporting the new feature, as it no longer uses a make-directory handler H in any way other than (funcall H DIR), thus using only the intersection of the old and new behavior for handlers. This will give us time to fix handlers at our leisure. * lisp/files.el (files--ensure-directory): New arg MKDIR. All uses changed. (files--ensure-directory, make-directory): Return non-nil if DIR is already a directory. All uses changed. * test/lisp/files-tests.el (files-tests-make-directory): Test new return-value convention. --- doc/lispref/files.texi | 3 +++ etc/NEWS | 5 ++++ lisp/files.el | 58 +++++++++++++++++++++------------------- test/lisp/files-tests.el | 6 ++--- 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 5bcbac6ceb8..29d9e514c72 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -3205,6 +3205,9 @@ Create/Delete Dirs @var{parents} is non-@code{nil}, as is always the case in an interactive call, that means to create the parent directories first, if they don't already exist. +As a function, @code{make-directory} returns non-@code{nil} if @var{dirname} +already exists as a directory and @var{parents} is non-@code{nil}, +and returns @code{nil} if it successfully created @var{dirname}. @code{mkdir} is an alias for this. @end deffn diff --git a/etc/NEWS b/etc/NEWS index dbf1642206b..d59d61a9d25 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -4481,6 +4481,11 @@ and cannot work with regular styles such as 'basic' or 'flex'. ** Magic file handlers for make-directory-internal are no longer needed. Instead, Emacs uses the already-existing make-directory handlers. ++++ +** (make-directory DIR t) returns non-nil if DIR already exists. +This can let a caller know whether it created DIR. Formerly, +make-directory's return value was unspecified. + \f * Changes in Emacs 29.1 on Non-Free Operating Systems diff --git a/lisp/files.el b/lisp/files.el index c74e7e808e4..235eacee704 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -6193,18 +6193,17 @@ rename-uniquely (rename-buffer (generate-new-buffer-name base-name)) (force-mode-line-update)))) -(defun files--ensure-directory (dir) - "Make directory DIR if it is not already a directory. Return nil." +(defun files--ensure-directory (mkdir dir) + "Use function MKDIR to make directory DIR if it is not already a directory. +Return non-nil if DIR is already a directory." (condition-case err - (make-directory-internal dir) + (funcall mkdir dir) (error - (unless (file-directory-p dir) - (signal (car err) (cdr err)))))) + (or (file-directory-p dir) + (signal (car err) (cdr err)))))) (defun make-directory (dir &optional parents) "Create the directory DIR and optionally any nonexistent parent dirs. -If DIR already exists as a directory, signal an error, unless -PARENTS is non-nil. Interactively, the default choice of directory to create is the current buffer's default directory. That is useful when you have @@ -6214,8 +6213,9 @@ make-directory non-nil, says whether to create parent directories that don't exist. Interactively, this happens by default. -If creating the directory or directories fail, an error will be -raised." +Return non-nil if PARENTS is non-nil and DIR already exists as a +directory, and nil if DIR did not already exist but was created. +Signal an error if unsuccessful." (interactive (list (read-file-name "Make directory: " default-directory default-directory nil nil) @@ -6223,25 +6223,27 @@ make-directory ;; If default-directory is a remote directory, ;; make sure we find its make-directory handler. (setq dir (expand-file-name dir)) - (let ((handler (find-file-name-handler dir 'make-directory))) - (if handler - (funcall handler 'make-directory dir parents) - (if (not parents) - (make-directory-internal dir) - (let ((dir (directory-file-name (expand-file-name dir))) - create-list parent) - (while (progn - (setq parent (directory-file-name - (file-name-directory dir))) - (condition-case () - (files--ensure-directory dir) - (file-missing - ;; Do not loop if root does not exist (Bug#2309). - (not (string= dir parent))))) - (setq create-list (cons dir create-list) - dir parent)) - (dolist (dir create-list) - (files--ensure-directory dir))))))) + (let ((mkdir (if-let ((handler (find-file-name-handler dir 'make-directory))) + #'(lambda (dir) (funcall handler 'make-directory dir)) + #'make-directory-internal))) + (if (not parents) + (funcall mkdir dir) + (let ((dir (directory-file-name (expand-file-name dir))) + already-dir create-list parent) + (while (progn + (setq parent (directory-file-name + (file-name-directory dir))) + (condition-case () + (ignore (setq already-dir + (files--ensure-directory mkdir dir))) + (error + ;; Do not loop if root does not exist (Bug#2309). + (not (string= dir parent))))) + (setq create-list (cons dir create-list) + dir parent)) + (dolist (dir create-list) + (setq already-dir (files--ensure-directory mkdir dir))) + already-dir)))) (defun make-empty-file (filename &optional parents) "Create an empty file FILENAME. diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el index efafb5583ac..b9fbeb8a4e0 100644 --- a/test/lisp/files-tests.el +++ b/test/lisp/files-tests.el @@ -1261,11 +1261,11 @@ files-tests-make-directory (a/b (concat dirname "a/b"))) (write-region "" nil file) (should-error (make-directory "/")) - (should-not (make-directory "/" t)) + (should (make-directory "/" t)) (should-error (make-directory dir)) - (should-not (make-directory dir t)) + (should (make-directory dir t)) (should-error (make-directory dirname)) - (should-not (make-directory dirname t)) + (should (make-directory dirname t)) (should-error (make-directory file)) (should-error (make-directory file t)) (should-not (make-directory subdir1)) -- 2.38.1 [-- Attachment #4: 0003-Fix-copy-directory-bug-when-dest-dir-exists.patch --] [-- Type: text/x-patch, Size: 3944 bytes --] From 5b6435e1e57ae0c20ce3078ac1fe97a7757c4ba7 Mon Sep 17 00:00:00 2001 From: Paul Eggert <eggert@penguin.cs.ucla.edu> Date: Fri, 16 Dec 2022 14:55:48 -0800 Subject: [PATCH 3/3] Fix copy-directory bug when dest dir exists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * lisp/files.el (copy-directory): Set ‘follow’ depending on whether we made the directory, not based on a guess that is sometimes wrong. When NEWNAME is a directory name and COPY-CONTENTS is nil, do not object merely because the adjusted NEWNAME is already a directory. (Bug#58919). * test/lisp/files-tests.el (files-tests-copy-directory): Test for the bug. --- lisp/files.el | 19 ++++++++++++------- test/lisp/files-tests.el | 9 ++++++++- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lisp/files.el b/lisp/files.el index 235eacee704..3cf7833ae02 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -6437,7 +6437,7 @@ copy-directory ;; copy-directory handler. (let ((handler (or (find-file-name-handler directory 'copy-directory) (find-file-name-handler newname 'copy-directory))) - (follow parents)) + follow) (if handler (funcall handler 'copy-directory directory newname keep-time parents copy-contents) @@ -6457,19 +6457,24 @@ copy-directory t) (make-symbolic-link target newname t))) ;; Else proceed to copy as a regular directory - (cond ((not (directory-name-p newname)) + ;; first by creating the destination directory if needed, + ;; preparing to follow any symlink to a directory we did not create. + (setq follow + (if (not (directory-name-p newname)) ;; If NEWNAME is not a directory name, create it; ;; that is where we will copy the files of DIRECTORY. - (make-directory newname parents)) + (make-directory newname parents) ;; NEWNAME is a directory name. If COPY-CONTENTS is non-nil, ;; create NEWNAME if it is not already a directory; ;; otherwise, create NEWNAME/[DIRECTORY-BASENAME]. - ((if copy-contents - (or parents (not (file-directory-p newname))) + (unless copy-contents (setq newname (concat newname (file-name-nondirectory directory)))) - (make-directory (directory-file-name newname) parents)) - (t (setq follow t))) + (condition-case err + (make-directory (directory-file-name newname) parents) + (error + (or (file-directory-p newname) + (signal (car err) (cdr err))))))) ;; Copy recursively. (dolist (file diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el index b9fbeb8a4e0..011bfa67cc2 100644 --- a/test/lisp/files-tests.el +++ b/test/lisp/files-tests.el @@ -1346,7 +1346,9 @@ files-tests-copy-directory (dest (concat dirname "dest/new/directory/")) (file (concat (file-name-as-directory source) "file")) (source2 (concat dirname "source2")) - (dest2 (concat dirname "dest/new2"))) + (dest2 (concat dirname "dest/new2")) + (source3 (concat dirname "source3/d")) + (dest3 (concat dirname "dest3/d"))) (make-directory source) (write-region "" nil file) (copy-directory source dest t t t) @@ -1354,6 +1356,11 @@ files-tests-copy-directory (make-directory (concat (file-name-as-directory source2) "a") t) (copy-directory source2 dest2) (should (file-directory-p (concat (file-name-as-directory dest2) "a"))) + (make-directory source3 t) + (write-region "x\n" nil (concat (file-name-as-directory source3) "file")) + (make-directory dest3 t) + (write-region "y\n" nil (concat (file-name-as-directory dest3) "file")) + (copy-directory source3 (file-name-directory dest3) t) (delete-directory dir 'recursive)))) (ert-deftest files-tests-abbreviate-file-name-homedir () -- 2.38.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-12-16 23:22 ` Paul Eggert @ 2022-12-17 8:04 ` Eli Zaretskii 2022-12-17 9:52 ` Michael Albinus 0 siblings, 1 reply; 17+ messages in thread From: Eli Zaretskii @ 2022-12-17 8:04 UTC (permalink / raw) To: Paul Eggert, michael.albinus; +Cc: thievol, 58919 > Date: Fri, 16 Dec 2022 15:22:16 -0800 > Cc: thievol@posteo.net, 58919@debbugs.gnu.org > From: Paul Eggert <eggert@cs.ucla.edu> > > On 12/11/22 02:46, Eli Zaretskii wrote: > > Paul, did you have an opportunity to come up with the patch you > > mentioned in this discussion? I'd like to solve this bug for Emacs > > 29, please. > > I hacked on it for a bit and came up with the attached proposed patches > to the emacs-29 branch. I have not installed them. > > These patches address the issues raised by Michael by passing only > single arguments to make-directory handlers. That way, we don't need to > worry about whether the handlers follow the new convention. At our > leisure, perhaps in Emacs 30, we can upgrade the make-directory handlers > to support the new convention. Thanks. Looks non-trivial, but I guess we cannot hope for a simpler fix. Michael, are you okay with this? do you see any problems, real or potential, that could endanger the release of Emacs 29? ^ permalink raw reply [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-12-17 8:04 ` Eli Zaretskii @ 2022-12-17 9:52 ` Michael Albinus 2022-12-17 10:40 ` Eli Zaretskii 2022-12-17 22:40 ` Paul Eggert 0 siblings, 2 replies; 17+ messages in thread From: Michael Albinus @ 2022-12-17 9:52 UTC (permalink / raw) To: Eli Zaretskii; +Cc: thievol, 58919, Paul Eggert Eli Zaretskii <eliz@gnu.org> writes: Hi Eli & Paul, >> These patches address the issues raised by Michael by passing only >> single arguments to make-directory handlers. That way, we don't need to >> worry about whether the handlers follow the new convention. At our >> leisure, perhaps in Emacs 30, we can upgrade the make-directory handlers >> to support the new convention. > > Michael, are you okay with this? do you see any problems, real or > potential, that could endanger the release of Emacs 29? I've reviewed them, and in general it looks OK. Needs some testing, of course. Since file name handlers still raise an error in case DIR exists and PARENTS is nil, we might see surprises in code assuming the new behavior. I guess I'll add a change in tramp-*-handle-make-directory like --8<---------------cut here---------------start------------->8--- (if (and (null parents) (file-exists-p dir)) (if (>= emacs-major-version 29) t (tramp-error v 'file-already-exists dir))) --8<---------------cut here---------------end--------------->8--- And, of course, the return value (nil or t) must be added. But this doesn't break compatibility, because until now no return value is specified. Similar changes to ange-ftp-make-directory. tramp-test13-make-directory of tramp-tests.el must be adapted as well, but this is minor. Will do. These changes must be applied anyway, for Tramp's compatibility over several Emacs versions. In short, I guess we could add the patch to the emacs-29 branch. Best regards, Michael. ^ permalink raw reply [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-12-17 9:52 ` Michael Albinus @ 2022-12-17 10:40 ` Eli Zaretskii 2022-12-17 22:40 ` Paul Eggert 1 sibling, 0 replies; 17+ messages in thread From: Eli Zaretskii @ 2022-12-17 10:40 UTC (permalink / raw) To: Michael Albinus; +Cc: thievol, 58919, eggert > From: Michael Albinus <michael.albinus@gmx.de> > Cc: Paul Eggert <eggert@cs.ucla.edu>, thievol@posteo.net, > 58919@debbugs.gnu.org > Date: Sat, 17 Dec 2022 10:52:25 +0100 > > In short, I guess we could add the patch to the emacs-29 branch. Thanks. Paul, please go ahead and install this on the emacs-29 branch at your earliest convenience. ^ permalink raw reply [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-12-17 9:52 ` Michael Albinus 2022-12-17 10:40 ` Eli Zaretskii @ 2022-12-17 22:40 ` Paul Eggert 2022-12-18 19:35 ` Michael Albinus 1 sibling, 1 reply; 17+ messages in thread From: Paul Eggert @ 2022-12-17 22:40 UTC (permalink / raw) To: Michael Albinus, Eli Zaretskii; +Cc: thievol, 58919-done [-- Attachment #1: Type: text/plain, Size: 2432 bytes --] On 12/17/22 01:52, Michael Albinus wrote: > Since file name handlers still raise an error in case DIR exists and > PARENTS is nil, we might see surprises in code assuming the new > behavior. I guess I'll add a change in tramp-*-handle-make-directory > like > > --8<---------------cut here---------------start------------->8--- > (if (and (null parents) (file-exists-p dir)) > (if (>= emacs-major-version 29) > t > (tramp-error v 'file-already-exists dir))) > --8<---------------cut here---------------end--------------->8--- That doesn't look right, as there is no change as to whether make-directory signals an error. Nor is there any change in behavior when PARENTS is nil. The only change in behavior is when PARENTS is non-nil and DIRECTORY already exists as a directory: in this case, Emacs 29 returns non-nil whereas earlier Emacs returns (undocumented) nil. So I think all that it would be nice to do is make sure the handlers ordinarily return nil, except that they return non-nil in the abovementioned special case. If a handler currently signals an error, it should continue to do so in the same way as it did before. Strictly speaking, modifying the handlers in this way won't affect whether they are compatible with Emacs 28- (since their return value is undocumented there) nor will it affect whether they work in Emacs 29 (since Emacs 29 ignores their return value). But it might affect whether the handlers will work with Emacs 30, which might start assuming the Emacs 29 API for make-directory handlers. Come to think of it, if an existing make-directory handler returns non-nil now (which it is allowed to in Emacs 28 as the return value is undocumented), then the proposed changes would sometimes have caused make-directory to return that non-nil value to its caller, even when the Emacs 29 doc says make-directory should return nil. As far as I know no such make-directory handler does so now, but to be safe I installed the attached additional patch to make sure Emacss 29 make-directory returns nil in this situation. As the combined set of patches should fix the original bug report I'm marking it as done. In Emacs 30 we could remove this additional patch once we've fixed all the handlers, along with omitting some of the other code that supports calling Emacs 28-style handlers in Emacs 30 environments. Or we could leave it in; there's no rush, I imagine. [-- Attachment #2: 0001-Don-t-assume-make-directory-handler-returns-nil.patch --] [-- Type: text/x-patch, Size: 1381 bytes --] From 4a8ff671b0e93e96f7fca4204cdbc83f99a3387c Mon Sep 17 00:00:00 2001 From: Paul Eggert <eggert@cs.ucla.edu> Date: Sat, 17 Dec 2022 14:09:03 -0800 Subject: [PATCH] =?UTF-8?q?Don=E2=80=99t=20assume=20make-directory=20handl?= =?UTF-8?q?er=20returns=20nil?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * lisp/files.el (make-directory): Ignore what the make-directory handler returns, as its return value was not documented in Emacs 28. --- lisp/files.el | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lisp/files.el b/lisp/files.el index 3cf7833ae02..cc7d7e2af94 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -6224,7 +6224,12 @@ make-directory ;; make sure we find its make-directory handler. (setq dir (expand-file-name dir)) (let ((mkdir (if-let ((handler (find-file-name-handler dir 'make-directory))) - #'(lambda (dir) (funcall handler 'make-directory dir)) + #'(lambda (dir) + ;; Use 'ignore' since the handler might be designed for + ;; Emacs 28-, so it might return an (undocumented) + ;; non-nil value, whereas the Emacs 29+ convention is + ;; to return nil here. + (ignore (funcall handler 'make-directory dir))) #'make-directory-internal))) (if (not parents) (funcall mkdir dir) -- 2.38.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-12-17 22:40 ` Paul Eggert @ 2022-12-18 19:35 ` Michael Albinus 2022-12-18 20:54 ` Paul Eggert 0 siblings, 1 reply; 17+ messages in thread From: Michael Albinus @ 2022-12-18 19:35 UTC (permalink / raw) To: Paul Eggert; +Cc: thievol, Eli Zaretskii, 58919-done Paul Eggert <eggert@cs.ucla.edu> writes: Hi Paul, > On 12/17/22 01:52, Michael Albinus wrote: >> Since file name handlers still raise an error in case DIR exists and >> PARENTS is nil, we might see surprises in code assuming the new >> behavior. I guess I'll add a change in tramp-*-handle-make-directory >> like >> >> --8<---------------cut here---------------start------------->8--- >> (if (and (null parents) (file-exists-p dir)) >> (if (>= emacs-major-version 29) >> t >> (tramp-error v 'file-already-exists dir))) >> --8<---------------cut here---------------end--------------->8--- > > That doesn't look right, as there is no change as to whether > make-directory signals an error. Nor is there any change in behavior > when PARENTS is nil. The only change in behavior is when PARENTS is > non-nil and DIRECTORY already exists as a directory: in this case, > Emacs 29 returns non-nil whereas earlier Emacs returns (undocumented) > nil. Hmm, you're right. I re-read your make-directory code, it looks like PARENTS isn't propagated any longer to the file name handlers. So this must be handled documented there, at least. > So I think all that it would be nice to do is make sure the handlers > ordinarily return nil, except that they return non-nil in the > abovementioned special case. If a handler currently signals an error, > it should continue to do so in the same way as it did before. Strictly > speaking, modifying the handlers in this way won't affect whether they > are compatible with Emacs 28- (since their return value is > undocumented there) nor will it affect whether they work in Emacs 29 > (since Emacs 29 ignores their return value). But it might affect > whether the handlers will work with Emacs 30, which might start > assuming the Emacs 29 API for make-directory handlers. Yep. Using the return value of the handlers shall be re-enabled in Emacs 30. > Come to think of it, if an existing make-directory handler returns > non-nil now (which it is allowed to in Emacs 28 as the return value is > undocumented), then the proposed changes would sometimes have caused > make-directory to return that non-nil value to its caller, even when > the Emacs 29 doc says make-directory should return nil. As far as I > know no such make-directory handler does so now, but to be safe I > installed the attached additional patch to make sure Emacss 29 > make-directory returns nil in this situation. As the combined set of > patches should fix the original bug report I'm marking it as done. > > In Emacs 30 we could remove this additional patch once we've fixed all > the handlers, along with omitting some of the other code that supports > calling Emacs 28-style handlers in Emacs 30 environments. Or we could > leave it in; there's no rush, I imagine. Yes, I will adapt the Tramp and ange-ftp handlers accordingly. Since the return value is either undocumented, or (in Emacs 29) suppressed, there's no harm. For the time being, I have applied a small patch fixing an issue from your last tramp-smb.el change. Best regards, Michael. ^ permalink raw reply [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-12-18 19:35 ` Michael Albinus @ 2022-12-18 20:54 ` Paul Eggert 2022-12-23 10:26 ` Michael Albinus 0 siblings, 1 reply; 17+ messages in thread From: Paul Eggert @ 2022-12-18 20:54 UTC (permalink / raw) To: Michael Albinus; +Cc: thievol, 58919, Eli Zaretskii On 12/18/22 11:35, Michael Albinus wrote: > I re-read your make-directory code, it looks like > PARENTS isn't propagated any longer to the file name handlers. So this > must be handled documented there, at least. Yes, the idea is that in Emacs 29, make-directory handlers never are passed a non-nil PARENTS flag, and their return values are always ignored. That way, Emacs 28 style make-directory handlers should work fine in Emacs 29 since only the intersection of the Emacs 28 and 29 make-directory APIs is used when calling a make-directory handler. In Emacs 30, once we've updated make-directory handlers to support the Emacs 29 make-directory API, we can simplify the code that calls these handlers. ^ permalink raw reply [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-12-18 20:54 ` Paul Eggert @ 2022-12-23 10:26 ` Michael Albinus 2022-12-24 9:11 ` Paul Eggert 0 siblings, 1 reply; 17+ messages in thread From: Michael Albinus @ 2022-12-23 10:26 UTC (permalink / raw) To: Paul Eggert; +Cc: thievol, 58919, Eli Zaretskii Paul Eggert <eggert@cs.ucla.edu> writes: Hi Paul, >> I re-read your make-directory code, it looks like >> PARENTS isn't propagated any longer to the file name handlers. So this >> must be handled documented there, at least. > > Yes, the idea is that in Emacs 29, make-directory handlers never are > passed a non-nil PARENTS flag, and their return values are always > ignored. That way, Emacs 28 style make-directory handlers should work > fine in Emacs 29 since only the intersection of the Emacs 28 and 29 > make-directory APIs is used when calling a make-directory handler. > > In Emacs 30, once we've updated make-directory handlers to support the > Emacs 29 make-directory API, we can simplify the code that calls these > handlers. In Emacs 30, I have adapted tramp-*-make-directory and ange-ftp-make-directory accordingly. There's also url-dav-make-directory, but I don't know whether it is still used. At least, I haven't been able to trigger it by a respective "dav://..." URL. And it looks strange, because it ignores PARENTS, and it doesn't raise an error in case the directory exists already. Hmmm. There don't seem to be other file name handlers for make-directory in core Emacs and in GNU ELPA packages. Do you want to simplify make-directory accordingly? Best regards, Michael. ^ permalink raw reply [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-12-23 10:26 ` Michael Albinus @ 2022-12-24 9:11 ` Paul Eggert 2022-12-24 10:13 ` Michael Albinus 0 siblings, 1 reply; 17+ messages in thread From: Paul Eggert @ 2022-12-24 9:11 UTC (permalink / raw) To: Michael Albinus; +Cc: thievol, 58919, Eli Zaretskii [-- Attachment #1: Type: text/plain, Size: 131 bytes --] On 12/23/22 02:26, Michael Albinus wrote: > Do you want to simplify > make-directory accordingly? Sure, I installed the attached. [-- Attachment #2: 0001-Assume-make-directory-handler-follows-new-API.patch --] [-- Type: text/x-patch, Size: 3710 bytes --] From cc2cc0c2971bf867283d1478bd0d99c2f420f982 Mon Sep 17 00:00:00 2001 From: Paul Eggert <eggert@cs.ucla.edu> Date: Sat, 24 Dec 2022 01:08:21 -0800 Subject: [PATCH] Assume make-directory handler follows new API Suggested by Michael Albinus (Bug#58919#56). * lisp/files.el (files--ensure-directory): Omit recently-added arg MKDIR, since it is now always make-directory again. All uses changed. (make-directory): Assume the make-directory handler follows the new API where it yields non-nil if DIR already exists. This reverts some of the recent changes in this area, and simplifies this funciton. --- lisp/files.el | 53 +++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/lisp/files.el b/lisp/files.el index f352d3a9a7..0fb080b53c 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -6193,11 +6193,11 @@ rename-uniquely (rename-buffer (generate-new-buffer-name base-name)) (force-mode-line-update)))) -(defun files--ensure-directory (mkdir dir) - "Use function MKDIR to make directory DIR if it is not already a directory. +(defun files--ensure-directory (dir) + "Make directory DIR if it is not already a directory. Return non-nil if DIR is already a directory." (condition-case err - (funcall mkdir dir) + (make-directory-internal dir) (error (or (file-directory-p dir) (signal (car err) (cdr err)))))) @@ -6223,32 +6223,27 @@ make-directory ;; If default-directory is a remote directory, ;; make sure we find its make-directory handler. (setq dir (expand-file-name dir)) - (let ((mkdir (if-let ((handler (find-file-name-handler dir 'make-directory))) - #'(lambda (dir) - ;; Use 'ignore' since the handler might be designed for - ;; Emacs 28-, so it might return an (undocumented) - ;; non-nil value, whereas the Emacs 29+ convention is - ;; to return nil here. - (ignore (funcall handler 'make-directory dir))) - #'make-directory-internal))) - (if (not parents) - (funcall mkdir dir) - (let ((dir (directory-file-name (expand-file-name dir))) - already-dir create-list parent) - (while (progn - (setq parent (directory-file-name - (file-name-directory dir))) - (condition-case () - (ignore (setq already-dir - (files--ensure-directory mkdir dir))) - (error - ;; Do not loop if root does not exist (Bug#2309). - (not (string= dir parent))))) - (setq create-list (cons dir create-list) - dir parent)) - (dolist (dir create-list) - (setq already-dir (files--ensure-directory mkdir dir))) - already-dir)))) + (let ((handler (find-file-name-handler dir 'make-directory))) + (if handler + (funcall handler 'make-directory dir parents) + (if (not parents) + (make-directory-internal dir) + (let ((dir (directory-file-name (expand-file-name dir))) + already-dir create-list parent) + (while (progn + (setq parent (directory-file-name + (file-name-directory dir))) + (condition-case () + (ignore (setq already-dir + (files--ensure-directory dir))) + (error + ;; Do not loop if root does not exist (Bug#2309). + (not (string= dir parent))))) + (setq create-list (cons dir create-list) + dir parent)) + (dolist (dir create-list) + (setq already-dir (files--ensure-directory dir))) + already-dir))))) (defun make-empty-file (filename &optional parents) "Create an empty file FILENAME. -- 2.38.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory 2022-12-24 9:11 ` Paul Eggert @ 2022-12-24 10:13 ` Michael Albinus 0 siblings, 0 replies; 17+ messages in thread From: Michael Albinus @ 2022-12-24 10:13 UTC (permalink / raw) To: Paul Eggert; +Cc: thievol, 58919, Eli Zaretskii Paul Eggert <eggert@cs.ucla.edu> writes: Hi Paul, >> Do you want to simplify >> make-directory accordingly? > > Sure, I installed the attached. Thanks. tramp-test13-make-directory (which I did change accordingly) still succeeds, so I guess we're done. Best regards, Michael. ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2022-12-24 10:13 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-10-31 8:54 bug#58919: 28.2; dired-copy-file-recursive fails to overwrite directory Thierry Volpiatto 2022-10-31 13:01 ` Eli Zaretskii 2022-11-01 17:34 ` Thierry Volpiatto 2022-11-01 18:04 ` Paul Eggert 2022-11-01 18:09 ` Eli Zaretskii 2022-11-01 19:21 ` Michael Albinus 2022-12-11 10:46 ` Eli Zaretskii 2022-12-16 23:22 ` Paul Eggert 2022-12-17 8:04 ` Eli Zaretskii 2022-12-17 9:52 ` Michael Albinus 2022-12-17 10:40 ` Eli Zaretskii 2022-12-17 22:40 ` Paul Eggert 2022-12-18 19:35 ` Michael Albinus 2022-12-18 20:54 ` Paul Eggert 2022-12-23 10:26 ` Michael Albinus 2022-12-24 9:11 ` Paul Eggert 2022-12-24 10:13 ` Michael Albinus
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.