annotate hgext/hooklib/reject_new_heads.py @ 47866:4162f6b40f2c stable

windows: degrade to py2 behavior when reading a non-symlink as a symlink While waiting for the push to hg-committed in WSL to complete, I ran a `phabimport` from Windows and got this traceback: $ hg phabimport 11313 ** Unknown exception encountered with possibly-broken third-party extension "mercurial_keyring" (version N/A) ** which supports versions unknown of Mercurial. ** Please disable "mercurial_keyring" and try your action again. ** If that fixes the bug please report it to https://foss.heptapod.net/mercurial/mercurial_keyring/issues ** Python 3.9.5 (default, May 6 2021, 17:29:31) [MSC v.1928 64 bit (AMD64)] ** Mercurial Distributed SCM (version 5.9rc1+hg32.0e2f5733563d) ** Extensions loaded: absorb, blackbox, evolve 10.3.3, extdiff, fastannotate, fix, mercurial_keyring, mq, phabblocker 20210126, phabricator, rebase, show, strip, topic 0.22.3 Traceback (most recent call last): File "mercurial.lock", line 279, in _trylock File "mercurial.vfs", line 202, in makelock File "mercurial.util", line 2147, in makelock FileExistsError: [WinError 183] Cannot create a file when that file already exists: b'hp-omen:78348' -> b'C:\\Users\\Matt\\hg/.hg/store/lock' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<string>", line 24, in <module> File "mercurial.dispatch", line 144, in run File "mercurial.dispatch", line 250, in dispatch File "mercurial.dispatch", line 294, in _rundispatch File "mercurial.dispatch", line 470, in _runcatch File "mercurial.dispatch", line 480, in _callcatch File "mercurial.scmutil", line 153, in callcatch File "mercurial.dispatch", line 460, in _runcatchfunc File "mercurial.dispatch", line 1273, in _dispatch File "mercurial.dispatch", line 918, in runcommand File "mercurial.dispatch", line 1285, in _runcommand File "mercurial.dispatch", line 1271, in <lambda> File "mercurial.util", line 1886, in check File "mercurial.util", line 1886, in check File "hgext.mq", line 4239, in mqcommand File "mercurial.util", line 1886, in check File "mercurial.util", line 1886, in check File "hgext.phabricator", line 314, in inner File "hgext.phabricator", line 2222, in phabimport File "hgext.phabricator", line 2123, in readpatch File "hgext.phabricator", line 2199, in _write File "mercurial.localrepo", line 2956, in lock File "mercurial.localrepo", line 2918, in _lock File "mercurial.lock", line 152, in trylock File "mercurial.lock", line 283, in _trylock File "mercurial.lock", line 314, in _readlock File "mercurial.vfs", line 221, in readlock File "mercurial.util", line 2163, in readlock File "mercurial.windows", line 619, in readlink ValueError: not a symbolic link Both exceptions look accurate (the file exists, and the Windows side can't read WSL side symlinks). I didn't try to reproduce this entirely within the Windows side, but we can do better than a cryptic stacktrace. With this change, the same scenario results in this abort: abort: C:\Users\Matt\hg/.hg/store/lock: The file cannot be accessed by the system When both the `push` and `phabimport` are done on the Windows side, it prints a message about waiting for the lock, and successfully applies the patch after the push completes. I'm not sure if there's enough info to be able to convert the abort into the wait scenario. As it stands now, we don't support symlinks on Windows, which requires either a UAC Administrator level process or an opt-in in developer mode, and there are several places where the new symlink on Windows support in py3 was explicitly disabled in order to get tests to pass quicker. Differential Revision: https://phab.mercurial-scm.org/D11333
author Matt Harbison <matt_harbison@yahoo.com>
date Sun, 22 Aug 2021 17:59:21 -0400
parents 4cabeea6d214
children 6000f5b25c9b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
44413
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
1 # Copyright 2020 Joerg Sonnenberger <joerg@bec.de>
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
2 #
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
3 # This software may be used and distributed according to the terms of the
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
4 # GNU General Public License version 2 or any later version.
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
5
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
6 """reject_new_heads is a hook to check that branches touched by new changesets
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
7 have at most one open head. It can be used to enforce policies for
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
8 merge-before-push or rebase-before-push. It does not handle pre-existing
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
9 hydras.
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
10
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
11 Usage:
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
12 [hooks]
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
13 pretxnclose.reject_new_heads = \
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
14 python:hgext.hooklib.reject_new_heads.hook
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
15 """
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
16
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
17 from __future__ import absolute_import
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
18
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
19 from mercurial.i18n import _
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
20 from mercurial import (
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
21 error,
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
22 pycompat,
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
23 )
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
24
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
25
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
26 def hook(ui, repo, hooktype, node=None, **kwargs):
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
27 if hooktype != b"pretxnclose":
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
28 raise error.Abort(
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
29 _(b'Unsupported hook type %r') % pycompat.bytestr(hooktype)
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
30 )
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
31 ctx = repo.unfiltered()[node]
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
32 branches = set()
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
33 for rev in repo.changelog.revs(start=ctx.rev()):
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
34 rev = repo[rev]
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
35 branches.add(rev.branch())
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
36 for branch in branches:
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
37 if len(repo.revs("head() and not closed() and branch(%s)", branch)) > 1:
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
38 raise error.Abort(
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
39 _(b'Changes on branch %r resulted in multiple heads')
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
40 % pycompat.bytestr(branch)
4cabeea6d214 hgext: start building a library for simple hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
41 )