From 6e8f8e5c9f74094fadebbea16e6d3777133e414c Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Sat, 4 Mar 2023 22:11:23 -0800 Subject: [PATCH] Support setting umask symbolically in Eshell * lisp/eshell/em-basic.el (eshell/umask): Handle setting umask symbolically, and make setting umask take precedence over "-S". * test/lisp/eshell/em-basic-tests.el (em-basic-test/umask-print-numeric, em-basic-test/umask-read-symbolic, em-basic-test/umask-set): Rename to... (em-basic-test/umask/print-numeric) (em-basic-test/umask/print-symbolic, em-basic-test/umask/set-numeric): ... these. (em-basic-test/umask/set-symbolic, em-basic-test/umask/set-with-S): New tests. * etc/NEWS: Announce this change. (cherry picked from commit a3cd284b90edcc7e06b21110cdbf55d11fb6fd0d) --- etc/NEWS | 8 +++++++ lisp/eshell/em-basic.el | 24 ++++++++++++--------- test/lisp/eshell/em-basic-tests.el | 34 ++++++++++++++++++++++++++---- 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 34e38129c73..abcd3bc3c3c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -661,6 +661,14 @@ command passed as arguments to 'env'. If you pass any initial arguments of the form 'VAR=VALUE', 'env' will first set 'VAR' to 'VALUE' before running the command. +--- +*** Eshell's 'umask' command now supports setting the mask symbolically. +Now, you can pass an argument like "u+w,o-r" to Eshell's 'umask' +command, which will give write permission for owners of newly-created +files and deny read permission for users who are not members of the +file's group. See the Info node '(coreutils)File permissions' for +more information on this notation. + +++ *** New special reference type '#'. This special reference type returns a marker at 'POSITION' in diff --git a/lisp/eshell/em-basic.el b/lisp/eshell/em-basic.el index 8f68a750bd7..6ec53ef9412 100644 --- a/lisp/eshell/em-basic.el +++ b/lisp/eshell/em-basic.el @@ -160,6 +160,18 @@ or `eshell-printn' for display." :preserve-args :usage "[-S] [mode]") (cond + (args + (let* ((mask (car args)) + (modes + (if (stringp mask) + (if (string-match (rx bos (+ (any "0-7")) eos) mask) + (- #o777 (string-to-number mask 8)) + (file-modes-symbolic-to-number + mask (default-file-modes))) + (- #o777 mask)))) + (set-default-file-modes modes) + (eshell-print + "Warning: umask changed for all new files created by Emacs.\n"))) (symbolic-p (let ((mode (default-file-modes))) (eshell-printn @@ -173,17 +185,9 @@ or `eshell-printn' for display." (concat (and (= (logand mode 1) 1) "r") (and (= (logand mode 2) 2) "w") (and (= (logand mode 4) 4) "x")))))) - ((not args) - (eshell-printn (format "%03o" (logand (lognot (default-file-modes)) - #o777)))) (t - (when (stringp (car args)) - (if (string-match "^[0-7]+$" (car args)) - (setcar args (string-to-number (car args) 8)) - (error "Setting umask symbolically is not yet implemented"))) - (set-default-file-modes (- #o777 (car args))) - (eshell-print - "Warning: umask changed for all new files created by Emacs.\n"))) + (eshell-printn (format "%03o" (logand (lognot (default-file-modes)) + #o777))))) nil)) (put 'eshell/umask 'eshell-no-numeric-conversions t) diff --git a/test/lisp/eshell/em-basic-tests.el b/test/lisp/eshell/em-basic-tests.el index 960e04690a5..ebb91cdeea0 100644 --- a/test/lisp/eshell/em-basic-tests.el +++ b/test/lisp/eshell/em-basic-tests.el @@ -33,7 +33,7 @@ ;;; Tests: -(ert-deftest em-basic-test/umask-print-numeric () +(ert-deftest em-basic-test/umask/print-numeric () "Test printing umask numerically." (cl-letf (((symbol-function 'default-file-modes) (lambda () #o775))) (eshell-command-result-equal "umask" "002\n")) @@ -43,7 +43,7 @@ (cl-letf (((symbol-function 'default-file-modes) (lambda () #o1775))) (eshell-command-result-equal "umask" "002\n"))) -(ert-deftest em-basic-test/umask-read-symbolic () +(ert-deftest em-basic-test/umask/print-symbolic () "Test printing umask symbolically." (cl-letf (((symbol-function 'default-file-modes) (lambda () #o775))) (eshell-command-result-equal "umask -S" @@ -56,8 +56,8 @@ (eshell-command-result-equal "umask -S" "u=rwx,g=rwx,o=rx\n"))) -(ert-deftest em-basic-test/umask-set () - "Test setting umask." +(ert-deftest em-basic-test/umask/set-numeric () + "Test setting umask numerically." (let ((file-modes 0)) (cl-letf (((symbol-function 'set-default-file-modes) (lambda (mode) (setq file-modes mode)))) @@ -68,4 +68,30 @@ (eshell-test-command-result "umask $(identity #o222)") (should (= file-modes #o555))))) +(ert-deftest em-basic-test/umask/set-symbolic () + "Test setting umask symbolically." + (let ((file-modes 0)) + (cl-letf (((symbol-function 'default-file-modes) + (lambda() file-modes)) + ((symbol-function 'set-default-file-modes) + (lambda (mode) (setq file-modes mode)))) + (eshell-test-command-result "umask u=rwx,g=rwx,o=rx") + (should (= file-modes #o775)) + (eshell-test-command-result "umask u=rw,g=rx,o=x") + (should (= file-modes #o651)) + (eshell-test-command-result "umask u+x,o-x") + (should (= file-modes #o750)) + (eshell-test-command-result "umask a+rx") + (should (= file-modes #o755))))) + +(ert-deftest em-basic-test/umask/set-with-S () + "Test that passing \"-S\" and a umask still sets the umask." + (let ((file-modes 0)) + (cl-letf (((symbol-function 'set-default-file-modes) + (lambda (mode) (setq file-modes mode)))) + (eshell-test-command-result "umask -S 002") + (should (= file-modes #o775)) + (eshell-test-command-result "umask -S 123") + (should (= file-modes #o654))))) + ;; em-basic-tests.el ends here -- 2.39.5