0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-27 23:27:11 +01:00
mongodb/site_scons/mongo/install_actions.py
Steve McClure fedfb0e8e4 SERVER-90617: Enable python formatting checks for site_scons directory (#22301)
GitOrigin-RevId: 0cd9cfa93f7cbfee24b19f6795ae366d5fa94625
2024-05-19 00:00:43 +00:00

150 lines
4.6 KiB
Python

# -*- mode: python; -*-
import os
import shutil
import stat
def _copy(src, dst):
shutil.copy2(src, dst)
st = os.stat(src)
os.chmod(dst, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
def _symlink(src, dst):
if os.path.islink(src):
_copy(src, dst)
else:
os.symlink(os.path.relpath(src, os.path.dirname(dst)), dst)
def _hardlink(src, dst):
if os.path.islink(src):
_copy(src, dst)
else:
try:
os.link(src, dst)
except:
_copy(src, dst)
available_actions = {
"copy": _copy,
"hardlink": _hardlink,
"symlink": _symlink,
}
class _CopytreeError(EnvironmentError):
pass
def _generate_install_actions(base_action):
# This is a patched version of shutil.copytree from python 2.5. It
# doesn't fail if the dir exists, which regular copytree does
# (annoyingly). Note the XXX comment in the docstring.
def _mongo_copytree(src, dst, symlinks=False):
"""Recursively copy a directory tree using copy2().
The destination directory must not already exist.
If exception(s) occur, an _CopytreeError is raised with a list of reasons.
If the optional symlinks flag is true, symbolic links in the
source tree result in symbolic links in the destination tree; if
it is false, the contents of the files pointed to by symbolic
links are copied.
XXX Consider this example code rather than the ultimate tool.
"""
names = os.listdir(src)
# garyo@genarts.com fix: check for dir before making dirs.
if not os.path.exists(dst):
os.makedirs(dst)
errors = []
for name in names:
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
try:
if symlinks and os.path.islink(srcname):
linkto = os.readlink(srcname)
os.symlink(linkto, dstname)
elif os.path.isdir(srcname):
_mongo_copytree(srcname, dstname, symlinks)
else:
base_action(srcname, dstname)
# XXX What about devices, sockets etc.?
except (IOError, os.error) as why:
errors.append((srcname, dstname, str(why)))
# catch the _CopytreeError from the recursive copytree so that we can
# continue with other files
except _CopytreeError as err:
errors.extend(err.args[0])
try:
shutil.copystat(src, dst)
except SCons.Util.WinError:
# can't copy file access times on Windows
pass
except OSError as why:
errors.extend((src, dst, str(why)))
if errors:
raise _CopytreeError(errors)
#
# Functions doing the actual work of the Install Builder.
#
def _mongo_copyFunc(dest, source, env):
"""Install a source file or directory into a destination by copying,
(including copying permission/mode bits)."""
if os.path.isdir(source):
if os.path.exists(dest):
if not os.path.isdir(dest):
raise SCons.Errors.UserError(
"cannot overwrite non-directory `%s' with a directory `%s'"
% (str(dest), str(source))
)
else:
parent = os.path.split(dest)[0]
if not os.path.exists(parent):
os.makedirs(parent)
_mongo_copytree(source, dest)
else:
base_action(source, dest)
return 0
#
# Functions doing the actual work of the InstallVersionedLib Builder.
#
def _mongo_copyFuncVersionedLib(dest, source, env):
"""Install a versioned library into a destination by copying,
(including copying permission/mode bits) and then creating
required symlinks."""
if os.path.isdir(source):
raise SCons.Errors.UserError(
"cannot install directory `%s' as a version library" % str(source)
)
else:
# remove the link if it is already there
try:
os.remove(dest)
except:
pass
base_action(source, dest)
SCons.tool.install.installShlibLinks(dest, source, env)
return 0
return (_mongo_copyFunc, _mongo_copyFuncVersionedLib)
def setup(env, action):
if action == "default":
return
base_action = available_actions.get(action, None)
handlers = _generate_install_actions(base_action)
env["INSTALL"] = handlers[0]
env["INSTALLVERSIONEDLIB"] = handlers[1]