perf: introduce safeattrsetter to replace direct attribute assignment
Referring not-existing attribute immediately causes failure, but
assigning a value to such attribute doesn't.
For example, perf.py has code paths below, which assign a value to
not-existing attribute. This causes incorrect performance measurement,
but these code paths are executed successfully.
- "repo._tags = None" in perftags()
recent Mercurial has tags cache information in repo._tagscache
- "branchmap.write = lambda repo: None" in perfbranchmap()
branchmap cache is written out by branchcache.write() in branchmap.py
"util.safehasattr() before assignment" can avoid this issue, but might
increase mistake at "copy & paste" attribute name or so.
To centralize (1) examining existence of, (2) assigning a value to,
and (3) restoring an old value to the attribute, this patch introduces
safeattrsetter(). This is used to replace direct attribute assignment
in subsequent patches.
Encapsulation of restoring is needed to completely remove direct
attribute assignment from perf.py, even though restoring isn't needed
so often.
$ hg init outer
$ cd outer
$ echo '[paths]' >> .hg/hgrc
$ echo 'default = http://example.net/' >> .hg/hgrc
hg debugsub with no remapping
$ echo 'sub = libfoo' > .hgsub
$ hg add .hgsub
$ hg debugsub
path sub
source libfoo
revision
hg debugsub with remapping
$ echo '[subpaths]' >> .hg/hgrc
$ printf 'http://example.net/lib(.*) = C:\\libs\\\\1-lib\\\n' >> .hg/hgrc
$ hg debugsub
path sub
source C:\libs\foo-lib\
revision
test cumulative remapping, the $HGRCPATH file is loaded first
$ echo '[subpaths]' >> $HGRCPATH
$ echo 'libfoo = libbar' >> $HGRCPATH
$ hg debugsub
path sub
source C:\libs\bar-lib\
revision
test absolute source path -- testing with a URL is important since
standard os.path.join wont treat that as an absolute path
$ echo 'abs = http://example.net/abs' > .hgsub
$ hg debugsub
path abs
source http://example.net/abs
revision
$ echo 'abs = /abs' > .hgsub
$ hg debugsub
path abs
source /abs
revision
test bad subpaths pattern
$ cat > .hg/hgrc <<EOF
> [subpaths]
> .* = \1
> EOF
$ hg debugsub
abort: bad subrepository pattern in $TESTTMP/outer/.hg/hgrc:2: invalid group reference (glob)
[255]
$ cd ..