17db96d56Sopenharmony_ci"""distutils.dep_util 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciUtility functions for simple, timestamp-based dependency of files 47db96d56Sopenharmony_ciand groups of files; also, function based entirely on such 57db96d56Sopenharmony_citimestamp dependency analysis.""" 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ciimport os 87db96d56Sopenharmony_cifrom distutils.errors import DistutilsFileError 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci 117db96d56Sopenharmony_cidef newer (source, target): 127db96d56Sopenharmony_ci """Return true if 'source' exists and is more recently modified than 137db96d56Sopenharmony_ci 'target', or if 'source' exists and 'target' doesn't. Return false if 147db96d56Sopenharmony_ci both exist and 'target' is the same age or younger than 'source'. 157db96d56Sopenharmony_ci Raise DistutilsFileError if 'source' does not exist. 167db96d56Sopenharmony_ci """ 177db96d56Sopenharmony_ci if not os.path.exists(source): 187db96d56Sopenharmony_ci raise DistutilsFileError("file '%s' does not exist" % 197db96d56Sopenharmony_ci os.path.abspath(source)) 207db96d56Sopenharmony_ci if not os.path.exists(target): 217db96d56Sopenharmony_ci return 1 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_ci from stat import ST_MTIME 247db96d56Sopenharmony_ci mtime1 = os.stat(source)[ST_MTIME] 257db96d56Sopenharmony_ci mtime2 = os.stat(target)[ST_MTIME] 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ci return mtime1 > mtime2 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_ci# newer () 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_cidef newer_pairwise (sources, targets): 337db96d56Sopenharmony_ci """Walk two filename lists in parallel, testing if each source is newer 347db96d56Sopenharmony_ci than its corresponding target. Return a pair of lists (sources, 357db96d56Sopenharmony_ci targets) where source is newer than target, according to the semantics 367db96d56Sopenharmony_ci of 'newer()'. 377db96d56Sopenharmony_ci """ 387db96d56Sopenharmony_ci if len(sources) != len(targets): 397db96d56Sopenharmony_ci raise ValueError("'sources' and 'targets' must be same length") 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_ci # build a pair of lists (sources, targets) where source is newer 427db96d56Sopenharmony_ci n_sources = [] 437db96d56Sopenharmony_ci n_targets = [] 447db96d56Sopenharmony_ci for i in range(len(sources)): 457db96d56Sopenharmony_ci if newer(sources[i], targets[i]): 467db96d56Sopenharmony_ci n_sources.append(sources[i]) 477db96d56Sopenharmony_ci n_targets.append(targets[i]) 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ci return (n_sources, n_targets) 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_ci# newer_pairwise () 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_cidef newer_group (sources, target, missing='error'): 557db96d56Sopenharmony_ci """Return true if 'target' is out-of-date with respect to any file 567db96d56Sopenharmony_ci listed in 'sources'. In other words, if 'target' exists and is newer 577db96d56Sopenharmony_ci than every file in 'sources', return false; otherwise return true. 587db96d56Sopenharmony_ci 'missing' controls what we do when a source file is missing; the 597db96d56Sopenharmony_ci default ("error") is to blow up with an OSError from inside 'stat()'; 607db96d56Sopenharmony_ci if it is "ignore", we silently drop any missing source files; if it is 617db96d56Sopenharmony_ci "newer", any missing source files make us assume that 'target' is 627db96d56Sopenharmony_ci out-of-date (this is handy in "dry-run" mode: it'll make you pretend to 637db96d56Sopenharmony_ci carry out commands that wouldn't work because inputs are missing, but 647db96d56Sopenharmony_ci that doesn't matter because you're not actually going to run the 657db96d56Sopenharmony_ci commands). 667db96d56Sopenharmony_ci """ 677db96d56Sopenharmony_ci # If the target doesn't even exist, then it's definitely out-of-date. 687db96d56Sopenharmony_ci if not os.path.exists(target): 697db96d56Sopenharmony_ci return 1 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ci # Otherwise we have to find out the hard way: if *any* source file 727db96d56Sopenharmony_ci # is more recent than 'target', then 'target' is out-of-date and 737db96d56Sopenharmony_ci # we can immediately return true. If we fall through to the end 747db96d56Sopenharmony_ci # of the loop, then 'target' is up-to-date and we return false. 757db96d56Sopenharmony_ci from stat import ST_MTIME 767db96d56Sopenharmony_ci target_mtime = os.stat(target)[ST_MTIME] 777db96d56Sopenharmony_ci for source in sources: 787db96d56Sopenharmony_ci if not os.path.exists(source): 797db96d56Sopenharmony_ci if missing == 'error': # blow up when we stat() the file 807db96d56Sopenharmony_ci pass 817db96d56Sopenharmony_ci elif missing == 'ignore': # missing source dropped from 827db96d56Sopenharmony_ci continue # target's dependency list 837db96d56Sopenharmony_ci elif missing == 'newer': # missing source means target is 847db96d56Sopenharmony_ci return 1 # out-of-date 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci source_mtime = os.stat(source)[ST_MTIME] 877db96d56Sopenharmony_ci if source_mtime > target_mtime: 887db96d56Sopenharmony_ci return 1 897db96d56Sopenharmony_ci else: 907db96d56Sopenharmony_ci return 0 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ci# newer_group () 93