17db96d56Sopenharmony_ci"""distutils.cmd
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ciProvides the Command class, the base class for the command classes
47db96d56Sopenharmony_ciin the distutils.command package.
57db96d56Sopenharmony_ci"""
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ciimport sys, os, re
87db96d56Sopenharmony_cifrom distutils.errors import DistutilsOptionError
97db96d56Sopenharmony_cifrom distutils import util, dir_util, file_util, archive_util, dep_util
107db96d56Sopenharmony_cifrom distutils import log
117db96d56Sopenharmony_ci
127db96d56Sopenharmony_ciclass Command:
137db96d56Sopenharmony_ci    """Abstract base class for defining command classes, the "worker bees"
147db96d56Sopenharmony_ci    of the Distutils.  A useful analogy for command classes is to think of
157db96d56Sopenharmony_ci    them as subroutines with local variables called "options".  The options
167db96d56Sopenharmony_ci    are "declared" in 'initialize_options()' and "defined" (given their
177db96d56Sopenharmony_ci    final values, aka "finalized") in 'finalize_options()', both of which
187db96d56Sopenharmony_ci    must be defined by every command class.  The distinction between the
197db96d56Sopenharmony_ci    two is necessary because option values might come from the outside
207db96d56Sopenharmony_ci    world (command line, config file, ...), and any options dependent on
217db96d56Sopenharmony_ci    other options must be computed *after* these outside influences have
227db96d56Sopenharmony_ci    been processed -- hence 'finalize_options()'.  The "body" of the
237db96d56Sopenharmony_ci    subroutine, where it does all its work based on the values of its
247db96d56Sopenharmony_ci    options, is the 'run()' method, which must also be implemented by every
257db96d56Sopenharmony_ci    command class.
267db96d56Sopenharmony_ci    """
277db96d56Sopenharmony_ci
287db96d56Sopenharmony_ci    # 'sub_commands' formalizes the notion of a "family" of commands,
297db96d56Sopenharmony_ci    # eg. "install" as the parent with sub-commands "install_lib",
307db96d56Sopenharmony_ci    # "install_headers", etc.  The parent of a family of commands
317db96d56Sopenharmony_ci    # defines 'sub_commands' as a class attribute; it's a list of
327db96d56Sopenharmony_ci    #    (command_name : string, predicate : unbound_method | string | None)
337db96d56Sopenharmony_ci    # tuples, where 'predicate' is a method of the parent command that
347db96d56Sopenharmony_ci    # determines whether the corresponding command is applicable in the
357db96d56Sopenharmony_ci    # current situation.  (Eg. we "install_headers" is only applicable if
367db96d56Sopenharmony_ci    # we have any C header files to install.)  If 'predicate' is None,
377db96d56Sopenharmony_ci    # that command is always applicable.
387db96d56Sopenharmony_ci    #
397db96d56Sopenharmony_ci    # 'sub_commands' is usually defined at the *end* of a class, because
407db96d56Sopenharmony_ci    # predicates can be unbound methods, so they must already have been
417db96d56Sopenharmony_ci    # defined.  The canonical example is the "install" command.
427db96d56Sopenharmony_ci    sub_commands = []
437db96d56Sopenharmony_ci
447db96d56Sopenharmony_ci
457db96d56Sopenharmony_ci    # -- Creation/initialization methods -------------------------------
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_ci    def __init__(self, dist):
487db96d56Sopenharmony_ci        """Create and initialize a new Command object.  Most importantly,
497db96d56Sopenharmony_ci        invokes the 'initialize_options()' method, which is the real
507db96d56Sopenharmony_ci        initializer and depends on the actual command being
517db96d56Sopenharmony_ci        instantiated.
527db96d56Sopenharmony_ci        """
537db96d56Sopenharmony_ci        # late import because of mutual dependence between these classes
547db96d56Sopenharmony_ci        from distutils.dist import Distribution
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ci        if not isinstance(dist, Distribution):
577db96d56Sopenharmony_ci            raise TypeError("dist must be a Distribution instance")
587db96d56Sopenharmony_ci        if self.__class__ is Command:
597db96d56Sopenharmony_ci            raise RuntimeError("Command is an abstract class")
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ci        self.distribution = dist
627db96d56Sopenharmony_ci        self.initialize_options()
637db96d56Sopenharmony_ci
647db96d56Sopenharmony_ci        # Per-command versions of the global flags, so that the user can
657db96d56Sopenharmony_ci        # customize Distutils' behaviour command-by-command and let some
667db96d56Sopenharmony_ci        # commands fall back on the Distribution's behaviour.  None means
677db96d56Sopenharmony_ci        # "not defined, check self.distribution's copy", while 0 or 1 mean
687db96d56Sopenharmony_ci        # false and true (duh).  Note that this means figuring out the real
697db96d56Sopenharmony_ci        # value of each flag is a touch complicated -- hence "self._dry_run"
707db96d56Sopenharmony_ci        # will be handled by __getattr__, below.
717db96d56Sopenharmony_ci        # XXX This needs to be fixed.
727db96d56Sopenharmony_ci        self._dry_run = None
737db96d56Sopenharmony_ci
747db96d56Sopenharmony_ci        # verbose is largely ignored, but needs to be set for
757db96d56Sopenharmony_ci        # backwards compatibility (I think)?
767db96d56Sopenharmony_ci        self.verbose = dist.verbose
777db96d56Sopenharmony_ci
787db96d56Sopenharmony_ci        # Some commands define a 'self.force' option to ignore file
797db96d56Sopenharmony_ci        # timestamps, but methods defined *here* assume that
807db96d56Sopenharmony_ci        # 'self.force' exists for all commands.  So define it here
817db96d56Sopenharmony_ci        # just to be safe.
827db96d56Sopenharmony_ci        self.force = None
837db96d56Sopenharmony_ci
847db96d56Sopenharmony_ci        # The 'help' flag is just used for command-line parsing, so
857db96d56Sopenharmony_ci        # none of that complicated bureaucracy is needed.
867db96d56Sopenharmony_ci        self.help = 0
877db96d56Sopenharmony_ci
887db96d56Sopenharmony_ci        # 'finalized' records whether or not 'finalize_options()' has been
897db96d56Sopenharmony_ci        # called.  'finalize_options()' itself should not pay attention to
907db96d56Sopenharmony_ci        # this flag: it is the business of 'ensure_finalized()', which
917db96d56Sopenharmony_ci        # always calls 'finalize_options()', to respect/update it.
927db96d56Sopenharmony_ci        self.finalized = 0
937db96d56Sopenharmony_ci
947db96d56Sopenharmony_ci    # XXX A more explicit way to customize dry_run would be better.
957db96d56Sopenharmony_ci    def __getattr__(self, attr):
967db96d56Sopenharmony_ci        if attr == 'dry_run':
977db96d56Sopenharmony_ci            myval = getattr(self, "_" + attr)
987db96d56Sopenharmony_ci            if myval is None:
997db96d56Sopenharmony_ci                return getattr(self.distribution, attr)
1007db96d56Sopenharmony_ci            else:
1017db96d56Sopenharmony_ci                return myval
1027db96d56Sopenharmony_ci        else:
1037db96d56Sopenharmony_ci            raise AttributeError(attr)
1047db96d56Sopenharmony_ci
1057db96d56Sopenharmony_ci    def ensure_finalized(self):
1067db96d56Sopenharmony_ci        if not self.finalized:
1077db96d56Sopenharmony_ci            self.finalize_options()
1087db96d56Sopenharmony_ci        self.finalized = 1
1097db96d56Sopenharmony_ci
1107db96d56Sopenharmony_ci    # Subclasses must define:
1117db96d56Sopenharmony_ci    #   initialize_options()
1127db96d56Sopenharmony_ci    #     provide default values for all options; may be customized by
1137db96d56Sopenharmony_ci    #     setup script, by options from config file(s), or by command-line
1147db96d56Sopenharmony_ci    #     options
1157db96d56Sopenharmony_ci    #   finalize_options()
1167db96d56Sopenharmony_ci    #     decide on the final values for all options; this is called
1177db96d56Sopenharmony_ci    #     after all possible intervention from the outside world
1187db96d56Sopenharmony_ci    #     (command-line, option file, etc.) has been processed
1197db96d56Sopenharmony_ci    #   run()
1207db96d56Sopenharmony_ci    #     run the command: do whatever it is we're here to do,
1217db96d56Sopenharmony_ci    #     controlled by the command's various option values
1227db96d56Sopenharmony_ci
1237db96d56Sopenharmony_ci    def initialize_options(self):
1247db96d56Sopenharmony_ci        """Set default values for all the options that this command
1257db96d56Sopenharmony_ci        supports.  Note that these defaults may be overridden by other
1267db96d56Sopenharmony_ci        commands, by the setup script, by config files, or by the
1277db96d56Sopenharmony_ci        command-line.  Thus, this is not the place to code dependencies
1287db96d56Sopenharmony_ci        between options; generally, 'initialize_options()' implementations
1297db96d56Sopenharmony_ci        are just a bunch of "self.foo = None" assignments.
1307db96d56Sopenharmony_ci
1317db96d56Sopenharmony_ci        This method must be implemented by all command classes.
1327db96d56Sopenharmony_ci        """
1337db96d56Sopenharmony_ci        raise RuntimeError("abstract method -- subclass %s must override"
1347db96d56Sopenharmony_ci                           % self.__class__)
1357db96d56Sopenharmony_ci
1367db96d56Sopenharmony_ci    def finalize_options(self):
1377db96d56Sopenharmony_ci        """Set final values for all the options that this command supports.
1387db96d56Sopenharmony_ci        This is always called as late as possible, ie.  after any option
1397db96d56Sopenharmony_ci        assignments from the command-line or from other commands have been
1407db96d56Sopenharmony_ci        done.  Thus, this is the place to code option dependencies: if
1417db96d56Sopenharmony_ci        'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as
1427db96d56Sopenharmony_ci        long as 'foo' still has the same value it was assigned in
1437db96d56Sopenharmony_ci        'initialize_options()'.
1447db96d56Sopenharmony_ci
1457db96d56Sopenharmony_ci        This method must be implemented by all command classes.
1467db96d56Sopenharmony_ci        """
1477db96d56Sopenharmony_ci        raise RuntimeError("abstract method -- subclass %s must override"
1487db96d56Sopenharmony_ci                           % self.__class__)
1497db96d56Sopenharmony_ci
1507db96d56Sopenharmony_ci
1517db96d56Sopenharmony_ci    def dump_options(self, header=None, indent=""):
1527db96d56Sopenharmony_ci        from distutils.fancy_getopt import longopt_xlate
1537db96d56Sopenharmony_ci        if header is None:
1547db96d56Sopenharmony_ci            header = "command options for '%s':" % self.get_command_name()
1557db96d56Sopenharmony_ci        self.announce(indent + header, level=log.INFO)
1567db96d56Sopenharmony_ci        indent = indent + "  "
1577db96d56Sopenharmony_ci        for (option, _, _) in self.user_options:
1587db96d56Sopenharmony_ci            option = option.translate(longopt_xlate)
1597db96d56Sopenharmony_ci            if option[-1] == "=":
1607db96d56Sopenharmony_ci                option = option[:-1]
1617db96d56Sopenharmony_ci            value = getattr(self, option)
1627db96d56Sopenharmony_ci            self.announce(indent + "%s = %s" % (option, value),
1637db96d56Sopenharmony_ci                          level=log.INFO)
1647db96d56Sopenharmony_ci
1657db96d56Sopenharmony_ci    def run(self):
1667db96d56Sopenharmony_ci        """A command's raison d'etre: carry out the action it exists to
1677db96d56Sopenharmony_ci        perform, controlled by the options initialized in
1687db96d56Sopenharmony_ci        'initialize_options()', customized by other commands, the setup
1697db96d56Sopenharmony_ci        script, the command-line, and config files, and finalized in
1707db96d56Sopenharmony_ci        'finalize_options()'.  All terminal output and filesystem
1717db96d56Sopenharmony_ci        interaction should be done by 'run()'.
1727db96d56Sopenharmony_ci
1737db96d56Sopenharmony_ci        This method must be implemented by all command classes.
1747db96d56Sopenharmony_ci        """
1757db96d56Sopenharmony_ci        raise RuntimeError("abstract method -- subclass %s must override"
1767db96d56Sopenharmony_ci                           % self.__class__)
1777db96d56Sopenharmony_ci
1787db96d56Sopenharmony_ci    def announce(self, msg, level=1):
1797db96d56Sopenharmony_ci        """If the current verbosity level is of greater than or equal to
1807db96d56Sopenharmony_ci        'level' print 'msg' to stdout.
1817db96d56Sopenharmony_ci        """
1827db96d56Sopenharmony_ci        log.log(level, msg)
1837db96d56Sopenharmony_ci
1847db96d56Sopenharmony_ci    def debug_print(self, msg):
1857db96d56Sopenharmony_ci        """Print 'msg' to stdout if the global DEBUG (taken from the
1867db96d56Sopenharmony_ci        DISTUTILS_DEBUG environment variable) flag is true.
1877db96d56Sopenharmony_ci        """
1887db96d56Sopenharmony_ci        from distutils.debug import DEBUG
1897db96d56Sopenharmony_ci        if DEBUG:
1907db96d56Sopenharmony_ci            print(msg)
1917db96d56Sopenharmony_ci            sys.stdout.flush()
1927db96d56Sopenharmony_ci
1937db96d56Sopenharmony_ci
1947db96d56Sopenharmony_ci    # -- Option validation methods -------------------------------------
1957db96d56Sopenharmony_ci    # (these are very handy in writing the 'finalize_options()' method)
1967db96d56Sopenharmony_ci    #
1977db96d56Sopenharmony_ci    # NB. the general philosophy here is to ensure that a particular option
1987db96d56Sopenharmony_ci    # value meets certain type and value constraints.  If not, we try to
1997db96d56Sopenharmony_ci    # force it into conformance (eg. if we expect a list but have a string,
2007db96d56Sopenharmony_ci    # split the string on comma and/or whitespace).  If we can't force the
2017db96d56Sopenharmony_ci    # option into conformance, raise DistutilsOptionError.  Thus, command
2027db96d56Sopenharmony_ci    # classes need do nothing more than (eg.)
2037db96d56Sopenharmony_ci    #   self.ensure_string_list('foo')
2047db96d56Sopenharmony_ci    # and they can be guaranteed that thereafter, self.foo will be
2057db96d56Sopenharmony_ci    # a list of strings.
2067db96d56Sopenharmony_ci
2077db96d56Sopenharmony_ci    def _ensure_stringlike(self, option, what, default=None):
2087db96d56Sopenharmony_ci        val = getattr(self, option)
2097db96d56Sopenharmony_ci        if val is None:
2107db96d56Sopenharmony_ci            setattr(self, option, default)
2117db96d56Sopenharmony_ci            return default
2127db96d56Sopenharmony_ci        elif not isinstance(val, str):
2137db96d56Sopenharmony_ci            raise DistutilsOptionError("'%s' must be a %s (got `%s`)"
2147db96d56Sopenharmony_ci                                       % (option, what, val))
2157db96d56Sopenharmony_ci        return val
2167db96d56Sopenharmony_ci
2177db96d56Sopenharmony_ci    def ensure_string(self, option, default=None):
2187db96d56Sopenharmony_ci        """Ensure that 'option' is a string; if not defined, set it to
2197db96d56Sopenharmony_ci        'default'.
2207db96d56Sopenharmony_ci        """
2217db96d56Sopenharmony_ci        self._ensure_stringlike(option, "string", default)
2227db96d56Sopenharmony_ci
2237db96d56Sopenharmony_ci    def ensure_string_list(self, option):
2247db96d56Sopenharmony_ci        r"""Ensure that 'option' is a list of strings.  If 'option' is
2257db96d56Sopenharmony_ci        currently a string, we split it either on /,\s*/ or /\s+/, so
2267db96d56Sopenharmony_ci        "foo bar baz", "foo,bar,baz", and "foo,   bar baz" all become
2277db96d56Sopenharmony_ci        ["foo", "bar", "baz"].
2287db96d56Sopenharmony_ci        """
2297db96d56Sopenharmony_ci        val = getattr(self, option)
2307db96d56Sopenharmony_ci        if val is None:
2317db96d56Sopenharmony_ci            return
2327db96d56Sopenharmony_ci        elif isinstance(val, str):
2337db96d56Sopenharmony_ci            setattr(self, option, re.split(r',\s*|\s+', val))
2347db96d56Sopenharmony_ci        else:
2357db96d56Sopenharmony_ci            if isinstance(val, list):
2367db96d56Sopenharmony_ci                ok = all(isinstance(v, str) for v in val)
2377db96d56Sopenharmony_ci            else:
2387db96d56Sopenharmony_ci                ok = False
2397db96d56Sopenharmony_ci            if not ok:
2407db96d56Sopenharmony_ci                raise DistutilsOptionError(
2417db96d56Sopenharmony_ci                      "'%s' must be a list of strings (got %r)"
2427db96d56Sopenharmony_ci                      % (option, val))
2437db96d56Sopenharmony_ci
2447db96d56Sopenharmony_ci    def _ensure_tested_string(self, option, tester, what, error_fmt,
2457db96d56Sopenharmony_ci                              default=None):
2467db96d56Sopenharmony_ci        val = self._ensure_stringlike(option, what, default)
2477db96d56Sopenharmony_ci        if val is not None and not tester(val):
2487db96d56Sopenharmony_ci            raise DistutilsOptionError(("error in '%s' option: " + error_fmt)
2497db96d56Sopenharmony_ci                                       % (option, val))
2507db96d56Sopenharmony_ci
2517db96d56Sopenharmony_ci    def ensure_filename(self, option):
2527db96d56Sopenharmony_ci        """Ensure that 'option' is the name of an existing file."""
2537db96d56Sopenharmony_ci        self._ensure_tested_string(option, os.path.isfile,
2547db96d56Sopenharmony_ci                                   "filename",
2557db96d56Sopenharmony_ci                                   "'%s' does not exist or is not a file")
2567db96d56Sopenharmony_ci
2577db96d56Sopenharmony_ci    def ensure_dirname(self, option):
2587db96d56Sopenharmony_ci        self._ensure_tested_string(option, os.path.isdir,
2597db96d56Sopenharmony_ci                                   "directory name",
2607db96d56Sopenharmony_ci                                   "'%s' does not exist or is not a directory")
2617db96d56Sopenharmony_ci
2627db96d56Sopenharmony_ci
2637db96d56Sopenharmony_ci    # -- Convenience methods for commands ------------------------------
2647db96d56Sopenharmony_ci
2657db96d56Sopenharmony_ci    def get_command_name(self):
2667db96d56Sopenharmony_ci        if hasattr(self, 'command_name'):
2677db96d56Sopenharmony_ci            return self.command_name
2687db96d56Sopenharmony_ci        else:
2697db96d56Sopenharmony_ci            return self.__class__.__name__
2707db96d56Sopenharmony_ci
2717db96d56Sopenharmony_ci    def set_undefined_options(self, src_cmd, *option_pairs):
2727db96d56Sopenharmony_ci        """Set the values of any "undefined" options from corresponding
2737db96d56Sopenharmony_ci        option values in some other command object.  "Undefined" here means
2747db96d56Sopenharmony_ci        "is None", which is the convention used to indicate that an option
2757db96d56Sopenharmony_ci        has not been changed between 'initialize_options()' and
2767db96d56Sopenharmony_ci        'finalize_options()'.  Usually called from 'finalize_options()' for
2777db96d56Sopenharmony_ci        options that depend on some other command rather than another
2787db96d56Sopenharmony_ci        option of the same command.  'src_cmd' is the other command from
2797db96d56Sopenharmony_ci        which option values will be taken (a command object will be created
2807db96d56Sopenharmony_ci        for it if necessary); the remaining arguments are
2817db96d56Sopenharmony_ci        '(src_option,dst_option)' tuples which mean "take the value of
2827db96d56Sopenharmony_ci        'src_option' in the 'src_cmd' command object, and copy it to
2837db96d56Sopenharmony_ci        'dst_option' in the current command object".
2847db96d56Sopenharmony_ci        """
2857db96d56Sopenharmony_ci        # Option_pairs: list of (src_option, dst_option) tuples
2867db96d56Sopenharmony_ci        src_cmd_obj = self.distribution.get_command_obj(src_cmd)
2877db96d56Sopenharmony_ci        src_cmd_obj.ensure_finalized()
2887db96d56Sopenharmony_ci        for (src_option, dst_option) in option_pairs:
2897db96d56Sopenharmony_ci            if getattr(self, dst_option) is None:
2907db96d56Sopenharmony_ci                setattr(self, dst_option, getattr(src_cmd_obj, src_option))
2917db96d56Sopenharmony_ci
2927db96d56Sopenharmony_ci    def get_finalized_command(self, command, create=1):
2937db96d56Sopenharmony_ci        """Wrapper around Distribution's 'get_command_obj()' method: find
2947db96d56Sopenharmony_ci        (create if necessary and 'create' is true) the command object for
2957db96d56Sopenharmony_ci        'command', call its 'ensure_finalized()' method, and return the
2967db96d56Sopenharmony_ci        finalized command object.
2977db96d56Sopenharmony_ci        """
2987db96d56Sopenharmony_ci        cmd_obj = self.distribution.get_command_obj(command, create)
2997db96d56Sopenharmony_ci        cmd_obj.ensure_finalized()
3007db96d56Sopenharmony_ci        return cmd_obj
3017db96d56Sopenharmony_ci
3027db96d56Sopenharmony_ci    # XXX rename to 'get_reinitialized_command()'? (should do the
3037db96d56Sopenharmony_ci    # same in dist.py, if so)
3047db96d56Sopenharmony_ci    def reinitialize_command(self, command, reinit_subcommands=0):
3057db96d56Sopenharmony_ci        return self.distribution.reinitialize_command(command,
3067db96d56Sopenharmony_ci                                                      reinit_subcommands)
3077db96d56Sopenharmony_ci
3087db96d56Sopenharmony_ci    def run_command(self, command):
3097db96d56Sopenharmony_ci        """Run some other command: uses the 'run_command()' method of
3107db96d56Sopenharmony_ci        Distribution, which creates and finalizes the command object if
3117db96d56Sopenharmony_ci        necessary and then invokes its 'run()' method.
3127db96d56Sopenharmony_ci        """
3137db96d56Sopenharmony_ci        self.distribution.run_command(command)
3147db96d56Sopenharmony_ci
3157db96d56Sopenharmony_ci    def get_sub_commands(self):
3167db96d56Sopenharmony_ci        """Determine the sub-commands that are relevant in the current
3177db96d56Sopenharmony_ci        distribution (ie., that need to be run).  This is based on the
3187db96d56Sopenharmony_ci        'sub_commands' class attribute: each tuple in that list may include
3197db96d56Sopenharmony_ci        a method that we call to determine if the subcommand needs to be
3207db96d56Sopenharmony_ci        run for the current distribution.  Return a list of command names.
3217db96d56Sopenharmony_ci        """
3227db96d56Sopenharmony_ci        commands = []
3237db96d56Sopenharmony_ci        for (cmd_name, method) in self.sub_commands:
3247db96d56Sopenharmony_ci            if method is None or method(self):
3257db96d56Sopenharmony_ci                commands.append(cmd_name)
3267db96d56Sopenharmony_ci        return commands
3277db96d56Sopenharmony_ci
3287db96d56Sopenharmony_ci
3297db96d56Sopenharmony_ci    # -- External world manipulation -----------------------------------
3307db96d56Sopenharmony_ci
3317db96d56Sopenharmony_ci    def warn(self, msg):
3327db96d56Sopenharmony_ci        log.warn("warning: %s: %s\n", self.get_command_name(), msg)
3337db96d56Sopenharmony_ci
3347db96d56Sopenharmony_ci    def execute(self, func, args, msg=None, level=1):
3357db96d56Sopenharmony_ci        util.execute(func, args, msg, dry_run=self.dry_run)
3367db96d56Sopenharmony_ci
3377db96d56Sopenharmony_ci    def mkpath(self, name, mode=0o777):
3387db96d56Sopenharmony_ci        dir_util.mkpath(name, mode, dry_run=self.dry_run)
3397db96d56Sopenharmony_ci
3407db96d56Sopenharmony_ci    def copy_file(self, infile, outfile, preserve_mode=1, preserve_times=1,
3417db96d56Sopenharmony_ci                  link=None, level=1):
3427db96d56Sopenharmony_ci        """Copy a file respecting verbose, dry-run and force flags.  (The
3437db96d56Sopenharmony_ci        former two default to whatever is in the Distribution object, and
3447db96d56Sopenharmony_ci        the latter defaults to false for commands that don't define it.)"""
3457db96d56Sopenharmony_ci        return file_util.copy_file(infile, outfile, preserve_mode,
3467db96d56Sopenharmony_ci                                   preserve_times, not self.force, link,
3477db96d56Sopenharmony_ci                                   dry_run=self.dry_run)
3487db96d56Sopenharmony_ci
3497db96d56Sopenharmony_ci    def copy_tree(self, infile, outfile, preserve_mode=1, preserve_times=1,
3507db96d56Sopenharmony_ci                   preserve_symlinks=0, level=1):
3517db96d56Sopenharmony_ci        """Copy an entire directory tree respecting verbose, dry-run,
3527db96d56Sopenharmony_ci        and force flags.
3537db96d56Sopenharmony_ci        """
3547db96d56Sopenharmony_ci        return dir_util.copy_tree(infile, outfile, preserve_mode,
3557db96d56Sopenharmony_ci                                  preserve_times, preserve_symlinks,
3567db96d56Sopenharmony_ci                                  not self.force, dry_run=self.dry_run)
3577db96d56Sopenharmony_ci
3587db96d56Sopenharmony_ci    def move_file (self, src, dst, level=1):
3597db96d56Sopenharmony_ci        """Move a file respecting dry-run flag."""
3607db96d56Sopenharmony_ci        return file_util.move_file(src, dst, dry_run=self.dry_run)
3617db96d56Sopenharmony_ci
3627db96d56Sopenharmony_ci    def spawn(self, cmd, search_path=1, level=1):
3637db96d56Sopenharmony_ci        """Spawn an external command respecting dry-run flag."""
3647db96d56Sopenharmony_ci        from distutils.spawn import spawn
3657db96d56Sopenharmony_ci        spawn(cmd, search_path, dry_run=self.dry_run)
3667db96d56Sopenharmony_ci
3677db96d56Sopenharmony_ci    def make_archive(self, base_name, format, root_dir=None, base_dir=None,
3687db96d56Sopenharmony_ci                     owner=None, group=None):
3697db96d56Sopenharmony_ci        return archive_util.make_archive(base_name, format, root_dir, base_dir,
3707db96d56Sopenharmony_ci                                         dry_run=self.dry_run,
3717db96d56Sopenharmony_ci                                         owner=owner, group=group)
3727db96d56Sopenharmony_ci
3737db96d56Sopenharmony_ci    def make_file(self, infiles, outfile, func, args,
3747db96d56Sopenharmony_ci                  exec_msg=None, skip_msg=None, level=1):
3757db96d56Sopenharmony_ci        """Special case of 'execute()' for operations that process one or
3767db96d56Sopenharmony_ci        more input files and generate one output file.  Works just like
3777db96d56Sopenharmony_ci        'execute()', except the operation is skipped and a different
3787db96d56Sopenharmony_ci        message printed if 'outfile' already exists and is newer than all
3797db96d56Sopenharmony_ci        files listed in 'infiles'.  If the command defined 'self.force',
3807db96d56Sopenharmony_ci        and it is true, then the command is unconditionally run -- does no
3817db96d56Sopenharmony_ci        timestamp checks.
3827db96d56Sopenharmony_ci        """
3837db96d56Sopenharmony_ci        if skip_msg is None:
3847db96d56Sopenharmony_ci            skip_msg = "skipping %s (inputs unchanged)" % outfile
3857db96d56Sopenharmony_ci
3867db96d56Sopenharmony_ci        # Allow 'infiles' to be a single string
3877db96d56Sopenharmony_ci        if isinstance(infiles, str):
3887db96d56Sopenharmony_ci            infiles = (infiles,)
3897db96d56Sopenharmony_ci        elif not isinstance(infiles, (list, tuple)):
3907db96d56Sopenharmony_ci            raise TypeError(
3917db96d56Sopenharmony_ci                  "'infiles' must be a string, or a list or tuple of strings")
3927db96d56Sopenharmony_ci
3937db96d56Sopenharmony_ci        if exec_msg is None:
3947db96d56Sopenharmony_ci            exec_msg = "generating %s from %s" % (outfile, ', '.join(infiles))
3957db96d56Sopenharmony_ci
3967db96d56Sopenharmony_ci        # If 'outfile' must be regenerated (either because it doesn't
3977db96d56Sopenharmony_ci        # exist, is out-of-date, or the 'force' flag is true) then
3987db96d56Sopenharmony_ci        # perform the action that presumably regenerates it
3997db96d56Sopenharmony_ci        if self.force or dep_util.newer_group(infiles, outfile):
4007db96d56Sopenharmony_ci            self.execute(func, args, exec_msg, level)
4017db96d56Sopenharmony_ci        # Otherwise, print the "skip" message
4027db96d56Sopenharmony_ci        else:
4037db96d56Sopenharmony_ci            log.debug(skip_msg)
404