# HG changeset patch # User FUJIWARA Katsunori # Date 1487607660 -32400 # Node ID 6afd8a87a6575fb253d74965e14dd256b44b1279 # Parent 0332b8fafd05f9aefd01bec339c7e616e75bdbb9 phases: check HG_PENDING strictly Before this patch, checking HG_PENDING in phases.py might cause unintentional reading unrelated 'phaseroots.pending' in, because it just examines existence of HG_PENDING environment variable. This patch uses txnutil.trypending() to check HG_PENDING strictly. BTW, this patch may cause failure of bisect in the repository of Mercurial itself, if examination at bisecting assumes that an external hook can see all pending changes while nested transactions across repositories. This invisibility issue will be fixed by subsequent patch, which allows HG_PENDING to refer multiple repositories. diff -r 0332b8fafd05 -r 6afd8a87a657 mercurial/phases.py --- a/mercurial/phases.py Tue Feb 21 01:21:00 2017 +0900 +++ b/mercurial/phases.py Tue Feb 21 01:21:00 2017 +0900 @@ -113,9 +113,9 @@ short, ) from . import ( - encoding, error, smartset, + txnutil, ) allphases = public, draft, secret = range(3) @@ -137,15 +137,7 @@ dirty = False roots = [set() for i in allphases] try: - f = None - if 'HG_PENDING' in encoding.environ: - try: - f = repo.svfs('phaseroots.pending') - except IOError as inst: - if inst.errno != errno.ENOENT: - raise - if f is None: - f = repo.svfs('phaseroots') + f, pending = txnutil.trypending(repo.root, repo.svfs, 'phaseroots') try: for line in f: phase, nh = line.split() diff -r 0332b8fafd05 -r 6afd8a87a657 tests/test-phases.t --- a/tests/test-phases.t Tue Feb 21 01:21:00 2017 +0900 +++ b/tests/test-phases.t Tue Feb 21 01:21:00 2017 +0900 @@ -590,3 +590,47 @@ crosschecking files in changesets and manifests checking files 7 files, 8 changesets, 7 total revisions + + $ cd .. + +check whether HG_PENDING makes pending changes only in related +repositories visible to an external hook. + +(emulate a transaction running concurrently by copied +.hg/phaseroots.pending in subsequent test) + + $ cat > $TESTTMP/savepending.sh < cp .hg/store/phaseroots.pending .hg/store/phaseroots.pending.saved + > exit 1 # to avoid changing phase for subsequent tests + > EOF + $ cd push-dest + $ hg phase 6 + 6: draft + $ hg --config hooks.pretxnclose="sh $TESTTMP/savepending.sh" phase -f -s 6 + transaction abort! + rollback completed + abort: pretxnclose hook exited with status 1 + [255] + $ cp .hg/store/phaseroots.pending.saved .hg/store/phaseroots.pending + +(check (in)visibility of phaseroot while transaction running in repo) + + $ cat > $TESTTMP/checkpending.sh < echo '@initialrepo' + > hg -R $TESTTMP/initialrepo phase 7 + > echo '@push-dest' + > hg -R $TESTTMP/push-dest phase 6 + > exit 1 # to avoid changing phase for subsequent tests + > EOF + $ cd ../initialrepo + $ hg phase 7 + 7: public + $ hg --config hooks.pretxnclose="sh $TESTTMP/checkpending.sh" phase -f -s 7 + @initialrepo + 7: secret + @push-dest + 6: draft + transaction abort! + rollback completed + abort: pretxnclose hook exited with status 1 + [255]