findrenames: Optimise "addremove -s100" by matching files by their SHA1 hashes.
We speed up 'findrenames' for the usecase when a user specifies they
want a similarity of 100% by matching files by their exact SHA1 hash
value. This reduces the number of comparisons required to find exact
matches from O(n^2) to O(n).
While it would be nice if we could just use mercurial's pre-calculated
SHA1 hash for existing files, this hash includes the file's ancestor
information making it unsuitable for our purposes. Instead, we calculate
the hash of old content from scratch.
The following benchmarks were taken on the current head of crew:
addremove 100% similarity:
rm -rf *; hg up -C; mv tests tests.new
hg --time addremove -s100 --dry-run
before: real 176.350 secs (user 128.890+0.000 sys 47.430+0.000)
after: real 2.130 secs (user 1.890+0.000 sys 0.240+0.000)
addremove 75% similarity:
rm -rf *; hg up -C; mv tests tests.new; \
for i in tests.new/*; do echo x >> $i; done
hg --time addremove -s75 --dry-run
before: real 264.560 secs (user 215.130+0.000 sys 49.410+0.000)
after: real 218.710 secs (user 172.790+0.000 sys 45.870+0.000)
precommit hook: HG_PARENT1=0000000000000000000000000000000000000000
pretxncommit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=$HGTMP/test-hook/a
0:29b62aeb769f
commit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
commit.b hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
pretxncommit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PENDING=$HGTMP/test-hook/a
1:b702efe96888
commit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
commit.b hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
pretxncommit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PENDING=$HGTMP/test-hook/a
2:1324a5531bac
commit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
commit.b hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
created new head
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
precommit hook: HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
pretxncommit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PENDING=$HGTMP/test-hook/a
3:4c52fb2e4022
commit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
commit.b hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
pre-identify hook: HG_ARGS=id
warning: pre-identify hook exited with status 1
pre-cat hook: HG_ARGS=cat b
post-cat hook: HG_ARGS=cat b HG_RESULT=0
b
prechangegroup hook: HG_SOURCE=pull HG_URL=file:
changegroup hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_SOURCE=pull HG_URL=file:
incoming hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_SOURCE=pull HG_URL=file:
incoming hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_SOURCE=pull HG_URL=file:
incoming hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_SOURCE=pull HG_URL=file:
pulling from ../a
searching for changes
adding changesets
adding manifests
adding file changes
added 3 changesets with 2 changes to 2 files
(run 'hg update' to get a working copy)
pretag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a
precommit hook: HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
pretxncommit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321 HG_PENDING=$HGTMP/test-hook/a
4:8ea2ef7ad3e8
commit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
commit.b hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
tag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a
pretag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=la
tag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=la
pretag hook: HG_LOCAL=0 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fa
pretag.forbid hook: HG_LOCAL=0 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fa
abort: pretag.forbid hook exited with status 1
pretag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fla
pretag.forbid hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fla
abort: pretag.forbid hook exited with status 1
4:8ea2ef7ad3e8
precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
pretxncommit hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook/a
5:fad284daf8c0
5:fad284daf8c0
pretxncommit.forbid hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook/a
transaction abort!
rollback completed
abort: pretxncommit.forbid1 hook exited with status 1
4:8ea2ef7ad3e8
precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
precommit.forbid hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
abort: precommit.forbid hook exited with status 1
4:8ea2ef7ad3e8
preupdate hook: HG_PARENT1=b702efe96888
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
preupdate hook: HG_PARENT1=8ea2ef7ad3e8
update hook: HG_ERROR=0 HG_PARENT1=8ea2ef7ad3e8
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
3:4c52fb2e4022
prechangegroup.forbid hook: HG_SOURCE=pull HG_URL=file:
pulling from ../a
searching for changes
abort: prechangegroup.forbid hook exited with status 1
4:8ea2ef7ad3e8
pretxnchangegroup.forbid hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook/b HG_SOURCE=pull HG_URL=file:
pulling from ../a
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
transaction abort!
rollback completed
abort: pretxnchangegroup.forbid1 hook exited with status 1
3:4c52fb2e4022
preoutgoing hook: HG_SOURCE=pull
outgoing hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_SOURCE=pull
pulling from ../a
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
(run 'hg update' to get a working copy)
rolling back to revision 4 (undo pull)
preoutgoing hook: HG_SOURCE=pull
preoutgoing.forbid hook: HG_SOURCE=pull
pulling from ../a
searching for changes
abort: preoutgoing.forbid hook exited with status 1
preoutgoing hook: HG_SOURCE=clone
outgoing hook: HG_NODE=0000000000000000000000000000000000000000 HG_SOURCE=clone
updating to branch default
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
preoutgoing hook: HG_SOURCE=clone
preoutgoing.forbid hook: HG_SOURCE=clone
abort: preoutgoing.forbid hook exited with status 1
# test python hooks
error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict'
error: preoutgoing.raise hook raised an exception: exception from hook
pulling from ../a
searching for changes
error: preoutgoing.abort hook failed: raise abort from hook
abort: raise abort from hook
pulling from ../a
searching for changes
hook args:
hooktype preoutgoing
source pull
abort: preoutgoing.fail hook failed
pulling from ../a
searching for changes
abort: preoutgoing.uncallable hook is invalid ("hooktests.uncallable" is not callable)
pulling from ../a
searching for changes
abort: preoutgoing.nohook hook is invalid ("hooktests.nohook" is not defined)
pulling from ../a
searching for changes
abort: preoutgoing.nomodule hook is invalid ("nomodule" not in a module)
pulling from ../a
searching for changes
abort: preoutgoing.badmodule hook is invalid (import of "nomodule" failed)
pulling from ../a
searching for changes
abort: preoutgoing.unreachable hook is invalid (import of "hooktests.container" failed)
pulling from ../a
searching for changes
hook args:
hooktype preoutgoing
source pull
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
(run 'hg update' to get a working copy)
# make sure --traceback works
Traceback (most recent call last):
Automatically installed hook
foo
calling hook commit.auto: <function autohook>
Automatically installed hook
committed changeset 1:52998019f6252a2b893452765fcb0a47351a5708
hooks.commit.auto=<function autohook>
# test python hook configured with python:[file]:[hook] syntax
hook works
nothing changed
# make sure --traceback works on hook import failure
exception from first failed import attempt:
Traceback (most recent call last):
ImportError: No module named somebogusmodule
exception from second failed import attempt:
Traceback (most recent call last):
ImportError: No module named hgext_importfail
Traceback (most recent call last):
# commit and update hooks should run after command completion (issue 1827)
8da618c33484 tip
29b62aeb769f
1 files updated, 0 files merged, 0 files removed, 0 files unresolved