sapling/edenscm/hgext/ownercheck.py
Jun Wu 9dc21f8d0b codemod: import from the edenscm package
Summary:
D13853115 adds `edenscm/` to `sys.path` and code still uses `import mercurial`.
That has nasty problems if both `import mercurial` and
`import edenscm.mercurial` are used, because Python would think `mercurial.foo`
and `edenscm.mercurial.foo` are different modules so code like
`try: ... except mercurial.error.Foo: ...`, or `isinstance(x, mercurial.foo.Bar)`
would fail to handle the `edenscm.mercurial` version. There are also some
module-level states (ex. `extensions._extensions`) that would cause trouble if
they have multiple versions in a single process.

Change imports to use the `edenscm` so ideally the `mercurial` is no longer
imported at all. Add checks in extensions.py to catch unexpected extensions
importing modules from the old (wrong) locations when running tests.

Reviewed By: phillco

Differential Revision: D13868981

fbshipit-source-id: f4e2513766957fd81d85407994f7521a08e4de48
2019-01-29 17:25:32 -08:00

73 lines
1.9 KiB
Python

# ownercheck.py - prevent operations on repos not owned
#
# Copyright 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.
"""prevent operations on repos not owned by the current user
This extension checks the ownership of the local repo path (or its parent if
the path does not exist) and aborts if it does not match the current user.
This prevents some common mistakes like using sudo to clone a repo.
"""
import os
from edenscm.mercurial import error, extensions, localrepo
from edenscm.mercurial.i18n import _
try:
import pwd
except ImportError:
pwd = None
def _getowner(path):
"""find uid of a path or its parents. return (uid, path)"""
path = os.path.abspath(path or "")
while True:
try:
stat = os.stat(path)
return stat.st_uid, path
except Exception:
parent = os.path.dirname(path)
if parent == path:
break
path = parent
return None, None
def _describeuser(uid):
"""convert uid to username if possible"""
if pwd:
try:
return pwd.getpwuid(uid).pw_name
except Exception:
pass
return "user %d" % uid
def _checkownedpath(path):
ownerid, path = _getowner(path)
uid = os.getuid()
# allow access to public places owned by root (ex. /tmp)
if ownerid in [None, 0, uid]:
return
raise error.Abort(
_("%s is owned by %s, not you (%s).\n" "you are likely doing something wrong.")
% (path, _describeuser(ownerid), _describeuser(uid)),
hint=_("you can skip the check using " "--config extensions.ownercheck=!"),
)
def _localrepoinit(orig, self, baseui, path=None, create=False):
_checkownedpath(path)
return orig(self, baseui, path, create)
def uisetup(ui):
extensions.wrapfunction(localrepo.localrepository, "__init__", _localrepoinit)