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