Fix some naming issues involving query buffers in ERC

* lisp/erc/erc-networks.el
(erc-networks-rename-surviving-target-buffer): Don't kill a surviving
target buffer when another, non-target buffer, possibly not even
belonging to ERC, already exists and sports the target's name.
(erc-networks--reconcile-buffer-names): Always append a network-ID
suffix to a target buffer's name if another buffer of that name
already exists.  (Bug#59976.)
* lisp/erc/erc.el (erc, erc-tls): Revise `:id' portion of doc strings.
Thanks to Mike Kazantsev for the suggestion and for filing this bug
and helping solve it.
* test/lisp/erc/erc-networks-tests.el:
(erc-networks-rename-surviving-target-buffer--query-non-target): Add
new test.
* test/lisp/erc/erc-scenarios-base-association-query.el: New file.
* test/lisp/erc/resources/base/assoc/queries/netnick.eld: New file.
* test/lisp/erc/resources/base/assoc/queries/non-erc.eld: New file.
This commit is contained in:
F. Jason Park 2022-12-12 07:38:44 -08:00
parent 173e02f4eb
commit f04680e067
6 changed files with 232 additions and 19 deletions

View file

@ -1097,7 +1097,8 @@ matching that of the dying buffer."
(erc--target-symbol erc--target))))))))
((not (cdr others))))
(with-current-buffer (car others)
(rename-buffer (erc--target-string target)))))
(unless (get-buffer (erc--target-string target))
(rename-buffer (erc--target-string target))))))
(defun erc-networks-shrink-ids-and-buffer-names ()
"Recompute network IDs and buffer names, ignoring the current buffer.
@ -1188,19 +1189,20 @@ rename them with <n> suffixes going from newest to oldest."
(erc--target-string target)))
placeholder)
;; If we don't exist, claim name temporarily while renaming others
(when-let* (namesakes
(ex (get-buffer name))
((not (memq ex existing)))
(temp-name (generate-new-buffer-name (format "*%s*" name))))
(setq existing (remq ex existing))
(with-current-buffer ex
(rename-buffer temp-name)
(setq placeholder (get-buffer-create name))
(rename-buffer name 'unique)))
(when-let* ((ex (get-buffer name))
((not (memq ex existing))))
(if namesakes ; if namesakes is nonempty, it contains ex
(with-current-buffer ex
(let ((temp-name (generate-new-buffer-name (format "*%s*" name))))
(rename-buffer temp-name)
(setq placeholder (get-buffer-create name))
(rename-buffer name 'unique)))
;; Here, ex must be a server buffer or a non-ERC buffer
(setq name (erc-networks--construct-target-buffer-name target))))
(unless (with-suppressed-warnings ((obsolete erc-reuse-buffers))
erc-reuse-buffers)
(when (string-suffix-p ">" name)
(setq name (substring name 0 -3))))
(setq name (string-trim-right name (rx "<" (+ digit) ">")))))
(dolist (ex (erc-networks--id-sort-buffers existing))
(with-current-buffer ex
(rename-buffer name 'unique)))

View file

@ -2226,9 +2226,7 @@ then the server and full-name will be set to those values,
whereas `erc-compute-port' and `erc-compute-nick' will be invoked
for the values of the other parameters.
When present, ID should be an opaque object used to identify the
connection unequivocally. This is rarely needed and not available
interactively."
See `erc-tls' for the meaning of ID."
(interactive (erc-select-read-args))
(erc-open server port nick full-name t password nil nil nil nil user id))
@ -2255,6 +2253,7 @@ Non-interactively, it takes the keyword arguments
(server (erc-compute-server))
(port (erc-compute-port))
(nick (erc-compute-nick))
(user (erc-compute-user))
password
(full-name (erc-compute-full-name))
client-certificate
@ -2283,11 +2282,11 @@ Example usage:
\\='(\"/home/bandali/my-cert.key\"
\"/home/bandali/my-cert.crt\"))
When present, ID should be an opaque object for identifying the
connection unequivocally. (In most cases, this would be a string or a
symbol composed of letters from the Latin alphabet.) This option is
generally unneeded, however. See info node `(erc) Connecting' for use
cases. Not available interactively."
When present, ID should be a symbol or a string to use for naming
the server buffer and identifying the connection unequivocally.
See info node `(erc) Network Identifier' for details. Like USER
and CLIENT-CERTIFICATE, this parameter cannot be specified
interactively."
(interactive (let ((erc-default-port erc-default-port-tls))
(erc-select-read-args)))
(let ((erc-server-connect-function 'erc-open-tls-stream))

View file

@ -197,6 +197,36 @@
(erc-networks-tests--clean-bufs))
;; A non-ERC buffer exists named "bob", and we're killing one of two
;; ERC target buffers named "bob@<netid>". The surviving buffer
;; retains its suffix.
(ert-deftest erc-networks-rename-surviving-target-buffer--query-non-target ()
(should (memq #'erc-networks-rename-surviving-target-buffer
erc-kill-buffer-hook))
(let ((existing (get-buffer-create "bob"))
(bob-foonet (get-buffer-create "bob@foonet")))
(with-current-buffer bob-foonet
(erc-mode)
(setq erc-networks--id (make-erc-networks--id-qualifying
:parts [foonet "bob"] :len 1)
erc--target (erc--target-from-string "bob")))
(with-current-buffer (get-buffer-create "bob@barnet")
(erc-mode)
(setq erc-networks--id (make-erc-networks--id-qualifying
:parts [barnet "bob"] :len 1)
erc--target (erc--target-from-string "bob")))
(kill-buffer "bob@barnet")
(should (buffer-live-p existing))
(should (buffer-live-p bob-foonet))
(kill-buffer existing))
(erc-networks-tests--clean-bufs))
(ert-deftest erc-networks-rename-surviving-target-buffer--multi ()
(ert-info ("Multiple leftover channels untouched")

View file

@ -0,0 +1,107 @@
;;; erc-scenarios-base-association-query.el --- assoc query scenarios -*- lexical-binding: t -*-
;; Copyright (C) 2022 Free Software Foundation, Inc.
;; This file is 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/>.
;;; Code:
(require 'ert-x)
(eval-and-compile
(let ((load-path (cons (ert-resource-directory) load-path)))
(require 'erc-scenarios-common)))
(eval-when-compile (require 'erc-join))
;; Non-ERC buffers exist whose names match the nicknames of query
;; targets, both newly arriving and outgoing. No target buffers yet
;; exist for these, so new ones are created that feature a net-ID
;; @suffix.
(ert-deftest erc-scenarios-base-association-existing-non-erc-buffer ()
:tags '(:expensive-test)
(erc-scenarios-common-with-cleanup
((erc-scenarios-common-dialog "base/assoc/queries")
(dumb-server (erc-d-run "localhost" t 'non-erc))
(port (process-contact dumb-server :service))
(expect (erc-d-t-make-expecter))
(nitwit (with-current-buffer (get-buffer-create "nitwit")
(prin1 (ert-test-name (ert-running-test)) (current-buffer))
(current-buffer))) ; these are killed on completion by macro
(dummy (with-current-buffer (get-buffer-create "dummy")
(prin1 (ert-test-name (ert-running-test)) (current-buffer))
(current-buffer)))
(erc-server-flood-penalty 0.1))
(ert-info ("Connect to foonet")
(with-current-buffer (erc :server "127.0.0.1"
:port port
:nick "tester"
:user "tester"
:full-name "tester")
(erc-scenarios-common-assert-initial-buf-name nil port)
(erc-d-t-wait-for 5 (eq erc-network 'foonet))
(funcall expect 15 "debug mode")))
(ert-info ("Nick dummy queries us")
(with-current-buffer (erc-d-t-wait-for 10 (get-buffer "dummy@foonet"))
(should (erc-query-buffer-p))
(funcall expect 5 "hi")
(ert-info ("We query nick nitwit")
(with-current-buffer (erc-cmd-QUERY "nitwit")
(should (equal (buffer-name) "nitwit@foonet"))
(erc-scenarios-common-say "hola")
(funcall expect 5 "ciao")))
(erc-scenarios-common-say "howdy")
(funcall expect 5 "bye")
(erc-cmd-QUIT "")))))
;; Someone sending you a PM has the same name as the network (bug#59976)
(ert-deftest erc-scenarios-base-association-some-nick-is-network ()
:tags '(:expensive-test)
(erc-scenarios-common-with-cleanup
((erc-scenarios-common-dialog "base/assoc/queries")
(dumb-server (erc-d-run "localhost" t 'netnick))
(port (process-contact dumb-server :service))
(expect (erc-d-t-make-expecter))
(erc-server-flood-penalty 0.5))
(ert-info ("Connect to foonet")
(with-current-buffer (erc :server "127.0.0.1"
:port port
:nick "tester"
:user "tester"
:full-name "tester")
(erc-scenarios-common-assert-initial-buf-name nil port)
(erc-d-t-wait-for 5 (eq erc-network 'foonet))))
(ert-info ("Join common channel as nick foonet")
(with-current-buffer "foonet"
(funcall expect 15 "debug mode")
(erc-cmd-JOIN "#chan"))
(with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
(funcall expect 5 "welcome")))
(ert-info ("Nick foonet PMs us")
(with-current-buffer (erc-d-t-wait-for 10 (get-buffer "foonet@foonet"))
(should (erc-query-buffer-p))
(funcall expect 5 "hi")))))
;;; erc-scenarios-base-association-query.el ends here

View file

@ -0,0 +1,42 @@
;; -*- mode: lisp-data; -*-
((nick 10 "NICK tester"))
((user 1 "USER tester 0 * :tester")
(0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
(0.00 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.8.0")
(0.00 ":irc.foonet.org 003 tester :This server was created Mon, 12 Dec 2022 01:25:38 UTC")
(0.00 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
(0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
(0.00 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
(0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
(0.00 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
(0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
(0.00 ":irc.foonet.org 253 tester 0 :unregistered connections")
(0.00 ":irc.foonet.org 254 tester 1 :channels formed")
(0.00 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
(0.00 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
(0.01 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
(0.00 ":irc.foonet.org 422 tester :MOTD File is missing"))
((mode 10 "MODE tester +i")
(0.00 ":irc.foonet.org 221 tester +i")
(0.00 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
((join 10 "JOIN #chan")
(0.03 ":tester!~u@z5d6jyn8pwxge.irc JOIN #chan"))
((mode-1 10 "MODE #chan")
(0.01 ":irc.foonet.org 353 tester = #chan :@alice bob foonet tester")
(0.00 ":irc.foonet.org 366 tester #chan :End of NAMES list")
(0.03 ":irc.foonet.org 324 tester #chan +nt")
(0.00 ":irc.foonet.org 329 tester #chan 1670808354")
(0.00 ":bob!~u@d6ftaiqzk8x2k.irc PRIVMSG #chan :tester, welcome!")
(0.00 ":alice!~u@d6ftaiqzk8x2k.irc PRIVMSG #chan :tester, welcome!")
(0.00 ":foonet!~u@z5d6jyn8pwxge.irc PRIVMSG tester :hi")
(0.03 ":bob!~u@d6ftaiqzk8x2k.irc PRIVMSG #chan :alice: Forbear it therefore; give your cause to heaven.")
(0.01 ":alice!~u@d6ftaiqzk8x2k.irc PRIVMSG #chan :bob: Even at thy teat thou hadst thy tyranny.")
(0.00 ":foonet!~u@z5d6jyn8pwxge.irc QUIT :connection closed"))
((quit 10 "QUIT :\2ERC\2")
(0.03 ":tester!~u@z5d6jyn8pwxge.irc QUIT :Quit: \2ERC\2"))

View file

@ -0,0 +1,33 @@
;; -*- mode: lisp-data; -*-
((nick 10 "NICK tester"))
((user 1 "USER tester 0 * :tester")
(0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
(0.00 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.8.0")
(0.00 ":irc.foonet.org 003 tester :This server was created Mon, 12 Dec 2022 01:25:38 UTC")
(0.00 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
(0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
(0.00 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
(0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
(0.00 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
(0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
(0.00 ":irc.foonet.org 253 tester 0 :unregistered connections")
(0.00 ":irc.foonet.org 254 tester 1 :channels formed")
(0.00 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
(0.00 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
(0.01 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
(0.00 ":irc.foonet.org 422 tester :MOTD File is missing"))
((mode 10 "MODE tester +i")
(0.00 ":irc.foonet.org 221 tester +i")
(0.00 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
(0.00 ":dummy!~u@z5d6jyn8pwxge.irc PRIVMSG tester :hi"))
((~privmsg-open 10 "PRIVMSG nitwit :hola")
(0.00 ":nitwit!~u@m5q6wla8cjktr.irc PRIVMSG tester :ciao"))
((privmsg 10 "PRIVMSG dummy :howdy")
(0.00 ":dummy!~u@z5d6jyn8pwxge.irc PRIVMSG tester :bye")
(0.01 ":dummy!~u@z5d6jyn8pwxge.irc QUIT :connection closed"))
((quit 10 "QUIT :\2ERC\2")
(0.03 ":tester!~u@z5d6jyn8pwxge.irc QUIT :Quit: \2ERC\2"))