aboutsummaryrefslogtreecommitdiff
path: root/pkg/private/install.py.tpl
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/private/install.py.tpl')
-rw-r--r--pkg/private/install.py.tpl203
1 files changed, 0 insertions, 203 deletions
diff --git a/pkg/private/install.py.tpl b/pkg/private/install.py.tpl
deleted file mode 100644
index b0517f4..0000000
--- a/pkg/private/install.py.tpl
+++ /dev/null
@@ -1,203 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright 2021 The Bazel Authors. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This template is completed by `pkg_install` to create installation scripts,
-# and will not function on its own. See pkg/install.bzl for more details.
-
-import argparse
-import logging
-import os
-import shutil
-import sys
-
-from pkg.private import manifest
-
-# Globals used for runfile path manipulation.
-#
-# These are necessary because runfiles are different when used as a part of
-# `bazel build` and `bazel run`. # See also
-# https://docs.bazel.build/versions/4.1.0/skylark/rules.html#tools-with-runfiles
-
-# Bazel's documentation claims these are set when calling `bazel run`, but not other
-# modes, like in `build` or `test`. We'll see.
-CALLED_FROM_BAZEL_RUN = bool(os.getenv("BUILD_WORKSPACE_DIRECTORY") and
- os.getenv("BUILD_WORKING_DIRECTORY"))
-
-WORKSPACE_NAME = "{WORKSPACE_NAME}"
-# This seems to be set when running in `bazel build` or `bazel test`
-# TODO(#382): This may not be the case in Windows.
-RUNFILE_PREFIX = os.path.join(os.getenv("RUNFILES_DIR"), WORKSPACE_NAME) if os.getenv("RUNFILES_DIR") else None
-
-
-# This is named "NativeInstaller" because it makes use of "native" python
-# functionality for installing files that should be cross-platform.
-#
-# A variant on this might be an installer at least partially based on coreutils.
-# Most notably, some filesystems on Linux (and maybe others) support
-# copy-on-write functionality that are known to tools like cp(1) and install(1)
-# but may not be in the available python runtime.
-#
-# See also https://bugs.python.org/issue37157.
-class NativeInstaller(object):
- def __init__(self, default_user=None, default_group=None, destdir=None):
- self.default_user = default_user
- self.default_group = default_group
- self.destdir = destdir
- self.entries = []
-
- # Logger helper method, may not be necessary or desired
- def _subst_destdir(path, self):
- return path.replace(self.destdir, "$DESTDIR")
-
- def _chown_chmod(self, dest, mode, user, group):
- if mode:
- logging.info("CHMOD %s %s", mode, dest)
- os.chmod(dest, int(mode, 8))
- if user or group:
- # Ownership can only be changed by sufficiently
- # privileged users.
- # TODO(nacl): This does not support windows
- if hasattr(os, "getuid") and os.getuid() == 0:
- logging.info("CHOWN %s:%s %s", user, group, dest)
- shutil.chown(dest, user, group)
-
- def _do_file_copy(self, src, dest, mode, user, group):
- logging.info("COPY %s <- %s", dest, src)
- shutil.copyfile(src, dest)
-
- def _do_mkdir(self, dirname, mode, user, group):
- logging.info("MKDIR %s %s", mode, dirname)
- os.makedirs(dirname, int(mode, 8), exist_ok=True)
-
- def _do_symlink(self, target, link_name, mode, user, group):
- raise NotImplementedError("symlinking not yet supported")
-
- def _maybe_make_unowned_dir(self, path):
- logging.info("MKDIR (unowned) %s", path)
- # TODO(nacl): consider default permissions here
- # TODO(nacl): consider default ownership here
- os.makedirs(path, 0o755, exist_ok=True)
-
- def _install_file(self, entry):
- self._maybe_make_unowned_dir(os.path.dirname(entry.dest))
- self._do_file_copy(entry.src, entry.dest, entry.mode, entry.user, entry.group)
- self._chown_chmod(entry.dest, entry.mode, entry.user, entry.group)
-
- def _install_directory(self, entry):
- self._maybe_make_unowned_dir(os.path.dirname(entry.dest))
- self._do_mkdir(entry.dest, entry.mode, entry.user, entry.group)
- self._chown_chmod(entry.dest, entry.mode, entry.user, entry.group)
-
- def _install_treeartifact(self, entry):
- logging.info("COPYTREE %s <- %s/**", entry.dest, entry.src)
- raise NotImplementedError("treeartifact installation not yet supported")
- for root, dirs, files in os.walk(entry.src):
- relative_installdir = os.path.join(entry.dest, root)
- for d in dirs:
- self._maybe_make_unowned_dir(os.path.join(relative_installdir, d))
-
- logging.info("COPY_FROM_TREE %s <- %s", entry.dest, entry.src)
- logging.info("CHMOD %s %s", entry.mode, entry.dest)
- logging.info("CHOWN %s:%s %s", entry.user, entry.group, entry.dest)
-
- def _install_symlink(self, entry):
- raise NotImplementedError("symlinking not yet supported")
- logging.info("SYMLINK %s <- %s", entry.dest, entry.link_to)
- logging.info("CHMOD %s %s", entry.dest, entry.mode)
- logging.info("CHOWN %s.%s %s", entry.dest, entry.user, entry.group)
-
- def include_manifest_path(self, path):
- with open(path, 'r') as fh:
- self.include_manifest(fh)
-
- def include_manifest(self, manifest_fh):
- manifest_entries = manifest.read_entries_from(manifest_fh)
-
- for entry in manifest_entries:
- # Swap out the source with the actual "runfile" location if we're
- # called as a part of the build rather than "bazel run"
- if not CALLED_FROM_BAZEL_RUN and entry.src is not None:
- entry.src = os.path.join(RUNFILE_PREFIX, entry.src)
- # Prepend the destdir path to all installation paths, if one is
- # specified.
- if self.destdir is not None:
- entry.dest = os.path.join(self.destdir, entry.dest)
- self.entries.append(entry)
-
- def do_the_thing(self):
- for entry in self.entries:
- if entry.type == manifest.ENTRY_IS_FILE:
- self._install_file(entry)
- elif entry.type == manifest.ENTRY_IS_LINK:
- self._install_symlink(entry)
- elif entry.type == manifest.ENTRY_IS_DIR:
- self._install_directory(entry)
- elif entry.type == manifest.ENTRY_IS_TREE:
- self._install_treeartifact(entry)
- else:
- raise ValueError("Unrecognized entry type '{}'".format(entry.type))
-
-
-def main(args):
- parser = argparse.ArgumentParser(
- prog="bazel run -- {TARGET_LABEL}",
- description='Installer for bazel target {TARGET_LABEL}',
- fromfile_prefix_chars='@',
- )
- parser.add_argument('-v', '--verbose', action='count', default=0,
- help="Be verbose. Specify multiple times to increase verbosity further")
- parser.add_argument('-q', '--quiet', action='store_true', default=False,
- help="Be silent, except for errors")
- # TODO(nacl): consider supporting DESTDIR=/whatever syntax, like "make
- # install".
- #
- # TODO(nacl): consider removing absolute path restriction, perhaps using
- # BUILD_WORKING_DIRECTORY.
- parser.add_argument('--destdir', action='store', default=os.getenv("DESTDIR"),
- help="Installation root directory (defaults to DESTDIR "
- "environment variable). Must be an absolute path.")
-
- args = parser.parse_args()
-
- loudness = args.verbose - args.quiet
-
- if args.quiet:
- logging.getLogger().setLevel(logging.ERROR)
- elif loudness == 0:
- logging.getLogger().setLevel(logging.WARNING)
- elif loudness == 1:
- logging.getLogger().setLevel(logging.INFO)
- else: # loudness >= 2:
- logging.getLogger().setLevel(logging.DEBUG)
-
- installer = NativeInstaller(destdir=args.destdir)
-
- if not CALLED_FROM_BAZEL_RUN and RUNFILE_PREFIX is None:
- logging.critical("RUNFILES_DIR must be set in your environment when this is run as a bazel build tool.")
- logging.critical("This is most likely an issue on Windows. See https://github.com/bazelbuild/rules_pkg/issues/387.")
- return 1
-
- for f in ["{MANIFEST_INCLUSION}"]:
- if CALLED_FROM_BAZEL_RUN:
- installer.include_manifest_path(f)
- else:
- installer.include_manifest_path(os.path.join(RUNFILE_PREFIX, f))
-
- installer.do_the_thing()
-
-
-if __name__ == "__main__":
- exit(main(sys.argv))