Mercurial > hg
view tests/test-histedit-edit.t @ 22778:80f2b63dd83a
parsers: add a function to efficiently lowercase ASCII strings
We need a way to efficiently lowercase ASCII strings. For example, 'hg status'
needs to build up the fold map -- a map from a canonical case (for OS X,
lowercase) to the actual case of each file and directory in the dirstate.
The current way we do that is to try decoding to ASCII and then calling
lower() on the string, labeled 'orig' below:
str.decode('ascii')
return str.lower()
This is pretty inefficient, and it turns out we can do much better.
I also tested out a condition-based approach, labeled 'cond' below:
(c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c
'cond' turned out to be slower in all cases. A 256-byte lookup table with
invalid values for everything past 127 performed similarly, but this was less
verbose.
On OS X 10.9 with LLVM version 6.0 (clang-600.0.51), the asciilower function
was run against two corpuses.
Corpus 1 (list of files from real-world repo, > 100k files):
orig: wall 0.428567 comb 0.430000 user 0.430000 sys 0.000000 (best of 24)
cond: wall 0.077204 comb 0.070000 user 0.070000 sys 0.000000 (best of 100)
lookup: wall 0.060714 comb 0.060000 user 0.060000 sys 0.000000 (best of 100)
Corpus 2 (mozilla-central, 113k files):
orig: wall 0.238406 comb 0.240000 user 0.240000 sys 0.000000 (best of 42)
cond: wall 0.040779 comb 0.040000 user 0.040000 sys 0.000000 (best of 100)
lookup: wall 0.037623 comb 0.040000 user 0.040000 sys 0.000000 (best of 100)
On a Linux server-class machine with GCC 4.4.6 20120305 (Red Hat 4.4.6-4):
Corpus 1 (real-world repo, > 100k files):
orig: wall 0.260899 comb 0.260000 user 0.260000 sys 0.000000 (best of 38)
cond: wall 0.054818 comb 0.060000 user 0.060000 sys 0.000000 (best of 100)
lookup: wall 0.048489 comb 0.050000 user 0.050000 sys 0.000000 (best of 100)
Corpus 2 (mozilla-central, 113k files):
orig: wall 0.153082 comb 0.150000 user 0.150000 sys 0.000000 (best of 65)
cond: wall 0.031007 comb 0.040000 user 0.040000 sys 0.000000 (best of 100)
lookup: wall 0.028793 comb 0.030000 user 0.030000 sys 0.000000 (best of 100)
SSE instructions might help even more, but I didn't experiment with those.
author | Siddharth Agarwal <sid0@fb.com> |
---|---|
date | Fri, 03 Oct 2014 18:42:39 -0700 |
parents | a5168eb9b2bc |
children | aa4a1672583e |
line wrap: on
line source
$ . "$TESTDIR/histedit-helpers.sh" $ cat >> $HGRCPATH <<EOF > [extensions] > histedit= > EOF $ initrepo () > { > hg init r > cd r > for x in a b c d e f ; do > echo $x > $x > hg add $x > hg ci -m $x > done > } $ initrepo log before edit $ hg log --graph @ changeset: 5:652413bf663e | tag: tip | user: test | date: Thu Jan 01 00:00:00 1970 +0000 | summary: f | o changeset: 4:e860deea161a | user: test | date: Thu Jan 01 00:00:00 1970 +0000 | summary: e | o changeset: 3:055a42cdd887 | user: test | date: Thu Jan 01 00:00:00 1970 +0000 | summary: d | o changeset: 2:177f92b77385 | user: test | date: Thu Jan 01 00:00:00 1970 +0000 | summary: c | o changeset: 1:d2ae7f538514 | user: test | date: Thu Jan 01 00:00:00 1970 +0000 | summary: b | o changeset: 0:cb9a9f314b8b user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: a edit the history $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle > pick 177f92b77385 c > pick 055a42cdd887 d > edit e860deea161a e > pick 652413bf663e f > EOF 0 files updated, 0 files merged, 2 files removed, 0 files unresolved Make changes as needed, you may commit or record as needed now. When you are finished, run hg histedit --continue to resume. Go at a random point and try to continue $ hg id -n 3+ $ hg up 0 abort: histedit in progress (use 'hg histedit --continue' or 'hg histedit --abort') [255] commit, then edit the revision $ hg ci -m 'wat' created new head $ echo a > e $ HGEDITOR='echo foobaz > ' hg histedit --continue 2>&1 | fixbundle 0 files updated, 0 files merged, 0 files removed, 0 files unresolved 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg log --graph @ changeset: 6:b5f70786f9b0 | tag: tip | user: test | date: Thu Jan 01 00:00:00 1970 +0000 | summary: f | o changeset: 5:a5e1ba2f7afb | user: test | date: Thu Jan 01 00:00:00 1970 +0000 | summary: foobaz | o changeset: 4:1a60820cd1f6 | user: test | date: Thu Jan 01 00:00:00 1970 +0000 | summary: wat | o changeset: 3:055a42cdd887 | user: test | date: Thu Jan 01 00:00:00 1970 +0000 | summary: d | o changeset: 2:177f92b77385 | user: test | date: Thu Jan 01 00:00:00 1970 +0000 | summary: c | o changeset: 1:d2ae7f538514 | user: test | date: Thu Jan 01 00:00:00 1970 +0000 | summary: b | o changeset: 0:cb9a9f314b8b user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: a $ hg cat e a check histedit_source $ hg log --debug --rev 5 changeset: 5:a5e1ba2f7afb899ef1581cea528fd885d2fca70d phase: draft parent: 4:1a60820cd1f6004a362aa622ebc47d59bc48eb34 parent: -1:0000000000000000000000000000000000000000 manifest: 5:5ad3be8791f39117565557781f5464363b918a45 user: test date: Thu Jan 01 00:00:00 1970 +0000 files: e extra: branch=default extra: histedit_source=e860deea161a2f77de56603b340ebbb4536308ae description: foobaz $ hg histedit tip --commands - 2>&1 <<EOF| fixbundle > edit b5f70786f9b0 f > EOF 0 files updated, 0 files merged, 1 files removed, 0 files unresolved Make changes as needed, you may commit or record as needed now. When you are finished, run hg histedit --continue to resume. $ hg status A f $ hg summary parent: 5:a5e1ba2f7afb foobaz branch: default commit: 1 added (new branch head) update: 1 new changesets (update) hist: 1 remaining (histedit --continue) (test also that editor is invoked if histedit is continued for "edit" action) $ HGEDITOR='cat' hg histedit --continue f HG: Enter commit message. Lines beginning with 'HG:' are removed. HG: Leave message empty to abort commit. HG: -- HG: user: test HG: branch 'default' HG: added f 0 files updated, 0 files merged, 0 files removed, 0 files unresolved saved backup bundle to $TESTTMP/r/.hg/strip-backup/b5f70786f9b0-backup.hg (glob) $ hg status log after edit $ hg log --limit 1 changeset: 6:a107ee126658 tag: tip user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: f say we'll change the message, but don't. $ cat > ../edit.sh <<EOF > cat "\$1" | sed s/pick/mess/ > tmp > mv tmp "\$1" > EOF $ HGEDITOR="sh ../edit.sh" hg histedit tip 2>&1 | fixbundle 0 files updated, 0 files merged, 1 files removed, 0 files unresolved 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg status $ hg log --limit 1 changeset: 6:1fd3b2fe7754 tag: tip user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: f modify the message check saving last-message.txt, at first $ cat > $TESTTMP/commitfailure.py <<EOF > from mercurial import util > def reposetup(ui, repo): > class commitfailure(repo.__class__): > def commit(self, *args, **kwargs): > raise util.Abort('emulating unexpected abort') > repo.__class__ = commitfailure > EOF $ cat >> .hg/hgrc <<EOF > [extensions] > # this failure occurs before editor invocation > commitfailure = $TESTTMP/commitfailure.py > EOF $ cat > $TESTTMP/editor.sh <<EOF > echo "==== before editing" > cat \$1 > echo "====" > echo "check saving last-message.txt" >> \$1 > EOF (test that editor is not invoked before transaction starting) $ rm -f .hg/last-message.txt $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit tip --commands - 2>&1 << EOF | fixbundle > mess 1fd3b2fe7754 f > EOF 0 files updated, 0 files merged, 1 files removed, 0 files unresolved abort: emulating unexpected abort $ test -f .hg/last-message.txt [1] $ cat >> .hg/hgrc <<EOF > [extensions] > commitfailure = ! > EOF $ hg histedit --abort -q (test that editor is invoked and commit message is saved into "last-message.txt") $ cat >> .hg/hgrc <<EOF > [hooks] > # this failure occurs after editor invocation > pretxncommit.unexpectedabort = false > EOF $ hg status --rev '1fd3b2fe7754^1' --rev 1fd3b2fe7754 A f $ rm -f .hg/last-message.txt $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit tip --commands - 2>&1 << EOF > mess 1fd3b2fe7754 f > EOF 0 files updated, 0 files merged, 1 files removed, 0 files unresolved adding f ==== before editing f HG: Enter commit message. Lines beginning with 'HG:' are removed. HG: Leave message empty to abort commit. HG: -- HG: user: test HG: branch 'default' HG: added f ==== transaction abort! rollback completed note: commit message saved in .hg/last-message.txt abort: pretxncommit.unexpectedabort hook exited with status 1 [255] $ cat .hg/last-message.txt f check saving last-message.txt (test also that editor is invoked if histedit is continued for "message" action) $ HGEDITOR=cat hg histedit --continue f HG: Enter commit message. Lines beginning with 'HG:' are removed. HG: Leave message empty to abort commit. HG: -- HG: user: test HG: branch 'default' HG: added f transaction abort! rollback completed note: commit message saved in .hg/last-message.txt abort: pretxncommit.unexpectedabort hook exited with status 1 [255] $ cat >> .hg/hgrc <<EOF > [hooks] > pretxncommit.unexpectedabort = > EOF $ hg histedit --abort -q then, check "modify the message" itself $ hg histedit tip --commands - 2>&1 << EOF | fixbundle > mess 1fd3b2fe7754 f > EOF 0 files updated, 0 files merged, 1 files removed, 0 files unresolved 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg status $ hg log --limit 1 changeset: 6:62feedb1200e tag: tip user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: f rollback should not work after a histedit $ hg rollback no rollback information available [1] $ cd .. $ hg clone -qr0 r r0 $ cd r0 $ hg phase -fdr0 $ hg histedit --commands - 0 2>&1 << EOF > edit cb9a9f314b8b a > $EDITED > EOF 0 files updated, 0 files merged, 1 files removed, 0 files unresolved adding a Make changes as needed, you may commit or record as needed now. When you are finished, run hg histedit --continue to resume. [1] $ HGEDITOR=true hg histedit --continue 0 files updated, 0 files merged, 0 files removed, 0 files unresolved saved backup bundle to $TESTTMP/r0/.hg/strip-backup/cb9a9f314b8b-backup.hg (glob)