1*cda5da8dSAndroid Build Coastguard Worker"""distutils.cmd 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard WorkerProvides the Command class, the base class for the command classes 4*cda5da8dSAndroid Build Coastguard Workerin the distutils.command package. 5*cda5da8dSAndroid Build Coastguard Worker""" 6*cda5da8dSAndroid Build Coastguard Worker 7*cda5da8dSAndroid Build Coastguard Workerimport sys, os, re 8*cda5da8dSAndroid Build Coastguard Workerfrom distutils.errors import DistutilsOptionError 9*cda5da8dSAndroid Build Coastguard Workerfrom distutils import util, dir_util, file_util, archive_util, dep_util 10*cda5da8dSAndroid Build Coastguard Workerfrom distutils import log 11*cda5da8dSAndroid Build Coastguard Worker 12*cda5da8dSAndroid Build Coastguard Workerclass Command: 13*cda5da8dSAndroid Build Coastguard Worker """Abstract base class for defining command classes, the "worker bees" 14*cda5da8dSAndroid Build Coastguard Worker of the Distutils. A useful analogy for command classes is to think of 15*cda5da8dSAndroid Build Coastguard Worker them as subroutines with local variables called "options". The options 16*cda5da8dSAndroid Build Coastguard Worker are "declared" in 'initialize_options()' and "defined" (given their 17*cda5da8dSAndroid Build Coastguard Worker final values, aka "finalized") in 'finalize_options()', both of which 18*cda5da8dSAndroid Build Coastguard Worker must be defined by every command class. The distinction between the 19*cda5da8dSAndroid Build Coastguard Worker two is necessary because option values might come from the outside 20*cda5da8dSAndroid Build Coastguard Worker world (command line, config file, ...), and any options dependent on 21*cda5da8dSAndroid Build Coastguard Worker other options must be computed *after* these outside influences have 22*cda5da8dSAndroid Build Coastguard Worker been processed -- hence 'finalize_options()'. The "body" of the 23*cda5da8dSAndroid Build Coastguard Worker subroutine, where it does all its work based on the values of its 24*cda5da8dSAndroid Build Coastguard Worker options, is the 'run()' method, which must also be implemented by every 25*cda5da8dSAndroid Build Coastguard Worker command class. 26*cda5da8dSAndroid Build Coastguard Worker """ 27*cda5da8dSAndroid Build Coastguard Worker 28*cda5da8dSAndroid Build Coastguard Worker # 'sub_commands' formalizes the notion of a "family" of commands, 29*cda5da8dSAndroid Build Coastguard Worker # eg. "install" as the parent with sub-commands "install_lib", 30*cda5da8dSAndroid Build Coastguard Worker # "install_headers", etc. The parent of a family of commands 31*cda5da8dSAndroid Build Coastguard Worker # defines 'sub_commands' as a class attribute; it's a list of 32*cda5da8dSAndroid Build Coastguard Worker # (command_name : string, predicate : unbound_method | string | None) 33*cda5da8dSAndroid Build Coastguard Worker # tuples, where 'predicate' is a method of the parent command that 34*cda5da8dSAndroid Build Coastguard Worker # determines whether the corresponding command is applicable in the 35*cda5da8dSAndroid Build Coastguard Worker # current situation. (Eg. we "install_headers" is only applicable if 36*cda5da8dSAndroid Build Coastguard Worker # we have any C header files to install.) If 'predicate' is None, 37*cda5da8dSAndroid Build Coastguard Worker # that command is always applicable. 38*cda5da8dSAndroid Build Coastguard Worker # 39*cda5da8dSAndroid Build Coastguard Worker # 'sub_commands' is usually defined at the *end* of a class, because 40*cda5da8dSAndroid Build Coastguard Worker # predicates can be unbound methods, so they must already have been 41*cda5da8dSAndroid Build Coastguard Worker # defined. The canonical example is the "install" command. 42*cda5da8dSAndroid Build Coastguard Worker sub_commands = [] 43*cda5da8dSAndroid Build Coastguard Worker 44*cda5da8dSAndroid Build Coastguard Worker 45*cda5da8dSAndroid Build Coastguard Worker # -- Creation/initialization methods ------------------------------- 46*cda5da8dSAndroid Build Coastguard Worker 47*cda5da8dSAndroid Build Coastguard Worker def __init__(self, dist): 48*cda5da8dSAndroid Build Coastguard Worker """Create and initialize a new Command object. Most importantly, 49*cda5da8dSAndroid Build Coastguard Worker invokes the 'initialize_options()' method, which is the real 50*cda5da8dSAndroid Build Coastguard Worker initializer and depends on the actual command being 51*cda5da8dSAndroid Build Coastguard Worker instantiated. 52*cda5da8dSAndroid Build Coastguard Worker """ 53*cda5da8dSAndroid Build Coastguard Worker # late import because of mutual dependence between these classes 54*cda5da8dSAndroid Build Coastguard Worker from distutils.dist import Distribution 55*cda5da8dSAndroid Build Coastguard Worker 56*cda5da8dSAndroid Build Coastguard Worker if not isinstance(dist, Distribution): 57*cda5da8dSAndroid Build Coastguard Worker raise TypeError("dist must be a Distribution instance") 58*cda5da8dSAndroid Build Coastguard Worker if self.__class__ is Command: 59*cda5da8dSAndroid Build Coastguard Worker raise RuntimeError("Command is an abstract class") 60*cda5da8dSAndroid Build Coastguard Worker 61*cda5da8dSAndroid Build Coastguard Worker self.distribution = dist 62*cda5da8dSAndroid Build Coastguard Worker self.initialize_options() 63*cda5da8dSAndroid Build Coastguard Worker 64*cda5da8dSAndroid Build Coastguard Worker # Per-command versions of the global flags, so that the user can 65*cda5da8dSAndroid Build Coastguard Worker # customize Distutils' behaviour command-by-command and let some 66*cda5da8dSAndroid Build Coastguard Worker # commands fall back on the Distribution's behaviour. None means 67*cda5da8dSAndroid Build Coastguard Worker # "not defined, check self.distribution's copy", while 0 or 1 mean 68*cda5da8dSAndroid Build Coastguard Worker # false and true (duh). Note that this means figuring out the real 69*cda5da8dSAndroid Build Coastguard Worker # value of each flag is a touch complicated -- hence "self._dry_run" 70*cda5da8dSAndroid Build Coastguard Worker # will be handled by __getattr__, below. 71*cda5da8dSAndroid Build Coastguard Worker # XXX This needs to be fixed. 72*cda5da8dSAndroid Build Coastguard Worker self._dry_run = None 73*cda5da8dSAndroid Build Coastguard Worker 74*cda5da8dSAndroid Build Coastguard Worker # verbose is largely ignored, but needs to be set for 75*cda5da8dSAndroid Build Coastguard Worker # backwards compatibility (I think)? 76*cda5da8dSAndroid Build Coastguard Worker self.verbose = dist.verbose 77*cda5da8dSAndroid Build Coastguard Worker 78*cda5da8dSAndroid Build Coastguard Worker # Some commands define a 'self.force' option to ignore file 79*cda5da8dSAndroid Build Coastguard Worker # timestamps, but methods defined *here* assume that 80*cda5da8dSAndroid Build Coastguard Worker # 'self.force' exists for all commands. So define it here 81*cda5da8dSAndroid Build Coastguard Worker # just to be safe. 82*cda5da8dSAndroid Build Coastguard Worker self.force = None 83*cda5da8dSAndroid Build Coastguard Worker 84*cda5da8dSAndroid Build Coastguard Worker # The 'help' flag is just used for command-line parsing, so 85*cda5da8dSAndroid Build Coastguard Worker # none of that complicated bureaucracy is needed. 86*cda5da8dSAndroid Build Coastguard Worker self.help = 0 87*cda5da8dSAndroid Build Coastguard Worker 88*cda5da8dSAndroid Build Coastguard Worker # 'finalized' records whether or not 'finalize_options()' has been 89*cda5da8dSAndroid Build Coastguard Worker # called. 'finalize_options()' itself should not pay attention to 90*cda5da8dSAndroid Build Coastguard Worker # this flag: it is the business of 'ensure_finalized()', which 91*cda5da8dSAndroid Build Coastguard Worker # always calls 'finalize_options()', to respect/update it. 92*cda5da8dSAndroid Build Coastguard Worker self.finalized = 0 93*cda5da8dSAndroid Build Coastguard Worker 94*cda5da8dSAndroid Build Coastguard Worker # XXX A more explicit way to customize dry_run would be better. 95*cda5da8dSAndroid Build Coastguard Worker def __getattr__(self, attr): 96*cda5da8dSAndroid Build Coastguard Worker if attr == 'dry_run': 97*cda5da8dSAndroid Build Coastguard Worker myval = getattr(self, "_" + attr) 98*cda5da8dSAndroid Build Coastguard Worker if myval is None: 99*cda5da8dSAndroid Build Coastguard Worker return getattr(self.distribution, attr) 100*cda5da8dSAndroid Build Coastguard Worker else: 101*cda5da8dSAndroid Build Coastguard Worker return myval 102*cda5da8dSAndroid Build Coastguard Worker else: 103*cda5da8dSAndroid Build Coastguard Worker raise AttributeError(attr) 104*cda5da8dSAndroid Build Coastguard Worker 105*cda5da8dSAndroid Build Coastguard Worker def ensure_finalized(self): 106*cda5da8dSAndroid Build Coastguard Worker if not self.finalized: 107*cda5da8dSAndroid Build Coastguard Worker self.finalize_options() 108*cda5da8dSAndroid Build Coastguard Worker self.finalized = 1 109*cda5da8dSAndroid Build Coastguard Worker 110*cda5da8dSAndroid Build Coastguard Worker # Subclasses must define: 111*cda5da8dSAndroid Build Coastguard Worker # initialize_options() 112*cda5da8dSAndroid Build Coastguard Worker # provide default values for all options; may be customized by 113*cda5da8dSAndroid Build Coastguard Worker # setup script, by options from config file(s), or by command-line 114*cda5da8dSAndroid Build Coastguard Worker # options 115*cda5da8dSAndroid Build Coastguard Worker # finalize_options() 116*cda5da8dSAndroid Build Coastguard Worker # decide on the final values for all options; this is called 117*cda5da8dSAndroid Build Coastguard Worker # after all possible intervention from the outside world 118*cda5da8dSAndroid Build Coastguard Worker # (command-line, option file, etc.) has been processed 119*cda5da8dSAndroid Build Coastguard Worker # run() 120*cda5da8dSAndroid Build Coastguard Worker # run the command: do whatever it is we're here to do, 121*cda5da8dSAndroid Build Coastguard Worker # controlled by the command's various option values 122*cda5da8dSAndroid Build Coastguard Worker 123*cda5da8dSAndroid Build Coastguard Worker def initialize_options(self): 124*cda5da8dSAndroid Build Coastguard Worker """Set default values for all the options that this command 125*cda5da8dSAndroid Build Coastguard Worker supports. Note that these defaults may be overridden by other 126*cda5da8dSAndroid Build Coastguard Worker commands, by the setup script, by config files, or by the 127*cda5da8dSAndroid Build Coastguard Worker command-line. Thus, this is not the place to code dependencies 128*cda5da8dSAndroid Build Coastguard Worker between options; generally, 'initialize_options()' implementations 129*cda5da8dSAndroid Build Coastguard Worker are just a bunch of "self.foo = None" assignments. 130*cda5da8dSAndroid Build Coastguard Worker 131*cda5da8dSAndroid Build Coastguard Worker This method must be implemented by all command classes. 132*cda5da8dSAndroid Build Coastguard Worker """ 133*cda5da8dSAndroid Build Coastguard Worker raise RuntimeError("abstract method -- subclass %s must override" 134*cda5da8dSAndroid Build Coastguard Worker % self.__class__) 135*cda5da8dSAndroid Build Coastguard Worker 136*cda5da8dSAndroid Build Coastguard Worker def finalize_options(self): 137*cda5da8dSAndroid Build Coastguard Worker """Set final values for all the options that this command supports. 138*cda5da8dSAndroid Build Coastguard Worker This is always called as late as possible, ie. after any option 139*cda5da8dSAndroid Build Coastguard Worker assignments from the command-line or from other commands have been 140*cda5da8dSAndroid Build Coastguard Worker done. Thus, this is the place to code option dependencies: if 141*cda5da8dSAndroid Build Coastguard Worker 'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as 142*cda5da8dSAndroid Build Coastguard Worker long as 'foo' still has the same value it was assigned in 143*cda5da8dSAndroid Build Coastguard Worker 'initialize_options()'. 144*cda5da8dSAndroid Build Coastguard Worker 145*cda5da8dSAndroid Build Coastguard Worker This method must be implemented by all command classes. 146*cda5da8dSAndroid Build Coastguard Worker """ 147*cda5da8dSAndroid Build Coastguard Worker raise RuntimeError("abstract method -- subclass %s must override" 148*cda5da8dSAndroid Build Coastguard Worker % self.__class__) 149*cda5da8dSAndroid Build Coastguard Worker 150*cda5da8dSAndroid Build Coastguard Worker 151*cda5da8dSAndroid Build Coastguard Worker def dump_options(self, header=None, indent=""): 152*cda5da8dSAndroid Build Coastguard Worker from distutils.fancy_getopt import longopt_xlate 153*cda5da8dSAndroid Build Coastguard Worker if header is None: 154*cda5da8dSAndroid Build Coastguard Worker header = "command options for '%s':" % self.get_command_name() 155*cda5da8dSAndroid Build Coastguard Worker self.announce(indent + header, level=log.INFO) 156*cda5da8dSAndroid Build Coastguard Worker indent = indent + " " 157*cda5da8dSAndroid Build Coastguard Worker for (option, _, _) in self.user_options: 158*cda5da8dSAndroid Build Coastguard Worker option = option.translate(longopt_xlate) 159*cda5da8dSAndroid Build Coastguard Worker if option[-1] == "=": 160*cda5da8dSAndroid Build Coastguard Worker option = option[:-1] 161*cda5da8dSAndroid Build Coastguard Worker value = getattr(self, option) 162*cda5da8dSAndroid Build Coastguard Worker self.announce(indent + "%s = %s" % (option, value), 163*cda5da8dSAndroid Build Coastguard Worker level=log.INFO) 164*cda5da8dSAndroid Build Coastguard Worker 165*cda5da8dSAndroid Build Coastguard Worker def run(self): 166*cda5da8dSAndroid Build Coastguard Worker """A command's raison d'etre: carry out the action it exists to 167*cda5da8dSAndroid Build Coastguard Worker perform, controlled by the options initialized in 168*cda5da8dSAndroid Build Coastguard Worker 'initialize_options()', customized by other commands, the setup 169*cda5da8dSAndroid Build Coastguard Worker script, the command-line, and config files, and finalized in 170*cda5da8dSAndroid Build Coastguard Worker 'finalize_options()'. All terminal output and filesystem 171*cda5da8dSAndroid Build Coastguard Worker interaction should be done by 'run()'. 172*cda5da8dSAndroid Build Coastguard Worker 173*cda5da8dSAndroid Build Coastguard Worker This method must be implemented by all command classes. 174*cda5da8dSAndroid Build Coastguard Worker """ 175*cda5da8dSAndroid Build Coastguard Worker raise RuntimeError("abstract method -- subclass %s must override" 176*cda5da8dSAndroid Build Coastguard Worker % self.__class__) 177*cda5da8dSAndroid Build Coastguard Worker 178*cda5da8dSAndroid Build Coastguard Worker def announce(self, msg, level=1): 179*cda5da8dSAndroid Build Coastguard Worker """If the current verbosity level is of greater than or equal to 180*cda5da8dSAndroid Build Coastguard Worker 'level' print 'msg' to stdout. 181*cda5da8dSAndroid Build Coastguard Worker """ 182*cda5da8dSAndroid Build Coastguard Worker log.log(level, msg) 183*cda5da8dSAndroid Build Coastguard Worker 184*cda5da8dSAndroid Build Coastguard Worker def debug_print(self, msg): 185*cda5da8dSAndroid Build Coastguard Worker """Print 'msg' to stdout if the global DEBUG (taken from the 186*cda5da8dSAndroid Build Coastguard Worker DISTUTILS_DEBUG environment variable) flag is true. 187*cda5da8dSAndroid Build Coastguard Worker """ 188*cda5da8dSAndroid Build Coastguard Worker from distutils.debug import DEBUG 189*cda5da8dSAndroid Build Coastguard Worker if DEBUG: 190*cda5da8dSAndroid Build Coastguard Worker print(msg) 191*cda5da8dSAndroid Build Coastguard Worker sys.stdout.flush() 192*cda5da8dSAndroid Build Coastguard Worker 193*cda5da8dSAndroid Build Coastguard Worker 194*cda5da8dSAndroid Build Coastguard Worker # -- Option validation methods ------------------------------------- 195*cda5da8dSAndroid Build Coastguard Worker # (these are very handy in writing the 'finalize_options()' method) 196*cda5da8dSAndroid Build Coastguard Worker # 197*cda5da8dSAndroid Build Coastguard Worker # NB. the general philosophy here is to ensure that a particular option 198*cda5da8dSAndroid Build Coastguard Worker # value meets certain type and value constraints. If not, we try to 199*cda5da8dSAndroid Build Coastguard Worker # force it into conformance (eg. if we expect a list but have a string, 200*cda5da8dSAndroid Build Coastguard Worker # split the string on comma and/or whitespace). If we can't force the 201*cda5da8dSAndroid Build Coastguard Worker # option into conformance, raise DistutilsOptionError. Thus, command 202*cda5da8dSAndroid Build Coastguard Worker # classes need do nothing more than (eg.) 203*cda5da8dSAndroid Build Coastguard Worker # self.ensure_string_list('foo') 204*cda5da8dSAndroid Build Coastguard Worker # and they can be guaranteed that thereafter, self.foo will be 205*cda5da8dSAndroid Build Coastguard Worker # a list of strings. 206*cda5da8dSAndroid Build Coastguard Worker 207*cda5da8dSAndroid Build Coastguard Worker def _ensure_stringlike(self, option, what, default=None): 208*cda5da8dSAndroid Build Coastguard Worker val = getattr(self, option) 209*cda5da8dSAndroid Build Coastguard Worker if val is None: 210*cda5da8dSAndroid Build Coastguard Worker setattr(self, option, default) 211*cda5da8dSAndroid Build Coastguard Worker return default 212*cda5da8dSAndroid Build Coastguard Worker elif not isinstance(val, str): 213*cda5da8dSAndroid Build Coastguard Worker raise DistutilsOptionError("'%s' must be a %s (got `%s`)" 214*cda5da8dSAndroid Build Coastguard Worker % (option, what, val)) 215*cda5da8dSAndroid Build Coastguard Worker return val 216*cda5da8dSAndroid Build Coastguard Worker 217*cda5da8dSAndroid Build Coastguard Worker def ensure_string(self, option, default=None): 218*cda5da8dSAndroid Build Coastguard Worker """Ensure that 'option' is a string; if not defined, set it to 219*cda5da8dSAndroid Build Coastguard Worker 'default'. 220*cda5da8dSAndroid Build Coastguard Worker """ 221*cda5da8dSAndroid Build Coastguard Worker self._ensure_stringlike(option, "string", default) 222*cda5da8dSAndroid Build Coastguard Worker 223*cda5da8dSAndroid Build Coastguard Worker def ensure_string_list(self, option): 224*cda5da8dSAndroid Build Coastguard Worker r"""Ensure that 'option' is a list of strings. If 'option' is 225*cda5da8dSAndroid Build Coastguard Worker currently a string, we split it either on /,\s*/ or /\s+/, so 226*cda5da8dSAndroid Build Coastguard Worker "foo bar baz", "foo,bar,baz", and "foo, bar baz" all become 227*cda5da8dSAndroid Build Coastguard Worker ["foo", "bar", "baz"]. 228*cda5da8dSAndroid Build Coastguard Worker """ 229*cda5da8dSAndroid Build Coastguard Worker val = getattr(self, option) 230*cda5da8dSAndroid Build Coastguard Worker if val is None: 231*cda5da8dSAndroid Build Coastguard Worker return 232*cda5da8dSAndroid Build Coastguard Worker elif isinstance(val, str): 233*cda5da8dSAndroid Build Coastguard Worker setattr(self, option, re.split(r',\s*|\s+', val)) 234*cda5da8dSAndroid Build Coastguard Worker else: 235*cda5da8dSAndroid Build Coastguard Worker if isinstance(val, list): 236*cda5da8dSAndroid Build Coastguard Worker ok = all(isinstance(v, str) for v in val) 237*cda5da8dSAndroid Build Coastguard Worker else: 238*cda5da8dSAndroid Build Coastguard Worker ok = False 239*cda5da8dSAndroid Build Coastguard Worker if not ok: 240*cda5da8dSAndroid Build Coastguard Worker raise DistutilsOptionError( 241*cda5da8dSAndroid Build Coastguard Worker "'%s' must be a list of strings (got %r)" 242*cda5da8dSAndroid Build Coastguard Worker % (option, val)) 243*cda5da8dSAndroid Build Coastguard Worker 244*cda5da8dSAndroid Build Coastguard Worker def _ensure_tested_string(self, option, tester, what, error_fmt, 245*cda5da8dSAndroid Build Coastguard Worker default=None): 246*cda5da8dSAndroid Build Coastguard Worker val = self._ensure_stringlike(option, what, default) 247*cda5da8dSAndroid Build Coastguard Worker if val is not None and not tester(val): 248*cda5da8dSAndroid Build Coastguard Worker raise DistutilsOptionError(("error in '%s' option: " + error_fmt) 249*cda5da8dSAndroid Build Coastguard Worker % (option, val)) 250*cda5da8dSAndroid Build Coastguard Worker 251*cda5da8dSAndroid Build Coastguard Worker def ensure_filename(self, option): 252*cda5da8dSAndroid Build Coastguard Worker """Ensure that 'option' is the name of an existing file.""" 253*cda5da8dSAndroid Build Coastguard Worker self._ensure_tested_string(option, os.path.isfile, 254*cda5da8dSAndroid Build Coastguard Worker "filename", 255*cda5da8dSAndroid Build Coastguard Worker "'%s' does not exist or is not a file") 256*cda5da8dSAndroid Build Coastguard Worker 257*cda5da8dSAndroid Build Coastguard Worker def ensure_dirname(self, option): 258*cda5da8dSAndroid Build Coastguard Worker self._ensure_tested_string(option, os.path.isdir, 259*cda5da8dSAndroid Build Coastguard Worker "directory name", 260*cda5da8dSAndroid Build Coastguard Worker "'%s' does not exist or is not a directory") 261*cda5da8dSAndroid Build Coastguard Worker 262*cda5da8dSAndroid Build Coastguard Worker 263*cda5da8dSAndroid Build Coastguard Worker # -- Convenience methods for commands ------------------------------ 264*cda5da8dSAndroid Build Coastguard Worker 265*cda5da8dSAndroid Build Coastguard Worker def get_command_name(self): 266*cda5da8dSAndroid Build Coastguard Worker if hasattr(self, 'command_name'): 267*cda5da8dSAndroid Build Coastguard Worker return self.command_name 268*cda5da8dSAndroid Build Coastguard Worker else: 269*cda5da8dSAndroid Build Coastguard Worker return self.__class__.__name__ 270*cda5da8dSAndroid Build Coastguard Worker 271*cda5da8dSAndroid Build Coastguard Worker def set_undefined_options(self, src_cmd, *option_pairs): 272*cda5da8dSAndroid Build Coastguard Worker """Set the values of any "undefined" options from corresponding 273*cda5da8dSAndroid Build Coastguard Worker option values in some other command object. "Undefined" here means 274*cda5da8dSAndroid Build Coastguard Worker "is None", which is the convention used to indicate that an option 275*cda5da8dSAndroid Build Coastguard Worker has not been changed between 'initialize_options()' and 276*cda5da8dSAndroid Build Coastguard Worker 'finalize_options()'. Usually called from 'finalize_options()' for 277*cda5da8dSAndroid Build Coastguard Worker options that depend on some other command rather than another 278*cda5da8dSAndroid Build Coastguard Worker option of the same command. 'src_cmd' is the other command from 279*cda5da8dSAndroid Build Coastguard Worker which option values will be taken (a command object will be created 280*cda5da8dSAndroid Build Coastguard Worker for it if necessary); the remaining arguments are 281*cda5da8dSAndroid Build Coastguard Worker '(src_option,dst_option)' tuples which mean "take the value of 282*cda5da8dSAndroid Build Coastguard Worker 'src_option' in the 'src_cmd' command object, and copy it to 283*cda5da8dSAndroid Build Coastguard Worker 'dst_option' in the current command object". 284*cda5da8dSAndroid Build Coastguard Worker """ 285*cda5da8dSAndroid Build Coastguard Worker # Option_pairs: list of (src_option, dst_option) tuples 286*cda5da8dSAndroid Build Coastguard Worker src_cmd_obj = self.distribution.get_command_obj(src_cmd) 287*cda5da8dSAndroid Build Coastguard Worker src_cmd_obj.ensure_finalized() 288*cda5da8dSAndroid Build Coastguard Worker for (src_option, dst_option) in option_pairs: 289*cda5da8dSAndroid Build Coastguard Worker if getattr(self, dst_option) is None: 290*cda5da8dSAndroid Build Coastguard Worker setattr(self, dst_option, getattr(src_cmd_obj, src_option)) 291*cda5da8dSAndroid Build Coastguard Worker 292*cda5da8dSAndroid Build Coastguard Worker def get_finalized_command(self, command, create=1): 293*cda5da8dSAndroid Build Coastguard Worker """Wrapper around Distribution's 'get_command_obj()' method: find 294*cda5da8dSAndroid Build Coastguard Worker (create if necessary and 'create' is true) the command object for 295*cda5da8dSAndroid Build Coastguard Worker 'command', call its 'ensure_finalized()' method, and return the 296*cda5da8dSAndroid Build Coastguard Worker finalized command object. 297*cda5da8dSAndroid Build Coastguard Worker """ 298*cda5da8dSAndroid Build Coastguard Worker cmd_obj = self.distribution.get_command_obj(command, create) 299*cda5da8dSAndroid Build Coastguard Worker cmd_obj.ensure_finalized() 300*cda5da8dSAndroid Build Coastguard Worker return cmd_obj 301*cda5da8dSAndroid Build Coastguard Worker 302*cda5da8dSAndroid Build Coastguard Worker # XXX rename to 'get_reinitialized_command()'? (should do the 303*cda5da8dSAndroid Build Coastguard Worker # same in dist.py, if so) 304*cda5da8dSAndroid Build Coastguard Worker def reinitialize_command(self, command, reinit_subcommands=0): 305*cda5da8dSAndroid Build Coastguard Worker return self.distribution.reinitialize_command(command, 306*cda5da8dSAndroid Build Coastguard Worker reinit_subcommands) 307*cda5da8dSAndroid Build Coastguard Worker 308*cda5da8dSAndroid Build Coastguard Worker def run_command(self, command): 309*cda5da8dSAndroid Build Coastguard Worker """Run some other command: uses the 'run_command()' method of 310*cda5da8dSAndroid Build Coastguard Worker Distribution, which creates and finalizes the command object if 311*cda5da8dSAndroid Build Coastguard Worker necessary and then invokes its 'run()' method. 312*cda5da8dSAndroid Build Coastguard Worker """ 313*cda5da8dSAndroid Build Coastguard Worker self.distribution.run_command(command) 314*cda5da8dSAndroid Build Coastguard Worker 315*cda5da8dSAndroid Build Coastguard Worker def get_sub_commands(self): 316*cda5da8dSAndroid Build Coastguard Worker """Determine the sub-commands that are relevant in the current 317*cda5da8dSAndroid Build Coastguard Worker distribution (ie., that need to be run). This is based on the 318*cda5da8dSAndroid Build Coastguard Worker 'sub_commands' class attribute: each tuple in that list may include 319*cda5da8dSAndroid Build Coastguard Worker a method that we call to determine if the subcommand needs to be 320*cda5da8dSAndroid Build Coastguard Worker run for the current distribution. Return a list of command names. 321*cda5da8dSAndroid Build Coastguard Worker """ 322*cda5da8dSAndroid Build Coastguard Worker commands = [] 323*cda5da8dSAndroid Build Coastguard Worker for (cmd_name, method) in self.sub_commands: 324*cda5da8dSAndroid Build Coastguard Worker if method is None or method(self): 325*cda5da8dSAndroid Build Coastguard Worker commands.append(cmd_name) 326*cda5da8dSAndroid Build Coastguard Worker return commands 327*cda5da8dSAndroid Build Coastguard Worker 328*cda5da8dSAndroid Build Coastguard Worker 329*cda5da8dSAndroid Build Coastguard Worker # -- External world manipulation ----------------------------------- 330*cda5da8dSAndroid Build Coastguard Worker 331*cda5da8dSAndroid Build Coastguard Worker def warn(self, msg): 332*cda5da8dSAndroid Build Coastguard Worker log.warn("warning: %s: %s\n", self.get_command_name(), msg) 333*cda5da8dSAndroid Build Coastguard Worker 334*cda5da8dSAndroid Build Coastguard Worker def execute(self, func, args, msg=None, level=1): 335*cda5da8dSAndroid Build Coastguard Worker util.execute(func, args, msg, dry_run=self.dry_run) 336*cda5da8dSAndroid Build Coastguard Worker 337*cda5da8dSAndroid Build Coastguard Worker def mkpath(self, name, mode=0o777): 338*cda5da8dSAndroid Build Coastguard Worker dir_util.mkpath(name, mode, dry_run=self.dry_run) 339*cda5da8dSAndroid Build Coastguard Worker 340*cda5da8dSAndroid Build Coastguard Worker def copy_file(self, infile, outfile, preserve_mode=1, preserve_times=1, 341*cda5da8dSAndroid Build Coastguard Worker link=None, level=1): 342*cda5da8dSAndroid Build Coastguard Worker """Copy a file respecting verbose, dry-run and force flags. (The 343*cda5da8dSAndroid Build Coastguard Worker former two default to whatever is in the Distribution object, and 344*cda5da8dSAndroid Build Coastguard Worker the latter defaults to false for commands that don't define it.)""" 345*cda5da8dSAndroid Build Coastguard Worker return file_util.copy_file(infile, outfile, preserve_mode, 346*cda5da8dSAndroid Build Coastguard Worker preserve_times, not self.force, link, 347*cda5da8dSAndroid Build Coastguard Worker dry_run=self.dry_run) 348*cda5da8dSAndroid Build Coastguard Worker 349*cda5da8dSAndroid Build Coastguard Worker def copy_tree(self, infile, outfile, preserve_mode=1, preserve_times=1, 350*cda5da8dSAndroid Build Coastguard Worker preserve_symlinks=0, level=1): 351*cda5da8dSAndroid Build Coastguard Worker """Copy an entire directory tree respecting verbose, dry-run, 352*cda5da8dSAndroid Build Coastguard Worker and force flags. 353*cda5da8dSAndroid Build Coastguard Worker """ 354*cda5da8dSAndroid Build Coastguard Worker return dir_util.copy_tree(infile, outfile, preserve_mode, 355*cda5da8dSAndroid Build Coastguard Worker preserve_times, preserve_symlinks, 356*cda5da8dSAndroid Build Coastguard Worker not self.force, dry_run=self.dry_run) 357*cda5da8dSAndroid Build Coastguard Worker 358*cda5da8dSAndroid Build Coastguard Worker def move_file (self, src, dst, level=1): 359*cda5da8dSAndroid Build Coastguard Worker """Move a file respecting dry-run flag.""" 360*cda5da8dSAndroid Build Coastguard Worker return file_util.move_file(src, dst, dry_run=self.dry_run) 361*cda5da8dSAndroid Build Coastguard Worker 362*cda5da8dSAndroid Build Coastguard Worker def spawn(self, cmd, search_path=1, level=1): 363*cda5da8dSAndroid Build Coastguard Worker """Spawn an external command respecting dry-run flag.""" 364*cda5da8dSAndroid Build Coastguard Worker from distutils.spawn import spawn 365*cda5da8dSAndroid Build Coastguard Worker spawn(cmd, search_path, dry_run=self.dry_run) 366*cda5da8dSAndroid Build Coastguard Worker 367*cda5da8dSAndroid Build Coastguard Worker def make_archive(self, base_name, format, root_dir=None, base_dir=None, 368*cda5da8dSAndroid Build Coastguard Worker owner=None, group=None): 369*cda5da8dSAndroid Build Coastguard Worker return archive_util.make_archive(base_name, format, root_dir, base_dir, 370*cda5da8dSAndroid Build Coastguard Worker dry_run=self.dry_run, 371*cda5da8dSAndroid Build Coastguard Worker owner=owner, group=group) 372*cda5da8dSAndroid Build Coastguard Worker 373*cda5da8dSAndroid Build Coastguard Worker def make_file(self, infiles, outfile, func, args, 374*cda5da8dSAndroid Build Coastguard Worker exec_msg=None, skip_msg=None, level=1): 375*cda5da8dSAndroid Build Coastguard Worker """Special case of 'execute()' for operations that process one or 376*cda5da8dSAndroid Build Coastguard Worker more input files and generate one output file. Works just like 377*cda5da8dSAndroid Build Coastguard Worker 'execute()', except the operation is skipped and a different 378*cda5da8dSAndroid Build Coastguard Worker message printed if 'outfile' already exists and is newer than all 379*cda5da8dSAndroid Build Coastguard Worker files listed in 'infiles'. If the command defined 'self.force', 380*cda5da8dSAndroid Build Coastguard Worker and it is true, then the command is unconditionally run -- does no 381*cda5da8dSAndroid Build Coastguard Worker timestamp checks. 382*cda5da8dSAndroid Build Coastguard Worker """ 383*cda5da8dSAndroid Build Coastguard Worker if skip_msg is None: 384*cda5da8dSAndroid Build Coastguard Worker skip_msg = "skipping %s (inputs unchanged)" % outfile 385*cda5da8dSAndroid Build Coastguard Worker 386*cda5da8dSAndroid Build Coastguard Worker # Allow 'infiles' to be a single string 387*cda5da8dSAndroid Build Coastguard Worker if isinstance(infiles, str): 388*cda5da8dSAndroid Build Coastguard Worker infiles = (infiles,) 389*cda5da8dSAndroid Build Coastguard Worker elif not isinstance(infiles, (list, tuple)): 390*cda5da8dSAndroid Build Coastguard Worker raise TypeError( 391*cda5da8dSAndroid Build Coastguard Worker "'infiles' must be a string, or a list or tuple of strings") 392*cda5da8dSAndroid Build Coastguard Worker 393*cda5da8dSAndroid Build Coastguard Worker if exec_msg is None: 394*cda5da8dSAndroid Build Coastguard Worker exec_msg = "generating %s from %s" % (outfile, ', '.join(infiles)) 395*cda5da8dSAndroid Build Coastguard Worker 396*cda5da8dSAndroid Build Coastguard Worker # If 'outfile' must be regenerated (either because it doesn't 397*cda5da8dSAndroid Build Coastguard Worker # exist, is out-of-date, or the 'force' flag is true) then 398*cda5da8dSAndroid Build Coastguard Worker # perform the action that presumably regenerates it 399*cda5da8dSAndroid Build Coastguard Worker if self.force or dep_util.newer_group(infiles, outfile): 400*cda5da8dSAndroid Build Coastguard Worker self.execute(func, args, exec_msg, level) 401*cda5da8dSAndroid Build Coastguard Worker # Otherwise, print the "skip" message 402*cda5da8dSAndroid Build Coastguard Worker else: 403*cda5da8dSAndroid Build Coastguard Worker log.debug(skip_msg) 404