comparison tests/test-hook.t @ 27192:a01d3d32b53a

commands: make commit acquire locks before processing (issue4368) Before this patch, "hg commit" (process A) executes steps below: 1. get current branch heads via 'repo.branchheads()' - cache 'repo.changelog' 2. invoke 'repo.commit()' 3. acquire wlock - invalidate 'repo.dirstate' 4. access 'repo.dirstate' - re-read '.hg/dirstate' - check validity of parent revisions with 'repo.changelog' 5. invoke 'repo.commitctx()' 6. acquire store lock (slock) - invalidate 'repo.changelog' 7. do committing 8. release slock 9. release wlock 10. check new branch head (via 'cmdutil.commitstatus()') If acquisition of wlock at (3) above waits for another "hg commit" (process B) or so running parallelly to release wlock, process A causes creating orphan revision, because: - '.hg/dirstate' refers the revision, which is newly added by process B, as its parent - but already cached 'repo.changelog' doesn't contain such revision - therefore, validating parents of '.hg/dirstate' at (4) above replaces such revision with 'nullid' Then, process A creates "orphan" revision, of which parent is "null" revision. In addition to it, "created new head" may be shown at the end of process A unintentionally, if store is updated parallelly, because both getting branch heads (1) and checking new branch head (10) are executed outside slock scope. To avoid this issue, this patch makes "hg commit" acquire wlock and slock before processing. This patch resolves the issue between "hg commit" processes, but not one between "hg commit" and other commands. Subsequent patches resolve the latter. Even after this patch, there are still corner case problems below: - filecache may overlook changes of '.hg/dirstate', and it causes similar issue (see below for detail) https://bz.mercurial-scm.org/show_bug.cgi?id=4368#c10 - 3rd party extension may cause similar issue, if it directly uses 'repo.commit()' without acquisition of wlock and slock This can be fixed by acquisition of slock at the beginning of 'repo.commit()', but it seems suitable for "default" branch In fact, acquisition of slock itself is already introduced at "default" branch by 4414d500604f, but acquisition is not at the beginning of 'repo.commit()'. This patch also changes some tests: - test-fncache.t needs this tricky wrapping, to release (= forced failure of) wlock certainly - order of "hg commit" output is changed by widening scope of locks, because some hooks are fired after releasing wlock
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Wed, 02 Dec 2015 03:12:07 +0900
parents 10a1a4b3e775
children 42aa0e570eaa
comparison
equal deleted inserted replaced
27191:20a9226bdc8a 27192:a01d3d32b53a
79 precommit hook: HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 79 precommit hook: HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
80 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob) 80 pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
81 pretxncommit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a 81 pretxncommit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
82 2:ee9deb46ab31 82 2:ee9deb46ab31
83 pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=commit (glob) 83 pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
84 created new head
84 txnclose hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob) 85 txnclose hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
85 commit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 86 commit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
86 commit.b hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 87 commit.b hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
87 created new head
88 $ hg merge 1 88 $ hg merge 1
89 1 files updated, 0 files merged, 0 files removed, 0 files unresolved 89 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 (branch merge, don't forget to commit) 90 (branch merge, don't forget to commit)
91 $ hg commit -m merge -d '2 0' 91 $ hg commit -m merge -d '2 0'
92 precommit hook: HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd 92 precommit hook: HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
561 $ hg ci --debug -d '0 0' -m 'change foo' 561 $ hg ci --debug -d '0 0' -m 'change foo'
562 committing files: 562 committing files:
563 foo 563 foo
564 committing manifest 564 committing manifest
565 committing changelog 565 committing changelog
566 committed changeset 1:52998019f6252a2b893452765fcb0a47351a5708
566 calling hook commit.auto: hgext_hookext.autohook 567 calling hook commit.auto: hgext_hookext.autohook
567 Automatically installed hook 568 Automatically installed hook
568 committed changeset 1:52998019f6252a2b893452765fcb0a47351a5708
569 569
570 $ hg showconfig hooks 570 $ hg showconfig hooks
571 hooks.commit.auto=<function autohook at *> (glob) 571 hooks.commit.auto=<function autohook at *> (glob)
572 572
573 test python hook configured with python:[file]:[hook] syntax 573 test python hook configured with python:[file]:[hook] syntax