Don't set erc-networks--id until network is known
* lisp/erc/erc-networks.el (erc-networks--id-given): Accept a null argument. (erc-networks--id-on-connect): Remove unused function. (erc-networks--id-equal-p): Add method for comparing initialized and unset IDs. (erc-networks--update-server-identity): Ensure `erc-networks--id' is set before continuing search. (erc-networks--init-identity): Don't assume `erc-networks--id' is non-nil. Add branch condition to reload ID on non-nil case. (erc-networks-on-MOTD-end): Let init-ID function handle renaming of server buffer. * lisp/erc/erc.el (erc-open): For continued sessions, try copying over the last network ID. (erc--auth-source-determine-params-default): Don't expect a network ID to have been initialized. (erc-set-current-nick): When connected, reload network ID. Leave comment warning that it may be unneeded. * lisp/erc/erc-backend.el (erc-server-NICK, erc-server-433): Unless already connected, schedule ID reload when server rejects or mandates a nick change. * test/lisp/erc/erc-scenarios-base-association-nick.el (erc-scenarios-base-association-nick-bumped, erc-scenarios-base-association-nick-bumped-mandated-renick): Update to reflect more liberal association behavior when renamed by IRCd.
This commit is contained in:
parent
71397175aa
commit
da30a4908e
4 changed files with 90 additions and 74 deletions
|
@ -1619,7 +1619,7 @@ add things to `%s' instead."
|
|||
(cl-pushnew (erc-server-buffer) bufs)
|
||||
(erc-set-current-nick nn)
|
||||
;; Rename session, possibly rename server buf and all targets
|
||||
(when (erc-network)
|
||||
(when erc-server-connected
|
||||
(erc-networks--id-reload erc-networks--id proc parsed))
|
||||
(erc-update-mode-line)
|
||||
(setq erc-nick-change-attempt-count 0)
|
||||
|
@ -1629,6 +1629,8 @@ add things to `%s' instead."
|
|||
'NICK-you ?n nick ?N nn)
|
||||
(run-hook-with-args 'erc-nick-changed-functions nn nick))
|
||||
(t
|
||||
(when erc-server-connected
|
||||
(erc-networks--id-reload erc-networks--id proc parsed))
|
||||
(erc-handle-user-status-change 'nick (list nick login host) (list nn))
|
||||
(erc-display-message parsed 'notice bufs 'NICK ?n nick
|
||||
?u login ?h host ?N nn))))))
|
||||
|
@ -2255,6 +2257,8 @@ See `erc-display-server-message'." nil
|
|||
|
||||
(define-erc-response-handler (433)
|
||||
"Login-time \"nick in use\"." nil
|
||||
(when erc-server-connected
|
||||
(erc-networks--id-reload erc-networks--id proc parsed))
|
||||
(erc-nickname-in-use (cadr (erc-response.command-args parsed))
|
||||
"already in use"))
|
||||
|
||||
|
|
|
@ -826,12 +826,11 @@ respectively. The separator is given by `erc-networks--id-sep'."
|
|||
|
||||
;; For now, please use this instead of `erc-networks--id-fixed-p'.
|
||||
(cl-defgeneric erc-networks--id-given (net-id)
|
||||
"Return the preassigned identifier for a network presence, if any.
|
||||
This may have originated from an `:id' arg to entry-point commands
|
||||
`erc-tls' or `erc'.")
|
||||
"Return the preassigned identifier for a network context, if any.
|
||||
When non-nil, assume NET-ID originated from an `:id' argument to
|
||||
entry-point commands `erc-tls' or `erc'.")
|
||||
|
||||
(cl-defmethod erc-networks--id-given ((_ erc-networks--id))
|
||||
nil)
|
||||
(cl-defmethod erc-networks--id-given (_) nil) ; _ may be nil
|
||||
|
||||
(cl-defmethod erc-networks--id-given ((nid erc-networks--id-fixed))
|
||||
(erc-networks--id-symbol nid))
|
||||
|
@ -866,22 +865,15 @@ This may have originated from an `:id' arg to entry-point commands
|
|||
((_ symbol) &context (erc-obsolete-var erc-reuse-buffers null))
|
||||
(erc-networks--id-fixed-create (intern (buffer-name))))
|
||||
|
||||
(cl-defgeneric erc-networks--id-on-connect (net-id)
|
||||
"Update NET-ID `erc-networks--id' after connection params known.
|
||||
This is typically during or just after MOTD.")
|
||||
|
||||
(cl-defmethod erc-networks--id-on-connect ((_ erc-networks--id))
|
||||
nil)
|
||||
|
||||
(cl-defmethod erc-networks--id-on-connect ((id erc-networks--id-qualifying))
|
||||
(erc-networks--id-qualifying-update id (erc-networks--id-qualifying-create)))
|
||||
|
||||
(cl-defgeneric erc-networks--id-equal-p (self other)
|
||||
"Return non-nil when two network identities exhibit underlying equality.
|
||||
SELF and OTHER are `erc-networks--id' struct instances. This
|
||||
should normally be used only for ID recovery or merging, after
|
||||
which no two identities should be `equal' (timestamps aside) that
|
||||
aren't also `eq'.")
|
||||
"Return non-nil when two network IDs exhibit underlying equality.
|
||||
Expect SELF and OTHER to be `erc-networks--id' struct instances
|
||||
and that this will only be called for ID recovery or merging,
|
||||
after which no two identities should be `equal' (timestamps
|
||||
aside) that aren't also `eq'.")
|
||||
|
||||
(cl-defmethod erc-networks--id-equal-p ((_ null) (_ erc-networks--id)) nil)
|
||||
(cl-defmethod erc-networks--id-equal-p ((_ erc-networks--id) (_ null)) nil)
|
||||
|
||||
(cl-defmethod erc-networks--id-equal-p ((self erc-networks--id)
|
||||
(other erc-networks--id))
|
||||
|
@ -1382,7 +1374,8 @@ considered as well because server buffers are often killed."
|
|||
(let* ((identity erc-networks--id)
|
||||
(buffer (current-buffer))
|
||||
(f (lambda ()
|
||||
(unless (or (eq (current-buffer) buffer)
|
||||
(unless (or (not erc-networks--id)
|
||||
(eq (current-buffer) buffer)
|
||||
(eq erc-networks--id identity))
|
||||
(if (erc-networks--id-equal-p identity erc-networks--id)
|
||||
(throw 'buffer erc-networks--id)
|
||||
|
@ -1397,16 +1390,17 @@ considered as well because server buffers are often killed."
|
|||
;; server buffer, whereas `erc-networks--rename-server-buffer' can run
|
||||
;; mid-session, after an identity's core components have changed.
|
||||
|
||||
(defun erc-networks--init-identity (_proc _parsed)
|
||||
(defun erc-networks--init-identity (proc parsed)
|
||||
"Update identity with real network name."
|
||||
;; Initialize identity for real now that we know the network
|
||||
(cl-assert erc-network)
|
||||
(unless (erc-networks--id-symbol erc-networks--id) ; unless just reconnected
|
||||
(erc-networks--id-on-connect erc-networks--id))
|
||||
;; Find duplicate identities or other conflicting ones and act
|
||||
;; accordingly.
|
||||
(erc-networks--update-server-identity)
|
||||
;;
|
||||
(if erc-networks--id
|
||||
(erc-networks--id-reload erc-networks--id proc parsed)
|
||||
(setq erc-networks--id (erc-networks--id-create nil))
|
||||
;; Find duplicate identities or other conflicting ones and act
|
||||
;; accordingly.
|
||||
(erc-networks--update-server-identity)
|
||||
(erc-networks--rename-server-buffer proc parsed))
|
||||
nil)
|
||||
|
||||
(defun erc-networks--rename-server-buffer (new-proc &optional _parsed)
|
||||
|
@ -1474,8 +1468,7 @@ This must run before `erc-server-connected' is set."
|
|||
;; For now, retain compatibility with erc-server-NNN-functions.
|
||||
(or (erc-networks--ensure-announced proc parsed)
|
||||
(erc-networks--set-name proc parsed)
|
||||
(erc-networks--init-identity proc parsed)
|
||||
(erc-networks--rename-server-buffer proc parsed)))
|
||||
(erc-networks--init-identity proc parsed)))
|
||||
|
||||
(define-erc-module networks nil
|
||||
"Provide data about IRC networks."
|
||||
|
|
|
@ -2017,10 +2017,12 @@ Returns the buffer for the given server or channel."
|
|||
(setq erc-default-nicks (if (consp erc-nick) erc-nick (list erc-nick)))
|
||||
;; client certificate (only useful if connecting over TLS)
|
||||
(setq erc-session-client-certificate client-certificate)
|
||||
(setq erc-networks--id (if connect
|
||||
(erc-networks--id-create id)
|
||||
(buffer-local-value 'erc-networks--id
|
||||
old-buffer)))
|
||||
(setq erc-networks--id
|
||||
(if connect
|
||||
(or (and continued-session
|
||||
(buffer-local-value 'erc-networks--id old-buffer))
|
||||
(and id (erc-networks--id-create id)))
|
||||
(buffer-local-value 'erc-networks--id old-buffer)))
|
||||
;; debug output buffer
|
||||
(setq erc-dbuf
|
||||
(when erc-log-p
|
||||
|
@ -3179,7 +3181,8 @@ node `(erc) Connecting'."
|
|||
function))
|
||||
|
||||
(defun erc--auth-source-determine-params-defaults ()
|
||||
(let* ((net (and-let* ((esid (erc-networks--id-symbol erc-networks--id))
|
||||
(let* ((net (and-let* ((erc-networks--id)
|
||||
(esid (erc-networks--id-symbol erc-networks--id))
|
||||
((symbol-name esid)))))
|
||||
(localp (and erc--target (erc--target-channel-local-p erc--target)))
|
||||
(hosts (if localp
|
||||
|
@ -5904,7 +5907,13 @@ strings over to the next call."
|
|||
(with-current-buffer (if (buffer-live-p (erc-server-buffer))
|
||||
(erc-server-buffer)
|
||||
(current-buffer))
|
||||
(setq erc-server-current-nick nick)))
|
||||
(unless (equal erc-server-current-nick nick)
|
||||
(setq erc-server-current-nick nick)
|
||||
;; This seems sensible but may well be superfluous. Should
|
||||
;; really prove that it's actually needed via test scenario.
|
||||
(when erc-server-connected
|
||||
(erc-networks--id-reload erc-networks--id)))
|
||||
nick))
|
||||
|
||||
(defun erc-current-nick ()
|
||||
"Return the current nickname."
|
||||
|
|
|
@ -25,13 +25,24 @@
|
|||
|
||||
(eval-when-compile (require 'erc-join))
|
||||
|
||||
;; You register a new nick, disconnect, and log back in, but your nick
|
||||
;; is not granted, so ERC obtains a backtick'd version. You open a
|
||||
;; query buffer for NickServ, and ERC names it using the net-ID (which
|
||||
;; includes the backtick'd nick) as a suffix. The original
|
||||
;; (disconnected) NickServ buffer gets renamed with *its* net-ID as
|
||||
;; well. You then identify to NickServ, and the dead session is no
|
||||
;; longer considered distinct.
|
||||
;; You register a new nick in a dedicated query buffer, disconnect,
|
||||
;; and log back in, but your nick is not granted (maybe you just
|
||||
;; turned off SASL). In any case, ERC obtains a backtick'd version.
|
||||
;; You open a query buffer for NickServ, and ERC gives you the
|
||||
;; existing one. And after you identify, all buffers retain their
|
||||
;; names, although your net ID has changed internally.
|
||||
;;
|
||||
;; If ERC would've instead failed (or intentionally refused) to make
|
||||
;; the association, you would've ended up with a new NickServ buffer
|
||||
;; named after the new net ID as a suffix (based on the backtick'd
|
||||
;; nick), for example, NickServ@foonet/tester`. And the original
|
||||
;; (disconnected) NickServ buffer would've gotten suffixed with *its*
|
||||
;; net-ID as well, e.g., NickServ@foonet/tester. And after
|
||||
;; identifying, you would've seen ERC merge the two as well as their
|
||||
;; server buffers. While this alternate behavior may arguably be a
|
||||
;; more honest reflection of reality, it's also quite inconvenient.
|
||||
;; For a clearer example, see the original version of this file
|
||||
;; introduced by "Add user-oriented test scenarios for ERC".
|
||||
|
||||
(ert-deftest erc-scenarios-base-association-nick-bumped ()
|
||||
:tags '(:expensive-test)
|
||||
|
@ -67,30 +78,29 @@
|
|||
(funcall expect 5 "ERC finished"))))
|
||||
|
||||
(with-current-buffer "foonet"
|
||||
(erc-cmd-RECONNECT))
|
||||
(erc-cmd-RECONNECT)
|
||||
(funcall expect 10 "User modes for tester`"))
|
||||
|
||||
(erc-d-t-wait-for 10 "Nick request rejection prevents reassociation (good)"
|
||||
(get-buffer "foonet/tester`"))
|
||||
(ert-info ("Server buffer reassociated with new nick")
|
||||
(should-not (get-buffer "foonet/tester`")))
|
||||
|
||||
(ert-info ("Ask NickServ to change nick")
|
||||
(with-current-buffer "foonet/tester`"
|
||||
(funcall expect 3 "already in use")
|
||||
(with-current-buffer "foonet"
|
||||
(funcall expect 3 "debug mode")
|
||||
(erc-cmd-QUERY "NickServ"))
|
||||
|
||||
(erc-d-t-wait-for 1 "Dead NickServ query buffer renamed, now qualified"
|
||||
(get-buffer "NickServ@foonet/tester"))
|
||||
(ert-info ( "NickServ buffer reassociated")
|
||||
(should-not (get-buffer "NickServ@foonet/tester`"))
|
||||
(should-not (get-buffer "NickServ@foonet/tester")))
|
||||
|
||||
(with-current-buffer "NickServ@foonet/tester`" ; new one
|
||||
(with-current-buffer "NickServ" ; new one
|
||||
(erc-scenarios-common-say "IDENTIFY tester changeme")
|
||||
(funcall expect 5 "You're now logged in as tester")
|
||||
(ert-info ("Original buffer found, reused")
|
||||
(erc-d-t-wait-for 2 (equal (buffer-name) "NickServ")))))
|
||||
(funcall expect 5 "You're now logged in as tester")))
|
||||
|
||||
(ert-info ("Ours is the only NickServ buffer that remains")
|
||||
(ert-info ("Still just one NickServ buffer")
|
||||
(should-not (cdr (erc-scenarios-common-buflist "NickServ"))))
|
||||
|
||||
(ert-info ("Visible network ID truncated to one component")
|
||||
(ert-info ("As well as one server buffer")
|
||||
(should (not (get-buffer "foonet/tester`")))
|
||||
(should (not (get-buffer "foonet/tester")))
|
||||
(should (get-buffer "foonet")))))
|
||||
|
@ -135,29 +145,29 @@
|
|||
;; Since we use reconnect, a new buffer won't be created
|
||||
;; TODO add variant with clean `erc' invocation
|
||||
(with-current-buffer "foonet"
|
||||
(erc-cmd-RECONNECT))
|
||||
(erc-cmd-RECONNECT)
|
||||
(funcall expect 10 "User modes for dummy"))
|
||||
|
||||
(ert-info ("Server-initiated renick")
|
||||
(with-current-buffer (erc-d-t-wait-for 10 (get-buffer "foonet/dummy"))
|
||||
(should-not (get-buffer "foonet/tester"))
|
||||
(funcall expect 15 "debug mode"))
|
||||
(ert-info ("Server-initiated renick associated correctly")
|
||||
(with-current-buffer "foonet"
|
||||
(funcall expect 15 "debug mode")
|
||||
(should-not (get-buffer "foonet/dummy"))
|
||||
(should-not (get-buffer "foonet/tester")))
|
||||
|
||||
(erc-d-t-wait-for 1 "Old query renamed, now qualified"
|
||||
(get-buffer "bob@foonet/tester"))
|
||||
(ert-info ("Old query reassociated")
|
||||
(should (get-buffer "bob"))
|
||||
(should-not (get-buffer "bob@foonet/tester"))
|
||||
(should-not (get-buffer "bob@foonet/dummy")))
|
||||
|
||||
(with-current-buffer (erc-d-t-wait-for 5 (get-buffer "bob@foonet/dummy"))
|
||||
(with-current-buffer "foonet"
|
||||
(erc-cmd-NICK "tester")
|
||||
(ert-info ("Buffers combined")
|
||||
(erc-d-t-wait-for 2 (equal (buffer-name) "bob")))))
|
||||
(funcall expect 5 "You're now logged in as tester")))
|
||||
|
||||
(with-current-buffer "foonet"
|
||||
(funcall expect 5 "You're now logged in as tester"))
|
||||
|
||||
(ert-info ("Ours is the only bob buffer that remains")
|
||||
(ert-info ("Ours is still the only bob buffer that remains")
|
||||
(should-not (cdr (erc-scenarios-common-buflist "bob"))))
|
||||
|
||||
(ert-info ("Visible network ID truncated to one component")
|
||||
(should (not (get-buffer "foonet/dummy")))
|
||||
(should (get-buffer "foonet")))))
|
||||
(ert-info ("Visible network ID still truncated to one component")
|
||||
(should (not (get-buffer "foonet/tester")))
|
||||
(should (not (get-buffer "foonet/dummy"))))))
|
||||
|
||||
;;; erc-scenarios-base-association-nick.el ends here
|
||||
|
|
Loading…
Add table
Reference in a new issue