interfaces: add the optional `bdiff.xdiffblocks()` method
PyCharm flagged where this was called on the protocol class in `mdiff.py` in the
previous commit, but pytype completely missed it. PyCharm is correct here, but
I'm committing this separately to highlight this potential problem- some of the
implementations don't implement _all_ of the methods the others do, and there's
not a great way to indicate on a protocol class that a method or attribute is
optional- that's kinda the opposite of what static typing is about.
Making the method an `Optional[Callable]` attribute works here, and keeps both
PyCharm and pytype happy, and the generated `mdiff.pyi` and `modules.pyi` look
reasonable. We might be getting a little lucky, because the method isn't
invoked directly- it is returned from another method that selects which block
function to use. Except since it is declared on the protocol class, every
module needs this attribute (in theory, but in practice this doesn't seem to be
checked), so the check for it on the module has to change from `hasattr()` to
`getattr(..., None)`. We defer defining the optional attrs to the type checking
phase as an extra precaution- that way it isn't an attr with a `None` value at
runtime if someone is still using `hasattr()`.
As to why pytype missed this, I have no clue. The generated `mdiff.pyi` even
has the global variable typed as `bdiff: intmod.BDiff`, so uses of it really
should comply with what is on the class, protocol class or not.
#if no-windows
For debugging: this is a pretty simple test that is a good candidate
for tracking down network-related bugs. Sometimes a command in this
hangs, so having showstack pre-loaded is sometimes helpful. This also
gives us a test that at least proves showstack can be loaded.
$ cat >> $HGRCPATH <<EOF
> [extensions]
> showstack = $TESTDIR/../contrib/showstack.py
> EOF
#endif
$ hg init test
$ cd test
$ echo a > a
$ hg ci -Ama
adding a
$ cd ..
$ hg clone test test2
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd test2
$ echo a >> a
$ hg ci -mb
Cloning with a password in the URL should not save the password in .hg/hgrc:
$ hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
$ cat hg.pid >> $DAEMON_PIDS
$ hg clone http://foo:xyzzy@localhost:$HGPORT/ test3
requesting all changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 1 files
new changesets cb9a9f314b8b:ba677d0156c1
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat test3/.hg/hgrc
# example repository config (see 'hg help config' for more info)
[paths]
default = http://foo@localhost:$HGPORT/
# path aliases to other clones of this repo in URLs or filesystem paths
# (see 'hg help config.paths' for more info)
#
# default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
# my-fork = ssh://jdoe@example.net/hg/jdoes-fork
# my-clone = /home/jdoe/jdoes-clone
[ui]
# name and email (local to this repository, optional), e.g.
# username = Jane Doe <jdoe@example.com>
$ killdaemons.py
expect error, cloning not allowed
$ echo '[web]' > .hg/hgrc
$ echo 'allowpull = false' >> .hg/hgrc
$ hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
$ cat hg.pid >> $DAEMON_PIDS
$ hg clone http://localhost:$HGPORT/ test4 # bundle2+
abort: authorization failed
[255]
$ hg clone http://localhost:$HGPORT/ test4 --config devel.legacy.exchange=bundle1
abort: authorization failed
[255]
$ killdaemons.py
serve errors
$ cat errors.log
$ req() {
> hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
> cat hg.pid >> $DAEMON_PIDS
> hg --cwd ../test pull http://localhost:$HGPORT/
> killdaemons.py hg.pid
> echo % serve errors
> cat errors.log
> }
expect error, pulling not allowed
$ req
pulling from http://localhost:$HGPORT/
abort: authorization failed
% serve errors
$ cd ..