* bug#72992: 29.4; towards xoauth2 support in Emacs
@ 2024-09-02 8:34 Xiyue Deng
[not found] ` <handler.72992.B.172532159013230.ack@debbugs.gnu.org>
` (2 more replies)
0 siblings, 3 replies; 26+ messages in thread
From: Xiyue Deng @ 2024-09-02 8:34 UTC (permalink / raw)
To: 72992
[-- Attachment #1: Type: text/plain, Size: 72591 bytes --]
Now that bug#72358 is done, as promised, I'm posting my plugin for
auth-sources that enables oauth2 handling which you can find on
Gitlab[1] (also attached). As the current approach tries to override
some existing handling in auth-source, I would like to gather some
comments on how to properly integrate this handling, and see if there is
any benefit on providing this as a separate package for older Emacs
versions.
In the comment section of the package I put notes on how xoauth2 is
enabled as well as existing restrictions in auth-source and how it
workarounds them. I'll briefly explain below.
Currently, auth-source search requires that the result include `:secret'
most of the time, where when using xoauth2 it is actually the
access-token. Actually, auth-source has existing support for xoauth2
authentication, though it assumes that the password value actually
stores the access-token. Because xoauth2 also makes use of
`secret'/`password', it makes it hard to determine whether to use
password-based or xoauth2-based authentication, which is why my plugin
asks users to set `auth' in auth-source to determine whether to use
xoauth2. Another complication from this is that auth-source search
requires the entry contains a `secret' most of the time, where it does
not need to be set when using xoauth2. Therefore I workaround this by
temporarily disables this check and try to retrieve access-token using
oauth2 and set the result as password.
Given the inconveniences of reusing password for access-token, I wonder
whether we can add support for a separate `:access-token' key in the
auth-source entry and use that instead of password when authenticating
using xoauth2. This way, we can have both password and access-token in
an auth-source entry and nnimap and smtpmail can use either one. More
specifically:
* When performing an auth-source search, if xoauth2 related fields are
set (see the list of fields in the comments of my plugin), it will
retrieve access-token using oauth2.
* The search should change to check for either `secret'/`password' or
`access-token' is available.
* For `nnimap-login' and `smtpmail-try-auth-method', pass in both
password and access-token, and for xoauth2 it should use access-token
instead of password.
If this is an acceptable approach, I'll try to draft a patch to
implement this in Emacs. Otherwise, it may still worth implement the
current approach directly in Emacs so as to avoid using hack like
advice.
Meanwhile, I wonder whether this may be worth release as a separate
package so that users of older versions can use xoauth2 as well. I'd
like to make it compatible with the agreed-upon approach to minimize any
incompatibilities.
Thanks for reading, and any comments are appreciated.
[1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin
In GNU Emacs 29.4 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.38,
cairo version 1.16.0) of 2024-07-02, modified by Debian built on
debian-hx90
System Description: Debian GNU/Linux 12 (bookworm)
Configured using:
'configure --build x86_64-linux-gnu --prefix=/usr
--sharedstatedir=/var/lib --libexecdir=/usr/libexec
--localstatedir=/var/lib --infodir=/usr/share/info
--mandir=/usr/share/man --with-libsystemd --with-pop=yes
--enable-locallisppath=/etc/emacs:/usr/local/share/emacs/29.4/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/29.4/site-lisp:/usr/share/emacs/site-lisp
--with-sound=alsa --without-gconf --with-mailutils
--with-native-compilation --build x86_64-linux-gnu --prefix=/usr
--sharedstatedir=/var/lib --libexecdir=/usr/libexec
--localstatedir=/var/lib --infodir=/usr/share/info
--mandir=/usr/share/man --with-libsystemd --with-pop=yes
--enable-locallisppath=/etc/emacs:/usr/local/share/emacs/29.4/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/29.4/site-lisp:/usr/share/emacs/site-lisp
--with-sound=alsa --without-gconf --with-mailutils
--with-native-compilation --with-cairo --with-x=yes
--with-x-toolkit=gtk3 --with-toolkit-scroll-bars 'CFLAGS=-g -O2
-ffile-prefix-map=/build/emacs-UNWIcy/emacs-29.4+1=. -fstack-protector-strong
-Wformat -Werror=format-security -Wall' 'CPPFLAGS=-Wdate-time
-D_FORTIFY_SOURCE=2' LDFLAGS=-Wl,-z,relro'
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_US.UTF-8
locale-coding-system: utf-8-unix
Major mode: Lisp Interaction
Minor modes in effect:
global-git-commit-mode: t
magit-auto-revert-mode: t
shell-dirtrack-mode: t
mu4e-modeline-mode: t
windmove-mode: t
rcirc-track-minor-mode: t
server-mode: t
subword-mode: t
bug-reference-prog-mode: t
whitespace-mode: t
yas-minor-mode: t
xclip-mode: t
global-treesit-auto-mode: t
treemacs-project-follow-mode: t
treemacs-follow-mode: t
treemacs-git-mode: t
treemacs-fringe-indicator-mode: t
corfu-terminal-mode: t
corfu-popupinfo-mode: t
corfu-echo-mode: t
global-corfu-mode: t
corfu-mode: t
activities-tabs-mode: t
activities-mode: t
fido-vertical-mode: t
icomplete-vertical-mode: t
icomplete-mode: t
fido-mode: t
override-global-mode: t
global-display-line-numbers-mode: t
display-line-numbers-mode: t
global-auto-revert-mode: t
tooltip-mode: t
global-eldoc-mode: t
eldoc-mode: t
show-paren-mode: t
electric-indent-mode: t
mouse-wheel-mode: t
tool-bar-mode: t
tab-bar-mode: t
file-name-shadow-mode: t
global-font-lock-mode: t
font-lock-mode: t
blink-cursor-mode: t
column-number-mode: t
line-number-mode: t
transient-mark-mode: t
auto-composition-mode: t
auto-encryption-mode: t
auto-compression-mode: t
Load-path shadows:
/usr/share/emacs/site-lisp/elpa/debian-el-37.16/debian-autoloads hides /usr/share/emacs/site-lisp/elpa/gnuplot-0.8.1/debian-autoloads
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-section hides /usr/share/emacs/site-lisp/elpa/magit-section-3.3.0/magit-section
/usr/share/emacs/site-lisp/elpa/ace-window-0.10.0/ace-window-autoloads hides /usr/share/emacs/site-lisp/elpa-src/ace-window-0.10.0/ace-window-autoloads
/usr/share/emacs/site-lisp/elpa/ace-window-0.10.0/ace-window-pkg hides /usr/share/emacs/site-lisp/elpa-src/ace-window-0.10.0/ace-window-pkg
/usr/share/emacs/site-lisp/elpa/ace-window-0.10.0/ace-window hides /usr/share/emacs/site-lisp/elpa-src/ace-window-0.10.0/ace-window
/usr/share/emacs/site-lisp/elpa/activities-0.7.1/activities-autoloads hides /usr/share/emacs/site-lisp/elpa-src/activities-0.7.1/activities-autoloads
/usr/share/emacs/site-lisp/elpa/activities-0.7.1/activities-pkg hides /usr/share/emacs/site-lisp/elpa-src/activities-0.7.1/activities-pkg
/usr/share/emacs/site-lisp/elpa/activities-0.7.1/activities-list hides /usr/share/emacs/site-lisp/elpa-src/activities-0.7.1/activities-list
/usr/share/emacs/site-lisp/elpa/activities-0.7.1/activities hides /usr/share/emacs/site-lisp/elpa-src/activities-0.7.1/activities
/usr/share/emacs/site-lisp/elpa/activities-0.7.1/activities-tabs hides /usr/share/emacs/site-lisp/elpa-src/activities-0.7.1/activities-tabs
/usr/share/emacs/site-lisp/elpa/apache-mode-2.2.0/apache-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/apache-mode-2.2.0/apache-mode-autoloads
/usr/share/emacs/site-lisp/elpa/apache-mode-2.2.0/apache-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/apache-mode-2.2.0/apache-mode-pkg
/usr/share/emacs/site-lisp/elpa/apache-mode-2.2.0/apache-mode hides /usr/share/emacs/site-lisp/elpa-src/apache-mode-2.2.0/apache-mode
/usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-info hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-info
/usr/share/emacs/site-lisp/elpa/auctex-13.3/latex-flymake hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/latex-flymake
/usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-site hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-site
/usr/share/emacs/site-lisp/elpa/auctex-13.3/texmathp hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/texmathp
/usr/share/emacs/site-lisp/elpa/auctex-13.3/toolbar-x hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/toolbar-x
/usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-style hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-style
/usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-font hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-font
/usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-jp hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-jp
/usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-mik hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-mik
/usr/share/emacs/site-lisp/elpa/auctex-13.3/plain-tex hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/plain-tex
/usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-fold hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-fold
/usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-ispell hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-ispell
/usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-bar hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-bar
/usr/share/emacs/site-lisp/elpa/auctex-13.3/preview-latex hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/preview-latex
/usr/share/emacs/site-lisp/elpa/auctex-13.3/bib-cite hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/bib-cite
/usr/share/emacs/site-lisp/elpa/auctex-13.3/preview hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/preview
/usr/share/emacs/site-lisp/elpa/auctex-13.3/context-nl hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/context-nl
/usr/share/emacs/site-lisp/elpa/auctex-13.3/auto-loads hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/auto-loads
/usr/share/emacs/site-lisp/elpa/auctex-13.3/multi-prompt hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/multi-prompt
/usr/share/emacs/site-lisp/elpa/auctex-13.3/context-en hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/context-en
/usr/share/emacs/site-lisp/elpa/auctex-13.3/lpath hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/lpath
/usr/share/emacs/site-lisp/elpa/auctex-13.3/auctex hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/auctex
/usr/share/emacs/site-lisp/elpa/auctex-13.3/tex hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex
/usr/share/emacs/site-lisp/elpa/auctex-13.3/auctex-autoloads hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/auctex-autoloads
/usr/share/emacs/site-lisp/elpa/auctex-13.3/font-latex hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/font-latex
/usr/share/emacs/site-lisp/elpa/auctex-13.3/auctex-pkg hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/auctex-pkg
/usr/share/emacs/site-lisp/elpa/auctex-13.3/context hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/context
/usr/share/emacs/site-lisp/elpa/auctex-13.3/latex hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/latex
/usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-wizard hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-wizard
/usr/share/emacs/site-lisp/elpa/avy-0.5.0/avy hides /usr/share/emacs/site-lisp/elpa-src/avy-0.5.0/avy
/usr/share/emacs/site-lisp/elpa/avy-0.5.0/avy-autoloads hides /usr/share/emacs/site-lisp/elpa-src/avy-0.5.0/avy-autoloads
/usr/share/emacs/site-lisp/elpa/avy-0.5.0/avy-pkg hides /usr/share/emacs/site-lisp/elpa-src/avy-0.5.0/avy-pkg
/usr/share/emacs/site-lisp/elpa/bazel-0/bazel-autoloads hides /usr/share/emacs/site-lisp/elpa-src/bazel-0/bazel-autoloads
/usr/share/emacs/site-lisp/elpa/bazel-0/bazel hides /usr/share/emacs/site-lisp/elpa-src/bazel-0/bazel
/usr/share/emacs/site-lisp/elpa/bazel-0/test hides /usr/share/emacs/site-lisp/elpa-src/bazel-0/test
/usr/share/emacs/site-lisp/elpa/bazel-0/bazel-pkg hides /usr/share/emacs/site-lisp/elpa-src/bazel-0/bazel-pkg
/usr/share/emacs/site-lisp/elpa/bison-mode-0.3/bison-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/bison-mode-0.3/bison-mode-pkg
/usr/share/emacs/site-lisp/elpa/bison-mode-0.3/bison-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/bison-mode-0.3/bison-mode-autoloads
/usr/share/emacs/site-lisp/elpa/bison-mode-0.3/bison-mode hides /usr/share/emacs/site-lisp/elpa-src/bison-mode-0.3/bison-mode
/usr/share/emacs/site-lisp/elpa/boxquote-2.3/boxquote hides /usr/share/emacs/site-lisp/elpa-src/boxquote-2.3/boxquote
/usr/share/emacs/site-lisp/elpa/boxquote-2.3/boxquote-autoloads hides /usr/share/emacs/site-lisp/elpa-src/boxquote-2.3/boxquote-autoloads
/usr/share/emacs/site-lisp/elpa/boxquote-2.3/boxquote-pkg hides /usr/share/emacs/site-lisp/elpa-src/boxquote-2.3/boxquote-pkg
/usr/share/emacs/site-lisp/elpa/buttercup-1.26/buttercup-pkg hides /usr/share/emacs/site-lisp/elpa-src/buttercup-1.26/buttercup-pkg
/usr/share/emacs/site-lisp/elpa/buttercup-1.26/buttercup hides /usr/share/emacs/site-lisp/elpa-src/buttercup-1.26/buttercup
/usr/share/emacs/site-lisp/elpa/buttercup-1.26/buttercup-autoloads hides /usr/share/emacs/site-lisp/elpa-src/buttercup-1.26/buttercup-autoloads
/usr/share/emacs/site-lisp/elpa/buttercup-1.26/buttercup-compat hides /usr/share/emacs/site-lisp/elpa-src/buttercup-1.26/buttercup-compat
/usr/share/emacs/site-lisp/elpa/cfrs-1.6.0/cfrs-pkg hides /usr/share/emacs/site-lisp/elpa-src/cfrs-1.6.0/cfrs-pkg
/usr/share/emacs/site-lisp/elpa/cfrs-1.6.0/cfrs hides /usr/share/emacs/site-lisp/elpa-src/cfrs-1.6.0/cfrs
/usr/share/emacs/site-lisp/elpa/cfrs-1.6.0/cfrs-autoloads hides /usr/share/emacs/site-lisp/elpa-src/cfrs-1.6.0/cfrs-autoloads
/usr/share/emacs/site-lisp/elpa/clojure-mode-5.19.0/clojure-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/clojure-mode-5.19.0/clojure-mode-pkg
/usr/share/emacs/site-lisp/elpa/clojure-mode-5.19.0/clojure-mode hides /usr/share/emacs/site-lisp/elpa-src/clojure-mode-5.19.0/clojure-mode
/usr/share/emacs/site-lisp/elpa/clojure-mode-5.19.0/clojure-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/clojure-mode-5.19.0/clojure-mode-autoloads
/usr/share/emacs/site-lisp/elpa/clojure-mode-extra-font-locking-3.0.0/clojure-mode-extra-font-locking-pkg hides /usr/share/emacs/site-lisp/elpa-src/clojure-mode-extra-font-locking-3.0.0/clojure-mode-extra-font-locking-pkg
/usr/share/emacs/site-lisp/elpa/clojure-mode-extra-font-locking-3.0.0/clojure-mode-extra-font-locking-autoloads hides /usr/share/emacs/site-lisp/elpa-src/clojure-mode-extra-font-locking-3.0.0/clojure-mode-extra-font-locking-autoloads
/usr/share/emacs/site-lisp/elpa/clojure-mode-extra-font-locking-3.0.0/clojure-mode-extra-font-locking hides /usr/share/emacs/site-lisp/elpa-src/clojure-mode-extra-font-locking-3.0.0/clojure-mode-extra-font-locking
/usr/share/emacs/site-lisp/elpa/cmake-mode-3.29.0/cmake-mode hides /usr/share/emacs/site-lisp/elpa-src/cmake-mode-3.29.0/cmake-mode
/usr/share/emacs/site-lisp/elpa/cmake-mode-3.29.0/cmake-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/cmake-mode-3.29.0/cmake-mode-autoloads
/usr/share/emacs/site-lisp/elpa/cmake-mode-3.29.0/cmake-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/cmake-mode-3.29.0/cmake-mode-pkg
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-dabbrev hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-dabbrev
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-capf hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-capf
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-yasnippet hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-yasnippet
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-ispell hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-ispell
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-etags hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-etags
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-template hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-template
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-abbrev hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-abbrev
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-files hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-files
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-css hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-css
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-tests hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-tests
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-dabbrev-code hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-dabbrev-code
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-pkg hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-pkg
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-oddmuse hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-oddmuse
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-bbdb hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-bbdb
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-clang hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-clang
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-nxml hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-nxml
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-gtags hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-gtags
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-tempo hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-tempo
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-autoloads hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-autoloads
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-cmake hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-cmake
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-tng hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-tng
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-elisp hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-elisp
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-semantic hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-semantic
/usr/share/emacs/site-lisp/elpa/company-0.10.2/company-keywords hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-keywords
/usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-26 hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-26
/usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-28 hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-28
/usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-macs hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-macs
/usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-autoloads hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-autoloads
/usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-pkg hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-pkg
/usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-25 hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-25
/usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-30 hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-30
/usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-29 hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-29
/usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-27 hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-27
/usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat
/usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu
/usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-quick hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-quick
/usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-info hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-info
/usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-history hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-history
/usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-popupinfo hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-popupinfo
/usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-indexed hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-indexed
/usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-pkg hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-pkg
/usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-echo hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-echo
/usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-autoloads hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-autoloads
/usr/share/emacs/site-lisp/elpa/corfu-terminal-0.7/corfu-terminal-autoloads hides /usr/share/emacs/site-lisp/elpa-src/corfu-terminal-0.7/corfu-terminal-autoloads
/usr/share/emacs/site-lisp/elpa/corfu-terminal-0.7/corfu-terminal-pkg hides /usr/share/emacs/site-lisp/elpa-src/corfu-terminal-0.7/corfu-terminal-pkg
/usr/share/emacs/site-lisp/elpa/corfu-terminal-0.7/corfu-terminal hides /usr/share/emacs/site-lisp/elpa-src/corfu-terminal-0.7/corfu-terminal
/usr/share/emacs/site-lisp/elpa/csv-mode-1.23/csv-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/csv-mode-1.23/csv-mode-autoloads
/usr/share/emacs/site-lisp/elpa/csv-mode-1.23/csv-mode hides /usr/share/emacs/site-lisp/elpa-src/csv-mode-1.23/csv-mode
/usr/share/emacs/site-lisp/elpa/csv-mode-1.23/csv-mode-tests hides /usr/share/emacs/site-lisp/elpa-src/csv-mode-1.23/csv-mode-tests
/usr/share/emacs/site-lisp/elpa/csv-mode-1.23/csv-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/csv-mode-1.23/csv-mode-pkg
/usr/share/emacs/site-lisp/elpa/dart-mode-1.0.7/dart-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/dart-mode-1.0.7/dart-mode-autoloads
/usr/share/emacs/site-lisp/elpa/dart-mode-1.0.7/dart-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/dart-mode-1.0.7/dart-mode-pkg
/usr/share/emacs/site-lisp/elpa/dart-mode-1.0.7/dart-mode hides /usr/share/emacs/site-lisp/elpa-src/dart-mode-1.0.7/dart-mode
/usr/share/emacs/site-lisp/elpa/dash-2.19.1/dash hides /usr/share/emacs/site-lisp/elpa-src/dash-2.19.1/dash
/usr/share/emacs/site-lisp/elpa/dash-2.19.1/dash-pkg hides /usr/share/emacs/site-lisp/elpa-src/dash-2.19.1/dash-pkg
/usr/share/emacs/site-lisp/elpa/dash-2.19.1/dash-autoloads hides /usr/share/emacs/site-lisp/elpa-src/dash-2.19.1/dash-autoloads
/usr/share/emacs/site-lisp/elpa/debian-el-37.16/debian-el-autoloads hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/debian-el-autoloads
/usr/share/emacs/site-lisp/elpa/debian-el-37.16/apt-sources hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/apt-sources
/usr/share/emacs/site-lisp/elpa/debian-el-37.16/debian-bug hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/debian-bug
/usr/share/emacs/site-lisp/elpa/debian-el-37.16/apt-utils hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/apt-utils
/usr/share/emacs/site-lisp/elpa/debian-el-37.16/debian-el-pkg hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/debian-el-pkg
/usr/share/emacs/site-lisp/elpa/debian-el-37.16/debian-autoloads hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/debian-autoloads
/usr/share/emacs/site-lisp/elpa/debian-el-37.16/gnus-BTS hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/gnus-BTS
/usr/share/emacs/site-lisp/elpa/debian-el-37.16/deb-view hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/deb-view
/usr/share/emacs/site-lisp/elpa/debian-el-37.16/debian-el hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/debian-el
/usr/share/emacs/site-lisp/elpa/debian-el-37.16/preseed hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/preseed
/usr/share/emacs/site-lisp/elpa/debpaste-0.1.5/debpaste hides /usr/share/emacs/site-lisp/elpa-src/debpaste-0.1.5/debpaste
/usr/share/emacs/site-lisp/elpa/debpaste-0.1.5/debpaste-pkg hides /usr/share/emacs/site-lisp/elpa-src/debpaste-0.1.5/debpaste-pkg
/usr/share/emacs/site-lisp/elpa/debpaste-0.1.5/debpaste-autoloads hides /usr/share/emacs/site-lisp/elpa-src/debpaste-0.1.5/debpaste-autoloads
/usr/share/emacs/site-lisp/elpa/devscripts-40/devscripts hides /usr/share/emacs/site-lisp/elpa-src/devscripts-40/devscripts
/usr/share/emacs/site-lisp/elpa/devscripts-40/devscripts-autoloads hides /usr/share/emacs/site-lisp/elpa-src/devscripts-40/devscripts-autoloads
/usr/share/emacs/site-lisp/elpa/devscripts-40/pbuilder-mode hides /usr/share/emacs/site-lisp/elpa-src/devscripts-40/pbuilder-mode
/usr/share/emacs/site-lisp/elpa/devscripts-40/devscripts-pkg hides /usr/share/emacs/site-lisp/elpa-src/devscripts-40/devscripts-pkg
/usr/share/emacs/site-lisp/elpa/devscripts-40/pbuilder-log-view-mode hides /usr/share/emacs/site-lisp/elpa-src/devscripts-40/pbuilder-log-view-mode
/usr/share/emacs/site-lisp/elpa/dockerfile-mode-1.7/dockerfile-mode hides /usr/share/emacs/site-lisp/elpa-src/dockerfile-mode-1.7/dockerfile-mode
/usr/share/emacs/site-lisp/elpa/dockerfile-mode-1.7/dockerfile-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/dockerfile-mode-1.7/dockerfile-mode-autoloads
/usr/share/emacs/site-lisp/elpa/dockerfile-mode-1.7/dockerfile-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/dockerfile-mode-1.7/dockerfile-mode-pkg
/usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/debian-bts-control hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/debian-bts-control
/usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/debian-changelog-mode hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/debian-changelog-mode
/usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/debian-autopkgtest-control-mode hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/debian-autopkgtest-control-mode
/usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/dpkg-dev-el-autoloads hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/dpkg-dev-el-autoloads
/usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/dpkg-dev-el-pkg hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/dpkg-dev-el-pkg
/usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/dpkg-dev-el hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/dpkg-dev-el
/usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/debian-control-mode hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/debian-control-mode
/usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/debian-copyright hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/debian-copyright
/usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/readme-debian hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/readme-debian
/usr/share/emacs/site-lisp/elpa/exec-path-from-shell-2.1/exec-path-from-shell hides /usr/share/emacs/site-lisp/elpa-src/exec-path-from-shell-2.1/exec-path-from-shell
/usr/share/emacs/site-lisp/elpa/exec-path-from-shell-2.1/exec-path-from-shell-autoloads hides /usr/share/emacs/site-lisp/elpa-src/exec-path-from-shell-2.1/exec-path-from-shell-autoloads
/usr/share/emacs/site-lisp/elpa/exec-path-from-shell-2.1/exec-path-from-shell-pkg hides /usr/share/emacs/site-lisp/elpa-src/exec-path-from-shell-2.1/exec-path-from-shell-pkg
/usr/share/emacs/site-lisp/elpa/format-all-0.6.0/format-all hides /usr/share/emacs/site-lisp/elpa-src/format-all-0.6.0/format-all
/usr/share/emacs/site-lisp/elpa/format-all-0.6.0/format-all-pkg hides /usr/share/emacs/site-lisp/elpa-src/format-all-0.6.0/format-all-pkg
/usr/share/emacs/site-lisp/elpa/format-all-0.6.0/format-all-autoloads hides /usr/share/emacs/site-lisp/elpa-src/format-all-0.6.0/format-all-autoloads
/usr/share/emacs/site-lisp/elpa/git-commit-3.3.0/git-commit hides /usr/share/emacs/site-lisp/elpa-src/git-commit-3.3.0/git-commit
/usr/share/emacs/site-lisp/elpa/git-commit-3.3.0/git-commit-autoloads hides /usr/share/emacs/site-lisp/elpa-src/git-commit-3.3.0/git-commit-autoloads
/usr/share/emacs/site-lisp/elpa/git-commit-3.3.0/git-commit-pkg hides /usr/share/emacs/site-lisp/elpa-src/git-commit-3.3.0/git-commit-pkg
/usr/share/emacs/site-lisp/elpa/git-modes-1.4.2/git-modes hides /usr/share/emacs/site-lisp/elpa-src/git-modes-1.4.2/git-modes
/usr/share/emacs/site-lisp/elpa/git-modes-1.4.2/git-modes-pkg hides /usr/share/emacs/site-lisp/elpa-src/git-modes-1.4.2/git-modes-pkg
/usr/share/emacs/site-lisp/elpa/git-modes-1.4.2/git-modes-autoloads hides /usr/share/emacs/site-lisp/elpa-src/git-modes-1.4.2/git-modes-autoloads
/usr/share/emacs/site-lisp/elpa/gitattributes-mode-1.4.2/gitattributes-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/gitattributes-mode-1.4.2/gitattributes-mode-pkg
/usr/share/emacs/site-lisp/elpa/gitattributes-mode-1.4.2/gitattributes-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/gitattributes-mode-1.4.2/gitattributes-mode-autoloads
/usr/share/emacs/site-lisp/elpa/gitattributes-mode-1.4.2/gitattributes-mode hides /usr/share/emacs/site-lisp/elpa-src/gitattributes-mode-1.4.2/gitattributes-mode
/usr/share/emacs/site-lisp/elpa/gitconfig-mode-1.4.2/gitconfig-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/gitconfig-mode-1.4.2/gitconfig-mode-autoloads
/usr/share/emacs/site-lisp/elpa/gitconfig-mode-1.4.2/gitconfig-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/gitconfig-mode-1.4.2/gitconfig-mode-pkg
/usr/share/emacs/site-lisp/elpa/gitconfig-mode-1.4.2/gitconfig-mode hides /usr/share/emacs/site-lisp/elpa-src/gitconfig-mode-1.4.2/gitconfig-mode
/usr/share/emacs/site-lisp/elpa/gitignore-mode-1.4.2/gitignore-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/gitignore-mode-1.4.2/gitignore-mode-pkg
/usr/share/emacs/site-lisp/elpa/gitignore-mode-1.4.2/gitignore-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/gitignore-mode-1.4.2/gitignore-mode-autoloads
/usr/share/emacs/site-lisp/elpa/gitignore-mode-1.4.2/gitignore-mode hides /usr/share/emacs/site-lisp/elpa-src/gitignore-mode-1.4.2/gitignore-mode
/usr/share/emacs/site-lisp/elpa/gnuplot-0.8.1/gnuplot hides /usr/share/emacs/site-lisp/elpa-src/gnuplot-0.8.1/gnuplot
/usr/share/emacs/site-lisp/elpa/gnuplot-0.8.1/gnuplot-autoloads hides /usr/share/emacs/site-lisp/elpa-src/gnuplot-0.8.1/gnuplot-autoloads
/usr/share/emacs/site-lisp/elpa/debian-el-37.16/debian-autoloads hides /usr/share/emacs/site-lisp/elpa-src/gnuplot-0.8.1/debian-autoloads
/usr/share/emacs/site-lisp/elpa/gnuplot-0.8.1/gnuplot-pkg hides /usr/share/emacs/site-lisp/elpa-src/gnuplot-0.8.1/gnuplot-pkg
/usr/share/emacs/site-lisp/elpa/gnuplot-0.8.1/gnuplot-context hides /usr/share/emacs/site-lisp/elpa-src/gnuplot-0.8.1/gnuplot-context
/usr/share/emacs/site-lisp/elpa/gnuplot-0.8.1/gnuplot-gui hides /usr/share/emacs/site-lisp/elpa-src/gnuplot-0.8.1/gnuplot-gui
/usr/share/emacs/site-lisp/elpa/go-mode-1.6.0/go-mode hides /usr/share/emacs/site-lisp/elpa-src/go-mode-1.6.0/go-mode
/usr/share/emacs/site-lisp/elpa/go-mode-1.6.0/go-guru hides /usr/share/emacs/site-lisp/elpa-src/go-mode-1.6.0/go-guru
/usr/share/emacs/site-lisp/elpa/go-mode-1.6.0/go-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/go-mode-1.6.0/go-mode-pkg
/usr/share/emacs/site-lisp/elpa/go-mode-1.6.0/go-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/go-mode-1.6.0/go-mode-autoloads
/usr/share/emacs/site-lisp/elpa/go-mode-1.6.0/go-rename hides /usr/share/emacs/site-lisp/elpa-src/go-mode-1.6.0/go-rename
/usr/share/emacs/site-lisp/elpa/graphviz-dot-mode-0.4.2/graphviz-dot-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/graphviz-dot-mode-0.4.2/graphviz-dot-mode-autoloads
/usr/share/emacs/site-lisp/elpa/graphviz-dot-mode-0.4.2/graphviz-dot-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/graphviz-dot-mode-0.4.2/graphviz-dot-mode-pkg
/usr/share/emacs/site-lisp/elpa/graphviz-dot-mode-0.4.2/graphviz-dot-mode hides /usr/share/emacs/site-lisp/elpa-src/graphviz-dot-mode-0.4.2/graphviz-dot-mode
/usr/share/emacs/site-lisp/elpa/ht-2.3/ht-pkg hides /usr/share/emacs/site-lisp/elpa-src/ht-2.3/ht-pkg
/usr/share/emacs/site-lisp/elpa/ht-2.3/ht-autoloads hides /usr/share/emacs/site-lisp/elpa-src/ht-2.3/ht-autoloads
/usr/share/emacs/site-lisp/elpa/ht-2.3/ht hides /usr/share/emacs/site-lisp/elpa-src/ht-2.3/ht
/usr/share/emacs/site-lisp/elpa/hydra-0.15.0/hydra-ox hides /usr/share/emacs/site-lisp/elpa-src/hydra-0.15.0/hydra-ox
/usr/share/emacs/site-lisp/elpa/hydra-0.15.0/hydra-autoloads hides /usr/share/emacs/site-lisp/elpa-src/hydra-0.15.0/hydra-autoloads
/usr/share/emacs/site-lisp/elpa/hydra-0.15.0/hydra-pkg hides /usr/share/emacs/site-lisp/elpa-src/hydra-0.15.0/hydra-pkg
/usr/share/emacs/site-lisp/elpa/hydra-0.15.0/hydra-examples hides /usr/share/emacs/site-lisp/elpa-src/hydra-0.15.0/hydra-examples
/usr/share/emacs/site-lisp/elpa/hydra-0.15.0/hydra hides /usr/share/emacs/site-lisp/elpa-src/hydra-0.15.0/hydra
/usr/share/emacs/site-lisp/elpa/inheritenv-0.2/inheritenv hides /usr/share/emacs/site-lisp/elpa-src/inheritenv-0.2/inheritenv
/usr/share/emacs/site-lisp/elpa/inheritenv-0.2/inheritenv-autoloads hides /usr/share/emacs/site-lisp/elpa-src/inheritenv-0.2/inheritenv-autoloads
/usr/share/emacs/site-lisp/elpa/inheritenv-0.2/inheritenv-pkg hides /usr/share/emacs/site-lisp/elpa-src/inheritenv-0.2/inheritenv-pkg
/usr/share/emacs/site-lisp/elpa/inheritenv-0.2/inheritenv-tests hides /usr/share/emacs/site-lisp/elpa-src/inheritenv-0.2/inheritenv-tests
/usr/share/emacs/site-lisp/elpa/language-id-0.20/language-id hides /usr/share/emacs/site-lisp/elpa-src/language-id-0.20/language-id
/usr/share/emacs/site-lisp/elpa/language-id-0.20/language-id-pkg hides /usr/share/emacs/site-lisp/elpa-src/language-id-0.20/language-id-pkg
/usr/share/emacs/site-lisp/elpa/language-id-0.20/language-id-autoloads hides /usr/share/emacs/site-lisp/elpa-src/language-id-0.20/language-id-autoloads
/usr/share/emacs/site-lisp/elpa/lintian-0.1/lintian-pkg hides /usr/share/emacs/site-lisp/elpa-src/lintian-0.1/lintian-pkg
/usr/share/emacs/site-lisp/elpa/lintian-0.1/lintian-autoloads hides /usr/share/emacs/site-lisp/elpa-src/lintian-0.1/lintian-autoloads
/usr/share/emacs/site-lisp/elpa/lintian-0.1/lintian hides /usr/share/emacs/site-lisp/elpa-src/lintian-0.1/lintian
/usr/share/emacs/site-lisp/elpa/lua-mode-20221027/lua-mode hides /usr/share/emacs/site-lisp/elpa-src/lua-mode-20221027/lua-mode
/usr/share/emacs/site-lisp/elpa/lua-mode-20221027/lua-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/lua-mode-20221027/lua-mode-autoloads
/usr/share/emacs/site-lisp/elpa/lua-mode-20221027/init-tryout hides /usr/share/emacs/site-lisp/elpa-src/lua-mode-20221027/init-tryout
/usr/share/emacs/site-lisp/elpa/lua-mode-20221027/lua-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/lua-mode-20221027/lua-mode-pkg
/usr/share/emacs/site-lisp/elpa/lv-0.15.0/lv-autoloads hides /usr/share/emacs/site-lisp/elpa-src/lv-0.15.0/lv-autoloads
/usr/share/emacs/site-lisp/elpa/lv-0.15.0/lv hides /usr/share/emacs/site-lisp/elpa-src/lv-0.15.0/lv
/usr/share/emacs/site-lisp/elpa/lv-0.15.0/lv-pkg hides /usr/share/emacs/site-lisp/elpa-src/lv-0.15.0/lv-pkg
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-remote hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-remote
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/git-rebase hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/git-rebase
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-bisect hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-bisect
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-margin hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-margin
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-merge hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-merge
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-section hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-section
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-patch hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-patch
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-commit hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-commit
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-autoloads hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-autoloads
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-files hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-files
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-stash hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-stash
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-bookmark hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-bookmark
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-submodule hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-submodule
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-apply hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-apply
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-repos hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-repos
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-core hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-core
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-subtree hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-subtree
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-autorevert hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-autorevert
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-gitignore hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-gitignore
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-transient hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-transient
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-extras hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-extras
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-git hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-git
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-notes hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-notes
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-reflog hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-reflog
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-mode hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-mode
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-push hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-push
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-tag hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-tag
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-process hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-process
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-ediff hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-ediff
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-imenu hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-imenu
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-diff hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-diff
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-clone hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-clone
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-log hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-log
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-utils hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-utils
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-wip hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-wip
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-branch hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-branch
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-pull hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-pull
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-reset hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-reset
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-sequence hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-sequence
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-status hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-status
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-refs hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-refs
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-obsolete hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-obsolete
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-fetch hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-fetch
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-worktree hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-worktree
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-blame hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-blame
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-pkg hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-pkg
/usr/share/emacs/site-lisp/elpa/magit-section-3.3.0/magit-section-autoloads hides /usr/share/emacs/site-lisp/elpa-src/magit-section-3.3.0/magit-section-autoloads
/usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-section hides /usr/share/emacs/site-lisp/elpa-src/magit-section-3.3.0/magit-section
/usr/share/emacs/site-lisp/elpa/magit-section-3.3.0/magit-section-pkg hides /usr/share/emacs/site-lisp/elpa-src/magit-section-3.3.0/magit-section-pkg
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-cgen hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-cgen
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-scan hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-scan
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-publish hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-publish
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-complete hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-complete
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-syntax hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-syntax
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/tlc hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/tlc
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-netshell hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-netshell
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/semantic-matlab hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/semantic-matlab
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/mlint hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/mlint
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/company-matlab-shell hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/company-matlab-shell
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-shell-gud hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-shell-gud
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/mlgud hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/mlgud
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/srecode-matlab hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/srecode-matlab
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-compat hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-compat
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-mode-pkg
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-maint hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-maint
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/cedet-matlab hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/cedet-matlab
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-topic hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-topic
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/linemark hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/linemark
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-shell hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-shell
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/semanticdb-matlab hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/semanticdb-matlab
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-load hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-load
/usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-mode-autoloads
/usr/share/emacs/site-lisp/elpa/meson-mode-0.2/meson-mode hides /usr/share/emacs/site-lisp/elpa-src/meson-mode-0.2/meson-mode
/usr/share/emacs/site-lisp/elpa/meson-mode-0.2/utils hides /usr/share/emacs/site-lisp/elpa-src/meson-mode-0.2/utils
/usr/share/emacs/site-lisp/elpa/meson-mode-0.2/meson-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/meson-mode-0.2/meson-mode-autoloads
/usr/share/emacs/site-lisp/elpa/meson-mode-0.2/meson-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/meson-mode-0.2/meson-mode-pkg
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-draft hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-draft
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-modeline hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-modeline
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-view hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-view
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-message hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-message
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-helpers hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-helpers
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-pkg hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-pkg
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-bookmarks hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-bookmarks
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-thread hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-thread
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-mime-parts hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-mime-parts
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-server hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-server
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-query-items hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-query-items
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-contrib hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-contrib
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-window hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-window
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-config hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-config
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-autoloads hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-autoloads
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-icalendar hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-icalendar
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-mark hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-mark
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-headers hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-headers
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-org hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-org
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-contacts hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-contacts
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-speedbar hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-speedbar
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-obsolete hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-obsolete
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-vars hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-vars
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-actions hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-actions
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-main hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-main
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-search hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-search
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-notification hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-notification
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-context hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-context
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-compose hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-compose
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-lists hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-lists
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-folders hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-folders
/usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-update hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-update
/usr/share/emacs/site-lisp/elpa/nginx-mode-1.1.9/nginx-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/nginx-mode-1.1.9/nginx-mode-autoloads
/usr/share/emacs/site-lisp/elpa/nginx-mode-1.1.9/nginx-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/nginx-mode-1.1.9/nginx-mode-pkg
/usr/share/emacs/site-lisp/elpa/nginx-mode-1.1.9/nginx-mode hides /usr/share/emacs/site-lisp/elpa-src/nginx-mode-1.1.9/nginx-mode
/usr/share/emacs/site-lisp/elpa/paredit-26/paredit-autoloads hides /usr/share/emacs/site-lisp/elpa-src/paredit-26/paredit-autoloads
/usr/share/emacs/site-lisp/elpa/paredit-26/paredit-pkg hides /usr/share/emacs/site-lisp/elpa-src/paredit-26/paredit-pkg
/usr/share/emacs/site-lisp/elpa/paredit-26/paredit hides /usr/share/emacs/site-lisp/elpa-src/paredit-26/paredit
/usr/share/emacs/site-lisp/elpa/persist-0.6.1/persist hides /usr/share/emacs/site-lisp/elpa-src/persist-0.6.1/persist
/usr/share/emacs/site-lisp/elpa/persist-0.6.1/persist-pkg hides /usr/share/emacs/site-lisp/elpa-src/persist-0.6.1/persist-pkg
/usr/share/emacs/site-lisp/elpa/persist-0.6.1/persist-autoloads hides /usr/share/emacs/site-lisp/elpa-src/persist-0.6.1/persist-autoloads
/usr/share/emacs/site-lisp/elpa/pfuture-1.9/pfuture hides /usr/share/emacs/site-lisp/elpa-src/pfuture-1.9/pfuture
/usr/share/emacs/site-lisp/elpa/pfuture-1.9/pfuture-autoloads hides /usr/share/emacs/site-lisp/elpa-src/pfuture-1.9/pfuture-autoloads
/usr/share/emacs/site-lisp/elpa/pfuture-1.9/pfuture-pkg hides /usr/share/emacs/site-lisp/elpa-src/pfuture-1.9/pfuture-pkg
/usr/share/emacs/site-lisp/elpa/po-mode-0.21/po-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/po-mode-0.21/po-mode-pkg
/usr/share/emacs/site-lisp/elpa/po-mode-0.21/po-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/po-mode-0.21/po-mode-autoloads
/usr/share/emacs/site-lisp/elpa/po-mode-0.21/po-mode hides /usr/share/emacs/site-lisp/elpa-src/po-mode-0.21/po-mode
/usr/share/emacs/site-lisp/elpa/popon-0.13/popon hides /usr/share/emacs/site-lisp/elpa-src/popon-0.13/popon
/usr/share/emacs/site-lisp/elpa/popon-0.13/popon-autoloads hides /usr/share/emacs/site-lisp/elpa-src/popon-0.13/popon-autoloads
/usr/share/emacs/site-lisp/elpa/popon-0.13/popon-pkg hides /usr/share/emacs/site-lisp/elpa-src/popon-0.13/popon-pkg
/usr/share/emacs/site-lisp/elpa/posframe-1.1.7/posframe-pkg hides /usr/share/emacs/site-lisp/elpa-src/posframe-1.1.7/posframe-pkg
/usr/share/emacs/site-lisp/elpa/posframe-1.1.7/posframe-autoloads hides /usr/share/emacs/site-lisp/elpa-src/posframe-1.1.7/posframe-autoloads
/usr/share/emacs/site-lisp/elpa/posframe-1.1.7/posframe hides /usr/share/emacs/site-lisp/elpa-src/posframe-1.1.7/posframe
/usr/share/emacs/site-lisp/elpa/projectile-2.8.0/projectile-pkg hides /usr/share/emacs/site-lisp/elpa-src/projectile-2.8.0/projectile-pkg
/usr/share/emacs/site-lisp/elpa/projectile-2.8.0/projectile-autoloads hides /usr/share/emacs/site-lisp/elpa-src/projectile-2.8.0/projectile-autoloads
/usr/share/emacs/site-lisp/elpa/projectile-2.8.0/projectile hides /usr/share/emacs/site-lisp/elpa-src/projectile-2.8.0/projectile
/usr/share/emacs/site-lisp/elpa/py-isort-2016.1/py-isort hides /usr/share/emacs/site-lisp/elpa-src/py-isort-2016.1/py-isort
/usr/share/emacs/site-lisp/elpa/py-isort-2016.1/py-isort-autoloads hides /usr/share/emacs/site-lisp/elpa-src/py-isort-2016.1/py-isort-autoloads
/usr/share/emacs/site-lisp/elpa/py-isort-2016.1/py-isort-pkg hides /usr/share/emacs/site-lisp/elpa-src/py-isort-2016.1/py-isort-pkg
/usr/share/emacs/site-lisp/elpa/pyvenv-1.21/pyvenv hides /usr/share/emacs/site-lisp/elpa-src/pyvenv-1.21/pyvenv
/usr/share/emacs/site-lisp/elpa/pyvenv-1.21/pyvenv-pkg hides /usr/share/emacs/site-lisp/elpa-src/pyvenv-1.21/pyvenv-pkg
/usr/share/emacs/site-lisp/elpa/pyvenv-1.21/pyvenv-autoloads hides /usr/share/emacs/site-lisp/elpa-src/pyvenv-1.21/pyvenv-autoloads
/usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-common hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-common
/usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-mode-tests hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-mode-tests
/usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-mode-treesitter hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-mode-treesitter
/usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-cargo hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-cargo
/usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-mode-autoloads
/usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-utils hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-utils
/usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-rustfmt hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-rustfmt
/usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-mode hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-mode
/usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-playpen hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-playpen
/usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-prog-mode hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-prog-mode
/usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-mode-pkg
/usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-cargo-tests hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-cargo-tests
/usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-compile hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-compile
/usr/share/emacs/site-lisp/elpa/s-1.12.0/s-autoloads hides /usr/share/emacs/site-lisp/elpa-src/s-1.12.0/s-autoloads
/usr/share/emacs/site-lisp/elpa/s-1.12.0/s-pkg hides /usr/share/emacs/site-lisp/elpa-src/s-1.12.0/s-pkg
/usr/share/emacs/site-lisp/elpa/s-1.12.0/s hides /usr/share/emacs/site-lisp/elpa-src/s-1.12.0/s
/usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-map hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-map
/usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-indent hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-indent
/usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-syntax hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-syntax
/usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-lib hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-lib
/usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-pkg
/usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-prettify-symbols hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-prettify-symbols
/usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-compile hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-compile
/usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode
/usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-organise hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-organise
/usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-autoloads
/usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-paragraph hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-paragraph
/usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-imenu hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-imenu
/usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-fontlock hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-fontlock
/usr/share/emacs/site-lisp/elpa/seq-2.24/seq-24 hides /usr/share/emacs/site-lisp/elpa-src/seq-2.24/seq-24
/usr/share/emacs/site-lisp/elpa/seq-2.24/seq-autoloads hides /usr/share/emacs/site-lisp/elpa-src/seq-2.24/seq-autoloads
/usr/share/emacs/site-lisp/elpa/seq-2.24/seq hides /usr/share/emacs/site-lisp/elpa-src/seq-2.24/seq
/usr/share/emacs/site-lisp/elpa/seq-2.24/seq-pkg hides /usr/share/emacs/site-lisp/elpa-src/seq-2.24/seq-pkg
/usr/share/emacs/site-lisp/elpa/seq-2.24/seq-25 hides /usr/share/emacs/site-lisp/elpa-src/seq-2.24/seq-25
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-project-follow-mode hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-project-follow-mode
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-dom hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-dom
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-follow-mode hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-follow-mode
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-logging hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-logging
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-autoloads hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-autoloads
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-compatibility hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-compatibility
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-async hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-async
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-themes hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-themes
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-mouse-interface hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-mouse-interface
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-tag-follow-mode hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-tag-follow-mode
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-bookmarks hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-bookmarks
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-fringe-indicator hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-fringe-indicator
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-filewatch-mode hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-filewatch-mode
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-interface hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-interface
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-tags hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-tags
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-visuals hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-visuals
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-core-utils hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-core-utils
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-peek-mode hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-peek-mode
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-annotations hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-annotations
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-icons hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-icons
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-persistence hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-persistence
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-diagnostics hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-diagnostics
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-scope hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-scope
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-extensions hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-extensions
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-rendering hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-rendering
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-customization hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-customization
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-file-management hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-file-management
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-faces hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-faces
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-macros hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-macros
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-git-commit-diff-mode hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-git-commit-diff-mode
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-treelib hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-treelib
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-hydras hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-hydras
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-pkg hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-pkg
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-header-line hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-header-line
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-icons-dired hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-icons-dired
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-workspaces hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-workspaces
/usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-mode hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-mode
/usr/share/emacs/site-lisp/elpa/treemacs-magit-3.1/treemacs-magit hides /usr/share/emacs/site-lisp/elpa-src/treemacs-magit-3.1/treemacs-magit
/usr/share/emacs/site-lisp/elpa/treemacs-magit-3.1/treemacs-magit-pkg hides /usr/share/emacs/site-lisp/elpa-src/treemacs-magit-3.1/treemacs-magit-pkg
/usr/share/emacs/site-lisp/elpa/treemacs-magit-3.1/treemacs-magit-autoloads hides /usr/share/emacs/site-lisp/elpa-src/treemacs-magit-3.1/treemacs-magit-autoloads
/usr/share/emacs/site-lisp/elpa/treemacs-projectile-3.1/treemacs-projectile-pkg hides /usr/share/emacs/site-lisp/elpa-src/treemacs-projectile-3.1/treemacs-projectile-pkg
/usr/share/emacs/site-lisp/elpa/treemacs-projectile-3.1/treemacs-projectile-autoloads hides /usr/share/emacs/site-lisp/elpa-src/treemacs-projectile-3.1/treemacs-projectile-autoloads
/usr/share/emacs/site-lisp/elpa/treemacs-projectile-3.1/treemacs-projectile hides /usr/share/emacs/site-lisp/elpa-src/treemacs-projectile-3.1/treemacs-projectile
/usr/share/emacs/site-lisp/elpa/vterm-0.0.2/vterm-load-path hides /usr/share/emacs/site-lisp/elpa-src/vterm-0.0.2/vterm-load-path
/usr/share/emacs/site-lisp/elpa/vterm-0.0.2/vterm hides /usr/share/emacs/site-lisp/elpa-src/vterm-0.0.2/vterm
/usr/share/emacs/site-lisp/elpa/vterm-0.0.2/vterm-pkg hides /usr/share/emacs/site-lisp/elpa-src/vterm-0.0.2/vterm-pkg
/usr/share/emacs/site-lisp/elpa/vterm-0.0.2/vterm-autoloads hides /usr/share/emacs/site-lisp/elpa-src/vterm-0.0.2/vterm-autoloads
/usr/share/emacs/site-lisp/elpa/web-mode-17.3.13/web-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/web-mode-17.3.13/web-mode-pkg
/usr/share/emacs/site-lisp/elpa/web-mode-17.3.13/web-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/web-mode-17.3.13/web-mode-autoloads
/usr/share/emacs/site-lisp/elpa/web-mode-17.3.13/web-mode hides /usr/share/emacs/site-lisp/elpa-src/web-mode-17.3.13/web-mode
/usr/share/emacs/site-lisp/elpa/with-editor-3.3.2/with-editor-pkg hides /usr/share/emacs/site-lisp/elpa-src/with-editor-3.3.2/with-editor-pkg
/usr/share/emacs/site-lisp/elpa/with-editor-3.3.2/with-editor-autoloads hides /usr/share/emacs/site-lisp/elpa-src/with-editor-3.3.2/with-editor-autoloads
/usr/share/emacs/site-lisp/elpa/with-editor-3.3.2/with-editor hides /usr/share/emacs/site-lisp/elpa-src/with-editor-3.3.2/with-editor
/usr/share/emacs/site-lisp/elpa/xml-rpc-1.6.17/xml-rpc hides /usr/share/emacs/site-lisp/elpa-src/xml-rpc-1.6.17/xml-rpc
/usr/share/emacs/site-lisp/elpa/xml-rpc-1.6.17/xml-rpc-pkg hides /usr/share/emacs/site-lisp/elpa-src/xml-rpc-1.6.17/xml-rpc-pkg
/usr/share/emacs/site-lisp/elpa/xml-rpc-1.6.17/xml-rpc-autoloads hides /usr/share/emacs/site-lisp/elpa-src/xml-rpc-1.6.17/xml-rpc-autoloads
/usr/share/emacs/site-lisp/elpa/yaml-mode-0.0.16/yaml-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/yaml-mode-0.0.16/yaml-mode-pkg
/usr/share/emacs/site-lisp/elpa/yaml-mode-0.0.16/yaml-mode hides /usr/share/emacs/site-lisp/elpa-src/yaml-mode-0.0.16/yaml-mode
/usr/share/emacs/site-lisp/elpa/yaml-mode-0.0.16/yaml-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/yaml-mode-0.0.16/yaml-mode-autoloads
/usr/share/emacs/site-lisp/elpa/yasnippet-0.14.1/yasnippet-autoloads hides /usr/share/emacs/site-lisp/elpa-src/yasnippet-0.14.1/yasnippet-autoloads
/usr/share/emacs/site-lisp/elpa/yasnippet-0.14.1/yasnippet-pkg hides /usr/share/emacs/site-lisp/elpa-src/yasnippet-0.14.1/yasnippet-pkg
/usr/share/emacs/site-lisp/elpa/yasnippet-0.14.1/yasnippet hides /usr/share/emacs/site-lisp/elpa-src/yasnippet-0.14.1/yasnippet
/usr/share/emacs/site-lisp/elpa/yasnippet-snippets-20220713/yasnippet-snippets hides /usr/share/emacs/site-lisp/elpa-src/yasnippet-snippets-20220713/yasnippet-snippets
/usr/share/emacs/site-lisp/elpa/yasnippet-snippets-20220713/yasnippet-snippets-pkg hides /usr/share/emacs/site-lisp/elpa-src/yasnippet-snippets-20220713/yasnippet-snippets-pkg
/usr/share/emacs/site-lisp/elpa/yasnippet-snippets-20220713/yasnippet-snippets-autoloads hides /usr/share/emacs/site-lisp/elpa-src/yasnippet-snippets-20220713/yasnippet-snippets-autoloads
/usr/share/emacs/site-lisp/elpa/zenburn-theme-2.8.0/zenburn-theme hides /usr/share/emacs/site-lisp/elpa-src/zenburn-theme-2.8.0/zenburn-theme
/usr/share/emacs/site-lisp/elpa/zenburn-theme-2.8.0/zenburn-theme-pkg hides /usr/share/emacs/site-lisp/elpa-src/zenburn-theme-2.8.0/zenburn-theme-pkg
/usr/share/emacs/site-lisp/elpa/zenburn-theme-2.8.0/zenburn-theme-autoloads hides /usr/share/emacs/site-lisp/elpa-src/zenburn-theme-2.8.0/zenburn-theme-autoloads
/usr/share/emacs/site-lisp/elpa/seq-2.24/seq hides /usr/share/emacs/29.4/lisp/emacs-lisp/seq
Features:
(shadow emacsbug url-queue magit-extras magit-bookmark magit-submodule
magit-obsolete 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 which-func imenu magit-diff
smerge-mode diff git-commit log-edit add-log magit-core magit-autorevert
magit-margin magit-transient magit-process with-editor shell magit-mode
transient magit-git magit-section etags fileloop generator xref
shr-color help-fns radix-tree cl-print debug backtrace magit-utils crm
dired-aux mailalias po face-remap matlab matlab-scan matlab-syntax
matlab-compat qp mm-archive sort gnus-cite mail-extr textsec uni-scripts
idna-mapping ucs-normalize uni-confusable textsec-check gnus-async
gnus-bcklg gnus-ml gnus-topic cursor-sensor utf-7 url-cache nnfolder
gnus-demon nnml ezgnus gnus-delay gnus-draft gnus-agent gnus-srvr
gnus-score score-mode nnvirtual nntp gnus-cache nndraft nnmh mu4e
mu4e-org org ob ob-tangle ob-ref ob-lob ob-table ob-exp org-macro
org-src ob-comint org-pcomplete pcomplete org-list org-footnote
org-faces org-entities noutline outline ob-emacs-lisp ob-core ob-eval
org-cycle org-table ol org-fold org-fold-core org-keys oc org-loaddefs
find-func org-version org-compat org-macs format-spec mu4e-notification
notifications mu4e-main mu4e-view mu4e-mime-parts cal-menu calendar
cal-loaddefs mu4e-headers mu4e-thread mu4e-actions mu4e-compose
mu4e-draft gnus-msg gnus-art mm-uu mml2015 mm-view mml-smime smime dig
gnus-sum gnus-group gnus-undo gnus-start gnus-dbus dbus gnus-cloud
nnimap nnmail mail-source utf7 nnoo gnus-spec gnus-int gnus-range
gnus-win gnus nnheader range mu4e-search mu4e-lists mu4e-bookmarks
mu4e-mark mu4e-message shr pixel-fill kinsoku url-file svg xml dom
flow-fill mu4e-contacts mu4e-update mu4e-folders mu4e-context
mu4e-query-items mu4e-server mu4e-modeline mu4e-vars mu4e-helpers
mu4e-config mu4e-window ido message yank-media rfc822 mml mml-sec
gnus-util mm-decode mm-bodies mm-encode mailabbrev gmm-utils mailheader
mu4e-obsolete mule-util jka-compr windmove flyspell ispell gnutls
network-stream epa-file epa derived rcirc parse-time iso8601 time-date
term/xterm xterm comp comp-cstr server cap-words superword subword vc-hg
vc-git diff-mode vc-bzr vc-src vc-sccs vc-svn vc-cvs vc-rcs log-view
pcvs-util vc vc-dispatcher bug-reference disp-table whitespace
yasnippet-snippets yasnippet cus-edit cus-start wid-edit init
mu4e-debian-hx90 zenburn-theme xclip treesit-auto treesit
treemacs-project-follow-mode treemacs-follow-mode treemacs-rendering
treemacs-annotations treemacs-async treemacs-visuals
treemacs-fringe-indicator pulse color treemacs-workspaces treemacs-dom
treemacs-icons treemacs-themes treemacs-scope treemacs-core-utils
treemacs-logging treemacs-customization pfuture inline ht s hl-line dash
keychain-environment exec-path-from-shell corfu-terminal popon
corfu-popupinfo corfu-echo corfu compat compat-30 activities-tabs
activities persist bookmark pp edmacro kmacro auth-source-xoauth2-plugin
smtpmail sendmail mail-utils oauth2 url-http url-auth mail-parse rfc2231
rfc2047 rfc2045 mm-util ietf-drums mail-prsvr url-gw nsm puny plstore
epg rfc6068 epg-config advice icomplete cus-load flymake-proc flymake
project compile text-property-search comint ansi-osc ansi-color ring
warnings icons thingatpt cl-extra help-mode use-package
use-package-ensure use-package-delight use-package-diminish
use-package-bind-key bind-key easy-mmode use-package-core
display-line-numbers autorevert filenotify
keychain-environment-autoloads treesit-auto-autoloads xclip-autoloads rx
info debian-el dired dired-loaddefs 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 1284383 173587)
(symbols 48 38751 38)
(strings 32 161682 13995)
(string-bytes 1 5119905)
(vectors 16 102981)
(vector-slots 8 2547120 157205)
(floats 8 1011 1550)
(intervals 56 48502 7145)
(buffers 984 76))
--
Xiyue Deng
[-- Attachment #2: auth-source-xoauth2-plugin.el --]
[-- Type: application/emacs-lisp, Size: 6506 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
[not found] ` <handler.72992.B.172532159013230.ack@debbugs.gnu.org>
@ 2024-09-11 0:27 ` Xiyue Deng
2024-09-17 17:33 ` Xiyue Deng
0 siblings, 1 reply; 26+ messages in thread
From: Xiyue Deng @ 2024-09-11 0:27 UTC (permalink / raw)
To: 72992
Friendly ping for feedback.
--
Xiyue Deng
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-11 0:27 ` Xiyue Deng
@ 2024-09-17 17:33 ` Xiyue Deng
0 siblings, 0 replies; 26+ messages in thread
From: Xiyue Deng @ 2024-09-17 17:33 UTC (permalink / raw)
To: 72992, Philip Kaludercic
Xiyue Deng <manphiz@gmail.com> writes:
> Friendly ping for feedback.
> --
> Xiyue Deng
Another friendly ping. Also CCing Philip who kindly provided feedback
for the previous bug.
--
Xiyue Deng
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-02 8:34 bug#72992: 29.4; towards xoauth2 support in Emacs Xiyue Deng
[not found] ` <handler.72992.B.172532159013230.ack@debbugs.gnu.org>
@ 2024-09-17 19:12 ` Philip Kaludercic
2024-09-18 6:24 ` Xiyue Deng
2024-09-17 21:33 ` Stefan Kangas
2 siblings, 1 reply; 26+ messages in thread
From: Philip Kaludercic @ 2024-09-17 19:12 UTC (permalink / raw)
To: Xiyue Deng; +Cc: 72992
Xiyue Deng <manphiz@gmail.com> writes:
> Now that bug#72358 is done, as promised, I'm posting my plugin for
> auth-sources that enables oauth2 handling which you can find on
> Gitlab[1] (also attached).
Once again I just want to be sure: When you say "plugin", you mean
package, right? You are proposing to add this to GNU ELPA?
[...]
>
> Thanks for reading, and any comments are appreciated.
I'll be honest, I have no idea about OAuth, so my comments are just
related to Elisp for now. Hope that's OK!
> [1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin
> ;; Copyright (C) 2024 Xiyue Deng <manphiz@gmail.com>
>
> ;; Author: Xiyue Deng <manphiz@gmail.com>
> ;; Version: 0.1-git
> ;; Package-Requires: ((emacs "28.1") (oauth2 "0.17"))
>
> ;; This file is not part of GNU Emacs.
>
> ;; GNU Emacs is free software: you can redistribute it and/or modify
> ;; it under the terms of the GNU General Public License as published by
> ;; the Free Software Foundation, either version 3 of the License, or
> ;; (at your option) any later version.
>
> ;; GNU Emacs is distributed in the hope that it will be useful,
> ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
> ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> ;; GNU General Public License for more details.
>
> ;; You should have received a copy of the GNU General Public License
> ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
>
> ;;; Commentary:
>
> ;; This package enables support for xoauth2 authentication with
> ;; auth-source. To set up, please put this file in the `load-path' of
> ;; Emacs, and add the following lines in your Emacs configuration:
>
> ;; (require 'auth-source-xoauth2-plugin)
> ;; (auth-source-xoauth2-plugin-enable)
>
> ;; or with use-package:
>
> ;; (use-package auth-source-xoauth2-plugin
> ;; :config
> ;; (auth-source-xoauth2-plugin-enable))
>
> ;; After enabling, smtpmail should be supported. To enable this in Gnus
> ;; nnimap, you should also set `(nnimap-authenticator xoauth2)' in the
> ;; corresponding account settings in `gnus-secondary-select-methods'
>
> ;; auth-source uses the `secret' field in auth-source file as password
> ;; for authentication, including xoauth2. To decide which
> ;; authentication method to use (e.g. plain password vs xoauth2), it
> ;; inspects the `auth' field from the auth-source entry, and if the
> ;; value is `xaouth2', it will try to gather data and get the access
> ;; token for use of xoauth2 authentication; otherwise, it will fallback
> ;; to the default authentication method.
>
> ;; When xoauth2 authentication is enabled, it will try to get the
> ;; following data from the auth-source entry: `auth-url', `token-url',
> ;; `scope', `client-id', `client-secret', `redirect-uri', and optionally
> ;; `state'. These information will be used by oauth2 to retrieve the
> ;; access-token. This package uses an advice to switch the auth-source
> ;; search result from the `password' to the `access-token' it got, which
> ;; in turn will be used to construct the xoauth2 authentication string,
> ;; currently in nnimap-login and smtpmail-try-auth-method. To really
> ;; enable xoauth2 in smtpmail, it will add 'xoauth2 to
> ;; 'smtpmail-auth-supported (if it is not already in the list) using
> ;; `add-to-list' so that xoauth2 is tried first.
>
> ;; Note that currently the auth-source requires the searched entry must
> ;; have `secret' field set in the entry, which is not necessary when
> ;; using xoauth2. Therefore in the advice it temporarily disables
> ;; checking for `:secret' if set and perform the search, and check the
> ;; result before returning.
>
> ;;; Code:
>
> (require 'auth-source)
> (require 'cl-lib)
> (require 'oauth2)
> (require 'smtpmail)
>
> (defun auth-source-xoauth2-plugin--search-backends (orig-fun &rest args)
> "Perform auth-source-search and set password as access-token when requested.
> The substitution only happens if one sets `auth' to `xoauth2' in
> your auth-source-entry. It is expected that `token_url',
> `client_id', `client_secret', and `refresh_token' are properly
> set along `host', `user', and `port' (note the snake_case)."
> (auth-source-do-trivia "Advising auth-source-search")
> (let (check-secret)
> (when (memq :secret (nth 5 args))
> (auth-source-do-trivia
> "Required fields include :secret. As we are requesting access token to replace the secret, we'll temporary remove :secret from the require list and check that it's properly set to a valid access token later.")
> (setf (nth 5 args) (remove :secret (nth 5 args)))
> (setq check-secret t))
> (let ((orig-res (apply orig-fun args))
> res)
> (dolist (auth-data orig-res)
> (auth-source-do-trivia "Matched auth data: %s" (pp-to-string auth-data))
Is "trivia" the right debug level for all the messages in this function?
I feel like some of them should at least be "debug".
> (let ((auth (plist-get auth-data :auth)))
> (when (and auth
> (stringp auth)
> (string= auth "xoauth2"))
You can simplify the check by just doing (equal auth "xoauth2"), as this
implies all of the above (if it is `equal' to a string, it must be a
string and hence also non-nil).
> (auth-source-do-debug
> ":auth set to `xoauth2'. Will get access token.")
> (let ((auth-url (plist-get auth-data :auth-url))
> (token-url (plist-get auth-data :token-url))
> (scope (plist-get auth-data :scope))
> (client-id (plist-get auth-data :client-id))
> (client-secret (plist-get auth-data :client-secret))
> (redirect-uri (plist-get auth-data :redirect-uri))
> (state (plist-get auth-data :state)))
I feel like this could be simplified with a map-let expression.
(map-let (:auth-url :token-url ...) auth-data
...)
You should be able to require 'map at compile time, so that the
expansions don't occur an overhead during run-time.
> (auth-source-do-trivia "Using oauth2 to auth and store token...")
> (let ((token (oauth2-auth-and-store
> auth-url token-url scope client-id client-secret
> redirect-uri state)))
> (auth-source-do-trivia "oauth2 token: %s" (pp-to-string token))
> (auth-source-do-trivia "Refreshing token...")
> (oauth2-refresh-access token)
> (auth-source-do-trivia "oauth2 token after refresh: %s"
> (pp-to-string token))
> (let ((access-token (oauth2-token-access-token token)))
> (auth-source-do-trivia
> "Updating :secret with access-token: %s" access-token)
> (plist-put auth-data :secret access-token))))))
The documentation for plist-put warns:
The new plist is returned;
use ‘(setq x (plist-put x prop val))’ to be sure to use the new value.
The PLIST is modified by side effects.
Alternatively, you should also be able to do:
(setf (plist-get auth-data :secret) access-token)
>
> (unless (and check-secret
> (not (plist-get auth-data :secret)))
> (auth-source-do-trivia "Updating auth-source-search results.")
> (add-to-list 'res auth-data t)))
This should definitely be a `push', as `res' is lexically scoped (see
docstring for `add-to-list').
> res)))
>
> ;;;###autoload
> (defun auth-source-xoauth2-plugin-enable ()
> "Enable auth-source-xoauth2-plugin."
> (unless (memq 'xoauth2 smtpmail-auth-supported)
> (add-to-list 'smtpmail-auth-supported 'xoauth2))
In functions, it would be more conventional to use push. Especially
because `add-to-list' checks for duplicates, which you have already
done.
>
> (advice-add 'auth-source-search-backends :around
There's no reason not to sharp-quote the function here as well?
> #'auth-source-xoauth2-plugin--search-backends))
I would recommend turning this into a global minor mode instead, so that
it is easy to disable, if a user just wants to try it out.
>
> (provide 'auth-source-xoauth2-plugin)
>
> ;;; auth-source-xoauth2-plugin.el ends here
--
Philip Kaludercic on siskin
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-02 8:34 bug#72992: 29.4; towards xoauth2 support in Emacs Xiyue Deng
[not found] ` <handler.72992.B.172532159013230.ack@debbugs.gnu.org>
2024-09-17 19:12 ` Philip Kaludercic
@ 2024-09-17 21:33 ` Stefan Kangas
2024-09-18 19:43 ` Xiyue Deng
2 siblings, 1 reply; 26+ messages in thread
From: Stefan Kangas @ 2024-09-17 21:33 UTC (permalink / raw)
To: Xiyue Deng, 72992; +Cc: Ted Zlatanov
Xiyue Deng <manphiz@gmail.com> writes:
> Now that bug#72358 is done, as promised, I'm posting my plugin for
> auth-sources that enables oauth2 handling which you can find on
> Gitlab[1] (also attached). As the current approach tries to override
> some existing handling in auth-source, I would like to gather some
> comments on how to properly integrate this handling, and see if there is
> any benefit on providing this as a separate package for older Emacs
> versions.
>
> In the comment section of the package I put notes on how xoauth2 is
> enabled as well as existing restrictions in auth-source and how it
> workarounds them. I'll briefly explain below.
I think it would be good if you could add to your package some general
explanation of what xoauth2 is, and what are its use cases both in a
general sense, and specifically together with the auth-source
package. Don't assume that people already know what xoauth2 is, how it
is different from oauth2, which services use it, etc. Explain it. I
would add such general information to the beginning of the "Commentary"
section. Nothing long is needed, just a general introduction and perhaps
links for where to read more.
Some examples of when it would be used, preferably with example code for
some use cases, would also go a long way.
> Currently, auth-source search requires that the result include `:secret'
> most of the time, where when using xoauth2 it is actually the
> access-token. Actually, auth-source has existing support for xoauth2
> authentication, though it assumes that the password value actually
> stores the access-token.
Where can we find this "existing support"? Do you mean the
'auth-source-xoauth2' package on GNU ELPA?
> Because xoauth2 also makes use of
> `secret'/`password', it makes it hard to determine whether to use
> password-based or xoauth2-based authentication, which is why my plugin
> asks users to set `auth' in auth-source to determine whether to use
> xoauth2. Another complication from this is that auth-source search
> requires the entry contains a `secret' most of the time, where it does
> not need to be set when using xoauth2. Therefore I workaround this by
> temporarily disables this check and try to retrieve access-token using
> oauth2 and set the result as password.
>
> Given the inconveniences of reusing password for access-token, I wonder
> whether we can add support for a separate `:access-token' key in the
> auth-source entry and use that instead of password when authenticating
> using xoauth2. This way, we can have both password and access-token in
> an auth-source entry and nnimap and smtpmail can use either one. More
> specifically:
>
> * When performing an auth-source search, if xoauth2 related fields are
> set (see the list of fields in the comments of my plugin), it will
> retrieve access-token using oauth2.
>
> * The search should change to check for either `secret'/`password' or
> `access-token' is available.
>
> * For `nnimap-login' and `smtpmail-try-auth-method', pass in both
> password and access-token, and for xoauth2 it should use access-token
> instead of password.
>
> If this is an acceptable approach, I'll try to draft a patch to
> implement this in Emacs. Otherwise, it may still worth implement the
> current approach directly in Emacs so as to avoid using hack like
> advice.
I'm not very familiar with auth-source.el, but on a general level the
above makes sense to me. I've also Cc:ed Ted Zlatanov, the author of
auth-source.el
> Meanwhile, I wonder whether this may be worth release as a separate
> package so that users of older versions can use xoauth2 as well. I'd
> like to make it compatible with the agreed-upon approach to minimize any
> incompatibilities.
>
> Thanks for reading, and any comments are appreciated.
Are you proposing to include this in Emacs core, on GNU ELPA, or
something else?
Thanks.
> [1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-17 19:12 ` Philip Kaludercic
@ 2024-09-18 6:24 ` Xiyue Deng
2024-09-18 14:11 ` Philip Kaludercic
0 siblings, 1 reply; 26+ messages in thread
From: Xiyue Deng @ 2024-09-18 6:24 UTC (permalink / raw)
To: Philip Kaludercic; +Cc: 72992
Philip Kaludercic <philipk@posteo.net> writes:
> Xiyue Deng <manphiz@gmail.com> writes:
>
>> Now that bug#72358 is done, as promised, I'm posting my plugin for
>> auth-sources that enables oauth2 handling which you can find on
>> Gitlab[1] (also attached).
>
> Once again I just want to be sure: When you say "plugin", you mean
> package, right?
Yes, though it's not really an independent package but a "plugin" for
auth-source, a.k.a. a hack (the advice) to make auth-source to work with
xoauth2.
> You are proposing to add this to GNU ELPA?
>
Actually I would like to see which of my proposed changes to auth-source
is acceptable and update auth-source in core accordingly. I think
Stefan's reply gave some suggestions in this regard and I'll follow-up
in a reply there.
Meanwhile, it may still worth adding this package to ELPA to support
older Emacs versions if desired.
> [...]
>
>>
>> Thanks for reading, and any comments are appreciated.
>
> I'll be honest, I have no idea about OAuth, so my comments are just
> related to Elisp for now. Hope that's OK!
>
Your comments are greatly helpful and much appreciated! Please see my
replies below.
>> [1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin
>
>> ;; Copyright (C) 2024 Xiyue Deng <manphiz@gmail.com>
>>
>> ;; Author: Xiyue Deng <manphiz@gmail.com>
>> ;; Version: 0.1-git
>> ;; Package-Requires: ((emacs "28.1") (oauth2 "0.17"))
>>
>> ;; This file is not part of GNU Emacs.
>>
>> ;; GNU Emacs is free software: you can redistribute it and/or modify
>> ;; it under the terms of the GNU General Public License as published by
>> ;; the Free Software Foundation, either version 3 of the License, or
>> ;; (at your option) any later version.
>>
>> ;; GNU Emacs is distributed in the hope that it will be useful,
>> ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
>> ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> ;; GNU General Public License for more details.
>>
>> ;; You should have received a copy of the GNU General Public License
>> ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
>>
>> ;;; Commentary:
>>
>> ;; This package enables support for xoauth2 authentication with
>> ;; auth-source. To set up, please put this file in the `load-path' of
>> ;; Emacs, and add the following lines in your Emacs configuration:
>>
>> ;; (require 'auth-source-xoauth2-plugin)
>> ;; (auth-source-xoauth2-plugin-enable)
>>
>> ;; or with use-package:
>>
>> ;; (use-package auth-source-xoauth2-plugin
>> ;; :config
>> ;; (auth-source-xoauth2-plugin-enable))
>>
>> ;; After enabling, smtpmail should be supported. To enable this in Gnus
>> ;; nnimap, you should also set `(nnimap-authenticator xoauth2)' in the
>> ;; corresponding account settings in `gnus-secondary-select-methods'
>>
>> ;; auth-source uses the `secret' field in auth-source file as password
>> ;; for authentication, including xoauth2. To decide which
>> ;; authentication method to use (e.g. plain password vs xoauth2), it
>> ;; inspects the `auth' field from the auth-source entry, and if the
>> ;; value is `xaouth2', it will try to gather data and get the access
>> ;; token for use of xoauth2 authentication; otherwise, it will fallback
>> ;; to the default authentication method.
>>
>> ;; When xoauth2 authentication is enabled, it will try to get the
>> ;; following data from the auth-source entry: `auth-url', `token-url',
>> ;; `scope', `client-id', `client-secret', `redirect-uri', and optionally
>> ;; `state'. These information will be used by oauth2 to retrieve the
>> ;; access-token. This package uses an advice to switch the auth-source
>> ;; search result from the `password' to the `access-token' it got, which
>> ;; in turn will be used to construct the xoauth2 authentication string,
>> ;; currently in nnimap-login and smtpmail-try-auth-method. To really
>> ;; enable xoauth2 in smtpmail, it will add 'xoauth2 to
>> ;; 'smtpmail-auth-supported (if it is not already in the list) using
>> ;; `add-to-list' so that xoauth2 is tried first.
>>
>> ;; Note that currently the auth-source requires the searched entry must
>> ;; have `secret' field set in the entry, which is not necessary when
>> ;; using xoauth2. Therefore in the advice it temporarily disables
>> ;; checking for `:secret' if set and perform the search, and check the
>> ;; result before returning.
>>
>> ;;; Code:
>>
>> (require 'auth-source)
>> (require 'cl-lib)
>> (require 'oauth2)
>> (require 'smtpmail)
>>
>> (defun auth-source-xoauth2-plugin--search-backends (orig-fun &rest args)
>> "Perform auth-source-search and set password as access-token when requested.
>> The substitution only happens if one sets `auth' to `xoauth2' in
>> your auth-source-entry. It is expected that `token_url',
>> `client_id', `client_secret', and `refresh_token' are properly
>> set along `host', `user', and `port' (note the snake_case)."
>> (auth-source-do-trivia "Advising auth-source-search")
>> (let (check-secret)
>> (when (memq :secret (nth 5 args))
>> (auth-source-do-trivia
>> "Required fields include :secret. As we are requesting access token to replace the secret, we'll temporary remove :secret from the require list and check that it's properly set to a valid access token later.")
>> (setf (nth 5 args) (remove :secret (nth 5 args)))
>> (setq check-secret t))
>> (let ((orig-res (apply orig-fun args))
>> res)
>> (dolist (auth-data orig-res)
>> (auth-source-do-trivia "Matched auth data: %s" (pp-to-string auth-data))
>
> Is "trivia" the right debug level for all the messages in this function?
> I feel like some of them should at least be "debug".
>
Indeed. I have changed logs without token to be "debug"-level.
>> (let ((auth (plist-get auth-data :auth)))
>> (when (and auth
>> (stringp auth)
>> (string= auth "xoauth2"))
>
> You can simplify the check by just doing (equal auth "xoauth2"), as this
> implies all of the above (if it is `equal' to a string, it must be a
> string and hence also non-nil).
>
Done. Nice tip! Coming from strong-typed languages I always want to do
type-checks first in fear of any aborting error :)
>> (auth-source-do-debug
>> ":auth set to `xoauth2'. Will get access token.")
>> (let ((auth-url (plist-get auth-data :auth-url))
>> (token-url (plist-get auth-data :token-url))
>> (scope (plist-get auth-data :scope))
>> (client-id (plist-get auth-data :client-id))
>> (client-secret (plist-get auth-data :client-secret))
>> (redirect-uri (plist-get auth-data :redirect-uri))
>> (state (plist-get auth-data :state)))
>
> I feel like this could be simplified with a map-let expression.
>
> (map-let (:auth-url :token-url ...) auth-data
> ...)
>
> You should be able to require 'map at compile time, so that the
> expansions don't occur an overhead during run-time.
>
Another nice TIL!
>> (auth-source-do-trivia "Using oauth2 to auth and store token...")
>> (let ((token (oauth2-auth-and-store
>> auth-url token-url scope client-id client-secret
>> redirect-uri state)))
>> (auth-source-do-trivia "oauth2 token: %s" (pp-to-string token))
>> (auth-source-do-trivia "Refreshing token...")
>> (oauth2-refresh-access token)
>> (auth-source-do-trivia "oauth2 token after refresh: %s"
>> (pp-to-string token))
>> (let ((access-token (oauth2-token-access-token token)))
>> (auth-source-do-trivia
>> "Updating :secret with access-token: %s" access-token)
>> (plist-put auth-data :secret access-token))))))
>
> The documentation for plist-put warns:
>
> The new plist is returned;
> use ‘(setq x (plist-put x prop val))’ to be sure to use the new value.
> The PLIST is modified by side effects.
>
> Alternatively, you should also be able to do:
>
> (setf (plist-get auth-data :secret) access-token)
>
Ah didn't know this as I learned the usage of plist-put from searching.
Changed to your `setq' version. Though I'd also expect that the side
effect is not going away anytime soon either ;)
>>
>> (unless (and check-secret
>> (not (plist-get auth-data :secret)))
>> (auth-source-do-trivia "Updating auth-source-search results.")
>> (add-to-list 'res auth-data t)))
>
> This should definitely be a `push', as `res' is lexically scoped (see
> docstring for `add-to-list').
>
Indeed. Guess I got lucky here that it behaves the same.
>> res)))
>>
>> ;;;###autoload
>> (defun auth-source-xoauth2-plugin-enable ()
>> "Enable auth-source-xoauth2-plugin."
>> (unless (memq 'xoauth2 smtpmail-auth-supported)
>> (add-to-list 'smtpmail-auth-supported 'xoauth2))
>
> In functions, it would be more conventional to use push. Especially
> because `add-to-list' checks for duplicates, which you have already
> done.
>
Ack.
>>
>> (advice-add 'auth-source-search-backends :around
>
> There's no reason not to sharp-quote the function here as well?
>
Indeed. Added.
>> #'auth-source-xoauth2-plugin--search-backends))
>
> I would recommend turning this into a global minor mode instead, so that
> it is easy to disable, if a user just wants to try it out.
>
This is an interesting suggestion and sounds like a good idea. Though
as a matter of fact the oauth2 support in auth-source in Emacs core
actually doesn't work without those hack as of now, so I don't think
it's of interest to support turning off. But of course it would be
great if auth-source can be changed to support all this out-of-the-box.
Will continue the discussion in my reply to Stefan.
I have updated the source code on GitLab[1] based on your review.
Please check it out. Thanks very much!
>>
>> (provide 'auth-source-xoauth2-plugin)
>>
>> ;;; auth-source-xoauth2-plugin.el ends here
>
> --
> Philip Kaludercic on siskin
--
Xiyue Deng
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-18 6:24 ` Xiyue Deng
@ 2024-09-18 14:11 ` Philip Kaludercic
2024-09-22 7:06 ` Xiyue Deng
0 siblings, 1 reply; 26+ messages in thread
From: Philip Kaludercic @ 2024-09-18 14:11 UTC (permalink / raw)
To: Xiyue Deng; +Cc: 72992
Xiyue Deng <manphiz@gmail.com> writes:
> Philip Kaludercic <philipk@posteo.net> writes:
>
>> Xiyue Deng <manphiz@gmail.com> writes:
>>
>>> Now that bug#72358 is done, as promised, I'm posting my plugin for
>>> auth-sources that enables oauth2 handling which you can find on
>>> Gitlab[1] (also attached).
>>
>> Once again I just want to be sure: When you say "plugin", you mean
>> package, right?
>
> Yes, though it's not really an independent package but a "plugin" for
> auth-source, a.k.a. a hack (the advice) to make auth-source to work with
> xoauth2.
Just to clarify: When I say package, I mean something to add to ELPA.
>> You are proposing to add this to GNU ELPA?
>
> Actually I would like to see which of my proposed changes to auth-source
> is acceptable and update auth-source in core accordingly.
Sure it's acceptable, but in that case it would better to submit a patch
modifying. auth-source.el
> I think
> Stefan's reply gave some suggestions in this regard and I'll follow-up
> in a reply there.
I just want to second Stefan's point that some clarification as to what
xoauth2 is.
> Meanwhile, it may still worth adding this package
> to ELPA to support older Emacs versions if desired.
In that case it might be better not to merge your changes into
auth-source.el directly, as that would make it more difficult to
automatically pull your changes out of the core to ELPA.
An alternative is that ELPA mirrors your repository, and then we
manually synchronise the changes into the core, whenever there is a new
release.
[...]
>>> (let ((auth (plist-get auth-data :auth)))
>>> (when (and auth
>>> (stringp auth)
>>> (string= auth "xoauth2"))
>>
>> You can simplify the check by just doing (equal auth "xoauth2"), as this
>> implies all of the above (if it is `equal' to a string, it must be a
>> string and hence also non-nil).
>>
>
> Done. Nice tip! Coming from strong-typed languages I always want to do
> type-checks first in fear of any aborting error :)
If you want strong typing, then string= is the right thing to use,
because if you want to assume that auth is always a string, then an
error will be signalled. That being said, if auth has the type "Maybe
String", then checking the values explicitly or implicitly using equal
is the right approach.
[...]
>>> (auth-source-do-trivia "Using oauth2 to auth and store token...")
>>> (let ((token (oauth2-auth-and-store
>>> auth-url token-url scope client-id client-secret
>>> redirect-uri state)))
>>> (auth-source-do-trivia "oauth2 token: %s" (pp-to-string token))
>>> (auth-source-do-trivia "Refreshing token...")
>>> (oauth2-refresh-access token)
>>> (auth-source-do-trivia "oauth2 token after refresh: %s"
>>> (pp-to-string token))
>>> (let ((access-token (oauth2-token-access-token token)))
>>> (auth-source-do-trivia
>>> "Updating :secret with access-token: %s" access-token)
>>> (plist-put auth-data :secret access-token))))))
>>
>> The documentation for plist-put warns:
>>
>> The new plist is returned;
>> use ‘(setq x (plist-put x prop val))’ to be sure to use the new value.
>> The PLIST is modified by side effects.
>>
>> Alternatively, you should also be able to do:
>>
>> (setf (plist-get auth-data :secret) access-token)
>>
>
> Ah didn't know this as I learned the usage of plist-put from searching.
> Changed to your `setq' version. Though I'd also expect that the side
> effect is not going away anytime soon either ;)
I am not sure what you mean? The crux of the issue is demonstrated
here:
(let (plist)
(list (plist-put plist :foo 1) plist))
;; ((:foo 1) nil)
I.e. the plist was not modified, because there was no cons-cell to
modify.
[...]
>>> #'auth-source-xoauth2-plugin--search-backends))
>>
>> I would recommend turning this into a global minor mode instead, so that
>> it is easy to disable, if a user just wants to try it out.
>>
>
> This is an interesting suggestion and sounds like a good idea. Though
> as a matter of fact the oauth2 support in auth-source in Emacs core
> actually doesn't work without those hack as of now, so I don't think
> it's of interest to support turning off.
I regard it as a matter of good style to allow the user to disable
anything then can enable, if anything then just to allow better
experimentation.
> But of course it would be
> great if auth-source can be changed to support all this out-of-the-box.
> Will continue the discussion in my reply to Stefan.
Ack.
> I have updated the source code on GitLab[1] based on your review.
> Please check it out. Thanks very much!
For anyone following the thread, it seem the footnote was missing:
[1]https://gitlab.com/xiyueden/auth-source-xoauth2-plugin/-/blob/main/auth-source-xoauth2-plugin.el
Watch out, in
(unless (memq 'xoauth2 smtpmail-auth-supported)
(push 'smtpmail-auth-supported 'xoauth2))
the push expression is malformed, as 'xoauth2 is not a place. I'm
guessing that you want to write
(... (push 'xoauth2 smtpmail-auth-supported))
Also, checkdoc complains about
`auth-source-xoauth2-plugin--search-backends's docstring. I'd try to
address the issues it mentions.
The (and auth (equal auth "xoauth2")) can be further simplified to just
(equal auth "xauth2"), as if auth is equal to "xauth2" is cannot be nil.
>>>
>>> (provide 'auth-source-xoauth2-plugin)
>>>
>>> ;;; auth-source-xoauth2-plugin.el ends here
>>
>> --
>> Philip Kaludercic on siskin
--
Philip Kaludercic on siskin
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-17 21:33 ` Stefan Kangas
@ 2024-09-18 19:43 ` Xiyue Deng
2024-09-19 5:13 ` Andrew Cohen
0 siblings, 1 reply; 26+ messages in thread
From: Xiyue Deng @ 2024-09-18 19:43 UTC (permalink / raw)
To: Stefan Kangas, 72992; +Cc: Ted Zlatanov, Philip Kaludercic
Hi Stefan,
Stefan Kangas <stefankangas@gmail.com> writes:
> Xiyue Deng <manphiz@gmail.com> writes:
>
>> Now that bug#72358 is done, as promised, I'm posting my plugin for
>> auth-sources that enables oauth2 handling which you can find on
>> Gitlab[1] (also attached). As the current approach tries to override
>> some existing handling in auth-source, I would like to gather some
>> comments on how to properly integrate this handling, and see if there is
>> any benefit on providing this as a separate package for older Emacs
>> versions.
>>
>> In the comment section of the package I put notes on how xoauth2 is
>> enabled as well as existing restrictions in auth-source and how it
>> workarounds them. I'll briefly explain below.
>
> I think it would be good if you could add to your package some general
> explanation of what xoauth2 is, and what are its use cases both in a
> general sense, and specifically together with the auth-source
> package. Don't assume that people already know what xoauth2 is, how it
> is different from oauth2, which services use it, etc. Explain it. I
> would add such general information to the beginning of the "Commentary"
> section. Nothing long is needed, just a general introduction and perhaps
> links for where to read more.
>
Good suggestions. Added to the comments part.
> Some examples of when it would be used, preferably with example code for
> some use cases, would also go a long way.
>
I have added some examples on how to set it up and use it in Gnus and
smtpmail after sending the earlier version. Please check it out at [1]
(with the changes above.)
>> Currently, auth-source search requires that the result include `:secret'
>> most of the time, where when using xoauth2 it is actually the
>> access-token. Actually, auth-source has existing support for xoauth2
>> authentication, though it assumes that the password value actually
>> stores the access-token.
>
> Where can we find this "existing support"? Do you mean the
> 'auth-source-xoauth2' package on GNU ELPA?
>
The basic support is actually in the Emacs core already, e.g. for Gnus
nnimap[2] and smtpmail[3]. However, this assumes one to put the
access_token in place of `:secret' in the auth-source file as Emacs uses
password as the access_token in both places. However, access_token
expires quite frequently (e.g. about 1 hour for Gmail) and without
refreshing it automatically it is practically impossible to use
conveniently. Hence the propose hack and the following suggestion.
>> Because xoauth2 also makes use of
>> `secret'/`password', it makes it hard to determine whether to use
>> password-based or xoauth2-based authentication, which is why my plugin
>> asks users to set `auth' in auth-source to determine whether to use
>> xoauth2. Another complication from this is that auth-source search
>> requires the entry contains a `secret' most of the time, where it does
>> not need to be set when using xoauth2. Therefore I workaround this by
>> temporarily disables this check and try to retrieve access-token using
>> oauth2 and set the result as password.
>>
>> Given the inconveniences of reusing password for access-token, I wonder
>> whether we can add support for a separate `:access-token' key in the
>> auth-source entry and use that instead of password when authenticating
>> using xoauth2. This way, we can have both password and access-token in
>> an auth-source entry and nnimap and smtpmail can use either one. More
>> specifically:
>>
>> * When performing an auth-source search, if xoauth2 related fields are
>> set (see the list of fields in the comments of my plugin), it will
>> retrieve access-token using oauth2.
>>
>> * The search should change to check for either `secret'/`password' or
>> `access-token' is available.
>>
>> * For `nnimap-login' and `smtpmail-try-auth-method', pass in both
>> password and access-token, and for xoauth2 it should use access-token
>> instead of password.
>>
>> If this is an acceptable approach, I'll try to draft a patch to
>> implement this in Emacs. Otherwise, it may still worth implement the
>> current approach directly in Emacs so as to avoid using hack like
>> advice.
>
> I'm not very familiar with auth-source.el, but on a general level the
> above makes sense to me. I've also Cc:ed Ted Zlatanov, the author of
> auth-source.el
>
Thanks! Would also like to hear Ted's opinion on this and decide which
route to take.
>> Meanwhile, I wonder whether this may be worth release as a separate
>> package so that users of older versions can use xoauth2 as well. I'd
>> like to make it compatible with the agreed-upon approach to minimize any
>> incompatibilities.
>>
>> Thanks for reading, and any comments are appreciated.
>
> Are you proposing to include this in Emacs core, on GNU ELPA, or
> something else?
>
I'd like to contribute to Emacs core once a direction is decided. Maybe
also put this plugin in ELPA to support older emacs versions if both are
compatible.
> Thanks.
>
[1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin
[2] https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/gnus/nnimap.el#n616
[3] https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/mail/smtpmail.el#n640
--
Xiyue Deng
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-18 19:43 ` Xiyue Deng
@ 2024-09-19 5:13 ` Andrew Cohen
2024-09-19 8:22 ` Xiyue Deng
0 siblings, 1 reply; 26+ messages in thread
From: Andrew Cohen @ 2024-09-19 5:13 UTC (permalink / raw)
To: Xiyue Deng; +Cc: Ted Zlatanov, Philip Kaludercic, 72992, Stefan Kangas
>>>>> "XD" == Xiyue Deng <dengxiyue@gmail.com> writes:
XD> Hi Stefan, Stefan Kangas <stefankangas@gmail.com> writes:
>> Xiyue Deng <manphiz@gmail.com> writes:
>>
[...]
>>> Currently, auth-source search requires that the result include
>>> `:secret' most of the time, where when using xoauth2 it is
>>> actually the access-token. Actually, auth-source has existing
>>> support for xoauth2 authentication, though it assumes that the
>>> password value actually stores the access-token.
>>
>> Where can we find this "existing support"? Do you mean the
>> 'auth-source-xoauth2' package on GNU ELPA?
>>
XD> The basic support is actually in the Emacs core already,
XD> e.g. for Gnus nnimap[2] and smtpmail[3]. However, this assumes
XD> one to put the access_token in place of `:secret' in the
XD> auth-source file as Emacs uses password as the access_token in
XD> both places. However, access_token expires quite frequently
XD> (e.g. about 1 hour for Gmail) and without refreshing it
XD> automatically it is practically impossible to use conveniently.
XD> Hence the propose hack and the following suggestion.
This isn't actually true. When I added the support many years ago, I
updated auth-source so that the :secret field can be a function, and
this is how you should be using the current xoauth support. On the bug
thread I posted a suitable function that handles token refreshing (and
its on my list of changes to emacs that I expect to push at some
point). So everything necessary to use xoauth for nnimap and smtpmail
with auth-source, including automatic token refreshing, is already
present in emacs.
Having said that, I think some of the ideas in Xiyue's code would be
useful. However I think it would be best to base this on the existing
code which works very well and is in use by at least me (and I think
some others as well).
Best,
Andy
--
Andrew Cohen
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-19 5:13 ` Andrew Cohen
@ 2024-09-19 8:22 ` Xiyue Deng
2024-09-19 9:06 ` Andrew Cohen
0 siblings, 1 reply; 26+ messages in thread
From: Xiyue Deng @ 2024-09-19 8:22 UTC (permalink / raw)
To: Andrew Cohen; +Cc: Ted Zlatanov, Philip Kaludercic, 72992, Stefan Kangas
Hi Andrew,
Andrew Cohen <acohen@ust.hk> writes:
>>>>>> "XD" == Xiyue Deng <dengxiyue@gmail.com> writes:
>
> XD> Hi Stefan, Stefan Kangas <stefankangas@gmail.com> writes:
>
> >> Xiyue Deng <manphiz@gmail.com> writes:
> >>
>
> [...]
>
>
> >>> Currently, auth-source search requires that the result include
> >>> `:secret' most of the time, where when using xoauth2 it is
> >>> actually the access-token. Actually, auth-source has existing
> >>> support for xoauth2 authentication, though it assumes that the
> >>> password value actually stores the access-token.
> >>
> >> Where can we find this "existing support"? Do you mean the
> >> 'auth-source-xoauth2' package on GNU ELPA?
> >>
>
> XD> The basic support is actually in the Emacs core already,
> XD> e.g. for Gnus nnimap[2] and smtpmail[3]. However, this assumes
> XD> one to put the access_token in place of `:secret' in the
> XD> auth-source file as Emacs uses password as the access_token in
> XD> both places. However, access_token expires quite frequently
> XD> (e.g. about 1 hour for Gmail) and without refreshing it
> XD> automatically it is practically impossible to use conveniently.
> XD> Hence the propose hack and the following suggestion.
>
>
> This isn't actually true. When I added the support many years ago, I
> updated auth-source so that the :secret field can be a function, and
> this is how you should be using the current xoauth support.
Thanks for pointing this out! I found the place where `:secret' is
handled as a function[1]. However, this requires a user to implement
the oauth2 logic oneself, which I'm afraid is a bit too low-level and
error-prone. (Actually, can I actually put a lisp function in
auth-source.gpg?) Maybe auth-source source can host a helper function
that checks if `:secret' is not set and xaouth2 is preferred
(e.g. `:auth' is `xoauth2') and all required credentials are available
it will get the access_token and put it `:secret' (or basically my hacky
advice :)
> On the bug thread I posted a suitable function that handles token
> refreshing (and its on my list of changes to emacs that I expect to
> push at some point). So everything necessary to use xoauth for nnimap
> and smtpmail with auth-source, including automatic token refreshing,
> is already present in emacs.
>
> Having said that, I think some of the ideas in Xiyue's code would be
> useful. However I think it would be best to base this on the existing
> code which works very well and is in use by at least me (and I think
> some others as well).
>
Just remembered your comment in Bug#72358[2]. And of course if your
proposals can be part of auth-source that would be great for the users.
Still would be great to have a unified plan and make it happen.
P.S. Is your set up mentioned in Bug#72358 still working for outlook.com
emails? After reaching out to an MS representative they mentioned that
token refresh was disabled[3] for outlook.com so I just gave up. Maybe
it still works for Outlook Org emails?
> Best,
> Andy
>
>
> --
> Andrew Cohen
[1] https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/auth-source.el#n872
[2] https://debbugs.gnu.org/cgi/bugreport.cgi?bug=72358#47
[3] https://stackoverflow.com/questions/78787763/getting-aadsts65001-error-invalid-grant-when-trying-to-refresh-access-token-fo
--
Xiyue Deng
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-19 8:22 ` Xiyue Deng
@ 2024-09-19 9:06 ` Andrew Cohen
2024-09-19 22:37 ` Xiyue Deng
` (2 more replies)
0 siblings, 3 replies; 26+ messages in thread
From: Andrew Cohen @ 2024-09-19 9:06 UTC (permalink / raw)
To: Xiyue Deng; +Cc: Ted Zlatanov, Philip Kaludercic, 72992, Stefan Kangas
>>>>> "XD" == Xiyue Deng <manphiz@gmail.com> writes:
XD> Hi Andrew, Andrew Cohen <acohen@ust.hk> writes:
>>>>>>> "XD" == Xiyue Deng <dengxiyue@gmail.com> writes:
>>
[...]
XD> The basic support is actually in the Emacs core already,
XD> e.g. for Gnus nnimap[2] and smtpmail[3]. However, this assumes
XD> one to put the access_token in place of `:secret' in the
XD> auth-source file as Emacs uses password as the access_token in
XD> both places. However, access_token expires quite frequently
XD> (e.g. about 1 hour for Gmail) and without refreshing it
XD> automatically it is practically impossible to use conveniently.
XD> Hence the propose hack and the following suggestion.
>>
>>
>> This isn't actually true. When I added the support many years
>> ago, I updated auth-source so that the :secret field can be a
>> function, and this is how you should be using the current xoauth
>> support.
XD> Thanks for pointing this out! I found the place where `:secret'
XD> is handled as a function[1]. However, this requires a user to
XD> implement the oauth2 logic oneself, which I'm afraid is a bit
XD> too low-level and error-prone. (Actually, can I actually put a
XD> lisp function in auth-source.gpg?)
I don't think you have to do anything low level, and I don't think there
is anything error prone here; you can use the functions from oauth
themselves (oauth2.el can create its own plstores, but I prefer to use
auth-source.el to manage the stores). The only things needed are a call
to oauth2-refresh-access to get a new token, and then
oauth2-token-access-token to return the new access token.
The function I wrote computes the refresh time to decide when to create
a new token. This logic could easily be put into oauth2 instead.
And yes, you can put the lisp function in auth-source.gpg (this is what
I do).
By the way there are some significant bugs in auth-source.el which I
have fixed in my personal tree but haven't yet pushed. I have so little
time for emacs at the moment, but I'll try to get around to it. And
there is one major deficiency in auth-source.el that I want to deal
with: obfuscation of the :secret. When Ted originally wrote
auth-source.el he wrapped the :secret in a closure so that the secret
itself wasn't visible in memory. At the time he did this, closures
weren't fully part of emacs, and their implementation at the time didn't
expose the contents of the closure in bytecode. But the current official
implementation does, so this obfuscation trick no longer works. I want
to remove it since it no longer works and might lead to confusion.
XD> Maybe auth-source source can host a helper function that checks
XD> if `:secret' is not set and xaouth2 is preferred (e.g. `:auth'
XD> is `xoauth2') and all required credentials are available it will
XD> get the access_token and put it `:secret' (or basically my hacky
XD> advice :)
I think this isn't the right way to go. Currently xoauth2 is one of
several supported SASL methods. The logic is supposed to be to try them
in a certain order, but this hasn't worked properly for some
time. Nobody has noticed since almost everyone uses only the basic
method. In gnus there has always been a server variable,
nnimap-authenticator, that chooses the preferred sasl method, which is
how the current support for xaouth2 is designed to work. I think this
is the right way to handle this (rather than relying on some specific
form of the auth-source entry) but it would be good to fix the logic in
nnimap.el to allow multiple methods to be tried.
[...]
XD> P.S. Is your set up mentioned in Bug#72358 still working for
XD> outlook.com emails? After reaching out to an MS representative
XD> they mentioned that token refresh was disabled[3] for
XD> outlook.com so I just gave up. Maybe it still works for Outlook
XD> Org emails?
Yes, it still works perfectly. I suspect that the information they gave
you isn't fully accurate :)
--
Andrew Cohen
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-19 9:06 ` Andrew Cohen
@ 2024-09-19 22:37 ` Xiyue Deng
2024-09-22 12:05 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
` (2 more replies)
2024-09-22 12:01 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
[not found] ` <66f00712.170a0220.29d948.0047SMTPIN_ADDED_BROKEN@mx.google.com>
2 siblings, 3 replies; 26+ messages in thread
From: Xiyue Deng @ 2024-09-19 22:37 UTC (permalink / raw)
To: Andrew Cohen; +Cc: Ted Zlatanov, Philip Kaludercic, 72992, Stefan Kangas
Andrew Cohen <acohen@ust.hk> writes:
>>>>>> "XD" == Xiyue Deng <manphiz@gmail.com> writes:
>
> XD> Hi Andrew, Andrew Cohen <acohen@ust.hk> writes:
>
> >>>>>>> "XD" == Xiyue Deng <dengxiyue@gmail.com> writes:
> >>
>
> [...]
>
> XD> The basic support is actually in the Emacs core already,
> XD> e.g. for Gnus nnimap[2] and smtpmail[3]. However, this assumes
> XD> one to put the access_token in place of `:secret' in the
> XD> auth-source file as Emacs uses password as the access_token in
> XD> both places. However, access_token expires quite frequently
> XD> (e.g. about 1 hour for Gmail) and without refreshing it
> XD> automatically it is practically impossible to use conveniently.
> XD> Hence the propose hack and the following suggestion.
> >>
> >>
> >> This isn't actually true. When I added the support many years
> >> ago, I updated auth-source so that the :secret field can be a
> >> function, and this is how you should be using the current xoauth
> >> support.
>
> XD> Thanks for pointing this out! I found the place where `:secret'
> XD> is handled as a function[1]. However, this requires a user to
> XD> implement the oauth2 logic oneself, which I'm afraid is a bit
> XD> too low-level and error-prone. (Actually, can I actually put a
> XD> lisp function in auth-source.gpg?)
>
> I don't think you have to do anything low level, and I don't think there
> is anything error prone here; you can use the functions from oauth
> themselves (oauth2.el can create its own plstores, but I prefer to use
> auth-source.el to manage the stores). The only things needed are a call
> to oauth2-refresh-access to get a new token, and then
> oauth2-token-access-token to return the new access token.
>
Yes, I'm not worried about power users. I just think that the average
Emacs user would be hesitant on writing ELisp themselves to enable
xoauth2 login (hence low-level), especially when they don't have
anything to copy from (yet). Many Gnus users are not programmers and
would prefer writing "(nnimap-authenticator 'xoauth2)" and expect it to
work. But I believe you don't object providing that convenience OOTB
either.
> The function I wrote computes the refresh time to decide when to create
> a new token. This logic could easily be put into oauth2 instead.
>
I am planning on adding this to oauth2 as well. Will ask for your
review when that happens.
> And yes, you can put the lisp function in auth-source.gpg (this is what
> I do).
>
TIL! (I used to have a handwritten script to get the values for
offlineimap. Guess we should all be using `auth-info-password')
> By the way there are some significant bugs in auth-source.el which I
> have fixed in my personal tree but haven't yet pushed. I have so little
> time for emacs at the moment, but I'll try to get around to it. And
> there is one major deficiency in auth-source.el that I want to deal
> with: obfuscation of the :secret. When Ted originally wrote
> auth-source.el he wrapped the :secret in a closure so that the secret
> itself wasn't visible in memory. At the time he did this, closures
> weren't fully part of emacs, and their implementation at the time didn't
> expose the contents of the closure in bytecode. But the current official
> implementation does, so this obfuscation trick no longer works. I want
> to remove it since it no longer works and might lead to confusion.
>
Looking forward to it!
> XD> Maybe auth-source source can host a helper function that checks
> XD> if `:secret' is not set and xaouth2 is preferred (e.g. `:auth'
> XD> is `xoauth2') and all required credentials are available it will
> XD> get the access_token and put it `:secret' (or basically my hacky
> XD> advice :)
>
> I think this isn't the right way to go. Currently xoauth2 is one of
> several supported SASL methods. The logic is supposed to be to try them
> in a certain order, but this hasn't worked properly for some
> time. Nobody has noticed since almost everyone uses only the basic
> method. In gnus there has always been a server variable,
> nnimap-authenticator, that chooses the preferred sasl method, which is
> how the current support for xaouth2 is designed to work. I think this
> is the right way to handle this (rather than relying on some specific
> form of the auth-source entry) but it would be good to fix the logic in
> nnimap.el to allow multiple methods to be tried.
>
Right. The `:auth' trick I did is just to workaround the restriction
that `nnimap-login' chooses basic method over other methods, and I'd
prefer a better built-in support in auth-source myself. As you
mentioned, maybe it can be remodeled after `smtpmail-try-auth-method' to
so that the login method is chosen on demand instead of trial-and-error.
> [...]
>
> XD> P.S. Is your set up mentioned in Bug#72358 still working for
> XD> outlook.com emails? After reaching out to an MS representative
> XD> they mentioned that token refresh was disabled[3] for
> XD> outlook.com so I just gave up. Maybe it still works for Outlook
> XD> Org emails?
>
> Yes, it still works perfectly. I suspect that the information they gave
> you isn't fully accurate :)
Thanks for confirming! I'll follow-up in private to try to figure this
out if you don't mind.
> --
> Andrew Cohen
--
Xiyue Deng
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-18 14:11 ` Philip Kaludercic
@ 2024-09-22 7:06 ` Xiyue Deng
2024-09-22 9:34 ` Philip Kaludercic
0 siblings, 1 reply; 26+ messages in thread
From: Xiyue Deng @ 2024-09-22 7:06 UTC (permalink / raw)
To: Philip Kaludercic; +Cc: 72992
Hi Philip,
Philip Kaludercic <philipk@posteo.net> writes:
> Xiyue Deng <manphiz@gmail.com> writes:
>
>> Philip Kaludercic <philipk@posteo.net> writes:
>>
>>> Xiyue Deng <manphiz@gmail.com> writes:
>>>
>>>> Now that bug#72358 is done, as promised, I'm posting my plugin for
>>>> auth-sources that enables oauth2 handling which you can find on
>>>> Gitlab[1] (also attached).
>>>
>>> Once again I just want to be sure: When you say "plugin", you mean
>>> package, right?
>>
>> Yes, though it's not really an independent package but a "plugin" for
>> auth-source, a.k.a. a hack (the advice) to make auth-source to work with
>> xoauth2.
>
> Just to clarify: When I say package, I mean something to add to ELPA.
>
Ah in that regard yes.
>>> You are proposing to add this to GNU ELPA?
>>
>> Actually I would like to see which of my proposed changes to auth-source
>> is acceptable and update auth-source in core accordingly.
>
> Sure it's acceptable, but in that case it would better to submit a patch
> modifying. auth-source.el
>
>> I think
>> Stefan's reply gave some suggestions in this regard and I'll follow-up
>> in a reply there.
>
> I just want to second Stefan's point that some clarification as to what
> xoauth2 is.
>
Updated the comments section with this info.
>> Meanwhile, it may still worth adding this package
>> to ELPA to support older Emacs versions if desired.
>
> In that case it might be better not to merge your changes into
> auth-source.el directly, as that would make it more difficult to
> automatically pull your changes out of the core to ELPA.
>
> An alternative is that ELPA mirrors your repository, and then we
> manually synchronise the changes into the core, whenever there is a new
> release.
>
I was thinking making it only for Emacs <30 if the auth-source side
changes are upstreamed for 31. Similar to "docker-tramp" which is only
for EMacs <28.
>
> [...]
>
>>>> (let ((auth (plist-get auth-data :auth)))
>>>> (when (and auth
>>>> (stringp auth)
>>>> (string= auth "xoauth2"))
>>>
>>> You can simplify the check by just doing (equal auth "xoauth2"), as this
>>> implies all of the above (if it is `equal' to a string, it must be a
>>> string and hence also non-nil).
>>>
>>
>> Done. Nice tip! Coming from strong-typed languages I always want to do
>> type-checks first in fear of any aborting error :)
>
> If you want strong typing, then string= is the right thing to use,
> because if you want to assume that auth is always a string, then an
> error will be signalled. That being said, if auth has the type "Maybe
> String", then checking the values explicitly or implicitly using equal
> is the right approach.
>
Ack. Thanks for the tip!
>
> [...]
>
>>>> (auth-source-do-trivia "Using oauth2 to auth and store token...")
>>>> (let ((token (oauth2-auth-and-store
>>>> auth-url token-url scope client-id client-secret
>>>> redirect-uri state)))
>>>> (auth-source-do-trivia "oauth2 token: %s" (pp-to-string token))
>>>> (auth-source-do-trivia "Refreshing token...")
>>>> (oauth2-refresh-access token)
>>>> (auth-source-do-trivia "oauth2 token after refresh: %s"
>>>> (pp-to-string token))
>>>> (let ((access-token (oauth2-token-access-token token)))
>>>> (auth-source-do-trivia
>>>> "Updating :secret with access-token: %s" access-token)
>>>> (plist-put auth-data :secret access-token))))))
>>>
>>> The documentation for plist-put warns:
>>>
>>> The new plist is returned;
>>> use ‘(setq x (plist-put x prop val))’ to be sure to use the new value.
>>> The PLIST is modified by side effects.
>>>
>>> Alternatively, you should also be able to do:
>>>
>>> (setf (plist-get auth-data :secret) access-token)
>>>
>>
>> Ah didn't know this as I learned the usage of plist-put from searching.
>> Changed to your `setq' version. Though I'd also expect that the side
>> effect is not going away anytime soon either ;)
>
> I am not sure what you mean? The crux of the issue is demonstrated
> here:
>
> (let (plist)
> (list (plist-put plist :foo 1) plist))
> ;; ((:foo 1) nil)
>
> I.e. the plist was not modified, because there was no cons-cell to
> modify.
>
I see. Thanks for the explanation. Looks like the side effect worked
for me because auth-data already had data in it.
>
> [...]
>
>>>> #'auth-source-xoauth2-plugin--search-backends))
>>>
>>> I would recommend turning this into a global minor mode instead, so that
>>> it is easy to disable, if a user just wants to try it out.
>>>
>>
>> This is an interesting suggestion and sounds like a good idea. Though
>> as a matter of fact the oauth2 support in auth-source in Emacs core
>> actually doesn't work without those hack as of now, so I don't think
>> it's of interest to support turning off.
>
> I regard it as a matter of good style to allow the user to disable
> anything then can enable, if anything then just to allow better
> experimentation.
>
You actually convinced me. Making it a minor mode also enables a user
to disable it temporarily if it causes any issues. It took me a while
to convert it. Please help take another look.
>> But of course it would be
>> great if auth-source can be changed to support all this out-of-the-box.
>> Will continue the discussion in my reply to Stefan.
>
> Ack.
>
>> I have updated the source code on GitLab[1] based on your review.
>> Please check it out. Thanks very much!
>
> For anyone following the thread, it seem the footnote was missing:
>
> [1]https://gitlab.com/xiyueden/auth-source-xoauth2-plugin/-/blob/main/auth-source-xoauth2-plugin.el
>
> Watch out, in
>
> (unless (memq 'xoauth2 smtpmail-auth-supported)
> (push 'smtpmail-auth-supported 'xoauth2))
>
> the push expression is malformed, as 'xoauth2 is not a place. I'm
> guessing that you want to write
>
> (... (push 'xoauth2 smtpmail-auth-supported))
>
Thanks! Fixed.
> Also, checkdoc complains about
> `auth-source-xoauth2-plugin--search-backends's docstring. I'd try to
> address the issues it mentions.
>
Also fixed. Thanks!
> The (and auth (equal auth "xoauth2")) can be further simplified to just
> (equal auth "xauth2"), as if auth is equal to "xauth2" is cannot be nil.
>
Ack and simplified.
The GitLab repo[1] is updated accordingly. PTAL. TIA!
>>>>
>>>> (provide 'auth-source-xoauth2-plugin)
>>>>
>>>> ;;; auth-source-xoauth2-plugin.el ends here
>>>
>>> --
>>> Philip Kaludercic on siskin
>
> --
> Philip Kaludercic on siskin
[1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin
--
Xiyue Deng
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-22 7:06 ` Xiyue Deng
@ 2024-09-22 9:34 ` Philip Kaludercic
2024-09-22 22:00 ` Xiyue Deng
0 siblings, 1 reply; 26+ messages in thread
From: Philip Kaludercic @ 2024-09-22 9:34 UTC (permalink / raw)
To: Xiyue Deng; +Cc: 72992
[-- Attachment #1: Type: text/plain, Size: 7600 bytes --]
Xiyue Deng <manphiz@gmail.com> writes:
> Hi Philip,
>
> Philip Kaludercic <philipk@posteo.net> writes:
>
>> Xiyue Deng <manphiz@gmail.com> writes:
>>
>>> Philip Kaludercic <philipk@posteo.net> writes:
>>>
>>>> Xiyue Deng <manphiz@gmail.com> writes:
>>>>
>>>>> Now that bug#72358 is done, as promised, I'm posting my plugin for
>>>>> auth-sources that enables oauth2 handling which you can find on
>>>>> Gitlab[1] (also attached).
>>>>
>>>> Once again I just want to be sure: When you say "plugin", you mean
>>>> package, right?
>>>
>>> Yes, though it's not really an independent package but a "plugin" for
>>> auth-source, a.k.a. a hack (the advice) to make auth-source to work with
>>> xoauth2.
>>
>> Just to clarify: When I say package, I mean something to add to ELPA.
>>
>
> Ah in that regard yes.
>
>>>> You are proposing to add this to GNU ELPA?
>>>
>>> Actually I would like to see which of my proposed changes to auth-source
>>> is acceptable and update auth-source in core accordingly.
>>
>> Sure it's acceptable, but in that case it would better to submit a patch
>> modifying. auth-source.el
>>
>>> I think
>>> Stefan's reply gave some suggestions in this regard and I'll follow-up
>>> in a reply there.
>>
>> I just want to second Stefan's point that some clarification as to what
>> xoauth2 is.
>>
>
> Updated the comments section with this info.
Great, that explains it well!
>>> Meanwhile, it may still worth adding this package
>>> to ELPA to support older Emacs versions if desired.
>>
>> In that case it might be better not to merge your changes into
>> auth-source.el directly, as that would make it more difficult to
>> automatically pull your changes out of the core to ELPA.
>>
>> An alternative is that ELPA mirrors your repository, and then we
>> manually synchronise the changes into the core, whenever there is a new
>> release.
>>
>
> I was thinking making it only for Emacs <30 if the auth-source side
> changes are upstreamed for 31. Similar to "docker-tramp" which is only
> for EMacs <28.
The issue here is that tramp is developed outside of Emacs and
synchronised manually back into the core/automatically on ELPA, while
auth-source is currently only in the core and not distributed on ELPA.
If this remains a separate file, we could easily add it to ELPA, but I
don't know what the preference is there.
>>
>> [...]
>>
>>>>> (let ((auth (plist-get auth-data :auth)))
>>>>> (when (and auth
>>>>> (stringp auth)
>>>>> (string= auth "xoauth2"))
>>>>
>>>> You can simplify the check by just doing (equal auth "xoauth2"), as this
>>>> implies all of the above (if it is `equal' to a string, it must be a
>>>> string and hence also non-nil).
>>>>
>>>
>>> Done. Nice tip! Coming from strong-typed languages I always want to do
>>> type-checks first in fear of any aborting error :)
>>
>> If you want strong typing, then string= is the right thing to use,
>> because if you want to assume that auth is always a string, then an
>> error will be signalled. That being said, if auth has the type "Maybe
>> String", then checking the values explicitly or implicitly using equal
>> is the right approach.
>>
>
> Ack. Thanks for the tip!
>
>>
>> [...]
>>
>>>>> (auth-source-do-trivia "Using oauth2 to auth and store token...")
>>>>> (let ((token (oauth2-auth-and-store
>>>>> auth-url token-url scope client-id client-secret
>>>>> redirect-uri state)))
>>>>> (auth-source-do-trivia "oauth2 token: %s" (pp-to-string token))
>>>>> (auth-source-do-trivia "Refreshing token...")
>>>>> (oauth2-refresh-access token)
>>>>> (auth-source-do-trivia "oauth2 token after refresh: %s"
>>>>> (pp-to-string token))
>>>>> (let ((access-token (oauth2-token-access-token token)))
>>>>> (auth-source-do-trivia
>>>>> "Updating :secret with access-token: %s" access-token)
>>>>> (plist-put auth-data :secret access-token))))))
>>>>
>>>> The documentation for plist-put warns:
>>>>
>>>> The new plist is returned;
>>>> use ‘(setq x (plist-put x prop val))’ to be sure to use the new value.
>>>> The PLIST is modified by side effects.
>>>>
>>>> Alternatively, you should also be able to do:
>>>>
>>>> (setf (plist-get auth-data :secret) access-token)
>>>>
>>>
>>> Ah didn't know this as I learned the usage of plist-put from searching.
>>> Changed to your `setq' version. Though I'd also expect that the side
>>> effect is not going away anytime soon either ;)
>>
>> I am not sure what you mean? The crux of the issue is demonstrated
>> here:
>>
>> (let (plist)
>> (list (plist-put plist :foo 1) plist))
>> ;; ((:foo 1) nil)
>>
>> I.e. the plist was not modified, because there was no cons-cell to
>> modify.
>>
>
> I see. Thanks for the explanation. Looks like the side effect worked
> for me because auth-data already had data in it.
Probably, but that's not the kind of thing I want to rely on.
>>
>> [...]
>>
>>>>> #'auth-source-xoauth2-plugin--search-backends))
>>>>
>>>> I would recommend turning this into a global minor mode instead, so that
>>>> it is easy to disable, if a user just wants to try it out.
>>>>
>>>
>>> This is an interesting suggestion and sounds like a good idea. Though
>>> as a matter of fact the oauth2 support in auth-source in Emacs core
>>> actually doesn't work without those hack as of now, so I don't think
>>> it's of interest to support turning off.
>>
>> I regard it as a matter of good style to allow the user to disable
>> anything then can enable, if anything then just to allow better
>> experimentation.
>>
>
> You actually convinced me. Making it a minor mode also enables a user
> to disable it temporarily if it causes any issues. It took me a while
> to convert it. Please help take another look.
Looks good.
>>> But of course it would be
>>> great if auth-source can be changed to support all this out-of-the-box.
>>> Will continue the discussion in my reply to Stefan.
>>
>> Ack.
>>
>>> I have updated the source code on GitLab[1] based on your review.
>>> Please check it out. Thanks very much!
>>
>> For anyone following the thread, it seem the footnote was missing:
>>
>> [1]https://gitlab.com/xiyueden/auth-source-xoauth2-plugin/-/blob/main/auth-source-xoauth2-plugin.el
>>
>> Watch out, in
>>
>> (unless (memq 'xoauth2 smtpmail-auth-supported)
>> (push 'smtpmail-auth-supported 'xoauth2))
>>
>> the push expression is malformed, as 'xoauth2 is not a place. I'm
>> guessing that you want to write
>>
>> (... (push 'xoauth2 smtpmail-auth-supported))
>>
>
> Thanks! Fixed.
>
>> Also, checkdoc complains about
>> `auth-source-xoauth2-plugin--search-backends's docstring. I'd try to
>> address the issues it mentions.
>>
>
> Also fixed. Thanks!
>
>> The (and auth (equal auth "xoauth2")) can be further simplified to just
>> (equal auth "xauth2"), as if auth is equal to "xauth2" is cannot be nil.
>>
>
> Ack and simplified.
>
> The GitLab repo[1] is updated accordingly. PTAL. TIA!
Looks good, just a few "soft" comments I can find:
[-- Attachment #2: Type: text/plain, Size: 2746 bytes --]
diff --git a/auth-source-xoauth2-plugin.el b/auth-source-xoauth2-plugin.el
index cdcc9e7..caf5baf 100644
--- a/auth-source-xoauth2-plugin.el
+++ b/auth-source-xoauth2-plugin.el
@@ -41,7 +41,7 @@
;; or with use-package:
;; (use-package auth-source-xoauth2-plugin
-;; :config
+;; :custom
;; (auth-source-xoauth2-plugin-mode t))
;; After enabling, smtpmail should be supported. To enable this in Gnus
@@ -107,13 +107,13 @@ expected that `token_url', `client_id', `client_secret', and
(when (equal auth "xoauth2")
(auth-source-do-debug
":auth set to `xoauth2'. Will get access token.")
- (map-let ((:auth-url auth-url)
- (:token-url token-url)
- (:scope scope)
- (:client-id client-id)
- (:client-secret client-secret)
- (:redirect-uri redirect-uri)
- (:state state))
+ (map-let (:auth-url ;You can simplify the `map-let'
+ :token-url ;expression if they keys match
+ :scope ;the bindings like they do here.
+ :client-id ;Perhaps you can use the additional
+ :client-secret ;space to document what the keys
+ :redirect-uri ;are for?
+ :state)
auth-data
(auth-source-do-debug "Using oauth2 to auth and store token...")
(let ((token (oauth2-auth-and-store
@@ -138,8 +138,7 @@ expected that `token_url', `client_id', `client_secret', and
res)))
(defvar auth-source-xoauth2-plugin--enabled-xoauth2-by-us nil
- "Used for tracking whether xoauth2 in smtpmail-auth-supported is
-set by us.")
+ "Non-nil means `smtpmail-auth-supported' was set by us.")
(defun auth-source-xoauth2-plugin--enable ()
"Enable auth-source-xoauth2-plugin."
@@ -154,17 +153,17 @@ set by us.")
"Disable auth-source-xoauth2-plugin."
(when (and auth-source-xoauth2-plugin--enabled-xoauth2-by-us
(memq 'xoauth2 smtpmail-auth-supported))
- (delete 'xoauth2 smtpmail-auth-supported)
+ (setq smtpmail-auth-supported (delq 'xoauth2 smtpmail-auth-supported))
(setq auth-source-xoauth2-plugin--enabled-xoauth2-by-us nil))
(advice-remove #'auth-source-search-backends
#'auth-source-xoauth2-plugin--search-backends))
+;;;###autoload
(define-minor-mode auth-source-xoauth2-plugin-mode
"Toggle auth-source-xoauth2-plugin-mode.
Enable auth-source-xoauth2-plugin-mode to use xoauth2
authentications for emails."
- :lighter nil
:global t
(if auth-source-xoauth2-plugin-mode
(auth-source-xoauth2-plugin--enable)
[-- Attachment #3: Type: text/plain, Size: 296 bytes --]
>
>>>>>
>>>>> (provide 'auth-source-xoauth2-plugin)
>>>>>
>>>>> ;;; auth-source-xoauth2-plugin.el ends here
>>>>
>>>> --
>>>> Philip Kaludercic on siskin
>>
>> --
>> Philip Kaludercic on siskin
>
> [1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin
--
Philip Kaludercic on siskin
^ permalink raw reply related [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-19 9:06 ` Andrew Cohen
2024-09-19 22:37 ` Xiyue Deng
@ 2024-09-22 12:01 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
[not found] ` <66f00712.170a0220.29d948.0047SMTPIN_ADDED_BROKEN@mx.google.com>
2 siblings, 0 replies; 26+ messages in thread
From: Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-22 12:01 UTC (permalink / raw)
To: Andrew Cohen
Cc: Stefan Kangas, Ted Zlatanov, 72992, Philip Kaludercic, Xiyue Deng
Andrew Cohen <acohen@ust.hk> writes:
>>>>>> "XD" == Xiyue Deng <manphiz@gmail.com> writes:
>
> XD> Hi Andrew, Andrew Cohen <acohen@ust.hk> writes:
>
> >>>>>>> "XD" == Xiyue Deng <dengxiyue@gmail.com> writes:
> >>
>
> [...]
>
> XD> The basic support is actually in the Emacs core already,
> XD> e.g. for Gnus nnimap[2] and smtpmail[3]. However, this assumes
> XD> one to put the access_token in place of `:secret' in the
> XD> auth-source file as Emacs uses password as the access_token in
> XD> both places. However, access_token expires quite frequently
> XD> (e.g. about 1 hour for Gmail) and without refreshing it
> XD> automatically it is practically impossible to use conveniently.
> XD> Hence the propose hack and the following suggestion.
> >>
> >>
> >> This isn't actually true. When I added the support many years
> >> ago, I updated auth-source so that the :secret field can be a
> >> function, and this is how you should be using the current xoauth
> >> support.
>
> XD> Thanks for pointing this out! I found the place where `:secret'
> XD> is handled as a function[1]. However, this requires a user to
> XD> implement the oauth2 logic oneself, which I'm afraid is a bit
> XD> too low-level and error-prone. (Actually, can I actually put a
> XD> lisp function in auth-source.gpg?)
>
> I don't think you have to do anything low level, and I don't think there
> is anything error prone here; you can use the functions from oauth
> themselves (oauth2.el can create its own plstores, but I prefer to use
> auth-source.el to manage the stores). The only things needed are a call
> to oauth2-refresh-access to get a new token, and then
> oauth2-token-access-token to return the new access token.
Is this documented? If yes where?
I tried to look inside the auth manual nothing was mentioned.
Would this method work with all backends?
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-19 22:37 ` Xiyue Deng
@ 2024-09-22 12:05 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
[not found] ` <66f00802.050a0220.988f0.9640SMTPIN_ADDED_BROKEN@mx.google.com>
2024-10-03 22:41 ` Xiyue Deng
2 siblings, 0 replies; 26+ messages in thread
From: Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-22 12:05 UTC (permalink / raw)
To: Xiyue Deng
Cc: Andrew Cohen, Ted Zlatanov, 72992, Philip Kaludercic,
Stefan Kangas
Xiyue Deng <manphiz@gmail.com> writes:
>> [...]
>>
>> XD> P.S. Is your set up mentioned in Bug#72358 still working for
>> XD> outlook.com emails? After reaching out to an MS representative
>> XD> they mentioned that token refresh was disabled[3] for
>> XD> outlook.com so I just gave up. Maybe it still works for Outlook
>> XD> Org emails?
>>
>> Yes, it still works perfectly. I suspect that the information they gave
>> you isn't fully accurate :)
>
> Thanks for confirming! I'll follow-up in private to try to figure this
> out if you don't mind.
Could you update me on this please too?
We have an issue with this at work.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
[not found] ` <66f00802.050a0220.988f0.9640SMTPIN_ADDED_BROKEN@mx.google.com>
@ 2024-09-22 21:40 ` Xiyue Deng
2024-09-22 23:50 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
[not found] ` <66f0ad4f.500a0220.10c3c2.dde8SMTPIN_ADDED_BROKEN@mx.google.com>
0 siblings, 2 replies; 26+ messages in thread
From: Xiyue Deng @ 2024-09-22 21:40 UTC (permalink / raw)
To: Björn Bidar
Cc: Andrew Cohen, Ted Zlatanov, 72992, Philip Kaludercic,
Stefan Kangas
Hi Björn,
Björn Bidar <bjorn.bidar@thaodan.de> writes:
> Xiyue Deng <manphiz@gmail.com> writes:
>
>>> [...]
>>>
>>> XD> P.S. Is your set up mentioned in Bug#72358 still working for
>>> XD> outlook.com emails? After reaching out to an MS representative
>>> XD> they mentioned that token refresh was disabled[3] for
>>> XD> outlook.com so I just gave up. Maybe it still works for Outlook
>>> XD> Org emails?
>>>
>>> Yes, it still works perfectly. I suspect that the information they gave
>>> you isn't fully accurate :)
>>
>> Thanks for confirming! I'll follow-up in private to try to figure this
>> out if you don't mind.
>
> Could you update me on this please too?
> We have an issue with this at work.
I have reached out to Andrew offline and confirmed Andrew was using a
corp account, so there might be some corp administration settings that
enables the refreshing of access_token. It seems to me that this is
still not possible for personal outlook.com accounts.
--
Xiyue Deng
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
[not found] ` <66f00712.170a0220.29d948.0047SMTPIN_ADDED_BROKEN@mx.google.com>
@ 2024-09-22 21:44 ` Xiyue Deng
0 siblings, 0 replies; 26+ messages in thread
From: Xiyue Deng @ 2024-09-22 21:44 UTC (permalink / raw)
To: Björn Bidar, Andrew Cohen
Cc: Ted Zlatanov, 72992, Philip Kaludercic, Stefan Kangas
Hi Björn,
Björn Bidar <bjorn.bidar@thaodan.de> writes:
> Andrew Cohen <acohen@ust.hk> writes:
>
>>>>>>> "XD" == Xiyue Deng <manphiz@gmail.com> writes:
>>
>> XD> Hi Andrew, Andrew Cohen <acohen@ust.hk> writes:
>>
>> >>>>>>> "XD" == Xiyue Deng <dengxiyue@gmail.com> writes:
>> >>
>>
>> [...]
>>
>> XD> The basic support is actually in the Emacs core already,
>> XD> e.g. for Gnus nnimap[2] and smtpmail[3]. However, this assumes
>> XD> one to put the access_token in place of `:secret' in the
>> XD> auth-source file as Emacs uses password as the access_token in
>> XD> both places. However, access_token expires quite frequently
>> XD> (e.g. about 1 hour for Gmail) and without refreshing it
>> XD> automatically it is practically impossible to use conveniently.
>> XD> Hence the propose hack and the following suggestion.
>> >>
>> >>
>> >> This isn't actually true. When I added the support many years
>> >> ago, I updated auth-source so that the :secret field can be a
>> >> function, and this is how you should be using the current xoauth
>> >> support.
>>
>> XD> Thanks for pointing this out! I found the place where `:secret'
>> XD> is handled as a function[1]. However, this requires a user to
>> XD> implement the oauth2 logic oneself, which I'm afraid is a bit
>> XD> too low-level and error-prone. (Actually, can I actually put a
>> XD> lisp function in auth-source.gpg?)
>>
>> I don't think you have to do anything low level, and I don't think there
>> is anything error prone here; you can use the functions from oauth
>> themselves (oauth2.el can create its own plstores, but I prefer to use
>> auth-source.el to manage the stores). The only things needed are a call
>> to oauth2-refresh-access to get a new token, and then
>> oauth2-token-access-token to return the new access token.
>
> Is this documented? If yes where?
> I tried to look inside the auth manual nothing was mentioned.
> Would this method work with all backends?
AIUI as of now you would need to implement this logic as a function in
`:secret' of the auth-source entry. Please do correct me though.
--
Xiyue Deng
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-22 9:34 ` Philip Kaludercic
@ 2024-09-22 22:00 ` Xiyue Deng
2024-09-23 6:17 ` Philip Kaludercic
0 siblings, 1 reply; 26+ messages in thread
From: Xiyue Deng @ 2024-09-22 22:00 UTC (permalink / raw)
To: Philip Kaludercic; +Cc: 72992
Philip Kaludercic <philipk@posteo.net> writes:
> Xiyue Deng <manphiz@gmail.com> writes:
>
>> Hi Philip,
>>
>> Philip Kaludercic <philipk@posteo.net> writes:
>>
>>> Xiyue Deng <manphiz@gmail.com> writes:
>>>
>>>> Philip Kaludercic <philipk@posteo.net> writes:
>>>>
>>>>> Xiyue Deng <manphiz@gmail.com> writes:
>>>>>
>>>>>> Now that bug#72358 is done, as promised, I'm posting my plugin for
>>>>>> auth-sources that enables oauth2 handling which you can find on
>>>>>> Gitlab[1] (also attached).
>>>>>
>>>>> Once again I just want to be sure: When you say "plugin", you mean
>>>>> package, right?
>>>>
>>>> Yes, though it's not really an independent package but a "plugin" for
>>>> auth-source, a.k.a. a hack (the advice) to make auth-source to work with
>>>> xoauth2.
>>>
>>> Just to clarify: When I say package, I mean something to add to ELPA.
>>>
>>
>> Ah in that regard yes.
>>
>>>>> You are proposing to add this to GNU ELPA?
>>>>
>>>> Actually I would like to see which of my proposed changes to auth-source
>>>> is acceptable and update auth-source in core accordingly.
>>>
>>> Sure it's acceptable, but in that case it would better to submit a patch
>>> modifying. auth-source.el
>>>
>>>> I think
>>>> Stefan's reply gave some suggestions in this regard and I'll follow-up
>>>> in a reply there.
>>>
>>> I just want to second Stefan's point that some clarification as to what
>>> xoauth2 is.
>>>
>>
>> Updated the comments section with this info.
>
> Great, that explains it well!
>
>>>> Meanwhile, it may still worth adding this package
>>>> to ELPA to support older Emacs versions if desired.
>>>
>>> In that case it might be better not to merge your changes into
>>> auth-source.el directly, as that would make it more difficult to
>>> automatically pull your changes out of the core to ELPA.
>>>
>>> An alternative is that ELPA mirrors your repository, and then we
>>> manually synchronise the changes into the core, whenever there is a new
>>> release.
>>>
>>
>> I was thinking making it only for Emacs <30 if the auth-source side
>> changes are upstreamed for 31. Similar to "docker-tramp" which is only
>> for EMacs <28.
>
> The issue here is that tramp is developed outside of Emacs and
> synchronised manually back into the core/automatically on ELPA, while
> auth-source is currently only in the core and not distributed on ELPA.
> If this remains a separate file, we could easily add it to ELPA, but I
> don't know what the preference is there.
>
>>>
>>> [...]
>>>
>>>>>> (let ((auth (plist-get auth-data :auth)))
>>>>>> (when (and auth
>>>>>> (stringp auth)
>>>>>> (string= auth "xoauth2"))
>>>>>
>>>>> You can simplify the check by just doing (equal auth "xoauth2"), as this
>>>>> implies all of the above (if it is `equal' to a string, it must be a
>>>>> string and hence also non-nil).
>>>>>
>>>>
>>>> Done. Nice tip! Coming from strong-typed languages I always want to do
>>>> type-checks first in fear of any aborting error :)
>>>
>>> If you want strong typing, then string= is the right thing to use,
>>> because if you want to assume that auth is always a string, then an
>>> error will be signalled. That being said, if auth has the type "Maybe
>>> String", then checking the values explicitly or implicitly using equal
>>> is the right approach.
>>>
>>
>> Ack. Thanks for the tip!
>>
>>>
>>> [...]
>>>
>>>>>> (auth-source-do-trivia "Using oauth2 to auth and store token...")
>>>>>> (let ((token (oauth2-auth-and-store
>>>>>> auth-url token-url scope client-id client-secret
>>>>>> redirect-uri state)))
>>>>>> (auth-source-do-trivia "oauth2 token: %s" (pp-to-string token))
>>>>>> (auth-source-do-trivia "Refreshing token...")
>>>>>> (oauth2-refresh-access token)
>>>>>> (auth-source-do-trivia "oauth2 token after refresh: %s"
>>>>>> (pp-to-string token))
>>>>>> (let ((access-token (oauth2-token-access-token token)))
>>>>>> (auth-source-do-trivia
>>>>>> "Updating :secret with access-token: %s" access-token)
>>>>>> (plist-put auth-data :secret access-token))))))
>>>>>
>>>>> The documentation for plist-put warns:
>>>>>
>>>>> The new plist is returned;
>>>>> use ‘(setq x (plist-put x prop val))’ to be sure to use the new value.
>>>>> The PLIST is modified by side effects.
>>>>>
>>>>> Alternatively, you should also be able to do:
>>>>>
>>>>> (setf (plist-get auth-data :secret) access-token)
>>>>>
>>>>
>>>> Ah didn't know this as I learned the usage of plist-put from searching.
>>>> Changed to your `setq' version. Though I'd also expect that the side
>>>> effect is not going away anytime soon either ;)
>>>
>>> I am not sure what you mean? The crux of the issue is demonstrated
>>> here:
>>>
>>> (let (plist)
>>> (list (plist-put plist :foo 1) plist))
>>> ;; ((:foo 1) nil)
>>>
>>> I.e. the plist was not modified, because there was no cons-cell to
>>> modify.
>>>
>>
>> I see. Thanks for the explanation. Looks like the side effect worked
>> for me because auth-data already had data in it.
>
> Probably, but that's not the kind of thing I want to rely on.
>
Ack.
>>>
>>> [...]
>>>
>>>>>> #'auth-source-xoauth2-plugin--search-backends))
>>>>>
>>>>> I would recommend turning this into a global minor mode instead, so that
>>>>> it is easy to disable, if a user just wants to try it out.
>>>>>
>>>>
>>>> This is an interesting suggestion and sounds like a good idea. Though
>>>> as a matter of fact the oauth2 support in auth-source in Emacs core
>>>> actually doesn't work without those hack as of now, so I don't think
>>>> it's of interest to support turning off.
>>>
>>> I regard it as a matter of good style to allow the user to disable
>>> anything then can enable, if anything then just to allow better
>>> experimentation.
>>>
>>
>> You actually convinced me. Making it a minor mode also enables a user
>> to disable it temporarily if it causes any issues. It took me a while
>> to convert it. Please help take another look.
>
> Looks good.
>
>>>> But of course it would be
>>>> great if auth-source can be changed to support all this out-of-the-box.
>>>> Will continue the discussion in my reply to Stefan.
>>>
>>> Ack.
>>>
>>>> I have updated the source code on GitLab[1] based on your review.
>>>> Please check it out. Thanks very much!
>>>
>>> For anyone following the thread, it seem the footnote was missing:
>>>
>>> [1]https://gitlab.com/xiyueden/auth-source-xoauth2-plugin/-/blob/main/auth-source-xoauth2-plugin.el
>>>
>>> Watch out, in
>>>
>>> (unless (memq 'xoauth2 smtpmail-auth-supported)
>>> (push 'smtpmail-auth-supported 'xoauth2))
>>>
>>> the push expression is malformed, as 'xoauth2 is not a place. I'm
>>> guessing that you want to write
>>>
>>> (... (push 'xoauth2 smtpmail-auth-supported))
>>>
>>
>> Thanks! Fixed.
>>
>>> Also, checkdoc complains about
>>> `auth-source-xoauth2-plugin--search-backends's docstring. I'd try to
>>> address the issues it mentions.
>>>
>>
>> Also fixed. Thanks!
>>
>>> The (and auth (equal auth "xoauth2")) can be further simplified to just
>>> (equal auth "xauth2"), as if auth is equal to "xauth2" is cannot be nil.
>>>
>>
>> Ack and simplified.
>>
>> The GitLab repo[1] is updated accordingly. PTAL. TIA!
>
> Looks good, just a few "soft" comments I can find:
>
> diff --git a/auth-source-xoauth2-plugin.el b/auth-source-xoauth2-plugin.el
> index cdcc9e7..caf5baf 100644
> --- a/auth-source-xoauth2-plugin.el
> +++ b/auth-source-xoauth2-plugin.el
> @@ -41,7 +41,7 @@
> ;; or with use-package:
>
> ;; (use-package auth-source-xoauth2-plugin
> -;; :config
> +;; :custom
> ;; (auth-source-xoauth2-plugin-mode t))
>
Quick question: I wonder whether customizing the minor mode variable is
preferred over toggling through the minor mode function? (I assume both
will run the minor mode body.)
> ;; After enabling, smtpmail should be supported. To enable this in Gnus
> @@ -107,13 +107,13 @@ expected that `token_url', `client_id', `client_secret', and
> (when (equal auth "xoauth2")
> (auth-source-do-debug
> ":auth set to `xoauth2'. Will get access token.")
> - (map-let ((:auth-url auth-url)
> - (:token-url token-url)
> - (:scope scope)
> - (:client-id client-id)
> - (:client-secret client-secret)
> - (:redirect-uri redirect-uri)
> - (:state state))
> + (map-let (:auth-url ;You can simplify the `map-let'
> + :token-url ;expression if they keys match
> + :scope ;the bindings like they do here.
> + :client-id ;Perhaps you can use the additional
> + :client-secret ;space to document what the keys
> + :redirect-uri ;are for?
> + :state)
> auth-data
> (auth-source-do-debug "Using oauth2 to auth and store token...")
> (let ((token (oauth2-auth-and-store
> @@ -138,8 +138,7 @@ expected that `token_url', `client_id', `client_secret', and
> res)))
>
> (defvar auth-source-xoauth2-plugin--enabled-xoauth2-by-us nil
> - "Used for tracking whether xoauth2 in smtpmail-auth-supported is
> -set by us.")
> + "Non-nil means `smtpmail-auth-supported' was set by us.")
>
> (defun auth-source-xoauth2-plugin--enable ()
> "Enable auth-source-xoauth2-plugin."
> @@ -154,17 +153,17 @@ set by us.")
> "Disable auth-source-xoauth2-plugin."
> (when (and auth-source-xoauth2-plugin--enabled-xoauth2-by-us
> (memq 'xoauth2 smtpmail-auth-supported))
> - (delete 'xoauth2 smtpmail-auth-supported)
> + (setq smtpmail-auth-supported (delq 'xoauth2 smtpmail-auth-supported))
> (setq auth-source-xoauth2-plugin--enabled-xoauth2-by-us nil))
>
> (advice-remove #'auth-source-search-backends
> #'auth-source-xoauth2-plugin--search-backends))
>
> +;;;###autoload
> (define-minor-mode auth-source-xoauth2-plugin-mode
> "Toggle auth-source-xoauth2-plugin-mode.
> Enable auth-source-xoauth2-plugin-mode to use xoauth2
> authentications for emails."
> - :lighter nil
> :global t
> (if auth-source-xoauth2-plugin-mode
> (auth-source-xoauth2-plugin--enable)
>
>>
>>>>>>
>>>>>> (provide 'auth-source-xoauth2-plugin)
>>>>>>
>>>>>> ;;; auth-source-xoauth2-plugin.el ends here
>>>>>
>>>>> --
>>>>> Philip Kaludercic on siskin
>>>
>>> --
>>> Philip Kaludercic on siskin
>>
>> [1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin
>
> --
> Philip Kaludercic on siskin
--
Xiyue Deng
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-22 21:40 ` Xiyue Deng
@ 2024-09-22 23:50 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
[not found] ` <66f0ad4f.500a0220.10c3c2.dde8SMTPIN_ADDED_BROKEN@mx.google.com>
1 sibling, 0 replies; 26+ messages in thread
From: Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-22 23:50 UTC (permalink / raw)
To: Xiyue Deng
Cc: Andrew Cohen, Ted Zlatanov, 72992, Philip Kaludercic,
Stefan Kangas
Xiyue Deng <manphiz@gmail.com> writes:
> Hi Björn,
>
> Björn Bidar <bjorn.bidar@thaodan.de> writes:
>
>> Xiyue Deng <manphiz@gmail.com> writes:
>>
>>>> [...]
>>>>
>>>> XD> P.S. Is your set up mentioned in Bug#72358 still working for
>>>> XD> outlook.com emails? After reaching out to an MS representative
>>>> XD> they mentioned that token refresh was disabled[3] for
>>>> XD> outlook.com so I just gave up. Maybe it still works for Outlook
>>>> XD> Org emails?
>>>>
>>>> Yes, it still works perfectly. I suspect that the information they gave
>>>> you isn't fully accurate :)
>>>
>>> Thanks for confirming! I'll follow-up in private to try to figure this
>>> out if you don't mind.
>>
>> Could you update me on this please too?
>> We have an issue with this at work.
>
> I have reached out to Andrew offline and confirmed Andrew was using a
> corp account, so there might be some corp administration settings that
> enables the refreshing of access_token. It seems to me that this is
> still not possible for personal outlook.com accounts.
That matches my personal experience. Cooperate accounts are not on
Outlook.com or are they?
To bad I hope there would be some change, maybe someone should reach out
to the EU or so.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
[not found] ` <66f0ad4f.500a0220.10c3c2.dde8SMTPIN_ADDED_BROKEN@mx.google.com>
@ 2024-09-23 2:20 ` Xiyue Deng
0 siblings, 0 replies; 26+ messages in thread
From: Xiyue Deng @ 2024-09-23 2:20 UTC (permalink / raw)
To: Björn Bidar
Cc: Andrew Cohen, Ted Zlatanov, 72992, Philip Kaludercic,
Stefan Kangas
Björn Bidar <bjorn.bidar@thaodan.de> writes:
> Xiyue Deng <manphiz@gmail.com> writes:
>
>> Hi Björn,
>>
>> Björn Bidar <bjorn.bidar@thaodan.de> writes:
>>
>>> Xiyue Deng <manphiz@gmail.com> writes:
>>>
>>>>> [...]
>>>>>
>>>>> XD> P.S. Is your set up mentioned in Bug#72358 still working for
>>>>> XD> outlook.com emails? After reaching out to an MS representative
>>>>> XD> they mentioned that token refresh was disabled[3] for
>>>>> XD> outlook.com so I just gave up. Maybe it still works for Outlook
>>>>> XD> Org emails?
>>>>>
>>>>> Yes, it still works perfectly. I suspect that the information they gave
>>>>> you isn't fully accurate :)
>>>>
>>>> Thanks for confirming! I'll follow-up in private to try to figure this
>>>> out if you don't mind.
>>>
>>> Could you update me on this please too?
>>> We have an issue with this at work.
>>
>> I have reached out to Andrew offline and confirmed Andrew was using a
>> corp account, so there might be some corp administration settings that
>> enables the refreshing of access_token. It seems to me that this is
>> still not possible for personal outlook.com accounts.
>
> That matches my personal experience. Cooperate accounts are not on
> Outlook.com or are they?
>
AIUI corp accounts usually have their own domain names, just the email
system is operated by Outlook.
> To bad I hope there would be some change, maybe someone should reach out
> to the EU or so.
OTOH, registered applications (e.g. thunderbird) can still login
outlook.com emails through OAuth2, which also have full support for 2FA.
Might worth taking a look at how they are doing it.
--
Xiyue Deng
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-22 22:00 ` Xiyue Deng
@ 2024-09-23 6:17 ` Philip Kaludercic
2024-09-23 6:39 ` Xiyue Deng
0 siblings, 1 reply; 26+ messages in thread
From: Philip Kaludercic @ 2024-09-23 6:17 UTC (permalink / raw)
To: Xiyue Deng; +Cc: 72992
Xiyue Deng <manphiz@gmail.com> writes:
[...]
>> diff --git a/auth-source-xoauth2-plugin.el b/auth-source-xoauth2-plugin.el
>> index cdcc9e7..caf5baf 100644
>> --- a/auth-source-xoauth2-plugin.el
>> +++ b/auth-source-xoauth2-plugin.el
>> @@ -41,7 +41,7 @@
>> ;; or with use-package:
>>
>> ;; (use-package auth-source-xoauth2-plugin
>> -;; :config
>> +;; :custom
>> ;; (auth-source-xoauth2-plugin-mode t))
>>
>
> Quick question: I wonder whether customizing the minor mode variable is
> preferred over toggling through the minor mode function? (I assume both
> will run the minor mode body.)
You are right, it doesn't matter. I changed this when adding the
autoload cookie, and somehow I had convinced myself that this would only
work as a user option, which of course is not the case.
[...]
--
Philip Kaludercic on siskin
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-23 6:17 ` Philip Kaludercic
@ 2024-09-23 6:39 ` Xiyue Deng
0 siblings, 0 replies; 26+ messages in thread
From: Xiyue Deng @ 2024-09-23 6:39 UTC (permalink / raw)
To: Philip Kaludercic; +Cc: 72992
Philip Kaludercic <philipk@posteo.net> writes:
> Xiyue Deng <manphiz@gmail.com> writes:
>
>
> [...]
>
>>> diff --git a/auth-source-xoauth2-plugin.el b/auth-source-xoauth2-plugin.el
>>> index cdcc9e7..caf5baf 100644
>>> --- a/auth-source-xoauth2-plugin.el
>>> +++ b/auth-source-xoauth2-plugin.el
>>> @@ -41,7 +41,7 @@
>>> ;; or with use-package:
>>>
>>> ;; (use-package auth-source-xoauth2-plugin
>>> -;; :config
>>> +;; :custom
>>> ;; (auth-source-xoauth2-plugin-mode t))
>>>
>>
>> Quick question: I wonder whether customizing the minor mode variable is
>> preferred over toggling through the minor mode function? (I assume both
>> will run the minor mode body.)
>
> You are right, it doesn't matter. I changed this when adding the
> autoload cookie, and somehow I had convinced myself that this would only
> work as a user option, which of course is not the case.
Thanks for confirming! I have incorporated your suggestions and pushed
to my repo. Thanks again for your review!
>
> [...]
>
>
> --
> Philip Kaludercic on siskin
--
Xiyue Deng
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-09-19 22:37 ` Xiyue Deng
2024-09-22 12:05 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
[not found] ` <66f00802.050a0220.988f0.9640SMTPIN_ADDED_BROKEN@mx.google.com>
@ 2024-10-03 22:41 ` Xiyue Deng
2024-10-08 13:38 ` Ted Zlatanov
2 siblings, 1 reply; 26+ messages in thread
From: Xiyue Deng @ 2024-10-03 22:41 UTC (permalink / raw)
To: Andrew Cohen; +Cc: Ted Zlatanov, Philip Kaludercic, 72992, Stefan Kangas
Xiyue Deng <manphiz@gmail.com> writes:
> Andrew Cohen <acohen@ust.hk> writes:
>
> [...]
>
>> By the way there are some significant bugs in auth-source.el which I
>> have fixed in my personal tree but haven't yet pushed. I have so little
>> time for emacs at the moment, but I'll try to get around to it. And
>> there is one major deficiency in auth-source.el that I want to deal
>> with: obfuscation of the :secret. When Ted originally wrote
>> auth-source.el he wrapped the :secret in a closure so that the secret
>> itself wasn't visible in memory. At the time he did this, closures
>> weren't fully part of emacs, and their implementation at the time didn't
>> expose the contents of the closure in bytecode. But the current official
>> implementation does, so this obfuscation trick no longer works. I want
>> to remove it since it no longer works and might lead to confusion.
>>
>
> Looking forward to it!
>
Just want to follow up on this: may we try your fixes and maybe try to
contribute for committing upstream? Also, for the :secret in closures,
do you suggest to remove it or is there another up-to-date way to hide
it in memory?
>> XD> Maybe auth-source source can host a helper function that checks
>> XD> if `:secret' is not set and xaouth2 is preferred (e.g. `:auth'
>> XD> is `xoauth2') and all required credentials are available it will
>> XD> get the access_token and put it `:secret' (or basically my hacky
>> XD> advice :)
>>
>> I think this isn't the right way to go. Currently xoauth2 is one of
>> several supported SASL methods. The logic is supposed to be to try them
>> in a certain order, but this hasn't worked properly for some
>> time. Nobody has noticed since almost everyone uses only the basic
>> method. In gnus there has always been a server variable,
>> nnimap-authenticator, that chooses the preferred sasl method, which is
>> how the current support for xaouth2 is designed to work. I think this
>> is the right way to handle this (rather than relying on some specific
>> form of the auth-source entry) but it would be good to fix the logic in
>> nnimap.el to allow multiple methods to be tried.
>>
>
> Right. The `:auth' trick I did is just to workaround the restriction
> that `nnimap-login' chooses basic method over other methods, and I'd
> prefer a better built-in support in auth-source myself. As you
> mentioned, maybe it can be remodeled after `smtpmail-try-auth-method' to
> so that the login method is chosen on demand instead of trial-and-error.
>
In this regard, is it desirable to make `auth-source-search-backends' a
defgeneric acting on a given protocol (basic vs. xoauth2 vs. others),
and similarly for `nnimap-login' et al.?
>> [...]
>>
--
Xiyue Deng
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-10-03 22:41 ` Xiyue Deng
@ 2024-10-08 13:38 ` Ted Zlatanov
2024-11-09 20:01 ` Xiyue Deng
0 siblings, 1 reply; 26+ messages in thread
From: Ted Zlatanov @ 2024-10-08 13:38 UTC (permalink / raw)
To: Xiyue Deng; +Cc: Andrew Cohen, Philip Kaludercic, 72992, Stefan Kangas
On Thu, 03 Oct 2024 15:41:34 -0700 Xiyue Deng <manphiz@gmail.com> wrote:
XD> Just want to follow up on this: may we try your fixes and maybe try to
XD> contribute for committing upstream? Also, for the :secret in closures,
XD> do you suggest to remove it or is there another up-to-date way to hide
XD> it in memory?
I think contributing the oauth2 support directly to Emacs is the best
approach because it would help the greatest number of users without
requiring extra configuration. I'd say modifying auth-source.el to fit
the need is absolutely OK. I would just ask that if you modify the
format of the authinfo file, to keep it compatible with JSON
serialization for those of us that use an authinfo.json file.
I'd prefer to find another way to hide the secrets if closures don't
work anymore. I don't know if Emacs offers something; if not then we
should make an effort to do it. But that effort should not block the
oauth2 support, it's completely separate IMO.
XD> Maybe auth-source source can host a helper function that checks
XD> if `:secret' is not set and xaouth2 is preferred (e.g. `:auth'
XD> is `xoauth2') and all required credentials are available it will
XD> get the access_token and put it `:secret' (or basically my hacky
XD> advice :)
Sure, if that makes the code easier. I think the important thing is just
to make it compatible with the current usage and to avoid making the
user customize things to make oauth2 support Just Work.
XD> In this regard, is it desirable to make `auth-source-search-backends' a
XD> defgeneric acting on a given protocol (basic vs. xoauth2 vs. others),
XD> and similarly for `nnimap-login' et al.?
I'm not sure if that would benefit the users. If it benefits the
developers that's nice, but definitely not required, and especially if
it changes the search API and can't be implemented in a compatible way.
Because there may be a dozen packages on Github or whatever using that
API, and updating all of them will be painful.
Basically if the search API works right now, it's probably easier to
leave it or make a new one and transition gradually.
I hope this was helpful :)
--
Ted Zlatanov <tzz@lifelogs.com>
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs
2024-10-08 13:38 ` Ted Zlatanov
@ 2024-11-09 20:01 ` Xiyue Deng
0 siblings, 0 replies; 26+ messages in thread
From: Xiyue Deng @ 2024-11-09 20:01 UTC (permalink / raw)
To: Ted Zlatanov; +Cc: Andrew Cohen, Philip Kaludercic, 72992, Stefan Kangas
[-- Attachment #1: Type: text/plain, Size: 2961 bytes --]
Hi Ted,
Ted Zlatanov <tzz@lifelogs.com> writes:
> On Thu, 03 Oct 2024 15:41:34 -0700 Xiyue Deng <manphiz@gmail.com> wrote:
>
> XD> Just want to follow up on this: may we try your fixes and maybe try to
> XD> contribute for committing upstream? Also, for the :secret in closures,
> XD> do you suggest to remove it or is there another up-to-date way to hide
> XD> it in memory?
>
> I think contributing the oauth2 support directly to Emacs is the best
> approach because it would help the greatest number of users without
> requiring extra configuration. I'd say modifying auth-source.el to fit
> the need is absolutely OK. I would just ask that if you modify the
> format of the authinfo file, to keep it compatible with JSON
> serialization for those of us that use an authinfo.json file.
>
> I'd prefer to find another way to hide the secrets if closures don't
> work anymore. I don't know if Emacs offers something; if not then we
> should make an effort to do it. But that effort should not block the
> oauth2 support, it's completely separate IMO.
>
> XD> Maybe auth-source source can host a helper function that checks
> XD> if `:secret' is not set and xaouth2 is preferred (e.g. `:auth'
> XD> is `xoauth2') and all required credentials are available it will
> XD> get the access_token and put it `:secret' (or basically my hacky
> XD> advice :)
>
> Sure, if that makes the code easier. I think the important thing is just
> to make it compatible with the current usage and to avoid making the
> user customize things to make oauth2 support Just Work.
>
> XD> In this regard, is it desirable to make `auth-source-search-backends' a
> XD> defgeneric acting on a given protocol (basic vs. xoauth2 vs. others),
> XD> and similarly for `nnimap-login' et al.?
>
> I'm not sure if that would benefit the users. If it benefits the
> developers that's nice, but definitely not required, and especially if
> it changes the search API and can't be implemented in a compatible way.
> Because there may be a dozen packages on Github or whatever using that
> API, and updating all of them will be painful.
>
> Basically if the search API works right now, it's probably easier to
> leave it or make a new one and transition gradually.
>
> I hope this was helpful :)
>
> --
> Ted Zlatanov <tzz@lifelogs.com>
It seems I completely missed your email, and sorry for that. I think
your suggestions are very helpful: we should make oauth2 available for
auth-source while keeping the existing interface. I think there are a
few more things to do before that can happen:
* Ship oauth2.el with Emacs, so that auth-source can make use of it.
* Decide which sequence of credentials to try before giving up and throw
an error.
I wonder how hard it would be to make these happen. Since this thread
is already very long, I'll probably file new bugs for tracking.
Thanks again!
--
Regards,
Xiyue Deng
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 857 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2024-11-09 20:01 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-02 8:34 bug#72992: 29.4; towards xoauth2 support in Emacs Xiyue Deng
[not found] ` <handler.72992.B.172532159013230.ack@debbugs.gnu.org>
2024-09-11 0:27 ` Xiyue Deng
2024-09-17 17:33 ` Xiyue Deng
2024-09-17 19:12 ` Philip Kaludercic
2024-09-18 6:24 ` Xiyue Deng
2024-09-18 14:11 ` Philip Kaludercic
2024-09-22 7:06 ` Xiyue Deng
2024-09-22 9:34 ` Philip Kaludercic
2024-09-22 22:00 ` Xiyue Deng
2024-09-23 6:17 ` Philip Kaludercic
2024-09-23 6:39 ` Xiyue Deng
2024-09-17 21:33 ` Stefan Kangas
2024-09-18 19:43 ` Xiyue Deng
2024-09-19 5:13 ` Andrew Cohen
2024-09-19 8:22 ` Xiyue Deng
2024-09-19 9:06 ` Andrew Cohen
2024-09-19 22:37 ` Xiyue Deng
2024-09-22 12:05 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
[not found] ` <66f00802.050a0220.988f0.9640SMTPIN_ADDED_BROKEN@mx.google.com>
2024-09-22 21:40 ` Xiyue Deng
2024-09-22 23:50 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
[not found] ` <66f0ad4f.500a0220.10c3c2.dde8SMTPIN_ADDED_BROKEN@mx.google.com>
2024-09-23 2:20 ` Xiyue Deng
2024-10-03 22:41 ` Xiyue Deng
2024-10-08 13:38 ` Ted Zlatanov
2024-11-09 20:01 ` Xiyue Deng
2024-09-22 12:01 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
[not found] ` <66f00712.170a0220.29d948.0047SMTPIN_ADDED_BROKEN@mx.google.com>
2024-09-22 21:44 ` Xiyue Deng
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.