fsmonitor: acquire localrepo.wlock prior to emitting hg.update state
we see some weird things in the watchman logs where the mercurial
process is seemingly confused about which hg.update state it is publishing
through watchman.
On closer examination, we're seeing conflicting pids for the clients involved
and this implies a race.
To resolve this, we extend the wlock around the state-enter/state-leave
events that are emitted to watchman.
Test Plan:
Some manual testing:
In one window, run this, and then checkout a different rev:
```
$ watchman -p -j <<<'["subscribe", "/data/users/wez/fbsource", "wez", {"expression": ["name", ".hg/updatestate"]}]'
{
"version": "4.9.0",
"subscribe": "wez",
"clock": "c:1495034090:814028:1:312576"
}
{
"state-enter": "hg.update",
"version": "4.9.0",
"clock": "c:1495034090:814028:1:312596",
"unilateral": true,
"subscription": "wez",
"metadata": {
"status": "ok",
"distance": 125,
"rev": "a1275d79ffa6c58b53116c8ec401c275ca6c1e2a",
"partial": false
},
"root": "/data/users/wez/fbsource"
}
{
"root": "/data/users/wez/fbsource",
"metadata": {
"status": "ok",
"distance": 125,
"rev": "a1275d79ffa6c58b53116c8ec401c275ca6c1e2a",
"partial": false
},
"subscription": "wez",
"unilateral": true,
"version": "4.9.0",
"clock": "c:1495034090:814028:1:312627",
"state-leave": "hg.update"
}
```
Tailed the watchman log file and looked for invalid state assertion errors,
then ran my `rebase-all` script to update/rebase all of my heads.
Didn't trigger the error condition (but couldn't reliably trigger it previously
anyway), and the output captured above shows that the states are being emitted
correctly.
#!/bin/sh -e
#
# Build a Mercurial debian package from the current repo
#
# Tested on Jessie (stable as of original script authoring.)
. $(dirname $0)/packagelib.sh
BUILD=1
CLEANUP=1
DISTID=`(lsb_release -is 2> /dev/null | tr '[:upper:]' '[:lower:]') || echo debian`
CODENAME=`lsb_release -cs 2> /dev/null || echo unknown`
DEBFLAGS=-b
while [ "$1" ]; do
case "$1" in
--distid )
shift
DISTID="$1"
shift
;;
--codename )
shift
CODENAME="$1"
shift
;;
--cleanup )
shift
BUILD=
;;
--build )
shift
CLEANUP=
;;
--source-only )
shift
DEBFLAGS=-S
;;
* )
echo "Invalid parameter $1!" 1>&2
exit 1
;;
esac
done
trap "if [ '$CLEANUP' ] ; then rm -r '$PWD/debian' ; fi" EXIT
set -u
if [ ! -d .hg ]; then
echo 'You are not inside a Mercurial repository!' 1>&2
exit 1
fi
gethgversion
debver="$version"
if [ -n "$type" ] ; then
debver="$debver~$type"
fi
if [ -n "$distance" ] ; then
debver="$debver+$distance-$CODENAME-$node"
elif [ "$DEBFLAGS" = "-S" ] ; then
# for building a ppa (--source-only) for a release (distance == 0), we need
# to version the distroseries so that we can upload to launchpad
debver="$debver~${CODENAME}1"
fi
control=debian/control
changelog=debian/changelog
if [ "$BUILD" ]; then
if [ -d debian ] ; then
echo "Error! debian control directory already exists!"
exit 1
fi
cp -r $PWD/contrib/debian debian
sed -i.tmp "s/__VERSION__/$debver/" $changelog
sed -i.tmp "s/__DATE__/$(date --rfc-2822)/" $changelog
sed -i.tmp "s/__CODENAME__/$CODENAME/" $changelog
rm $changelog.tmp
# remove the node from the version string
SRCFILE="mercurial_$(echo $debver | sed "s,-$node,,").orig.tar.gz"
"$PWD/hg" archive $SRCFILE
mv $SRCFILE ..
debuild -us -uc -i -I $DEBFLAGS
if [ $? != 0 ]; then
echo 'debuild failed!'
exit 1
fi
fi
if [ "$CLEANUP" ] ; then
echo
OUTPUTDIR=${OUTPUTDIR:=packages/$DISTID-$CODENAME}
mkdir -p "$OUTPUTDIR"
find ../mercurial*.deb ../mercurial_*.build ../mercurial_*.changes \
../mercurial*.dsc ../mercurial*.gz \
-type f -newer $control -print0 2>/dev/null | \
xargs -Inarf -0 mv narf "$OUTPUTDIR"
echo "Built packages for $debver:"
find "$OUTPUTDIR" -type f -newer $control -name '*.deb'
fi