Mercurial > hg
view hgext/fsmonitor/state.py @ 45755:8ed69bd42f10 stable
demandimport: don't raise AttributeError if `exec_module` is missing
I assume this was meant to do the check gracefully. After shoveling a bunch of
modules into the ignore list in order to get keyring to work out of the box on
CentOS 8, I hit the following error accessing the password, which the change
fixes. Now the SecretStorage backend works out of the box, without any edits to
the ignore list.
** Unknown exception encountered with possibly-broken third-party extension mercurial_keyring
** 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.6.8 (default, Apr 16 2020, 01:36:27) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]
** Mercurial Distributed SCM (version 5.5.2)
** Extensions loaded: evolve, topic, rebase, absorb, mercurial_keyring
Traceback (most recent call last):
File "/home/mharbison/hg_py3.6.8_venv/lib64/python3.6/site-packages/mercurial_keyring.py", line 230, in _read_password_from_keyring
password = keyring.get_password(KEYRING_SERVICE, pwdkey)
File "/home/mharbison/hg_py3.6.8_venv/lib64/python3.6/site-packages/keyring/core.py", line 53, in get_password
return _keyring_backend.get_password(service_name, username)
File "/home/mharbison/hg_py3.6.8_venv/lib64/python3.6/site-packages/keyring/backends/chainer.py", line 51, in get_password
password = keyring.get_password(service, username)
File "/home/mharbison/hg_py3.6.8_venv/lib64/python3.6/site-packages/keyring/backends/SecretService.py", line 79, in get_password
return item.get_secret().decode('utf-8')
File "/home/mharbison/hg_py3.6.8_venv/lib64/python3.6/site-packages/secretstorage/item.py", line 105, in get_secret
decryptor = Cipher(aes, modes.CBC(aes_iv), default_backend()).decryptor()
File "/home/mharbison/hg_py3.6.8_venv/lib64/python3.6/site-packages/cryptography/hazmat/backends/__init__.py", line 15, in default_backend
from cryptography.hazmat.backends.openssl.backend import backend
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
File "/home/mharbison/hg_py3.6.8_venv/lib64/python3.6/site-packages/hgdemandimport/demandimportpy3.py", line 53, in exec_module
self.loader.exec_module(module)
File "/home/mharbison/hg_py3.6.8_venv/lib64/python3.6/site-packages/cryptography/hazmat/backends/openssl/__init__.py", line 7, in <module>
from cryptography.hazmat.backends.openssl.backend import backend
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
File "/home/mharbison/hg_py3.6.8_venv/lib64/python3.6/site-packages/hgdemandimport/demandimportpy3.py", line 53, in exec_module
self.loader.exec_module(module)
File "/home/mharbison/hg_py3.6.8_venv/lib64/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 14, in <module>
from six.moves import range
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 951, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 894, in _find_spec
File "/home/mharbison/hg_py3.6.8_venv/lib64/python3.6/site-packages/hgdemandimport/demandimportpy3.py", line 117, in find_spec
and getattr(spec.loader, "exec_module")
AttributeError: '_SixMetaPathImporter' object has no attribute 'exec_module'
Differential Revision: https://phab.mercurial-scm.org/D9243
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Thu, 22 Oct 2020 18:38:41 -0400 |
parents | 8a9e53b974ee |
children | 6000f5b25c9b |
line wrap: on
line source
# state.py - fsmonitor persistent state # # Copyright 2013-2016 Facebook, Inc. # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. from __future__ import absolute_import import errno import os import socket import struct from mercurial.i18n import _ from mercurial import ( encoding, pathutil, util, ) _version = 4 _versionformat = b">I" class state(object): def __init__(self, repo): self._vfs = repo.vfs self._ui = repo.ui self._rootdir = pathutil.normasprefix(repo.root) self._lastclock = None self._identity = util.filestat(None) self.mode = self._ui.config(b'fsmonitor', b'mode') self.walk_on_invalidate = self._ui.configbool( b'fsmonitor', b'walk_on_invalidate' ) self.timeout = float(self._ui.config(b'fsmonitor', b'timeout')) def get(self): try: file = self._vfs(b'fsmonitor.state', b'rb') except IOError as inst: self._identity = util.filestat(None) if inst.errno != errno.ENOENT: raise return None, None, None self._identity = util.filestat.fromfp(file) versionbytes = file.read(4) if len(versionbytes) < 4: self._ui.log( b'fsmonitor', b'fsmonitor: state file only has %d bytes, ' b'nuking state\n' % len(versionbytes), ) self.invalidate() return None, None, None try: diskversion = struct.unpack(_versionformat, versionbytes)[0] if diskversion != _version: # different version, nuke state and start over self._ui.log( b'fsmonitor', b'fsmonitor: version switch from %d to ' b'%d, nuking state\n' % (diskversion, _version), ) self.invalidate() return None, None, None state = file.read().split(b'\0') # state = hostname\0clock\0ignorehash\0 + list of files, each # followed by a \0 if len(state) < 3: self._ui.log( b'fsmonitor', b'fsmonitor: state file truncated (expected ' b'3 chunks, found %d), nuking state\n', len(state), ) self.invalidate() return None, None, None diskhostname = state[0] hostname = encoding.strtolocal(socket.gethostname()) if diskhostname != hostname: # file got moved to a different host self._ui.log( b'fsmonitor', b'fsmonitor: stored hostname "%s" ' b'different from current "%s", nuking state\n' % (diskhostname, hostname), ) self.invalidate() return None, None, None clock = state[1] ignorehash = state[2] # discard the value after the last \0 notefiles = state[3:-1] finally: file.close() return clock, ignorehash, notefiles def set(self, clock, ignorehash, notefiles): if clock is None: self.invalidate() return # Read the identity from the file on disk rather than from the open file # pointer below, because the latter is actually a brand new file. identity = util.filestat.frompath(self._vfs.join(b'fsmonitor.state')) if identity != self._identity: self._ui.debug( b'skip updating fsmonitor.state: identity mismatch\n' ) return try: file = self._vfs( b'fsmonitor.state', b'wb', atomictemp=True, checkambig=True ) except (IOError, OSError): self._ui.warn(_(b"warning: unable to write out fsmonitor state\n")) return with file: file.write(struct.pack(_versionformat, _version)) file.write(encoding.strtolocal(socket.gethostname()) + b'\0') file.write(clock + b'\0') file.write(ignorehash + b'\0') if notefiles: file.write(b'\0'.join(notefiles)) file.write(b'\0') def invalidate(self): try: os.unlink(os.path.join(self._rootdir, b'.hg', b'fsmonitor.state')) except OSError as inst: if inst.errno != errno.ENOENT: raise self._identity = util.filestat(None) def setlastclock(self, clock): self._lastclock = clock def getlastclock(self): return self._lastclock