* bug#61326: 30.0.50; Editing fil in zip file without extension save creates new file @ 2023-02-06 17:00 Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-06 18:04 ` Eli Zaretskii 2023-02-06 18:57 ` bug#61326: Adding --no-add-suffix to zip patch Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 2 replies; 28+ messages in thread From: Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-06 17:00 UTC (permalink / raw) To: 61326 If I open a zip archive in Emacs, I get a listing of files within the archive, and I can edit the files by pressing RET, and if I then save the file, Emacs updates the archive. However, if the zip archive doesn't have ".zip" (or ".jar") at the end of the filename, Emacs instead of updating the archive opened, creates a new archive with ".zip" added. Example: $ echo ABBA > a.txt $ zip a.zip a.txt adding: a.txt (stored 0%) $ mv a.zip extless $ ls a.txt extless $ emacs -Q extless $ # RET on a.txt, add to content, save $ ls a.txt extless extless.zip $ I was expecting the zip archive I opened, "extless" to be updated, instead of a new file "extless.zip" appearing. The expected behaviour is useful when editing e.g. "zipimport" binaries, such as yt-dlp: https://github.com/yt-dlp/yt-dlp#release-files In GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.36, cairo version 1.16.0) of 2023-01-15 built on tullinup Repository revision: b017c0453c73798c30b2f046bfa62a57cf6ea72b Repository branch: master Windowing system distributor 'The X.Org Foundation', version 11.0.12101006 System Description: Debian GNU/Linux bookworm/sid Configured using: 'configure -C --with-tree-sitter --with-librsvg --with-xinput2 --without-pgtk --with-native-compilation=aot' Configured features: ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG JSON LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS TREE_SITTER WEBP X11 XDBE XIM XINPUT2 XPM GTK3 ZLIB Important settings: value of $LANG: en_GB.UTF-8 locale-coding-system: utf-8-unix Major mode: Group Minor modes in effect: gnus-topic-mode: t gnus-undo-mode: t age-encryption-mode: t pixel-scroll-precision-mode: t global-git-commit-mode: t magit-auto-revert-mode: t dumb-jump-mode: t shell-dirtrack-mode: t which-function-mode: t global-auto-complete-mode: t save-place-mode: t jabber-activity-mode: t winner-mode: t server-mode: t tooltip-mode: t global-eldoc-mode: t electric-indent-mode: t mouse-wheel-mode: t menu-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t buffer-read-only: t line-number-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t Load-path shadows: ~/elisp/let-alist/let-alist hides ~/elisp/extra/let-alist /home/asjo/elisp/boxquote.el/boxquote hides ~/elisp/extra/boxquote ~/elisp/let-alist/let-alist hides /usr/src/emacs/lisp/emacs-lisp/let-alist Features: (shadow bbdb-message emacsbug shr-color executable js-mode-expansions js c-ts-mode treesit cc-mode-expansions cc-mode cc-fonts cc-guess cc-menus cc-cmds cc-styles cc-align cc-engine cc-vars cc-defs flow-fill rng-xsd xsd-regexp rng-cmpct nxml-mode-expansions rng-nxml rng-valid rng-loc rng-uri rng-parse nxml-parse rng-match rng-dt rng-util rng-pttrn nxml-ns nxml-mode nxml-outln nxml-rap nxml-util nxml-enc xmltok jka-compr mm-archive bbdb-gnus-aux qp mule-util url-http url-gw url-auth gnus-gravatar gravatar sort smiley gnus-cite textsec uni-scripts idna-mapping ucs-normalize uni-confusable textsec-check gnus-bcklg gnus-async gnus-dup gnus-ml disp-table gnus-topic utf-7 imap rfc2104 face-remap epa-file network-stream nsm nnml bbdb-gnus bbdb-mua nnnil gnus-demon gnus-delay gnus-draft gnus-agent gnus-srvr gnus-score score-mode nnvirtual nntp gnus-cache nndraft nnmh mail-extr spam spam-stat bbdb-com gnus-uu yenc gnus-msg gnus-html url-queue help-fns radix-tree url-cache mm-url bbdb-picture gnus-art mm-uu mml2015 mm-view mml-smime smime dig gnus-sum shr pixel-fill kinsoku url-file svg gnus-group gnus-undo gnus-fun hashcash gnus-start gnus-dbus gnus-cloud nnimap nnmail mail-source utf7 nnoo gnus-spec gnus-int gnus-range gnus-win gnus nnheader range flymake-proc flymake time age pixel-scroll cua-base litable magithub magithub-ci magithub-issue magithub-cache magithub-core magit-submodule magit-obsolete magit-popup magit-blame magit-stash magit-reflog magit-bisect magit-push magit-pull magit-fetch magit-clone magit-remote magit-commit magit-sequence magit-notes magit-worktree magit-tag magit-merge magit-branch magit-reset magit-files magit-refs magit-status magit magit-repos magit-apply magit-wip magit-log magit-diff smerge-mode diff git-commit log-edit message sendmail yank-media rfc822 mml mml-sec epa epg rfc6068 epg-config gnus-util mm-decode mm-bodies mm-encode mail-parse rfc2231 rfc2047 rfc2045 mm-util ietf-drums mail-prsvr mailabbrev mail-utils gmm-utils mailheader pcvs-util magit-core magit-autorevert autorevert filenotify magit-margin magit-transient magit-process with-editor magit-mode magit-git magit-section benchmark magit-utils vc-git diff-mode ido crm markdown-mode color noutline outline rg pcase rg-info-hack rg-menu transient rg-ibuffer ibuf-macs rg-result wgrep-rg rg-history rg-header ibuf-ext ibuffer ibuffer-loaddefs wgrep grep compile text-property-search dumb-jump f dash s etags fileloop generator xref project tramp tramp-loaddefs trampver tramp-integration cus-edit pp cus-load files-x tramp-compat shell pcomplete parse-time iso8601 ls-lisp auto-loads tex-site expand-region subword-mode-expansions cperl-mode-expansions text-mode-expansions html-mode-expansions er-basic-expansions thingatpt expand-region-core expand-region-custom which-func cperl-mode auto-complete-config auto-complete edmacro kmacro popup debian-changelog-mode imenu add-log dpkg-dev-el saveplace vc vc-dispatcher bbdb bbdb-site timezone bbdb-loaddefs julia-mode julia-mode-latexsubs boxquote rect jabber-last-message-correction jabber-http-file-upload jabber-print-html jabber-otr jabber jabber-notifications notifications jabber-libnotify dbus jabber-awesome jabber-osd jabber-wmii jabber-xmessage jabber-festival jabber-sawfish jabber-ratpoison jabber-tmux jabber-screen jabber-socks5 jabber-ft-server jabber-si-server jabber-ft-client jabber-ft-common jabber-si-client jabber-si-common jabber-feature-neg jabber-truncate jabber-time jabber-autoaway time-date jabber-vcard-avatars jabber-chatstates jabber-events jabber-vcard jabber-avatar jabber-activity jabber-watch jabber-modeline easy-mmode advice jabber-ahc-presence jabber-ahc jabber-version jabber-ourversion jabber-muc-nick-completion hippie-exp comint ansi-osc ansi-color jabber-browse jabber-search jabber-register jabber-roster format-spec jabber-presence jabber-muc jabber-bookmarks jabber-private jabber-muc-nick-coloring hexrgb jabber-widget jabber-disco wid-edit jabber-chat jabber-history jabber-chatbuffer jabber-alert jabber-iq jabber-core jabber-console derived sgml-mode facemenu dom ewoc jabber-keymap jabber-sasl sasl sasl-anonymous sasl-login sasl-plain fsm jabber-logon jabber-conn comp comp-cstr warnings icons rx cl-extra help-mode srv dns starttls tls jabber-xml xml jabber-menu jabber-util cl winner ring gnutls puny find-file-from-selection find-lisp dired dired-loaddefs cap-words superword subword server finder-inf package browse-url url url-proxy url-privacy url-expand url-methods url-history url-cookie generate-lisp-file url-domsuf url-util mailcap url-handlers url-parse auth-source cl-seq eieio eieio-core cl-macs password-cache json subr-x map byte-opt gv bytecomp byte-compile url-vars cl-loaddefs cl-lib rmc iso-transl tooltip cconv 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 nadvice seq simple cl-generic indonesian philippine 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 abbrev obarray oclosure cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp files window text-properties overlay sha1 md5 base64 format env code-pages mule custom widget keymap hashtable-print-readable backquote threads dbusbind inotify lcms2 dynamic-setting system-font-setting font-render-setting cairo move-toolbar gtk x-toolkit xinput2 x multi-tty make-network-process native-compile emacs) Memory information: ((conses 16 1135254 142749) (symbols 48 43507 17) (strings 32 298866 21178) (string-bytes 1 12616608) (vectors 16 98259) (vector-slots 8 3113739 175347) (floats 8 750 1097) (intervals 56 795 371) (buffers 984 33)) -- "Den ene mands loft Adam Sjøgren Er den anden mands gulv" asjo@koldfront.dk ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: 30.0.50; Editing fil in zip file without extension save creates new file 2023-02-06 17:00 bug#61326: 30.0.50; Editing fil in zip file without extension save creates new file Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-06 18:04 ` Eli Zaretskii 2023-02-06 18:15 ` Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-06 18:57 ` bug#61326: Adding --no-add-suffix to zip patch Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 1 reply; 28+ messages in thread From: Eli Zaretskii @ 2023-02-06 18:04 UTC (permalink / raw) To: Adam Sjøgren; +Cc: 61326 > Date: Mon, 06 Feb 2023 18:00:14 +0100 > From: Adam Sjøgren via "Bug reports for GNU Emacs, > the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> > > > If I open a zip archive in Emacs, I get a listing of files within the > archive, and I can edit the files by pressing RET, and if I then save > the file, Emacs updates the archive. > > However, if the zip archive doesn't have ".zip" (or ".jar") at the end > of the filename, Emacs instead of updating the archive opened, creates a > new archive with ".zip" added. AFAIR, Emacs uses the 'zip' program to create or update a zip archive, and I suspect that the fact the archive has .zip appended is because that's what the 'zip' program does. Did you try looking at the command that Emacs invokes when you update a member of the archive? ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: 30.0.50; Editing fil in zip file without extension save creates new file 2023-02-06 18:04 ` Eli Zaretskii @ 2023-02-06 18:15 ` Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 0 replies; 28+ messages in thread From: Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-06 18:15 UTC (permalink / raw) To: 61326 Eli writes: > I suspect that the fact the archive has .zip appended is because > that's what the 'zip' program does. Yes - I skimmed the man-page for zip(1), and there doesn't seem to be an option to turn off "add .zip if there is no '.' in the filename" - unfortunately, that would have been really handy here. > Did you try looking at the command that Emacs invokes when you update > a member of the archive? I did not. ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: Adding --no-add-suffix to zip patch 2023-02-06 17:00 bug#61326: 30.0.50; Editing fil in zip file without extension save creates new file Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-06 18:04 ` Eli Zaretskii @ 2023-02-06 18:57 ` Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-07 1:31 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 1 reply; 28+ messages in thread From: Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-06 18:57 UTC (permalink / raw) To: 61326 Adding a '--no-add-suffix' option to zip 3.0 is not too bad: diff -u orig/zip-3.0/globals.c chan/zip-3.0/globals.c --- orig/zip-3.0/globals.c 2008-05-25 19:26:38.000000000 +0200 +++ chan/zip-3.0/globals.c 2023-02-06 19:42:48.000000000 +0100 @@ -106,6 +106,7 @@ int noisy = 1; /* 0=quiet operation */ int extra_fields = 1; /* 0=create minimum, 1=don't copy old, 2=keep old */ int use_descriptors = 0; /* 1=use data descriptors 12/29/04 */ +int no_add_suffix = 0; /* 1=do not add suffix .zip to archive names without . */ int zip_to_stdout = 0; /* output zipfile to stdout 12/30/04 */ int allow_empty_archive = 0; /* if no files, create empty archive anyway 12/28/05 */ int copy_only = 0; /* 1=copying archive entries only */ diff -u orig/zip-3.0/zip.c chan/zip-3.0/zip.c --- orig/zip-3.0/zip.c 2023-02-06 19:49:42.000000000 +0100 +++ chan/zip-3.0/zip.c 2023-02-06 19:47:26.000000000 +0100 @@ -1942,6 +1942,7 @@ #ifdef UNICODE_TEST #define o_sC 0x146 #endif +#define o_nas 0x147 /* the below is mainly from the old main command line @@ -2042,6 +2043,7 @@ {"N", "notes", o_NO_VALUE, o_NOT_NEGATABLE, 'N', "add notes as entry comments"}, #endif {"o", "latest-time", o_NO_VALUE, o_NOT_NEGATABLE, 'o', "use latest entry time as archive time"}, + {"", "no-add-suffix", o_NO_VALUE, o_NOT_NEGATABLE, o_nas, "do not add .zip suffix to archive name without ."}, {"O", "output-file", o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'O', "set out zipfile different than in zipfile"}, {"p", "paths", o_NO_VALUE, o_NOT_NEGATABLE, 'p', "store paths"}, {"P", "password", o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'P', "encrypt entries, option value is password"}, @@ -2378,6 +2380,7 @@ before = 0; /* 0=ignore, else exclude files before this time */ after = 0; /* 0=ignore, else exclude files newer than this time */ + no_add_suffix = 0 /* 0=add .zip if no . as usual, else use archive name unchanged */ special = ".Z:.zip:.zoo:.arc:.lzh:.arj"; /* List of special suffixes */ key = NULL; /* Scramble password if scrambling */ key_needed = 0; /* Need scramble password */ @@ -3299,6 +3302,11 @@ break; #endif + case o_nas: + no_add_suffix = 1; + break; + + case o_NON_OPTION_ARG: /* not an option */ /* no more options as permuting */ @@ -3340,8 +3348,14 @@ #endif /* !MACOS && !WINDLL */ { /* name of zipfile */ - if ((zipfile = ziptyp(value)) == NULL) { - ZIPERR(ZE_MEM, "was processing arguments"); + if (no_add_suffix) { + zipfile = value; + } + else { + if ((zipfile = ziptyp(value)) == NULL) { + ZIPERR(ZE_MEM, "was processing arguments"); + } + free(value); } /* read zipfile if exists */ /* @@ -3349,7 +3363,6 @@ ZIPERR(r, zipfile); } */ - free(value); } if (show_what_doing) { fprintf(mesg, "sd: Zipfile name '%s'\n", zipfile); diff -u orig/zip-3.0/zip.h chan/zip-3.0/zip.h --- orig/zip-3.0/zip.h 2008-05-25 19:23:22.000000000 +0200 +++ chan/zip-3.0/zip.h 2023-02-06 19:43:41.000000000 +0100 @@ -442,6 +442,7 @@ extern int use_privileges; /* use security privilege overrides */ #endif extern int use_descriptors; /* use data descriptors (extended headings) */ +extern int no_add_suffix; /* do not add suffix .zip to archive names without . */ extern int allow_empty_archive; /* if no files, create empty archive anyway */ extern int copy_only; /* 1 = copy archive with no changes */ extern int zip_to_stdout; /* output to stdout */ But getting something like that accepted and distributed, and for Emacs to tell whether the installed zip has that option or not, seems like a lot of work. ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: Adding --no-add-suffix to zip patch 2023-02-06 18:57 ` bug#61326: Adding --no-add-suffix to zip patch Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-07 1:31 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-07 3:27 ` Eli Zaretskii 2023-02-07 19:59 ` bug#61326: Adding --no-add-suffix to zip patch Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 2 replies; 28+ messages in thread From: Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-07 1:31 UTC (permalink / raw) To: Adam Sjøgren; +Cc: 61326 On Feb 7, 2023, at 02:58, Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors <bug-gnu-emacs@gnu.org> wrote: > > Adding a '--no-add-suffix' option to zip 3.0 is not too bad: > > diff -u orig/zip-3.0/globals.c chan/zip-3.0/globals.c > --- orig/zip-3.0/globals.c 2008-05-25 19:26:38.000000000 +0200 > +++ chan/zip-3.0/globals.c 2023-02-06 19:42:48.000000000 +0100 > @@ -106,6 +106,7 @@ > int noisy = 1; /* 0=quiet operation */ > int extra_fields = 1; /* 0=create minimum, 1=don't copy old, 2=keep old */ > int use_descriptors = 0; /* 1=use data descriptors 12/29/04 */ > +int no_add_suffix = 0; /* 1=do not add suffix .zip to archive names without . */ > int zip_to_stdout = 0; /* output zipfile to stdout 12/30/04 */ > int allow_empty_archive = 0; /* if no files, create empty archive anyway 12/28/05 */ > int copy_only = 0; /* 1=copying archive entries only */ > diff -u orig/zip-3.0/zip.c chan/zip-3.0/zip.c > --- orig/zip-3.0/zip.c 2023-02-06 19:49:42.000000000 +0100 > +++ chan/zip-3.0/zip.c 2023-02-06 19:47:26.000000000 +0100 > @@ -1942,6 +1942,7 @@ > #ifdef UNICODE_TEST > #define o_sC 0x146 > #endif > +#define o_nas 0x147 > > > /* the below is mainly from the old main command line > @@ -2042,6 +2043,7 @@ > {"N", "notes", o_NO_VALUE, o_NOT_NEGATABLE, 'N', "add notes as entry comments"}, > #endif > {"o", "latest-time", o_NO_VALUE, o_NOT_NEGATABLE, 'o', "use latest entry time as archive time"}, > + {"", "no-add-suffix", o_NO_VALUE, o_NOT_NEGATABLE, o_nas, "do not add .zip suffix to archive name without ."}, > {"O", "output-file", o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'O', "set out zipfile different than in zipfile"}, > {"p", "paths", o_NO_VALUE, o_NOT_NEGATABLE, 'p', "store paths"}, > {"P", "password", o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'P', "encrypt entries, option value is password"}, > @@ -2378,6 +2380,7 @@ > before = 0; /* 0=ignore, else exclude files before this time */ > after = 0; /* 0=ignore, else exclude files newer than this time */ > > + no_add_suffix = 0 /* 0=add .zip if no . as usual, else use archive name unchanged */ > special = ".Z:.zip:.zoo:.arc:.lzh:.arj"; /* List of special suffixes */ > key = NULL; /* Scramble password if scrambling */ > key_needed = 0; /* Need scramble password */ > @@ -3299,6 +3302,11 @@ > break; > #endif > > + case o_nas: > + no_add_suffix = 1; > + break; > + > + > case o_NON_OPTION_ARG: > /* not an option */ > /* no more options as permuting */ > @@ -3340,8 +3348,14 @@ > #endif /* !MACOS && !WINDLL */ > { > /* name of zipfile */ > - if ((zipfile = ziptyp(value)) == NULL) { > - ZIPERR(ZE_MEM, "was processing arguments"); > + if (no_add_suffix) { > + zipfile = value; > + } > + else { > + if ((zipfile = ziptyp(value)) == NULL) { > + ZIPERR(ZE_MEM, "was processing arguments"); > + } > + free(value); > } > /* read zipfile if exists */ > /* > @@ -3349,7 +3363,6 @@ > ZIPERR(r, zipfile); > } > */ > - free(value); > } > if (show_what_doing) { > fprintf(mesg, "sd: Zipfile name '%s'\n", zipfile); > diff -u orig/zip-3.0/zip.h chan/zip-3.0/zip.h > --- orig/zip-3.0/zip.h 2008-05-25 19:23:22.000000000 +0200 > +++ chan/zip-3.0/zip.h 2023-02-06 19:43:41.000000000 +0100 > @@ -442,6 +442,7 @@ > extern int use_privileges; /* use security privilege overrides */ > #endif > extern int use_descriptors; /* use data descriptors (extended headings) */ > +extern int no_add_suffix; /* do not add suffix .zip to archive names without . */ > extern int allow_empty_archive; /* if no files, create empty archive anyway */ > extern int copy_only; /* 1 = copy archive with no changes */ > extern int zip_to_stdout; /* output to stdout */ > > But getting something like that accepted and distributed, and for Emacs > to tell whether the installed zip has that option or not, seems like a > lot of work. Maybe, at least in the meantime, we change it such that all write operations for zip create files in temp, and move to / overwrite the original file when done? Although I don’t have a full understanding on how that would be done and whether there are problems along with it. ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: Adding --no-add-suffix to zip patch 2023-02-07 1:31 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-07 3:27 ` Eli Zaretskii 2023-02-07 13:53 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-07 19:59 ` bug#61326: Adding --no-add-suffix to zip patch Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 1 reply; 28+ messages in thread From: Eli Zaretskii @ 2023-02-07 3:27 UTC (permalink / raw) To: Ruijie Yu; +Cc: asjo, 61326 > Cc: 61326@debbugs.gnu.org > Date: Tue, 7 Feb 2023 09:31:11 +0800 > From: Ruijie Yu via "Bug reports for GNU Emacs, > the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> > > Maybe, at least in the meantime, we change it such that all write operations for zip create files in temp, and move to / overwrite the original file when done? Although I don’t have a full understanding on how that would be done and whether there are problems along with it. How about submitting a patch to do that, but only when the original file doesn't have an extension? ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: Adding --no-add-suffix to zip patch 2023-02-07 3:27 ` Eli Zaretskii @ 2023-02-07 13:53 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-07 14:54 ` Eli Zaretskii 2023-02-08 16:48 ` bug#61326: [DRAFT PATCH] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 2 replies; 28+ messages in thread From: Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-07 13:53 UTC (permalink / raw) To: Eli Zaretskii; +Cc: asjo, 61326 Eli Zaretskii <eliz@gnu.org> writes: >> Cc: 61326@debbugs.gnu.org >> Date: Tue, 7 Feb 2023 09:31:11 +0800 >> From: Ruijie Yu via "Bug reports for GNU Emacs, >> the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> >> >> Maybe, at least in the meantime, we change it such that all write operations >> for zip create files in temp, and move to / overwrite the original file when >> done? Although I don’t have a full understanding on how that would be done and >> whether there are problems along with it. > > How about submitting a patch to do that, but only when the original > file doesn't have an extension? Will do. Will report back in 2-3 days unless someone else gets to it first. Best, RY ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: Adding --no-add-suffix to zip patch 2023-02-07 13:53 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-07 14:54 ` Eli Zaretskii 2023-02-08 16:48 ` bug#61326: [DRAFT PATCH] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 0 replies; 28+ messages in thread From: Eli Zaretskii @ 2023-02-07 14:54 UTC (permalink / raw) To: Ruijie Yu; +Cc: asjo, 61326 > From: Ruijie Yu <ruijie@netyu.xyz> > Cc: asjo@koldfront.dk, 61326@debbugs.gnu.org > Date: Tue, 07 Feb 2023 21:53:12 +0800 > > > Eli Zaretskii <eliz@gnu.org> writes: > > >> Cc: 61326@debbugs.gnu.org > >> Date: Tue, 7 Feb 2023 09:31:11 +0800 > >> From: Ruijie Yu via "Bug reports for GNU Emacs, > >> the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> > >> > >> Maybe, at least in the meantime, we change it such that all write operations > >> for zip create files in temp, and move to / overwrite the original file when > >> done? Although I don’t have a full understanding on how that would be done and > >> whether there are problems along with it. > > > > How about submitting a patch to do that, but only when the original > > file doesn't have an extension? > > Will do. Will report back in 2-3 days unless someone else gets to it > first. Thanks in advance. ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: [DRAFT PATCH] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-02-07 13:53 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-07 14:54 ` Eli Zaretskii @ 2023-02-08 16:48 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-08 18:02 ` Eli Zaretskii 1 sibling, 1 reply; 28+ messages in thread From: Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-08 16:48 UTC (permalink / raw) To: 61326; +Cc: Eli Zaretskii, asjo [-- Attachment #1: Type: text/plain, Size: 1539 bytes --] Ruijie Yu via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> writes: > Eli Zaretskii <eliz@gnu.org> writes: > >>> Cc: 61326@debbugs.gnu.org >>> Date: Tue, 7 Feb 2023 09:31:11 +0800 >>> From: Ruijie Yu via "Bug reports for GNU Emacs, >>> the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> >>> >>> Maybe, at least in the meantime, we change it such that all write operations >>> for zip create files in temp, and move to / overwrite the original file when >>> done? Although I don’t have a full understanding on how that would be done and >>> whether there are problems along with it. >> >> How about submitting a patch to do that, but only when the original >> file doesn't have an extension? > > Will do. Will report back in 2-3 days unless someone else gets to it > first. > > Best, > > > RY Here is a preliminary patch that contains some "REVIEW" comments where I need inputs. I have tested with the following recipe and things seem to work correctly: $ touch 1 2 && zip z 1 2 && mv z.zip z $ ls -l .... 1 .... 2 .... z $ src/emacs -Q RET ; open file "1" from within "z" archive s C-x C-s ; insert "s" and save file "1" C-x C-c ; exit $ ls -l # notice that no "z.zip" exists, and "z" is correctly updated .... 1 .... 2 .... z Patch based on 907fd1f7ff402f9d226ebb3b891ea5b54fac1d1c which is ~3 days old. I will amend the commit (and rebase if necessary) according to ML reviews and further progress. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-lisp-arc-mode.el-Work-around-zip-s-filename-limitati.patch --] [-- Type: text/x-patch, Size: 6335 bytes --] From bc086395929520a66eb928fd5d3baf6c9fa79bb5 Mon Sep 17 00:00:00 2001 From: Ruijie Yu <ruijie+git@netyu.xyz> Date: Thu, 9 Feb 2023 00:45:19 +0800 Subject: [PATCH] lisp/arc-mode.el Work around zip's filename limitations on extension [DRAFT PATCH] Fixes 61326. The "zip" executable requires that the named archive must have an extension, else it attaches ".zip" to the supplied file name, causing incorrect behaviors. This patch looks for such scenarios and temporarily rename extension-less archives so that "zip" would function correctly. TODO: 1. Address all REVIEW points. 2. Make sure other write operations, in addition to zip-write-member, are fixed. 3. Tests? (I might need some pointers as to where existing tests are and how to write them.) --- lisp/arc-mode.el | 82 +++++++++++++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 28 deletions(-) diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el index 6f3e922880d..ac8c7cefa89 100644 --- a/lisp/arc-mode.el +++ b/lisp/arc-mode.el @@ -1350,42 +1350,61 @@ archive-write-file-member (setq last-coding-system-used archive-member-coding-system)) t) -(defun archive-*-write-file-member (archive descr command) +;; REVIEW: is there a better name than AVOID-EXTLESS-P? +(defun archive-*-write-file-member (archive descr command + &optional avoid-extless-p) (let* ((archive (expand-file-name archive)) (ename (archive--file-desc-ext-file-name descr)) (tmpfile (expand-file-name ename archive-tmpdir)) (top (directory-file-name (file-name-as-directory archive-tmpdir))) (default-directory (file-name-as-directory top))) + ;; REVIEW: the diff here is because the previous code had TAB's + ;; (while assuming each TAB is 4 spaces), and my Emacs replaced + ;; them with spaces. What is the status quo on this kind of diff? + ;; I can remove them if we consider this change excessive and/or + ;; intrusive. (unwind-protect (progn (make-directory (file-name-directory tmpfile) t) - ;; If the member is itself an archive, write it without - ;; the dired-like listing we created. - (if (eq major-mode 'archive-mode) - (archive-write-file tmpfile) - (write-region nil nil tmpfile nil 'nomessage)) - ;; basic-save-buffer needs last-coding-system-used to have - ;; the value used to write the file, so save it before any - ;; further processing clobbers it (we restore it in - ;; archive-write-file-member, above). - (setq archive-member-coding-system last-coding-system-used) - (if (archive--file-desc-mode descr) - ;; Set the file modes, but make sure we can read it. - (set-file-modes tmpfile - (logior ?\400 (archive--file-desc-mode descr)))) - (setq ename - (encode-coding-string ename archive-file-name-coding-system)) + ;; If the member is itself an archive, write it without + ;; the dired-like listing we created. + (if (eq major-mode 'archive-mode) + (archive-write-file tmpfile) + (write-region nil nil tmpfile nil 'nomessage)) + ;; basic-save-buffer needs last-coding-system-used to have + ;; the value used to write the file, so save it before any + ;; further processing clobbers it (we restore it in + ;; archive-write-file-member, above). + (setq archive-member-coding-system last-coding-system-used) + (if (archive--file-desc-mode descr) + ;; Set the file modes, but make sure we can read it. + (set-file-modes tmpfile + (logior ?\400 (archive--file-desc-mode descr)))) + (setq ename + (encode-coding-string ename archive-file-name-coding-system)) (let* ((coding-system-for-write 'no-conversion) - (default-directory (file-name-as-directory archive-tmpdir)) - (exitcode (apply #'call-process - (car command) - nil - nil - nil - (append (cdr command) - (list archive ename))))) - (or (zerop exitcode) - (error "Updating was unsuccessful (%S)" exitcode)))) + (default-directory (file-name-as-directory archive-tmpdir)) + (safe-archive + (if avoid-extless-p + (make-temp-name + (expand-file-name (concat archive "_tmp."))) + archive)) + (maybe-rename + (lambda (newname) + (when avoid-extless-p + (with-current-buffer archive-superior-buffer + (rename-visited-file newname)))))) + ;; REVIEW: is `unwind-protect' necessary here? + (prog2 (funcall maybe-rename safe-archive) + (let ((exitcode + (apply #'call-process (car command) + nil nil nil + (append (cdr command) + (list safe-archive ename))))) + (or (zerop exitcode) + (error "Updating was unsuccessful (%S)" + exitcode))) + (funcall maybe-rename archive)))) (archive-delete-local tmpfile)))) (defun archive-write-file (&optional file) @@ -2048,12 +2067,19 @@ archive--file-desc-case-fiddled (not (eq (archive--file-desc-int-file-name fd) (archive--file-desc-ext-file-name fd)))) +(defun archive--file-name-zip-extless-p (fname) + ;; zip's rule: if the filename contains "." anywhere in the name + ;; (including obscure names like ".foo" and "bar."), then this + ;; filename is considered to have an extension. + (not (seq-contains-p (file-name-nondirectory fname) ?. #'eq))) + (defun archive-zip-write-file-member (archive descr) (archive-*-write-file-member archive descr (if (archive--file-desc-case-fiddled descr) - archive-zip-update-case archive-zip-update))) + archive-zip-update-case archive-zip-update) + (archive--file-name-zip-extless-p archive))) (defun archive-zip-chmod-entry (newmode files) (save-restriction -- 2.39.1 [-- Attachment #3: Type: text/plain, Size: 12 bytes --] Best, RY ^ permalink raw reply related [flat|nested] 28+ messages in thread
* bug#61326: [DRAFT PATCH] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-02-08 16:48 ` bug#61326: [DRAFT PATCH] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-08 18:02 ` Eli Zaretskii 2023-02-10 8:40 ` bug#61326: [DRAFT PATCH v2] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 28+ messages in thread From: Eli Zaretskii @ 2023-02-08 18:02 UTC (permalink / raw) To: Ruijie Yu; +Cc: asjo, 61326 > From: Ruijie Yu <ruijie@netyu.xyz> > Cc: Eli Zaretskii <eliz@gnu.org>, asjo@koldfront.dk > Date: Thu, 09 Feb 2023 00:48:15 +0800 > > Here is a preliminary patch that contains some "REVIEW" comments where I > need inputs. Thanks, but could you perhaps post diffs disregarding the whitespace changes? That would make it easier to review the real changes. > -(defun archive-*-write-file-member (archive descr command) > +;; REVIEW: is there a better name than AVOID-EXTLESS-P? > +(defun archive-*-write-file-member (archive descr command > + &optional avoid-extless-p) ensure-extension? > + ;; REVIEW: the diff here is because the previous code had TAB's > + ;; (while assuming each TAB is 4 spaces), and my Emacs replaced > + ;; them with spaces. What is the status quo on this kind of diff? > + ;; I can remove them if we consider this change excessive and/or > + ;; intrusive. TABs in Emacs are by default 8 columns, not 4. It is OK to convert TABs to spaces when changing the code in Lisp, but please do that only for the last commit, to make the review process easier. For all the draft versions, please use "git diff" options that cause Git to ignore changes in whitespace. Thanks. ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: [DRAFT PATCH v2] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-02-08 18:02 ` Eli Zaretskii @ 2023-02-10 8:40 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-13 10:35 ` bug#61326: [DRAFT PATCH v3] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 28+ messages in thread From: Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-10 8:40 UTC (permalink / raw) To: Eli Zaretskii; +Cc: asjo, 61326 [-- Attachment #1: Type: text/plain, Size: 2051 bytes --] Eli Zaretskii <eliz@gnu.org> writes: >> From: Ruijie Yu <ruijie@netyu.xyz> >> Cc: Eli Zaretskii <eliz@gnu.org>, asjo@koldfront.dk >> Date: Thu, 09 Feb 2023 00:48:15 +0800 >> >> Here is a preliminary patch that contains some "REVIEW" comments where I >> need inputs. > > Thanks, but could you perhaps post diffs disregarding the whitespace > changes? That would make it easier to review the real changes. Thanks, done. >> -(defun archive-*-write-file-member (archive descr command) >> +;; REVIEW: is there a better name than AVOID-EXTLESS-P? >> +(defun archive-*-write-file-member (archive descr command >> + &optional avoid-extless-p) > > ensure-extension? That sounds better, and I have renamed the variable in this iteration. >> + ;; REVIEW: the diff here is because the previous code had TAB's >> + ;; (while assuming each TAB is 4 spaces), and my Emacs replaced >> + ;; them with spaces. What is the status quo on this kind of diff? >> + ;; I can remove them if we consider this change excessive and/or >> + ;; intrusive. > > TABs in Emacs are by default 8 columns, not 4. > > It is OK to convert TABs to spaces when changing the code in Lisp, but > please do that only for the last commit, to make the review process > easier. For all the draft versions, please use "git diff" options > that cause Git to ignore changes in whitespace. > > Thanks. Thanks, I will keep that in mind. I have also made some rearrangements in the code to minimize delta. In addition, I fixed an issue from the first iteration: in the first iteration, the user would be prompted to revert buffer from disk if the rename was in action; in this iteration this should no longer be the case -- that is, the user should expect no difference between filenames with extensions and without. As pointed out in the commit message, two things remain: to ensure that all write operations to extensionless zip archives behave correctly, and to have some way to test that things continue to work in the future. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-lisp-arc-mode.el-Work-around-zip-s-filename-limitati.patch --] [-- Type: text/x-patch, Size: 4186 bytes --] From bc56c17082ea3ff2a76308f14310908853e3a2d1 Mon Sep 17 00:00:00 2001 From: Ruijie Yu <ruijie+git@netyu.xyz> Date: Thu, 9 Feb 2023 00:45:19 +0800 Subject: [PATCH] lisp/arc-mode.el Work around zip's filename limitations on extension [DRAFT PATCH] Fixes 61326. The "zip" executable requires that the named archive must have an extension, else it attaches ".zip" to the supplied file name, causing incorrect behaviors. This patch looks for such scenarios and temporarily rename extension-less archives so that "zip" would function correctly. TODO: 1. Make sure other write operations, in addition to zip-write-member, are fixed. 2. Tests? (I might need some pointers as to where existing tests are and how to write them.) --- lisp/arc-mode.el | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el index 6f3e922880d..cd7f4ca1134 100644 --- a/lisp/arc-mode.el +++ b/lisp/arc-mode.el @@ -1350,14 +1350,23 @@ archive-write-file-member (setq last-coding-system-used archive-member-coding-system)) t) -(defun archive-*-write-file-member (archive descr command) +(defun archive-*-write-file-member + (archive descr command &optional ensure-extension) (let* ((archive (expand-file-name archive)) + (real-archive archive) + (archive (if ensure-extension + (make-temp-name + (expand-file-name (concat archive "_tmp."))) + archive)) (ename (archive--file-desc-ext-file-name descr)) (tmpfile (expand-file-name ename archive-tmpdir)) (top (directory-file-name (file-name-as-directory archive-tmpdir))) (default-directory (file-name-as-directory top))) (unwind-protect - (progn + (cl-flet ((maybe-rename (newname) + (when ensure-extension + (with-current-buffer archive-superior-buffer + (rename-visited-file newname))))) (make-directory (file-name-directory tmpfile) t) ;; If the member is itself an archive, write it without ;; the dired-like listing we created. @@ -1376,16 +1385,20 @@ archive-*-write-file-member (setq ename (encode-coding-string ename archive-file-name-coding-system)) (let* ((coding-system-for-write 'no-conversion) - (default-directory (file-name-as-directory archive-tmpdir)) - (exitcode (apply #'call-process - (car command) - nil - nil - nil + (default-directory (file-name-as-directory archive-tmpdir))) + (unwind-protect + (progn + (maybe-rename archive) + (let ((exitcode + (apply #'call-process (car command) + nil nil nil (append (cdr command) (list archive ename))))) (or (zerop exitcode) (error "Updating was unsuccessful (%S)" exitcode)))) + (progn (maybe-rename real-archive) + (with-current-buffer archive-superior-buffer + (revert-buffer nil t)))))) (archive-delete-local tmpfile)))) (defun archive-write-file (&optional file) @@ -2048,12 +2061,19 @@ archive--file-desc-case-fiddled (not (eq (archive--file-desc-int-file-name fd) (archive--file-desc-ext-file-name fd)))) +(defun archive--file-name-zip-extless-p (fname) + ;; zip's rule: if the filename contains "." anywhere in the name + ;; (including obscure names like ".foo" and "bar."), then this + ;; filename is considered to have an extension. + (not (seq-contains-p (file-name-nondirectory fname) ?. #'eq))) + (defun archive-zip-write-file-member (archive descr) (archive-*-write-file-member archive descr (if (archive--file-desc-case-fiddled descr) - archive-zip-update-case archive-zip-update))) + archive-zip-update-case archive-zip-update) + (archive--file-name-zip-extless-p archive))) (defun archive-zip-chmod-entry (newmode files) (save-restriction -- 2.39.1 [-- Attachment #3: Type: text/plain, Size: 12 bytes --] Best, RY ^ permalink raw reply related [flat|nested] 28+ messages in thread
* bug#61326: [DRAFT PATCH v3] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-02-10 8:40 ` bug#61326: [DRAFT PATCH v2] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-13 10:35 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-03-04 11:21 ` Eli Zaretskii 0 siblings, 1 reply; 28+ messages in thread From: Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-13 10:35 UTC (permalink / raw) To: Eli Zaretskii; +Cc: asjo, 61326 [-- Attachment #1: Type: text/plain, Size: 760 bytes --] I believe the functionalities (both update and deletion) are done in this patch. I have not added any tests nor updates on documentation, as I am not sure what and where they should be. I have done some basic tests locally to confirm that it works: - update subfile in a zip archive named "z" - delete subfile in a zip archive named "z" - update subfile in a zip archive named "x.zip" - delete subfile in a zip archive named "x.zip" FTR, if this is of any importance: the filesystem containing the archives "z" and "x.zip" is btrfs, and /tmp is ext2 on zram. Not sure if any problems would arise in other filesystems / OSes -- hopefully someone else on those platforms can confirm that it works. Comments welcome. Particularly on my choices of naming. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-lisp-arc-mode.el-Work-around-zip-s-filename-limitati.patch --] [-- Type: text/x-patch, Size: 4444 bytes --] From 0766bec8071c7c793d6c81211577832d9a7a78f9 Mon Sep 17 00:00:00 2001 From: Ruijie Yu <ruijie+git@netyu.xyz> Date: Thu, 9 Feb 2023 00:45:19 +0800 Subject: [PATCH] lisp/arc-mode.el Work around zip's filename limitations on extension [DRAFT PATCH] Fixes 61326. The "zip" executable requires that the named archive must have an extension, else it attaches ".zip" to the supplied file name, causing incorrect behaviors. This patch looks for such scenarios and temporarily rename extension-less archives so that "zip" would function correctly. Currently there are no tests. I might need some pointers as to where existing tests are and how to write them. --- lisp/arc-mode.el | 64 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el index 6f3e922880d..875b3971086 100644 --- a/lisp/arc-mode.el +++ b/lisp/arc-mode.el @@ -645,6 +645,49 @@ archive-get-descr (if (not noerror) (error "Line does not describe a member of the archive"))))) ;; ------------------------------------------------------------------------- +;;; Section: Helper functions for requiring filename extensions + +(defun archive--act-files (command files) + (lambda (archive) + (apply #'call-process (car command) + nil nil nil (append (cdr command) (cons archive files))))) + +(defun archive--need-rename-p (&optional archive) + (let ((archive + (file-name-nondirectory (or archive buffer-file-name)))) + (cl-case archive-subtype + ((zip) (not (seq-contains-p archive ?. #'eq)))))) + +(defun archive--ensure-extension (archive ensure-extension) + (if ensure-extension + (make-temp-name (expand-file-name (concat archive "_tmp."))) + archive)) + +(defun archive--maybe-rename (newname need-rename-p) + ;; Operating with archive as current buffer, and protect + ;; `default-directory' from being modified in `rename-visited-file'. + (when need-rename-p + (let ((default-directory default-directory)) + (rename-visited-file newname)))) + +(defun archive--with-ensure-extension (archive proc-fn) + (let ((saved default-directory)) + (with-current-buffer (find-buffer-visiting archive) + (let ((ensure-extension (archive--need-rename-p)) + (default-directory saved)) + (unwind-protect + ;; Some archive programs (like zip) expect filenames to + ;; have an extension, so if necessary, temporarily rename + ;; an extensionless file for write accesses. + (let ((archive (archive--ensure-extension + archive ensure-extension))) + (archive--maybe-rename archive ensure-extension) + (let ((exitcode (funcall proc-fn archive))) + (or (zerop exitcode) + (error "Updating was unsuccessful (%S)" exitcode)))) + (progn (archive--maybe-rename archive ensure-extension) + (revert-buffer nil t))))))) +;; ------------------------------------------------------------------------- ;;; Section: the mode definition ;;;###autoload @@ -1376,16 +1419,9 @@ archive-*-write-file-member (setq ename (encode-coding-string ename archive-file-name-coding-system)) (let* ((coding-system-for-write 'no-conversion) - (default-directory (file-name-as-directory archive-tmpdir)) - (exitcode (apply #'call-process - (car command) - nil - nil - nil - (append (cdr command) - (list archive ename))))) - (or (zerop exitcode) - (error "Updating was unsuccessful (%S)" exitcode)))) + (default-directory (file-name-as-directory archive-tmpdir))) + (archive--with-ensure-extension + archive (archive--act-files command (list ename))))) (archive-delete-local tmpfile)))) (defun archive-write-file (&optional file) @@ -1539,12 +1575,8 @@ archive-expunge (revert-buffer)))))) (defun archive-*-expunge (archive files command) - (apply #'call-process - (car command) - nil - nil - nil - (append (cdr command) (cons archive files)))) + (archive--with-ensure-extension + archive (archive--act-files command files))) (defun archive-rename-entry (newname) "Change the name associated with this entry in the archive file." -- 2.39.1 [-- Attachment #3: Type: text/plain, Size: 15 bytes --] -- Best, RY ^ permalink raw reply related [flat|nested] 28+ messages in thread
* bug#61326: [DRAFT PATCH v3] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-02-13 10:35 ` bug#61326: [DRAFT PATCH v3] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-03-04 11:21 ` Eli Zaretskii 2023-03-04 14:56 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 28+ messages in thread From: Eli Zaretskii @ 2023-03-04 11:21 UTC (permalink / raw) To: Ruijie Yu; +Cc: asjo, 61326 > From: Ruijie Yu <ruijie@netyu.xyz> > Cc: asjo@koldfront.dk, 61326@debbugs.gnu.org > Date: Mon, 13 Feb 2023 18:35:17 +0800 > > I believe the functionalities (both update and deletion) are done in > this patch. I have not added any tests nor updates on documentation, as > I am not sure what and where they should be. Thanks. I don't think we need any updates to the documentation, as this just fixes a subtle bug. It would be nice to have a few tests, though. Please add them to test/lisp/arc-mode-tests.el. I see that you don't have a copyright assignment on file, so would you like me to send you the form to fill, which will start the legal paperwork of assigning the copyright to the FSF? Once that is completed, we can install these changes. Thanks. ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: [DRAFT PATCH v3] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-03-04 11:21 ` Eli Zaretskii @ 2023-03-04 14:56 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-03-04 15:12 ` Eli Zaretskii 0 siblings, 1 reply; 28+ messages in thread From: Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-03-04 14:56 UTC (permalink / raw) To: Eli Zaretskii; +Cc: asjo, 61326 Eli Zaretskii <eliz@gnu.org> writes: >> From: Ruijie Yu <ruijie@netyu.xyz> >> Cc: asjo@koldfront.dk, 61326@debbugs.gnu.org >> Date: Mon, 13 Feb 2023 18:35:17 +0800 >> >> I believe the functionalities (both update and deletion) are done in >> this patch. I have not added any tests nor updates on documentation, as >> I am not sure what and where they should be. > > Thanks. > > I don't think we need any updates to the documentation, as this just > fixes a subtle bug. It would be nice to have a few tests, though. > Please add them to test/lisp/arc-mode-tests.el. Sure, will do in a few days. > I see that you don't have a copyright assignment on file, so would you > like me to send you the form to fill, which will start the legal > paperwork of assigning the copyright to the FSF? Once that is > completed, we can install these changes. > > Thanks. Please do, thanks. -- Best, RY ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: [DRAFT PATCH v3] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-03-04 14:56 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-03-04 15:12 ` Eli Zaretskii 2023-03-05 15:23 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 28+ messages in thread From: Eli Zaretskii @ 2023-03-04 15:12 UTC (permalink / raw) To: Ruijie Yu; +Cc: asjo, 61326 > From: Ruijie Yu <ruijie@netyu.xyz> > Cc: asjo@koldfront.dk, 61326@debbugs.gnu.org > Date: Sat, 04 Mar 2023 22:56:21 +0800 > > > I see that you don't have a copyright assignment on file, so would you > > like me to send you the form to fill, which will start the legal > > paperwork of assigning the copyright to the FSF? Once that is > > completed, we can install these changes. > > > > Thanks. > > Please do, thanks. Form sent off-list. ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: [DRAFT PATCH v3] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-03-04 15:12 ` Eli Zaretskii @ 2023-03-05 15:23 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-03-05 15:52 ` Eli Zaretskii 0 siblings, 1 reply; 28+ messages in thread From: Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-03-05 15:23 UTC (permalink / raw) To: Eli Zaretskii; +Cc: asjo, 61326 Eli Zaretskii <eliz@gnu.org> writes: >> From: Ruijie Yu <ruijie@netyu.xyz> >> Cc: asjo@koldfront.dk, 61326@debbugs.gnu.org >> Date: Sat, 04 Mar 2023 22:56:21 +0800 >> >> > I see that you don't have a copyright assignment on file, so would you >> > like me to send you the form to fill, which will start the legal >> > paperwork of assigning the copyright to the FSF? Once that is >> > completed, we can install these changes. >> > >> > Thanks. >> >> Please do, thanks. > > Form sent off-list. Response sent to assign@gnu, thanks. By the way, while writing tests, I see a need to modify `archive-expunge' to accept an additional optional argument FORCE acting as the prefix argument. I suppose if this is favored, I should probably say something in the etc/NEWS file (as well as the docstring, and maybe an info page somewhere)? FTR, previously prefix arguments are ignored for `archive-expunge'. The reason for the need of a FORCE argument is so that I want to ensure that file contents are correct after deleting a member using archive-mode functionalities without getting prompted for confirmation. However, `archive-expunge' ATM requires a user prompt via its baked-in `yes-or-no-p' call. An alternative to the above is to move the meat of said function into a new internal helper function which simply skips over prompting the user. This would keep the `archive-expunge' API untouched. A new draft iteration should be here in a few days, with the question(s) above answered. Thanks. -- Best, RY ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: [DRAFT PATCH v3] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-03-05 15:23 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-03-05 15:52 ` Eli Zaretskii 2023-03-06 4:05 ` bug#61326: [DRAFT PATCH v4] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 28+ messages in thread From: Eli Zaretskii @ 2023-03-05 15:52 UTC (permalink / raw) To: Ruijie Yu; +Cc: asjo, 61326 > From: Ruijie Yu <ruijie@netyu.xyz> > Cc: asjo@koldfront.dk, 61326@debbugs.gnu.org > Date: Sun, 05 Mar 2023 23:23:59 +0800 > > > Form sent off-list. > > Response sent to assign@gnu, thanks. Thanks. > By the way, while writing tests, I see a need to modify > `archive-expunge' to accept an additional optional argument FORCE acting > as the prefix argument. I suppose if this is favored, I should probably > say something in the etc/NEWS file (as well as the docstring, and maybe > an info page somewhere)? FTR, previously prefix arguments are ignored > for `archive-expunge'. > > The reason for the need of a FORCE argument is so that I want to ensure > that file contents are correct after deleting a member using > archive-mode functionalities without getting prompted for confirmation. > However, `archive-expunge' ATM requires a user prompt via its baked-in > `yes-or-no-p' call. This is a separate feature. In Dired-like user interfaces, we always ask the user for confirmation before deleting items; 'C-u x' in Dired AFAIR just avoids messages when no files are flagged for deletion, but doesn't prevent the confirmation. So if we are going to treat archive-expunge differently, I think we'll need a very good reason. ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: [DRAFT PATCH v4] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-03-05 15:52 ` Eli Zaretskii @ 2023-03-06 4:05 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-03-11 8:54 ` Eli Zaretskii 0 siblings, 1 reply; 28+ messages in thread From: Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-03-06 4:05 UTC (permalink / raw) To: Eli Zaretskii; +Cc: asjo, 61326 [-- Attachment #1: Type: text/plain, Size: 2422 bytes --] Eli Zaretskii <eliz@gnu.org> writes: > [...] >> By the way, while writing tests, I see a need to modify >> `archive-expunge' to accept an additional optional argument FORCE acting >> as the prefix argument. I suppose if this is favored, I should probably >> say something in the etc/NEWS file (as well as the docstring, and maybe >> an info page somewhere)? FTR, previously prefix arguments are ignored >> for `archive-expunge'. >> >> The reason for the need of a FORCE argument is so that I want to ensure >> that file contents are correct after deleting a member using >> archive-mode functionalities without getting prompted for confirmation. >> However, `archive-expunge' ATM requires a user prompt via its baked-in >> `yes-or-no-p' call. > > This is a separate feature. [...] So if we are going to treat > archive-expunge differently, I think we'll need a very good reason. I see, thanks for explaining. In the attached patches I followed the alternative approach which I described in my previous message: take the meat of the function into a separate helper function, and use that in the `archive-expunge' function and in my new test. If someone else has a good reason for using prefix argument to "force" deletion, they can ask in a new bug report. Another question regarding this change: when moving `archive-expunge' into `archive--expunge-maybe-force', I rewrote the portion that populates the list of files that are marked for deletion. Originally it was using `while' + `setq', and seeing that arc-mode.el already requires `cl-lib', I turned it into a `cl-do' construct. Do people have a preference or does it matter? I can change this portion back to the original if there's objection. To ease the review process, I have broken down the changes into two patch files. The first one is merely to take out `archive-expunge' into helper function `archive--expunge-maybe-force', and the second one is everything else, including the tests. The goal for the final patch is to combine these two into one, to make necessary indentation changes around the portions that I touched, and to only use the commit message of the second patch _verbatim_ -- so please verify that this commit message is satisfactory in emacs.git, thanks. FTR, I ran `make check' and ensured that my changes didn't introduce regressions, while also noticed that some tests in vc and eglot fail both before and after my changes. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-REVIEW-pull-out-content-of-arc-expunge-for-nonintera.patch --] [-- Type: text/x-patch, Size: 2229 bytes --] From 3b9196a095c6843b7c87b867a82fa7a2d930bb0b Mon Sep 17 00:00:00 2001 From: Ruijie Yu <ruijie+git@netyu.xyz> Date: Mon, 6 Mar 2023 11:03:32 +0800 Subject: [PATCH 1/2] REVIEW: pull out content of arc-expunge for noninteractive deletion --- lisp/arc-mode.el | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el index 6f3e922880d..f8d7182597b 100644 --- a/lisp/arc-mode.el +++ b/lisp/arc-mode.el @@ -1508,23 +1508,26 @@ archive-chgrp-entry (archive-resummarize)) (error "Setting group is not supported for this archive type")))) -(defun archive-expunge () - "Do the flagged deletions." - (interactive) - (let (files) +(defun archive--expunge-maybe-force (force) + (let ((files (save-excursion (goto-char archive-file-list-start) - (while (< (point) archive-file-list-end) - (if (= (following-char) ?D) - (setq files (cons (archive--file-desc-ext-file-name + (cl-do ((files + nil + (prog1 + (if (eq (following-char) ?D) + (cons (archive--file-desc-ext-file-name (archive-get-descr)) - files))) - (forward-line 1))) - (setq files (nreverse files)) + files) + files) + (forward-line 1)))) + ((>= (point) archive-file-list-end) + (nreverse files)))))) (and files (or (not archive-read-only) (error "Archive is read-only")) - (or (yes-or-no-p (format "Really delete %d member%s? " + (or force + (yes-or-no-p (format "Really delete %d member%s? " (length files) (if (null (cdr files)) "" "s"))) (error "Operation aborted")) @@ -1538,6 +1541,11 @@ archive-expunge (archive-resummarize) (revert-buffer)))))) +(defun archive-expunge () + "Do the flagged deletions." + (interactive) + (archive--expunge-maybe-force nil)) + (defun archive-*-expunge (archive files command) (apply #'call-process (car command) -- 2.39.2 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #3: 0002-Handle-modifications-on-extensionless-zips-correctly.patch --] [-- Type: text/x-patch, Size: 7625 bytes --] From ba5825f9bdd323a460f4a327670d99ed34df3128 Mon Sep 17 00:00:00 2001 From: Ruijie Yu <ruijie+git@netyu.xyz> Date: Thu, 9 Feb 2023 00:45:19 +0800 Subject: [PATCH 2/2] Handle modifications on extensionless zips correctly (bug#61326) * lisp/arc-mode.el: Refactor to handle extless zips * test/lisp/arc-mode-tests.el: New test for correctly handling extless zips --- lisp/arc-mode.el | 64 ++++++++++++++++++++++++++--------- test/lisp/arc-mode-tests.el | 67 +++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 16 deletions(-) diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el index f8d7182597b..47611f13b6f 100644 --- a/lisp/arc-mode.el +++ b/lisp/arc-mode.el @@ -645,6 +645,49 @@ archive-get-descr (if (not noerror) (error "Line does not describe a member of the archive"))))) ;; ------------------------------------------------------------------------- +;;; Section: Helper functions for requiring filename extensions + +(defun archive--act-files (command files) + (lambda (archive) + (apply #'call-process (car command) + nil nil nil (append (cdr command) (cons archive files))))) + +(defun archive--need-rename-p (&optional archive) + (let ((archive + (file-name-nondirectory (or archive buffer-file-name)))) + (cl-case archive-subtype + ((zip) (not (seq-contains-p archive ?. #'eq)))))) + +(defun archive--ensure-extension (archive ensure-extension) + (if ensure-extension + (make-temp-name (expand-file-name (concat archive "_tmp."))) + archive)) + +(defun archive--maybe-rename (newname need-rename-p) + ;; Operating with archive as current buffer, and protect + ;; `default-directory' from being modified in `rename-visited-file'. + (when need-rename-p + (let ((default-directory default-directory)) + (rename-visited-file newname)))) + +(defun archive--with-ensure-extension (archive proc-fn) + (let ((saved default-directory)) + (with-current-buffer (find-buffer-visiting archive) + (let ((ensure-extension (archive--need-rename-p)) + (default-directory saved)) + (unwind-protect + ;; Some archive programs (like zip) expect filenames to + ;; have an extension, so if necessary, temporarily rename + ;; an extensionless file for write accesses. + (let ((archive (archive--ensure-extension + archive ensure-extension))) + (archive--maybe-rename archive ensure-extension) + (let ((exitcode (funcall proc-fn archive))) + (or (zerop exitcode) + (error "Updating was unsuccessful (%S)" exitcode)))) + (progn (archive--maybe-rename archive ensure-extension) + (revert-buffer nil t))))))) +;; ------------------------------------------------------------------------- ;;; Section: the mode definition ;;;###autoload @@ -1376,16 +1419,9 @@ archive-*-write-file-member (setq ename (encode-coding-string ename archive-file-name-coding-system)) (let* ((coding-system-for-write 'no-conversion) - (default-directory (file-name-as-directory archive-tmpdir)) - (exitcode (apply #'call-process - (car command) - nil - nil - nil - (append (cdr command) - (list archive ename))))) - (or (zerop exitcode) - (error "Updating was unsuccessful (%S)" exitcode)))) + (default-directory (file-name-as-directory archive-tmpdir))) + (archive--with-ensure-extension + archive (archive--act-files command (list ename))))) (archive-delete-local tmpfile)))) (defun archive-write-file (&optional file) @@ -1547,12 +1583,8 @@ archive-expunge (archive--expunge-maybe-force nil)) (defun archive-*-expunge (archive files command) - (apply #'call-process - (car command) - nil - nil - nil - (append (cdr command) (cons archive files)))) + (archive--with-ensure-extension + archive (archive--act-files command files))) (defun archive-rename-entry (newname) "Change the name associated with this entry in the archive file." diff --git a/test/lisp/arc-mode-tests.el b/test/lisp/arc-mode-tests.el index 32bce1b71bd..ae44ef3439c 100644 --- a/test/lisp/arc-mode-tests.el +++ b/test/lisp/arc-mode-tests.el @@ -46,6 +46,73 @@ arc-mode-test-zip-extract-gz (when (buffer-live-p zip-buffer) (kill-buffer zip-buffer)) (when (buffer-live-p gz-buffer) (kill-buffer gz-buffer))))) +(ert-deftest arc-mode-test-zip-ensure-ext () + ;; Bug#61326 + (skip-unless (executable-find "zip")) + (let* ((default-directory arc-mode-tests-data-directory) + (base-zip-1 "base-1.zip") + (base-zip-2 "base-2.zip") + (content-1 '("1" "2")) + (content-2 '("3" "4")) + (make-file (lambda (name) + (with-temp-buffer + (insert name) + (write-file name)))) + (make-zip + (lambda (zip files) + (delete-file zip nil) + (funcall (archive--act-files '("zip") files) zip))) + (update-fn + (lambda (zip-nonempty) + (with-current-buffer (find-file-noselect zip-nonempty) + (save-excursion + (goto-char archive-file-list-start) + (save-current-buffer + (archive-extract) + (save-excursion + (goto-char (point-max)) + (insert ?a) + (save-buffer)) + (kill-buffer (current-buffer))) + (archive-extract) + ;; [2] must be ?a; [3] must be (eobp) + (should (eq (char-after 2) ?a)) + (should (eq (point-max) 3)))))) + (delete-fn + (lambda (zip-nonempty) + (with-current-buffer (find-file-noselect zip-nonempty) + ;; mark delete and expunge first entry + (save-excursion + (goto-char archive-file-list-start) + (should (length= archive-files 2)) + (archive-flag-deleted 1) + (archive--expunge-maybe-force t) + (should (length= archive-files 1)))))) + (test-modify + (lambda (zip mod-fn) + (let ((zip-base (concat zip ".zip")) + (tag (gensym))) + (copy-file base-zip-1 zip t) + (copy-file base-zip-2 zip-base t) + (file-has-changed-p zip tag) + (file-has-changed-p zip-base tag) + (funcall mod-fn zip) + (should-not (file-has-changed-p zip-base tag)) + (should (file-has-changed-p zip tag)))))) + ;; setup: make two zip files with different contents + (mapc make-file (append content-1 content-2)) + (mapc (lambda (args) (apply make-zip args)) + (list (list base-zip-1 content-1) + (list base-zip-2 content-2))) + ;; test 1: with "test-update" and "test-update.zip", update + ;; "test-update": (1) ensure only "test-update" is modified, (2) + ;; ensure the contents of the new member is expected. + (funcall test-modify "test-update" update-fn) + ;; test 2: with "test-delete" and "test-delete.zip", delete entry + ;; from "test-delete": (1) ensure only "test-delete" is modified, + ;; (2) ensure the file list is reduced as expected. + (funcall test-modify "test-delete" delete-fn))) + (provide 'arc-mode-tests) ;;; arc-mode-tests.el ends here -- 2.39.2 [-- Attachment #4: Type: text/plain, Size: 15 bytes --] -- Best, RY ^ permalink raw reply related [flat|nested] 28+ messages in thread
* bug#61326: [DRAFT PATCH v4] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-03-06 4:05 ` bug#61326: [DRAFT PATCH v4] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-03-11 8:54 ` Eli Zaretskii 2023-03-11 8:57 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 28+ messages in thread From: Eli Zaretskii @ 2023-03-11 8:54 UTC (permalink / raw) To: Ruijie Yu; +Cc: asjo, 61326 > From: Ruijie Yu <ruijie@netyu.xyz> > Cc: asjo@koldfront.dk, 61326@debbugs.gnu.org > Date: Mon, 06 Mar 2023 12:05:23 +0800 > > In the attached patches I followed the alternative approach which I > described in my previous message: take the meat of the function into a > separate helper function, and use that in the `archive-expunge' function > and in my new test. If someone else has a good reason for using prefix > argument to "force" deletion, they can ask in a new bug report. > > Another question regarding this change: when moving `archive-expunge' > into `archive--expunge-maybe-force', I rewrote the portion that > populates the list of files that are marked for deletion. Originally it > was using `while' + `setq', and seeing that arc-mode.el already requires > `cl-lib', I turned it into a `cl-do' construct. Do people have a > preference or does it matter? I can change this portion back to the > original if there's objection. I don't object in principle, but in this case it looks like the implementation based on cl-do needs much more complex code than the original? If so, I'd prefer the original, simpler and easier-to-understand code. > To ease the review process, I have broken down the changes into two > patch files. The first one is merely to take out `archive-expunge' into > helper function `archive--expunge-maybe-force', and the second one is > everything else, including the tests. > > The goal for the final patch is to combine these two into one, to make > necessary indentation changes around the portions that I touched, and to > only use the commit message of the second patch _verbatim_ -- so please > verify that this commit message is satisfactory in emacs.git, thanks. The commit log message is not detailed enough: it doesn't mention the functions you modify. Please see the conventions we follow for log messages described in CONTRIBUTE, which also mentions useful Emacs functions which will help you format the log message according to our conventions. Thanks. ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: [DRAFT PATCH v4] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-03-11 8:54 ` Eli Zaretskii @ 2023-03-11 8:57 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-03-17 3:19 ` bug#61326: [DRAFT PATCH v5] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 28+ messages in thread From: Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-03-11 8:57 UTC (permalink / raw) To: Eli Zaretskii; +Cc: asjo, 61326 Eli Zaretskii <eliz@gnu.org> writes: >> [...] I turned it into a `cl-do' construct. [...] > > I don't object in principle, but in this case it looks like the > implementation based on cl-do needs much more complex code than the > original? If so, I'd prefer the original, simpler and > easier-to-understand code. It's more that everything is buried under the let expression, so it _looks_ more complex. But I do agree that this change might introduce unnecessary cognative load for maintainers and I will revert that change in my next iteration. > The commit log message is not detailed enough: it doesn't mention the > functions you modify. Please see the conventions we follow for log > messages described in CONTRIBUTE, which also mentions useful Emacs > functions which will help you format the log message according to our > conventions. > > Thanks. Thank you for the review. I will take a closer look at etc/CONTRIBUTE -- apparently I didn't read it in enough detail. I will report back within the next few days. -- Best, RY ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: [DRAFT PATCH v5] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-03-11 8:57 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-03-17 3:19 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-04-17 8:48 ` bug#61326: [PATCH " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 28+ messages in thread From: Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-03-17 3:19 UTC (permalink / raw) To: Ruijie Yu; +Cc: Eli Zaretskii, asjo, 61326 [-- Attachment #1: Type: text/plain, Size: 905 bytes --] > [...] > Thank you for the review. I will take a closer look at etc/CONTRIBUTE > -- apparently I didn't read it in enough detail. I will report back > within the next few days. New iteration. As mentioned from my last message, I have reverted the part where I tried to rewrite part of `archive-expunge' using `cl-do'. Test cases for arc-mode still pass: $ make -C test arc-mode-tests Note that I mentioned the new internal helper functions in the commit message, as I saw João too has mentioned updates to internal functions in 9d3fdf7e0. If mentioning the internal functions turns out to be unnecessary, simply removing these lines from the patch should suffice. Otherwise, if there's something else that looks wrong in the commit message, please let me know. FTR, I am still waiting for the counter signature from FSF before this can be included into emacs.git. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-Handle-modifications-on-extensionless-zips-correctly.patch --] [-- Type: text/x-patch, Size: 9155 bytes --] From f3b29596ef3ddfa63d6cd65fcbf8a5210e99989f Mon Sep 17 00:00:00 2001 From: Ruijie Yu <ruijie+git@netyu.xyz> Date: Mon, 6 Mar 2023 11:03:32 +0800 Subject: [PATCH] Handle modifications on extensionless zips correctly (Bug#61326) * lisp/arc-mode.el (archive-*-write-file-member) (archive-*-expunge): Refactor to correctly modify extensionless zip archives. (archive-expunge): Move implementation to a separate helper function to facilitate testing. (archive--act-files): New helper function to wrap around `call-process' calls. (archive--need-rename-p): New helper function to check whether a temporary rename is necessary. (archive--ensure-extension) (archive--maybe-rename): New helper functions to rename archive if the caller deems it necessary. (archive--with-ensure-extension): New helper function to handle writing an archive while ensuring extensionless archives work correctly by temporarily renaming them. * test/lisp/arc-mode-tests.el (arc-mode-test-zip-ensure-ext): New regression test for bug#61326. --- lisp/arc-mode.el | 76 +++++++++++++++++++++++++++---------- test/lisp/arc-mode-tests.el | 67 ++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 20 deletions(-) diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el index 5e696c091b2..0a971799746 100644 --- a/lisp/arc-mode.el +++ b/lisp/arc-mode.el @@ -645,6 +645,49 @@ archive-get-descr (if (not noerror) (error "Line does not describe a member of the archive"))))) ;; ------------------------------------------------------------------------- +;;; Section: Helper functions for requiring filename extensions + +(defun archive--act-files (command files) + (lambda (archive) + (apply #'call-process (car command) + nil nil nil (append (cdr command) (cons archive files))))) + +(defun archive--need-rename-p (&optional archive) + (let ((archive + (file-name-nondirectory (or archive buffer-file-name)))) + (cl-case archive-subtype + ((zip) (not (seq-contains-p archive ?. #'eq)))))) + +(defun archive--ensure-extension (archive ensure-extension) + (if ensure-extension + (make-temp-name (expand-file-name (concat archive "_tmp."))) + archive)) + +(defun archive--maybe-rename (newname need-rename-p) + ;; Operating with archive as current buffer, and protect + ;; `default-directory' from being modified in `rename-visited-file'. + (when need-rename-p + (let ((default-directory default-directory)) + (rename-visited-file newname)))) + +(defun archive--with-ensure-extension (archive proc-fn) + (let ((saved default-directory)) + (with-current-buffer (find-buffer-visiting archive) + (let ((ensure-extension (archive--need-rename-p)) + (default-directory saved)) + (unwind-protect + ;; Some archive programs (like zip) expect filenames to + ;; have an extension, so if necessary, temporarily rename + ;; an extensionless file for write accesses. + (let ((archive (archive--ensure-extension + archive ensure-extension))) + (archive--maybe-rename archive ensure-extension) + (let ((exitcode (funcall proc-fn archive))) + (or (zerop exitcode) + (error "Updating was unsuccessful (%S)" exitcode)))) + (progn (archive--maybe-rename archive ensure-extension) + (revert-buffer nil t))))))) +;; ------------------------------------------------------------------------- ;;; Section: the mode definition ;;;###autoload @@ -1378,16 +1421,9 @@ archive-*-write-file-member (setq ename (encode-coding-string ename archive-file-name-coding-system)) (let* ((coding-system-for-write 'no-conversion) - (default-directory (file-name-as-directory archive-tmpdir)) - (exitcode (apply #'call-process - (car command) - nil - nil - nil - (append (cdr command) - (list archive ename))))) - (or (zerop exitcode) - (error "Updating was unsuccessful (%S)" exitcode)))) + (default-directory (file-name-as-directory archive-tmpdir))) + (archive--with-ensure-extension + archive (archive--act-files command (list ename))))) (archive-delete-local tmpfile)))) (defun archive-write-file (&optional file) @@ -1510,9 +1546,7 @@ archive-chgrp-entry (archive-resummarize)) (error "Setting group is not supported for this archive type")))) -(defun archive-expunge () - "Do the flagged deletions." - (interactive) +(defun archive--expunge-maybe-force (force) (let (files) (save-excursion (goto-char archive-file-list-start) @@ -1526,7 +1560,8 @@ archive-expunge (and files (or (not archive-read-only) (error "Archive is read-only")) - (or (yes-or-no-p (format "Really delete %d member%s? " + (or force + (yes-or-no-p (format "Really delete %d member%s? " (length files) (if (null (cdr files)) "" "s"))) (error "Operation aborted")) @@ -1540,13 +1575,14 @@ archive-expunge (archive-resummarize) (revert-buffer)))))) +(defun archive-expunge () + "Do the flagged deletions." + (interactive) + (archive--expunge-maybe-force nil)) + (defun archive-*-expunge (archive files command) - (apply #'call-process - (car command) - nil - nil - nil - (append (cdr command) (cons archive files)))) + (archive--with-ensure-extension + archive (archive--act-files command files))) (defun archive-rename-entry (newname) "Change the name associated with this entry in the archive file." diff --git a/test/lisp/arc-mode-tests.el b/test/lisp/arc-mode-tests.el index 32bce1b71bd..ae44ef3439c 100644 --- a/test/lisp/arc-mode-tests.el +++ b/test/lisp/arc-mode-tests.el @@ -46,6 +46,73 @@ arc-mode-test-zip-extract-gz (when (buffer-live-p zip-buffer) (kill-buffer zip-buffer)) (when (buffer-live-p gz-buffer) (kill-buffer gz-buffer))))) +(ert-deftest arc-mode-test-zip-ensure-ext () + ;; Bug#61326 + (skip-unless (executable-find "zip")) + (let* ((default-directory arc-mode-tests-data-directory) + (base-zip-1 "base-1.zip") + (base-zip-2 "base-2.zip") + (content-1 '("1" "2")) + (content-2 '("3" "4")) + (make-file (lambda (name) + (with-temp-buffer + (insert name) + (write-file name)))) + (make-zip + (lambda (zip files) + (delete-file zip nil) + (funcall (archive--act-files '("zip") files) zip))) + (update-fn + (lambda (zip-nonempty) + (with-current-buffer (find-file-noselect zip-nonempty) + (save-excursion + (goto-char archive-file-list-start) + (save-current-buffer + (archive-extract) + (save-excursion + (goto-char (point-max)) + (insert ?a) + (save-buffer)) + (kill-buffer (current-buffer))) + (archive-extract) + ;; [2] must be ?a; [3] must be (eobp) + (should (eq (char-after 2) ?a)) + (should (eq (point-max) 3)))))) + (delete-fn + (lambda (zip-nonempty) + (with-current-buffer (find-file-noselect zip-nonempty) + ;; mark delete and expunge first entry + (save-excursion + (goto-char archive-file-list-start) + (should (length= archive-files 2)) + (archive-flag-deleted 1) + (archive--expunge-maybe-force t) + (should (length= archive-files 1)))))) + (test-modify + (lambda (zip mod-fn) + (let ((zip-base (concat zip ".zip")) + (tag (gensym))) + (copy-file base-zip-1 zip t) + (copy-file base-zip-2 zip-base t) + (file-has-changed-p zip tag) + (file-has-changed-p zip-base tag) + (funcall mod-fn zip) + (should-not (file-has-changed-p zip-base tag)) + (should (file-has-changed-p zip tag)))))) + ;; setup: make two zip files with different contents + (mapc make-file (append content-1 content-2)) + (mapc (lambda (args) (apply make-zip args)) + (list (list base-zip-1 content-1) + (list base-zip-2 content-2))) + ;; test 1: with "test-update" and "test-update.zip", update + ;; "test-update": (1) ensure only "test-update" is modified, (2) + ;; ensure the contents of the new member is expected. + (funcall test-modify "test-update" update-fn) + ;; test 2: with "test-delete" and "test-delete.zip", delete entry + ;; from "test-delete": (1) ensure only "test-delete" is modified, + ;; (2) ensure the file list is reduced as expected. + (funcall test-modify "test-delete" delete-fn))) + (provide 'arc-mode-tests) ;;; arc-mode-tests.el ends here -- 2.39.2 [-- Attachment #3: Type: text/plain, Size: 15 bytes --] -- Best, RY ^ permalink raw reply related [flat|nested] 28+ messages in thread
* bug#61326: [PATCH v5] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-03-17 3:19 ` bug#61326: [DRAFT PATCH v5] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-04-17 8:48 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-04-20 7:47 ` Eli Zaretskii 0 siblings, 1 reply; 28+ messages in thread From: Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-04-17 8:48 UTC (permalink / raw) To: Ruijie Yu; +Cc: Eli Zaretskii, asjo, 61326 Ruijie Yu <ruijie@netyu.xyz> writes: > New iteration. As mentioned from my last message, I have reverted the > part where I tried to rewrite part of `archive-expunge' using `cl-do'. > > FTR, I am still waiting for the counter signature from FSF before this > can be included into emacs.git. > > [2. text/x-patch; 0001-Handle-modifications-on-extensionless-zips-correctly.patch]... Ping? Removing the "DRAFT" from subject, because I think it is probably complete. Also, my FSF process should now be complete. -- Best, RY ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: [PATCH v5] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-04-17 8:48 ` bug#61326: [PATCH " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-04-20 7:47 ` Eli Zaretskii 2023-04-20 8:49 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 28+ messages in thread From: Eli Zaretskii @ 2023-04-20 7:47 UTC (permalink / raw) To: Ruijie Yu; +Cc: asjo, 61326 > From: Ruijie Yu <ruijie@netyu.xyz> > Cc: Eli Zaretskii <eliz@gnu.org>, asjo@koldfront.dk, 61326@debbugs.gnu.org > Date: Mon, 17 Apr 2023 16:48:13 +0800 > > > Ruijie Yu <ruijie@netyu.xyz> writes: > > > New iteration. As mentioned from my last message, I have reverted the > > part where I tried to rewrite part of `archive-expunge' using `cl-do'. > > > > FTR, I am still waiting for the counter signature from FSF before this > > can be included into emacs.git. > > > > Ping? > > Removing the "DRAFT" from subject, because I think it is probably > complete. Also, my FSF process should now be complete. Great, then, with these two issues out of our way, we can install this now. However, the patch as posted back then no longer applies. Please rebase on the current master branch and re-post. Thanks. ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: [PATCH v5] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-04-20 7:47 ` Eli Zaretskii @ 2023-04-20 8:49 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-04-20 9:29 ` Eli Zaretskii 0 siblings, 1 reply; 28+ messages in thread From: Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-04-20 8:49 UTC (permalink / raw) To: Eli Zaretskii; +Cc: asjo, 61326 [-- Attachment #1: Type: text/plain, Size: 1149 bytes --] Eli Zaretskii <eliz@gnu.org> writes: >> From: Ruijie Yu <ruijie@netyu.xyz> >> Cc: Eli Zaretskii <eliz@gnu.org>, asjo@koldfront.dk, 61326@debbugs.gnu.org >> Date: Mon, 17 Apr 2023 16:48:13 +0800 >> >> >> Ruijie Yu <ruijie@netyu.xyz> writes: >> >> > New iteration. As mentioned from my last message, I have reverted the >> > part where I tried to rewrite part of `archive-expunge' using `cl-do'. >> > >> > FTR, I am still waiting for the counter signature from FSF before this >> > can be included into emacs.git. >> > >> >> Ping? >> >> Removing the "DRAFT" from subject, because I think it is probably >> complete. Also, my FSF process should now be complete. > > Great, then, with these two issues out of our way, we can install this > now. > > However, the patch as posted back then no longer applies. Please > rebase on the current master branch and re-post. > > Thanks. Thanks. I have made one change after the previous iteration: I turned the "bug#xxx" comment in the test/lisp/arc-mode-tests.el into a docstring. Also, interestingly, git-rebase finishes cleanly on my end. Here attached is a patch _without_ indentation changes. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: Patch *without* indentation changes --] [-- Type: text/x-patch, Size: 9046 bytes --] From a98a530d7a7e73404c107e77c173d8981db811ce Mon Sep 17 00:00:00 2001 From: Ruijie Yu <ruijie+git@netyu.xyz> Date: Mon, 6 Mar 2023 11:03:32 +0800 Subject: [PATCH] Handle modifications on extensionless zips correctly (Bug#61326) * lisp/arc-mode.el (archive-*-write-file-member) (archive-*-expunge): Refactor to correctly modify extensionless zip archives. (archive-expunge): Move implementation to a separate helper function to facilitate testing. (archive--act-files): New helper function to wrap around `call-process' calls. (archive--need-rename-p): New helper function to check whether a temporary rename is necessary. (archive--ensure-extension) (archive--maybe-rename): New helper functions to rename archive if the caller deems it necessary. (archive--with-ensure-extension): New helper function to handle writing an archive while ensuring extensionless archives work correctly by temporarily renaming them. * test/lisp/arc-mode-tests.el (arc-mode-test-zip-ensure-ext): New regression test for bug#61326. --- lisp/arc-mode.el | 76 +++++++++++++++++++++++++++---------- test/lisp/arc-mode-tests.el | 67 ++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 20 deletions(-) diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el index 5e696c091b2..0a971799746 100644 --- a/lisp/arc-mode.el +++ b/lisp/arc-mode.el @@ -645,6 +645,49 @@ archive-get-descr (if (not noerror) (error "Line does not describe a member of the archive"))))) ;; ------------------------------------------------------------------------- +;;; Section: Helper functions for requiring filename extensions + +(defun archive--act-files (command files) + (lambda (archive) + (apply #'call-process (car command) + nil nil nil (append (cdr command) (cons archive files))))) + +(defun archive--need-rename-p (&optional archive) + (let ((archive + (file-name-nondirectory (or archive buffer-file-name)))) + (cl-case archive-subtype + ((zip) (not (seq-contains-p archive ?. #'eq)))))) + +(defun archive--ensure-extension (archive ensure-extension) + (if ensure-extension + (make-temp-name (expand-file-name (concat archive "_tmp."))) + archive)) + +(defun archive--maybe-rename (newname need-rename-p) + ;; Operating with archive as current buffer, and protect + ;; `default-directory' from being modified in `rename-visited-file'. + (when need-rename-p + (let ((default-directory default-directory)) + (rename-visited-file newname)))) + +(defun archive--with-ensure-extension (archive proc-fn) + (let ((saved default-directory)) + (with-current-buffer (find-buffer-visiting archive) + (let ((ensure-extension (archive--need-rename-p)) + (default-directory saved)) + (unwind-protect + ;; Some archive programs (like zip) expect filenames to + ;; have an extension, so if necessary, temporarily rename + ;; an extensionless file for write accesses. + (let ((archive (archive--ensure-extension + archive ensure-extension))) + (archive--maybe-rename archive ensure-extension) + (let ((exitcode (funcall proc-fn archive))) + (or (zerop exitcode) + (error "Updating was unsuccessful (%S)" exitcode)))) + (progn (archive--maybe-rename archive ensure-extension) + (revert-buffer nil t))))))) +;; ------------------------------------------------------------------------- ;;; Section: the mode definition ;;;###autoload @@ -1378,16 +1421,9 @@ archive-*-write-file-member (setq ename (encode-coding-string ename archive-file-name-coding-system)) (let* ((coding-system-for-write 'no-conversion) - (default-directory (file-name-as-directory archive-tmpdir)) - (exitcode (apply #'call-process - (car command) - nil - nil - nil - (append (cdr command) - (list archive ename))))) - (or (zerop exitcode) - (error "Updating was unsuccessful (%S)" exitcode)))) + (default-directory (file-name-as-directory archive-tmpdir))) + (archive--with-ensure-extension + archive (archive--act-files command (list ename))))) (archive-delete-local tmpfile)))) (defun archive-write-file (&optional file) @@ -1510,9 +1546,7 @@ archive-chgrp-entry (archive-resummarize)) (error "Setting group is not supported for this archive type")))) -(defun archive-expunge () - "Do the flagged deletions." - (interactive) +(defun archive--expunge-maybe-force (force) (let (files) (save-excursion (goto-char archive-file-list-start) @@ -1526,7 +1560,8 @@ archive-expunge (and files (or (not archive-read-only) (error "Archive is read-only")) - (or (yes-or-no-p (format "Really delete %d member%s? " + (or force + (yes-or-no-p (format "Really delete %d member%s? " (length files) (if (null (cdr files)) "" "s"))) (error "Operation aborted")) @@ -1540,13 +1575,14 @@ archive-expunge (archive-resummarize) (revert-buffer)))))) +(defun archive-expunge () + "Do the flagged deletions." + (interactive) + (archive--expunge-maybe-force nil)) + (defun archive-*-expunge (archive files command) - (apply #'call-process - (car command) - nil - nil - nil - (append (cdr command) (cons archive files)))) + (archive--with-ensure-extension + archive (archive--act-files command files))) (defun archive-rename-entry (newname) "Change the name associated with this entry in the archive file." diff --git a/test/lisp/arc-mode-tests.el b/test/lisp/arc-mode-tests.el index 32bce1b71bd..b6e06a563fe 100644 --- a/test/lisp/arc-mode-tests.el +++ b/test/lisp/arc-mode-tests.el @@ -46,6 +46,73 @@ arc-mode-test-zip-extract-gz (when (buffer-live-p zip-buffer) (kill-buffer zip-buffer)) (when (buffer-live-p gz-buffer) (kill-buffer gz-buffer))))) +(ert-deftest arc-mode-test-zip-ensure-ext () + "Regression test for bug#61326." + (skip-unless (executable-find "zip")) + (let* ((default-directory arc-mode-tests-data-directory) + (base-zip-1 "base-1.zip") + (base-zip-2 "base-2.zip") + (content-1 '("1" "2")) + (content-2 '("3" "4")) + (make-file (lambda (name) + (with-temp-buffer + (insert name) + (write-file name)))) + (make-zip + (lambda (zip files) + (delete-file zip nil) + (funcall (archive--act-files '("zip") files) zip))) + (update-fn + (lambda (zip-nonempty) + (with-current-buffer (find-file-noselect zip-nonempty) + (save-excursion + (goto-char archive-file-list-start) + (save-current-buffer + (archive-extract) + (save-excursion + (goto-char (point-max)) + (insert ?a) + (save-buffer)) + (kill-buffer (current-buffer))) + (archive-extract) + ;; [2] must be ?a; [3] must be (eobp) + (should (eq (char-after 2) ?a)) + (should (eq (point-max) 3)))))) + (delete-fn + (lambda (zip-nonempty) + (with-current-buffer (find-file-noselect zip-nonempty) + ;; mark delete and expunge first entry + (save-excursion + (goto-char archive-file-list-start) + (should (length= archive-files 2)) + (archive-flag-deleted 1) + (archive--expunge-maybe-force t) + (should (length= archive-files 1)))))) + (test-modify + (lambda (zip mod-fn) + (let ((zip-base (concat zip ".zip")) + (tag (gensym))) + (copy-file base-zip-1 zip t) + (copy-file base-zip-2 zip-base t) + (file-has-changed-p zip tag) + (file-has-changed-p zip-base tag) + (funcall mod-fn zip) + (should-not (file-has-changed-p zip-base tag)) + (should (file-has-changed-p zip tag)))))) + ;; setup: make two zip files with different contents + (mapc make-file (append content-1 content-2)) + (mapc (lambda (args) (apply make-zip args)) + (list (list base-zip-1 content-1) + (list base-zip-2 content-2))) + ;; test 1: with "test-update" and "test-update.zip", update + ;; "test-update": (1) ensure only "test-update" is modified, (2) + ;; ensure the contents of the new member is expected. + (funcall test-modify "test-update" update-fn) + ;; test 2: with "test-delete" and "test-delete.zip", delete entry + ;; from "test-delete": (1) ensure only "test-delete" is modified, + ;; (2) ensure the file list is reduced as expected. + (funcall test-modify "test-delete" delete-fn))) + (provide 'arc-mode-tests) ;;; arc-mode-tests.el ends here -- 2.40.0 [-- Attachment #3: Type: text/plain, Size: 273 bytes --] Here attached is a patch _with_ indentation changes (on functions which I have touched) -- I simply re-indented these functions without tabs. Not sure if you want this, so I provided the other patch file as an alternative. Please choose whichever you prefer to install. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #4: Patch *with* indentation changes --] [-- Type: text/x-patch, Size: 12416 bytes --] From 36c5f839042e39b3d49e7939543b988142103033 Mon Sep 17 00:00:00 2001 From: Ruijie Yu <ruijie+git@netyu.xyz> Date: Mon, 6 Mar 2023 11:03:32 +0800 Subject: [PATCH] Handle modifications on extensionless zips correctly (Bug#61326) * lisp/arc-mode.el (archive-*-write-file-member) (archive-*-expunge): Refactor to correctly modify extensionless zip archives. (archive-expunge): Move implementation to a separate helper function to facilitate testing. (archive--act-files): New helper function to wrap around `call-process' calls. (archive--need-rename-p): New helper function to check whether a temporary rename is necessary. (archive--ensure-extension) (archive--maybe-rename): New helper functions to rename archive if the caller deems it necessary. (archive--with-ensure-extension): New helper function to handle writing an archive while ensuring extensionless archives work correctly by temporarily renaming them. * test/lisp/arc-mode-tests.el (arc-mode-test-zip-ensure-ext): New regression test for bug#61326. --- lisp/arc-mode.el | 144 ++++++++++++++++++++++-------------- test/lisp/arc-mode-tests.el | 67 +++++++++++++++++ 2 files changed, 157 insertions(+), 54 deletions(-) diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el index 5e696c091b2..89b3e720ed9 100644 --- a/lisp/arc-mode.el +++ b/lisp/arc-mode.el @@ -645,6 +645,49 @@ archive-get-descr (if (not noerror) (error "Line does not describe a member of the archive"))))) ;; ------------------------------------------------------------------------- +;;; Section: Helper functions for requiring filename extensions + +(defun archive--act-files (command files) + (lambda (archive) + (apply #'call-process (car command) + nil nil nil (append (cdr command) (cons archive files))))) + +(defun archive--need-rename-p (&optional archive) + (let ((archive + (file-name-nondirectory (or archive buffer-file-name)))) + (cl-case archive-subtype + ((zip) (not (seq-contains-p archive ?. #'eq)))))) + +(defun archive--ensure-extension (archive ensure-extension) + (if ensure-extension + (make-temp-name (expand-file-name (concat archive "_tmp."))) + archive)) + +(defun archive--maybe-rename (newname need-rename-p) + ;; Operating with archive as current buffer, and protect + ;; `default-directory' from being modified in `rename-visited-file'. + (when need-rename-p + (let ((default-directory default-directory)) + (rename-visited-file newname)))) + +(defun archive--with-ensure-extension (archive proc-fn) + (let ((saved default-directory)) + (with-current-buffer (find-buffer-visiting archive) + (let ((ensure-extension (archive--need-rename-p)) + (default-directory saved)) + (unwind-protect + ;; Some archive programs (like zip) expect filenames to + ;; have an extension, so if necessary, temporarily rename + ;; an extensionless file for write accesses. + (let ((archive (archive--ensure-extension + archive ensure-extension))) + (archive--maybe-rename archive ensure-extension) + (let ((exitcode (funcall proc-fn archive))) + (or (zerop exitcode) + (error "Updating was unsuccessful (%S)" exitcode)))) + (progn (archive--maybe-rename archive ensure-extension) + (revert-buffer nil t))))))) +;; ------------------------------------------------------------------------- ;;; Section: the mode definition ;;;###autoload @@ -1357,37 +1400,30 @@ archive-*-write-file-member (ename (archive--file-desc-ext-file-name descr)) (tmpfile (expand-file-name ename archive-tmpdir)) (top (directory-file-name (file-name-as-directory archive-tmpdir))) - (default-directory (file-name-as-directory top))) + (default-directory (file-name-as-directory top))) (unwind-protect (progn (make-directory (file-name-directory tmpfile) t) - ;; If the member is itself an archive, write it without - ;; the dired-like listing we created. - (if (eq major-mode 'archive-mode) - (archive-write-file tmpfile) - (write-region nil nil tmpfile nil 'nomessage)) - ;; basic-save-buffer needs last-coding-system-used to have - ;; the value used to write the file, so save it before any - ;; further processing clobbers it (we restore it in - ;; archive-write-file-member, above). - (setq archive-member-coding-system last-coding-system-used) - (if (archive--file-desc-mode descr) - ;; Set the file modes, but make sure we can read it. - (set-file-modes tmpfile - (logior ?\400 (archive--file-desc-mode descr)))) - (setq ename - (encode-coding-string ename archive-file-name-coding-system)) + ;; If the member is itself an archive, write it without + ;; the dired-like listing we created. + (if (eq major-mode 'archive-mode) + (archive-write-file tmpfile) + (write-region nil nil tmpfile nil 'nomessage)) + ;; basic-save-buffer needs last-coding-system-used to have + ;; the value used to write the file, so save it before any + ;; further processing clobbers it (we restore it in + ;; archive-write-file-member, above). + (setq archive-member-coding-system last-coding-system-used) + (if (archive--file-desc-mode descr) + ;; Set the file modes, but make sure we can read it. + (set-file-modes tmpfile + (logior ?\400 (archive--file-desc-mode descr)))) + (setq ename + (encode-coding-string ename archive-file-name-coding-system)) (let* ((coding-system-for-write 'no-conversion) - (default-directory (file-name-as-directory archive-tmpdir)) - (exitcode (apply #'call-process - (car command) - nil - nil - nil - (append (cdr command) - (list archive ename))))) - (or (zerop exitcode) - (error "Updating was unsuccessful (%S)" exitcode)))) + (default-directory (file-name-as-directory archive-tmpdir))) + (archive--with-ensure-extension + archive (archive--act-files command (list ename))))) (archive-delete-local tmpfile)))) (defun archive-write-file (&optional file) @@ -1510,43 +1546,43 @@ archive-chgrp-entry (archive-resummarize)) (error "Setting group is not supported for this archive type")))) -(defun archive-expunge () - "Do the flagged deletions." - (interactive) +(defun archive--expunge-maybe-force (force) (let (files) (save-excursion (goto-char archive-file-list-start) (while (< (point) archive-file-list-end) (if (= (following-char) ?D) - (setq files (cons (archive--file-desc-ext-file-name - (archive-get-descr)) - files))) + (setq files (cons (archive--file-desc-ext-file-name + (archive-get-descr)) + files))) (forward-line 1))) (setq files (nreverse files)) (and files - (or (not archive-read-only) - (error "Archive is read-only")) - (or (yes-or-no-p (format "Really delete %d member%s? " - (length files) - (if (null (cdr files)) "" "s"))) - (error "Operation aborted")) - (let ((archive (archive-maybe-copy (buffer-file-name))) - (expunger (archive-name "expunge"))) - (if (fboundp expunger) - (funcall expunger archive files) - (archive-*-expunge archive files (symbol-value expunger))) - (archive-maybe-update nil) - (if archive-remote - (archive-resummarize) - (revert-buffer)))))) + (or (not archive-read-only) + (error "Archive is read-only")) + (or force + (yes-or-no-p (format "Really delete %d member%s? " + (length files) + (if (null (cdr files)) "" "s"))) + (error "Operation aborted")) + (let ((archive (archive-maybe-copy (buffer-file-name))) + (expunger (archive-name "expunge"))) + (if (fboundp expunger) + (funcall expunger archive files) + (archive-*-expunge archive files (symbol-value expunger))) + (archive-maybe-update nil) + (if archive-remote + (archive-resummarize) + (revert-buffer)))))) + +(defun archive-expunge () + "Do the flagged deletions." + (interactive) + (archive--expunge-maybe-force nil)) (defun archive-*-expunge (archive files command) - (apply #'call-process - (car command) - nil - nil - nil - (append (cdr command) (cons archive files)))) + (archive--with-ensure-extension + archive (archive--act-files command files))) (defun archive-rename-entry (newname) "Change the name associated with this entry in the archive file." diff --git a/test/lisp/arc-mode-tests.el b/test/lisp/arc-mode-tests.el index 32bce1b71bd..b6e06a563fe 100644 --- a/test/lisp/arc-mode-tests.el +++ b/test/lisp/arc-mode-tests.el @@ -46,6 +46,73 @@ arc-mode-test-zip-extract-gz (when (buffer-live-p zip-buffer) (kill-buffer zip-buffer)) (when (buffer-live-p gz-buffer) (kill-buffer gz-buffer))))) +(ert-deftest arc-mode-test-zip-ensure-ext () + "Regression test for bug#61326." + (skip-unless (executable-find "zip")) + (let* ((default-directory arc-mode-tests-data-directory) + (base-zip-1 "base-1.zip") + (base-zip-2 "base-2.zip") + (content-1 '("1" "2")) + (content-2 '("3" "4")) + (make-file (lambda (name) + (with-temp-buffer + (insert name) + (write-file name)))) + (make-zip + (lambda (zip files) + (delete-file zip nil) + (funcall (archive--act-files '("zip") files) zip))) + (update-fn + (lambda (zip-nonempty) + (with-current-buffer (find-file-noselect zip-nonempty) + (save-excursion + (goto-char archive-file-list-start) + (save-current-buffer + (archive-extract) + (save-excursion + (goto-char (point-max)) + (insert ?a) + (save-buffer)) + (kill-buffer (current-buffer))) + (archive-extract) + ;; [2] must be ?a; [3] must be (eobp) + (should (eq (char-after 2) ?a)) + (should (eq (point-max) 3)))))) + (delete-fn + (lambda (zip-nonempty) + (with-current-buffer (find-file-noselect zip-nonempty) + ;; mark delete and expunge first entry + (save-excursion + (goto-char archive-file-list-start) + (should (length= archive-files 2)) + (archive-flag-deleted 1) + (archive--expunge-maybe-force t) + (should (length= archive-files 1)))))) + (test-modify + (lambda (zip mod-fn) + (let ((zip-base (concat zip ".zip")) + (tag (gensym))) + (copy-file base-zip-1 zip t) + (copy-file base-zip-2 zip-base t) + (file-has-changed-p zip tag) + (file-has-changed-p zip-base tag) + (funcall mod-fn zip) + (should-not (file-has-changed-p zip-base tag)) + (should (file-has-changed-p zip tag)))))) + ;; setup: make two zip files with different contents + (mapc make-file (append content-1 content-2)) + (mapc (lambda (args) (apply make-zip args)) + (list (list base-zip-1 content-1) + (list base-zip-2 content-2))) + ;; test 1: with "test-update" and "test-update.zip", update + ;; "test-update": (1) ensure only "test-update" is modified, (2) + ;; ensure the contents of the new member is expected. + (funcall test-modify "test-update" update-fn) + ;; test 2: with "test-delete" and "test-delete.zip", delete entry + ;; from "test-delete": (1) ensure only "test-delete" is modified, + ;; (2) ensure the file list is reduced as expected. + (funcall test-modify "test-delete" delete-fn))) + (provide 'arc-mode-tests) ;;; arc-mode-tests.el ends here -- 2.40.0 [-- Attachment #5: Type: text/plain, Size: 128 bytes --] -- Best, RY [Please note that this mail might go to spam due to some misconfiguration in my mail server -- will fix soon.] ^ permalink raw reply related [flat|nested] 28+ messages in thread
* bug#61326: [PATCH v5] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) 2023-04-20 8:49 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-04-20 9:29 ` Eli Zaretskii 0 siblings, 0 replies; 28+ messages in thread From: Eli Zaretskii @ 2023-04-20 9:29 UTC (permalink / raw) To: Ruijie Yu; +Cc: asjo, 61326-done > From: Ruijie Yu <ruijie@netyu.xyz> > Cc: asjo@koldfront.dk, 61326@debbugs.gnu.org, bug-gnu-emacs@gnu.org > Date: Thu, 20 Apr 2023 16:49:29 +0800 > > Eli Zaretskii <eliz@gnu.org> writes: > > > However, the patch as posted back then no longer applies. Please > > rebase on the current master branch and re-post. > > > > Thanks. > > Thanks. I have made one change after the previous iteration: I turned > the "bug#xxx" comment in the test/lisp/arc-mode-tests.el into a > docstring. Also, interestingly, git-rebase finishes cleanly on my end. > > Here attached is a patch _without_ indentation changes. Thanks, the first patch applied cleanly, so I've now pushed this to the master branch, and I'm closing this bug. ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: Adding --no-add-suffix to zip patch 2023-02-07 1:31 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-07 3:27 ` Eli Zaretskii @ 2023-02-07 19:59 ` Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-08 1:21 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 1 reply; 28+ messages in thread From: Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-07 19:59 UTC (permalink / raw) To: 61326 Ruijie writes: > Maybe, at least in the meantime, we change it such that all write > operations for zip create files in temp, and move to / overwrite the > original file when done? Although I don’t have a full understanding on > how that would be done and whether there are problems along with it. That sounds like a good solution, for archives with no '.' in the filename. I guess the main problem is if the archive is huge, updating an existing archive might (?) be more efficient than creating an entirely new one. Another way to go about it could be to temporarily rename the archive to have a name with a '.' in it, make the change, and then rename it back; conceptually: mv a a.zip # update a.zip rather than a mv a.zip a That has its own set of possible problems. Maybe you could make a link to the original archive, where the link has a '.' in the name, have zip update the file via the link and then remove the link again; conceptually: ln a a.zip # update a.zip rather than a rm a.zip I think I like this the most, but again... ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: Adding --no-add-suffix to zip patch 2023-02-07 19:59 ` bug#61326: Adding --no-add-suffix to zip patch Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-08 1:21 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-08 3:28 ` Eli Zaretskii 0 siblings, 1 reply; 28+ messages in thread From: Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-08 1:21 UTC (permalink / raw) To: Adam Sjøgren; +Cc: 61326 Adam Sjøgren via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> writes: > Ruijie writes: > >> Maybe, at least in the meantime, we change it such that all write >> operations for zip create files in temp, and move to / overwrite the >> original file when done? Although I don’t have a full understanding on >> how that would be done and whether there are problems along with it. > > That sounds like a good solution, for archives with no '.' in the filename. > > I guess the main problem is if the archive is huge, updating an existing > archive might (?) be more efficient than creating an entirely new one. > > Another way to go about it could be to temporarily rename the archive to > have a name with a '.' in it, make the change, and then rename it back; > conceptually: > > mv a a.zip > # update a.zip rather than a > mv a.zip a > > That has its own set of possible problems. > > Maybe you could make a link to the original archive, where the link has > a '.' in the name, have zip update the file via the link and then remove > the link again; conceptually: > > ln a a.zip > # update a.zip rather than a > rm a.zip > > I think I like this the most, but again... I like the link solution, but I don't think we can reliably "link" without knowing that we actually can do so -- i.e., on MS Windows, IIUC, one needs admin privilege to create symlinks on cmd unless something in the registry is changed. Also, on old MS Windows versions like XP and earier, I believe it is impossible to create symlinks at all. (Do we still support them?) Come to think of it, I think your mv idea might be better and even easier to implement than my zip-offsite-then-overwrite idea. I might lean towards that method if people have no bias when I work on the patch in a couple hours. Best, RY ^ permalink raw reply [flat|nested] 28+ messages in thread
* bug#61326: Adding --no-add-suffix to zip patch 2023-02-08 1:21 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-08 3:28 ` Eli Zaretskii 0 siblings, 0 replies; 28+ messages in thread From: Eli Zaretskii @ 2023-02-08 3:28 UTC (permalink / raw) To: Ruijie Yu; +Cc: asjo, 61326 > Cc: 61326@debbugs.gnu.org > Date: Wed, 08 Feb 2023 09:21:11 +0800 > From: Ruijie Yu via "Bug reports for GNU Emacs, > the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> > > Also, on old MS Windows versions like XP and earier, I believe it is > impossible to create symlinks at all. (Do we still support them?) Yes, we do. ^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2023-04-20 9:29 UTC | newest] Thread overview: 28+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-02-06 17:00 bug#61326: 30.0.50; Editing fil in zip file without extension save creates new file Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-06 18:04 ` Eli Zaretskii 2023-02-06 18:15 ` Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-06 18:57 ` bug#61326: Adding --no-add-suffix to zip patch Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-07 1:31 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-07 3:27 ` Eli Zaretskii 2023-02-07 13:53 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-07 14:54 ` Eli Zaretskii 2023-02-08 16:48 ` bug#61326: [DRAFT PATCH] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-08 18:02 ` Eli Zaretskii 2023-02-10 8:40 ` bug#61326: [DRAFT PATCH v2] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-13 10:35 ` bug#61326: [DRAFT PATCH v3] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-03-04 11:21 ` Eli Zaretskii 2023-03-04 14:56 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-03-04 15:12 ` Eli Zaretskii 2023-03-05 15:23 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-03-05 15:52 ` Eli Zaretskii 2023-03-06 4:05 ` bug#61326: [DRAFT PATCH v4] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-03-11 8:54 ` Eli Zaretskii 2023-03-11 8:57 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-03-17 3:19 ` bug#61326: [DRAFT PATCH v5] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-04-17 8:48 ` bug#61326: [PATCH " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-04-20 7:47 ` Eli Zaretskii 2023-04-20 8:49 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-04-20 9:29 ` Eli Zaretskii 2023-02-07 19:59 ` bug#61326: Adding --no-add-suffix to zip patch Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-08 1:21 ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-02-08 3:28 ` Eli Zaretskii
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).