diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CHANGES.txt | 5 | ||||
-rw-r--r-- | src/engine/SCons/Node/FS.py | 116 | ||||
-rw-r--r-- | src/engine/SCons/Script/Main.py | 44 |
3 files changed, 133 insertions, 32 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt index d246dae..6a3e259 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -296,6 +296,11 @@ RELEASE 0.97 - XXX - Remove support for conversion from old (pre 0.96) .sconsign formats. + - Add support for a --diskcheck option to enable or disable various + on-disk checks: that File and Dir nodes match on-disk entries; + whether an RCS file exists for a missing source file; whether an + SCCS file exists for a missing source file. + From Wayne Lee: - Avoid "maximum recursion limit" errors when removing $(-$) pairs diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 3b4e77f..a1cadf0 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -288,6 +288,65 @@ else: def _my_normcase(x): return string.upper(x) + + +class DiskChecker: + def __init__(self, type, do, ignore): + self.type = type + self.do = do + self.ignore = ignore + self.set_do() + def set_do(self): + self.__call__ = self.do + def set_ignore(self): + self.__call__ = self.ignore + def set(self, list): + if self.type in list: + self.set_do() + else: + self.set_ignore() + +def do_diskcheck_match(node, predicate, errorfmt): + path = node.abspath + if predicate(path): + raise TypeError, errorfmt % path + +def ignore_diskcheck_match(node, predicate, errorfmt): + pass + +def do_diskcheck_rcs(node, name): + rcspath = 'RCS' + os.sep + name+',v' + return node.entry_exists_on_disk(rcspath) + +def ignore_diskcheck_rcs(node, name): + return None + +def do_diskcheck_sccs(node, name): + sccspath = 'SCCS' + os.sep + 's.'+name + return node.entry_exists_on_disk(sccspath) + +def ignore_diskcheck_sccs(node, name): + return None + +diskcheck_match = DiskChecker('match', do_diskcheck_match, ignore_diskcheck_match) +diskcheck_rcs = DiskChecker('rcs', do_diskcheck_rcs, ignore_diskcheck_rcs) +diskcheck_sccs = DiskChecker('sccs', do_diskcheck_sccs, ignore_diskcheck_sccs) + +diskcheckers = [ + diskcheck_match, + diskcheck_rcs, + diskcheck_sccs, +] + +def set_diskcheck(list): + for dc in diskcheckers: + dc.set(list) + +def diskcheck_types(): + return map(lambda dc: dc.type, diskcheckers) + + + class EntryProxy(SCons.Util.Proxy): def __get_abspath(self): entry = self.get() @@ -597,6 +656,9 @@ class Entry(Base): time comes, and then call the same-named method in the transformed class.""" + def diskcheck_match(self): + pass + def disambiguate(self): if self.isdir(): self.__class__ = Dir @@ -852,14 +914,12 @@ class FS(LocalFS): if not create: raise SCons.Errors.UserError - # look at the actual filesystem and make sure there isn't - # a file already there - path = directory.entry_abspath(orig) - if self.isfile(path): - raise TypeError, \ - "File %s found where directory expected." % path - d = Dir(orig, directory, self) + + # Check the file system (or not, as configured) to make + # sure there isn't already a file there. + d.diskcheck_match() + directory.entries[norm] = d directory.add_wkid(d) directory = d @@ -878,19 +938,13 @@ class FS(LocalFS): if not create: raise SCons.Errors.UserError - # make sure we don't create File nodes when there is actually - # a directory at that path on the disk, and vice versa - path = directory.entry_abspath(last_orig) - if fsclass == File: - if self.isdir(path): - raise TypeError, \ - "Directory %s found where file expected." % path - elif fsclass == Dir: - if self.isfile(path): - raise TypeError, \ - "File %s found where directory expected." % path - result = fsclass(last_orig, directory, self) + + # Check the file system (or not, as configured) to make + # sure there isn't already a directory at the path on + # disk where we just created a File node, and vice versa. + result.diskcheck_match() + directory.entries[last_norm] = result directory.add_wkid(result) else: @@ -1080,6 +1134,10 @@ class Dir(Base): self.builder = get_MkdirBuilder() self.get_executor().set_action_list(self.builder.action) + def diskcheck_match(self): + diskcheck_match(self, self.fs.isfile, + "File %s found where directory expected.") + def disambiguate(self): return self @@ -1342,14 +1400,6 @@ class Dir(Base): """__cacheable__""" return self.fs.exists(self.entry_abspath(name)) - def rcs_on_disk(self, name): - rcspath = 'RCS' + os.sep + name+',v' - return self.entry_exists_on_disk(rcspath) - - def sccs_on_disk(self, name): - sccspath = 'SCCS' + os.sep + 's.'+name - return self.entry_exists_on_disk(sccspath) - def srcdir_list(self): """__cacheable__""" result = [] @@ -1417,8 +1467,8 @@ class Dir(Base): def file_on_disk(self, name): if self.entry_exists_on_disk(name) or \ - self.sccs_on_disk(name) or \ - self.rcs_on_disk(name): + diskcheck_rcs(self, name) or \ + diskcheck_sccs(self, name): try: return self.File(name) except TypeError: pass return self.srcdir_duplicate(name) @@ -1532,6 +1582,10 @@ class BuildInfo(SCons.Node.BuildInfo): class File(Base): """A class for files in a file system. """ + def diskcheck_match(self): + diskcheck_match(self, self.fs.isdir, + "Directory %s found where file expected.") + def __init__(self, name, directory, fs): if __debug__: logInstanceCreation(self, 'Node.FS.File') Base.__init__(self, name, directory, fs) @@ -1703,9 +1757,9 @@ class File(Base): else: scb = self.dir.src_builder() if scb is _null: - if self.dir.sccs_on_disk(self.name): + if diskcheck_sccs(self.dir, self.name): scb = get_DefaultSCCSBuilder() - elif self.dir.rcs_on_disk(self.name): + elif diskcheck_rcs(self.dir, self.name): scb = get_DefaultRCSBuilder() else: scb = None diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index d5be3eb..a6b4f88 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -258,6 +258,26 @@ exit_status = 0 # exit status, assume success by default repositories = [] num_jobs = 1 # this is modifed by SConscript.SetJobs() +diskcheck_all = SCons.Node.FS.diskcheck_types() +diskcheck_option_set = None + +def diskcheck_convert(value): + if value is None: + return [] + if not SCons.Util.is_List(value): + value = string.split(value, ',') + result = [] + for v in map(string.lower, value): + if v == 'all': + result = diskcheck_all + elif v == 'none': + result = [] + elif v in diskcheck_all: + result.append(v) + else: + raise ValueError, v + return result + # class Stats: def __init__(self): @@ -613,6 +633,20 @@ class OptParser(OptionParser): help="Print various types of debugging information: " "%s." % string.join(debug_options, ", ")) + def opt_diskcheck(option, opt, value, parser): + try: + global diskcheck_option_set + diskcheck_option_set = diskcheck_convert(value) + SCons.Node.FS.set_diskcheck(diskcheck_option_set) + except ValueError, e: + raise OptionValueError("Warning: `%s' is not a valid diskcheck type" % e) + + + self.add_option('--diskcheck', action="callback", type="string", + callback=opt_diskcheck, dest='diskcheck', + metavar="TYPE", + help="Enable specific on-disk checks.") + def opt_duplicate(option, opt, value, parser): if not value in SCons.Node.FS.Valid_Duplicates: raise OptionValueError("`%s' is not a valid duplication style." % value) @@ -799,7 +833,8 @@ class SConscriptSettableOptions: 'max_drift':SCons.Sig.default_max_drift, 'implicit_cache':0, 'clean':0, - 'duplicate':'hard-soft-copy'} + 'duplicate':'hard-soft-copy', + 'diskcheck':diskcheck_all} def get(self, name): if not self.settable.has_key(name): @@ -835,6 +870,13 @@ class SConscriptSettableOptions: # Set the duplicate stye right away so it can affect linking # of SConscript files. SCons.Node.FS.set_duplicate(value) + elif name == 'diskcheck': + try: + value = diskcheck_convert(value) + except ValueError, v: + raise SCons.Errors.UserError, "Not a valid diskcheck value: %s"%v + if not diskcheck_option_set: + SCons.Node.FS.set_diskcheck(value) self.settable[name] = value |