mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 09:14:18 +00:00
Ignore non-existing or empty files in auth-sources
* doc/misc/auth.texi: Replace @code{"..."} by @t{"..."}.
(Help for users): Describe property lists format. Explain, that
empty files in auth-sources are ignored when
auth-source-ignore-empty-file is non-nil.
(Help for developers): Add auth-source-creation-defaults to vindex.
* etc/NEWS: Introduce auth-source-ignore-empty-file.
Presentational fixes and improvements.
* lisp/auth-source.el (auth-source-ignore-empty-file): New defcustom.
(auth-source-backends-parser-file): Use it. (Bug#9113)
* test/lisp/auth-source-tests.el (auth-source-validate-backend):
Let-bind `auth-source-ignore-empty-file'.
(auth-source-test-searches): Set file suffix.
(auth-source-test-netrc-create-secret): Adapt test.
This commit is contained in:
parent
a2d4034242
commit
d1221a427f
4 changed files with 136 additions and 75 deletions
|
|
@ -136,9 +136,9 @@ You can use spaces inside a password or other token by surrounding the
|
|||
token with either single or double quotes.
|
||||
|
||||
You can use apostrophes inside a password or other token by
|
||||
surrounding it with double quotes, e.g., @code{"he'llo"}. Similarly you
|
||||
surrounding it with double quotes, e.g., @t{"he'llo"}. Similarly you
|
||||
can use double quotes inside a password or other token by surrounding
|
||||
it with apostrophes, e.g., @code{'he"llo'}. You can't mix both (so a
|
||||
it with apostrophes, e.g., @t{'he"llo'}. You can't mix both (so a
|
||||
password or other token can't have both apostrophes and double quotes).
|
||||
|
||||
All this is optional. You could just say (but we don't recommend it,
|
||||
|
|
@ -157,7 +157,7 @@ library encourages this confusion by accepting both, as you'll see
|
|||
later.
|
||||
|
||||
If you have problems with the search, set @code{auth-source-debug} to
|
||||
@code{'trivia} and see what host, port, and user the library is
|
||||
@code{trivia} and see what host, port, and user the library is
|
||||
checking in the @file{*Messages*} buffer. Ditto for any other
|
||||
problems, your first step is always to see what's being checked. The
|
||||
second step, of course, is to write a blog entry about it and wait for
|
||||
|
|
@ -267,16 +267,34 @@ earlier. Since Tramp has about 88 connection methods, this may be
|
|||
necessary if you have an unusual (see earlier comment on those) setup.
|
||||
@xref{Password handling, Password handling,, tramp, Tramp}.
|
||||
|
||||
The netrc format is directly translated into JSON, if you are into
|
||||
that sort of thing. Just point to a JSON file with entries like this:
|
||||
The netrc format is directly translated into JSON, if you are into that
|
||||
sort of thing. Just point to a file which has the name extension
|
||||
@file{.json} with entries like this:
|
||||
|
||||
@example
|
||||
[
|
||||
@{ "machine": "yourmachine.com", "port": "http",
|
||||
"login": "testuser", "password": "testpass" @}
|
||||
"login": "testuser", "password": "testpass" @}
|
||||
]
|
||||
@end example
|
||||
|
||||
It is also possible to translate this into property lists, used in files
|
||||
with name extension @file{.plist}. Its format is described in the
|
||||
@file{plstore.el} library:
|
||||
|
||||
@example
|
||||
(("foo" :host "yourmachine.com" :port "http"
|
||||
:user "testuser" :password "testpass"))
|
||||
@end example
|
||||
|
||||
@vindex auth-source-ignore-empty-file
|
||||
File-based data stores are ignored in @code{auth-sources}, if the
|
||||
underlying data file does not exist, or is empty. This is relevant, if
|
||||
a new secret is stored in such a file; the first usable entry of
|
||||
@code{auth-sources} is selected as target. If you want also empty or
|
||||
not existing files to be selected, set the user option
|
||||
@code{auth-source-ignore-empty-file} to @code{nil}.
|
||||
|
||||
@node Multiple GMail accounts with Gnus
|
||||
@chapter Multiple GMail accounts with Gnus
|
||||
|
||||
|
|
@ -335,12 +353,12 @@ sometimes called a @samp{keyring} or @samp{wallet} in GNOME Keyring
|
|||
and KDE Wallet but it's the same thing, a group of secrets.
|
||||
Collections are personal and protected so only the owner can open them.
|
||||
|
||||
The most common collection is called @code{"login"}.
|
||||
The most common collection is called @t{"login"}.
|
||||
|
||||
A collection can have an alias. The alias @code{"default"} is
|
||||
A collection can have an alias. The alias @t{"default"} is
|
||||
commonly used so the clients don't have to know the specific name of
|
||||
the collection they open. Other aliases are not supported yet.
|
||||
Since aliases are globally accessible, set the @code{"default"} alias
|
||||
Since aliases are globally accessible, set the @t{"default"} alias
|
||||
only when you're sure it's appropriate.
|
||||
|
||||
@defun secrets-list-collections
|
||||
|
|
@ -349,31 +367,31 @@ This function returns all the collection names as a list.
|
|||
|
||||
@defun secrets-set-alias collection alias
|
||||
Set @var{alias} as alias of collection labeled @var{collection}.
|
||||
Currently only the alias @code{"default"} is supported.
|
||||
Currently only the alias @t{"default"} is supported.
|
||||
@end defun
|
||||
|
||||
@defun secrets-get-alias alias
|
||||
Return the collection name @var{alias} is referencing to.
|
||||
Currently only the alias @code{"default"} is supported.
|
||||
Currently only the alias @t{"default"} is supported.
|
||||
@end defun
|
||||
|
||||
Collections can be created and deleted by the functions
|
||||
@code{secrets-create-collection} and @code{secrets-delete-collection}.
|
||||
Usually, this is not done from within Emacs. Do not delete standard
|
||||
collections such as @code{"login"}.
|
||||
collections such as @t{"login"}.
|
||||
|
||||
With GNOME Keyring, there exists a special collection called
|
||||
@code{"session"}, which has the lifetime of the user being logged in.
|
||||
@t{"session"}, which has the lifetime of the user being logged in.
|
||||
Its data is not stored on disk and goes away when the user logs out.
|
||||
Therefore, it can be used to store and retrieve secret items
|
||||
temporarily. The @code{"session"} collection is better than a
|
||||
temporarily. The @t{"session"} collection is better than a
|
||||
persistent collection when the secret items should not live
|
||||
permanently. The @code{"session"} collection can be addressed either
|
||||
by the string @code{"session"}, or by @code{nil}, whenever a
|
||||
permanently. The @t{"session"} collection can be addressed either
|
||||
by the string @t{"session"}, or by @code{nil}, whenever a
|
||||
collection parameter is needed.
|
||||
|
||||
However, other Secret Service provider don't create this temporary
|
||||
@code{"session"} collection. You must check first that this
|
||||
@t{"session"} collection. You must check first that this
|
||||
collection exists, before you use it.
|
||||
|
||||
@defun secrets-list-items collection
|
||||
|
|
@ -451,12 +469,12 @@ in @code{secrets-create-item}. Example:
|
|||
|
||||
The auth-source library uses the @file{secrets.el} library and thus
|
||||
the Secret Service API when you specify a source matching
|
||||
@code{"secrets:COLLECTION"}. For instance, you could use
|
||||
@code{"secrets:session"} to use the @code{"session"} collection, open only
|
||||
for the lifetime of Emacs. Or you could use @code{"secrets:Login"} to
|
||||
open the @code{"Login"} collection. As a special case, you can use the
|
||||
@t{"secrets:@var{collection}"}. For instance, you could use
|
||||
@t{"secrets:session"} to use the @t{"session"} collection, open only
|
||||
for the lifetime of Emacs. Or you could use @t{"secrets:Login"} to
|
||||
open the @t{"Login"} collection. As a special case, you can use the
|
||||
symbol @code{default} in @code{auth-sources} (not a string, but a
|
||||
symbol) to specify the @code{"default"} alias. Here is a contrived
|
||||
symbol) to specify the @t{"default"} alias. Here is a contrived
|
||||
example that sets @code{auth-sources} to search three collections and
|
||||
then fall back to @file{~/.authinfo.gpg}.
|
||||
|
||||
|
|
@ -578,7 +596,7 @@ expecting to query multiple backends uniformly, try flipping it to
|
|||
The auth-source library lets you control logging output easily.
|
||||
|
||||
@defopt auth-source-debug
|
||||
Set this user option to @code{'trivia} to see lots of output in
|
||||
Set this user option to @code{trivia} to see lots of output in
|
||||
@file{*Messages*}, or set it to a function that behaves like
|
||||
@code{message} to do your own logging.
|
||||
@end defopt
|
||||
|
|
@ -611,6 +629,7 @@ from Gnus's @code{nnimap.el}.
|
|||
nil)))
|
||||
@end example
|
||||
|
||||
@vindex auth-source-creation-defaults
|
||||
This call requires the user and password (secret) to be in the
|
||||
results. It also requests that an entry be created if it doesn't
|
||||
exist already. While the created entry is being assembled, the shown
|
||||
|
|
@ -636,7 +655,7 @@ authentication information we just used, if it was newly created.''
|
|||
|
||||
After the first time it's called, the @code{:save-function} will not
|
||||
run again (but it will log something if you have set
|
||||
@code{auth-source-debug} to @code{'trivia}). This is so it won't ask
|
||||
@code{auth-source-debug} to @code{trivia}). This is so it won't ask
|
||||
the same question again, which is annoying.
|
||||
|
||||
So the responsibility of the API user that specified @code{:create t}
|
||||
|
|
|
|||
67
etc/NEWS
67
etc/NEWS
|
|
@ -189,10 +189,10 @@ be updated as you type, or nil to suppress this always. Note that for
|
|||
large or inefficient completion tables this can slow down typing.
|
||||
|
||||
---
|
||||
*** RET chooses the completion selected with M-<up>/M-<down>
|
||||
If a completion candidate is selected with M-<up> or M-<down>, hitting
|
||||
RET will exit completion with that as the result. This works both in
|
||||
minibuffer completion and in-buffer completion. This supersedes
|
||||
*** 'RET' chooses the completion selected with 'M-<up>/M-<down>'.
|
||||
If a completion candidate is selected with 'M-<up>' or 'M-<down>',
|
||||
hitting 'RET' will exit completion with that as the result. This works
|
||||
both in minibuffer completion and in-buffer completion. This supersedes
|
||||
'minibuffer-completion-auto-choose', which previously provided similar
|
||||
behavior; that variable is now nil by default.
|
||||
|
||||
|
|
@ -525,10 +525,10 @@ project.
|
|||
|
||||
The value must be an alist where each element must be in the form:
|
||||
|
||||
(WHEN . PREDICATE)
|
||||
(WHEN . PREDICATE)
|
||||
|
||||
where WHEN specifies where the deletion will be performed, and PREDICATE
|
||||
a function which takes one argument, and must return non-nil if the
|
||||
is a function which takes one argument, and must return non-nil if the
|
||||
project should be removed.
|
||||
|
||||
---
|
||||
|
|
@ -763,6 +763,17 @@ you could already use 'C-u C-x C-n' to clear the goal column.
|
|||
|
||||
* Changes in Specialized Modes and Packages in Emacs 31.1
|
||||
|
||||
** Auth Source
|
||||
|
||||
+++
|
||||
*** Non-existing or empty files are ignored in 'auth-sources'.
|
||||
File-based data stores are ignored in ‘auth-sources’, if the
|
||||
underlying data file does not exist, or is empty. This is relevant, if
|
||||
a new secret is stored in such a file; the first usable entry of
|
||||
‘auth-sources’ is selected as target. If you want also empty or not
|
||||
existing files to be selected, set the user option
|
||||
‘auth-source-ignore-empty-file’ to nil.
|
||||
|
||||
** Autoinsert
|
||||
|
||||
+++
|
||||
|
|
@ -782,10 +793,12 @@ the default UI you get, i.e., when 'register-use-preview' is 'traditional'.
|
|||
|
||||
+++
|
||||
*** New user option 'treesit-enabled-modes'.
|
||||
You can customize it either to t to enable all available ts-modes,
|
||||
or to select a list of ts-modes to enable. Depending on customization,
|
||||
it modifies the variable 'major-mode-remap-alist' from the corresponding
|
||||
variable 'treesit-major-mode-remap-alist' prepared by ts-mode packages.
|
||||
You can customize it either to t to enable all available tree-sitter
|
||||
based modes, or to select a list of tree-sitter based modes to enable.
|
||||
Depending on customization, it modifies the variable
|
||||
'major-mode-remap-alist' from the corresponding variable
|
||||
'treesit-major-mode-remap-alist' prepared by tree-sitter based mode
|
||||
packages.
|
||||
|
||||
*** New user option 'treesit-auto-install-grammar'.
|
||||
It controls the automatic installation of tree-sitter grammar libraries
|
||||
|
|
@ -1003,9 +1016,9 @@ option controls how much is indented for method chaining.
|
|||
|
||||
---
|
||||
*** 'php-ts-mode' now depends on 'mhtml-ts-mode'.
|
||||
The direct dependency on js-ts-mode, css-ts-mode and html-ts-mode has
|
||||
now been replaced by ‘mhtml-ts-mode’. Navigation, Outline and Imenu
|
||||
work for all languages and code maintenance is easier.
|
||||
The direct dependency on 'js-ts-mode', 'css-ts-mode' and 'html-ts-mode'
|
||||
has now been replaced by ‘mhtml-ts-mode’. Navigation, Outline and Imenu
|
||||
work for all languages, and code maintenance is easier.
|
||||
|
||||
---
|
||||
*** 'php-ts-mode-run-php-webserver' can now accept a custom "php.ini" file.
|
||||
|
|
@ -1016,7 +1029,7 @@ argument, 'php-ts-mode-run-php-webserver' prompts for the config file as
|
|||
well as for other connection parameters.
|
||||
|
||||
---
|
||||
*** The option 'php-ts-mode-css-fontify-colors' has been removed.
|
||||
*** The user option 'php-ts-mode-css-fontify-colors' has been removed.
|
||||
'mhtml-ts-mode-css-fontify-colors' replaces this option.
|
||||
|
||||
---
|
||||
|
|
@ -1040,8 +1053,8 @@ When non nil, it highlights unknown PHPDOC tags using
|
|||
|
||||
---
|
||||
*** New command 'php-ts-mode-show-ini'.
|
||||
Show the location of the PHP ini files, if the buffer is associated to a remote
|
||||
PHP file show the remote PHP ini files.
|
||||
Show the location of the PHP ini files. If the current buffer is
|
||||
associated to a remote PHP file, show the remote PHP ini files.
|
||||
|
||||
** Rust-ts mode
|
||||
|
||||
|
|
@ -1262,10 +1275,10 @@ If 'whitespace-style' includes 'missing-newline-at-eof' (which is the
|
|||
default), the 'whitespace-cleanup' function will now add the newline.
|
||||
|
||||
---
|
||||
*** 'whitespace-mode' now can prettify page delimiter characters (^L).
|
||||
*** 'whitespace-mode' now can prettify page delimiter characters ('^L').
|
||||
If 'page-delimiters' is set in 'whitespace-style', or the new minor mode
|
||||
'whitespace-page-delimiters-mode' is on, the page delimiter characters
|
||||
(^L) are displayed as a pretty horizontal line that spans the entire
|
||||
('^L') are displayed as a pretty horizontal line that spans the entire
|
||||
width of the window. The new 'whitespace-page-delimiter' face can be
|
||||
used to customize the appearence.
|
||||
|
||||
|
|
@ -2154,7 +2167,7 @@ statuses to files, and 'C-x v v' behaved subtly differently for the two
|
|||
statuses. The combination of these differences between backends and in
|
||||
'C-x v v' behavior was confusing. Now,
|
||||
|
||||
- in VC-Dir, you can use 'C-x v v' on missing files to mark them as
|
||||
- in VC Directory, you can use 'C-x v v' on missing files to mark them as
|
||||
removed
|
||||
- when committing, you can include missing files in a set of files with
|
||||
different statuses, just like you've always been able to include
|
||||
|
|
@ -2259,7 +2272,7 @@ backend functions instead. These are jointly sufficient to support the
|
|||
*** Marking revisions in Log View now works more like other modes.
|
||||
Previously, 'm' toggled whether the current revision was marked, and
|
||||
didn't advance point. Now 'm' only adds marks, 'u' removes marks, and
|
||||
both advance point, like how marking works in Dired and VC-Dir.
|
||||
both advance point, like how marking works in Dired and VC Directory.
|
||||
You can get back the old behavior with something like this:
|
||||
|
||||
(with-eval-after-load 'log-view
|
||||
|
|
@ -2332,7 +2345,7 @@ packages.
|
|||
** Rcirc
|
||||
|
||||
+++
|
||||
*** Authentication via NickServ can access password from 'auth-source'.
|
||||
*** Authentication via NickServ can access passwords with auth-source.el.
|
||||
For details, consult 'rcirc-authinfo'.
|
||||
|
||||
** Xref
|
||||
|
|
@ -2559,10 +2572,10 @@ If non-nil, FFAP always finds remote files in buffers with remote
|
|||
'default-directory'. If nil, FFAP finds local files first for absolute
|
||||
file names in above buffers. The default is nil.
|
||||
|
||||
** Debugging
|
||||
** Edebug
|
||||
|
||||
+++
|
||||
*** New command 'edebug-bounce-to-previous-value' (bound to 'P')
|
||||
*** New command 'edebug-bounce-to-previous-value' (bound to 'P').
|
||||
This command temporarily displays the outside current buffer with the
|
||||
outside point corresponding to the previous value, where the previous
|
||||
value is what Edebug has evaluated before its last stop point or what
|
||||
|
|
@ -2603,7 +2616,7 @@ widths based on content, optimizing display space and readability.
|
|||
|
||||
*** New user option 'elisp-flymake-byte-compile-executable'.
|
||||
This allows customizing the Emacs executable used for Flymake byte
|
||||
compilation in emacs-lisp-mode. This option should be set when editing
|
||||
compilation in 'emacs-lisp-mode'. This option should be set when editing
|
||||
Lisp code which will run with a different Emacs version than the running
|
||||
Emacs, such as code from an older or newer version of Emacs. This will
|
||||
provide more accurate warnings from byte compilation.
|
||||
|
|
@ -2854,15 +2867,15 @@ on GNU/Linux systems.
|
|||
|
||||
---
|
||||
** New variable 'tty-cursor-movement-use-TAB-BS'.
|
||||
The display optimization where the combination TAB characters +
|
||||
BACKSPACE is used to move to a position on a TTY frame is now disabled
|
||||
The display optimization where the combination 'TAB' characters +
|
||||
'BACKSPACE' is used to move to a position on a TTY frame is now disabled
|
||||
by default and controlled by this variable; it can be set to non-nil
|
||||
to keep the old behavior. This change is to accomodate screen
|
||||
readers.
|
||||
|
||||
+++
|
||||
** A thread's current buffer can now be killed.
|
||||
We introduce a new attribute for threads called buffer-disposition.
|
||||
We introduce a new attribute for threads called 'buffer-disposition'.
|
||||
See the new argument in 'make-thread'. The default value allows the
|
||||
thread's current buffer to be killed by another thread. This does not
|
||||
apply to the main thread's buffer.
|
||||
|
|
|
|||
|
|
@ -370,6 +370,16 @@ soon as a function returns non-nil.")
|
|||
:type 'ignore)))
|
||||
(auth-source-backend-parse-parameters entry backend)))
|
||||
|
||||
(defcustom auth-source-ignore-empty-file t
|
||||
"If set non-nil, file-based backends with no data are ignored.
|
||||
A backend is ignored, when the underlying file does not exist, or it is
|
||||
empty. Consequently, no newly created entry is saved in an empty
|
||||
backend when this user option is non-nil.
|
||||
|
||||
Supported backend types are `netrc', `plstore' and `json'."
|
||||
:version "31.1"
|
||||
:type 'boolean)
|
||||
|
||||
(defun auth-source-backends-parser-file (entry)
|
||||
;; take just a file name use it as a netrc/plist file
|
||||
;; matching any user, host, and protocol
|
||||
|
|
@ -384,26 +394,41 @@ soon as a function returns non-nil.")
|
|||
(extension (or (and (stringp source-without-gpg)
|
||||
(file-name-extension source-without-gpg))
|
||||
"")))
|
||||
(when (stringp source)
|
||||
(cond
|
||||
((equal extension "plist")
|
||||
(auth-source-backend
|
||||
:source source
|
||||
:type 'plstore
|
||||
:search-function #'auth-source-plstore-search
|
||||
:create-function #'auth-source-plstore-create
|
||||
:data (plstore-open source)))
|
||||
((member-ignore-case extension '("json"))
|
||||
(auth-source-backend
|
||||
:source source
|
||||
:type 'json
|
||||
:search-function #'auth-source-json-search))
|
||||
(t
|
||||
(auth-source-backend
|
||||
:source source
|
||||
:type 'netrc
|
||||
:search-function #'auth-source-netrc-search
|
||||
:create-function #'auth-source-netrc-create))))))
|
||||
(if (and (stringp source)
|
||||
(or (not auth-source-ignore-empty-file)
|
||||
(and-let*
|
||||
(;; File exists.
|
||||
(attr (file-attributes source))
|
||||
;; File isn't empty.
|
||||
((not (zerop (file-attribute-size attr))))))))
|
||||
(cond
|
||||
((equal extension "plist")
|
||||
(auth-source-backend
|
||||
:source source
|
||||
:type 'plstore
|
||||
:search-function #'auth-source-plstore-search
|
||||
:create-function #'auth-source-plstore-create
|
||||
:data (plstore-open source)))
|
||||
((member-ignore-case extension '("json"))
|
||||
(auth-source-backend
|
||||
:source source
|
||||
:type 'json
|
||||
:search-function #'auth-source-json-search))
|
||||
(t
|
||||
(auth-source-backend
|
||||
:source source
|
||||
:type 'netrc
|
||||
:search-function #'auth-source-netrc-search
|
||||
:create-function #'auth-source-netrc-create)))
|
||||
|
||||
(when auth-source-debug
|
||||
(auth-source-do-warn
|
||||
(concat "auth-source-backend-parse: "
|
||||
"not existing or empty file, ignoring spec: %S")
|
||||
entry))
|
||||
(auth-source-backend
|
||||
:source ""
|
||||
:type 'ignore))))
|
||||
|
||||
;; Note this function should be last in the parser functions, so we add it first
|
||||
(add-hook 'auth-source-backend-parser-functions #'auth-source-backends-parser-file)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@
|
|||
(type . ignore))))
|
||||
|
||||
(defun auth-source-validate-backend (source validation-alist)
|
||||
(let ((backend (auth-source-backend-parse source)))
|
||||
(let* (auth-source-ignore-empty-file
|
||||
(backend (auth-source-backend-parse source)))
|
||||
(should (auth-source-backend-p backend))
|
||||
(dolist (pair validation-alist)
|
||||
(should (equal (eieio-oref backend (car pair)) (cdr pair))))))
|
||||
|
|
@ -308,7 +309,7 @@
|
|||
:host "b1" :port "b2" :user "b3")
|
||||
)))
|
||||
(ert-with-temp-file netrc-file
|
||||
:text (mapconcat 'identity entries "\n")
|
||||
:suffix "auth-source-test" :text (mapconcat 'identity entries "\n")
|
||||
(let ((auth-sources (list netrc-file))
|
||||
(auth-source-do-cache nil)
|
||||
found found-as-string)
|
||||
|
|
@ -374,10 +375,13 @@
|
|||
"%s@%s" (plist-get auth-info :user) (plist-get auth-info :host)))))))
|
||||
|
||||
(ert-deftest auth-source-test-netrc-create-secret ()
|
||||
(ert-with-temp-file empty-file :suffix "auth-source-test"
|
||||
(ert-with-temp-file netrc-file
|
||||
:suffix "auth-source-test"
|
||||
(let* ((auth-sources (list netrc-file))
|
||||
:text "machine a1 port a2 user a3 password a4"
|
||||
(let* ((auth-sources (list empty-file netrc-file))
|
||||
(auth-source-save-behavior t)
|
||||
(auth-source-ignore-empty-file t)
|
||||
host auth-info auth-passwd)
|
||||
(dolist (passwd '("foo" "" nil))
|
||||
;; Redefine `read-*' in order to avoid interactive input.
|
||||
|
|
@ -415,7 +419,7 @@
|
|||
(string-equal (plist-get auth-info :user) (user-login-name)))
|
||||
(should (string-equal (plist-get auth-info :host) host))
|
||||
(should (string-equal auth-passwd passwd))
|
||||
(should (search-forward host nil 'noerror)))))))))
|
||||
(should (search-forward host nil 'noerror))))))))))
|
||||
|
||||
(ert-deftest auth-source-delete ()
|
||||
(ert-with-temp-file netrc-file
|
||||
|
|
|
|||
Loading…
Reference in a new issue