diff options
| -rwxr-xr-x | cdist | 95 | ||||
| -rw-r--r-- | test.py | 10 |
2 files changed, 95 insertions, 10 deletions
@@ -49,14 +49,11 @@ class Trees: def get(self, name, specifier, target): for t in self.trees: - if t.name == name and t.specifier == specifier and t.target == target: + if t.name == name and t.target == target: return t - elif t.name == name and t.specifier != specifier: - raise Error('conflicting versions of %s requested (%s and %s)' % (name, specifier, t.specifier)) - nt = Tree(name, specifier, target) + def add(nt): self.trees.append(nt) - return nt class Globals: quiet = False @@ -569,6 +566,70 @@ def target_factory(s, debug, work): return target +class Specifier: + """Helper class for union()""" + def __init__(self, s): + self.revision = None + self.branch = None + self.at_least = False + + if len(s) == 7: + self.revision = s + elif len(s) == 8 and s[-1] == '+': + self.revision = s[:7] + self.at_least = True + else: + self.branch = s + + def specific_revision(self): + return self.revision is not None and self.at_least == False + + def __str__(self): + s = '' + if self.revision is not None: + s = self.revision + else: + s = self.branch + if self.at_least: + s += '+' + return s + +def union(a, b, tree): + """Take two specifiers and return one which satisfies both""" + + # One or other is None -> the other one wins + if a is None: + return b + if b is None: + return a + + a = Specifier(a) + b = Specifier(b) + + # Two specific revisions + if a.specific_revision() and b.specific_revision(): + if a.revision == b.revision: + return a.revision + else: + raise 'Incompatible specifiers %s and %s for %s' % (a, b, tree.name) + + # Two different branches + if a.branch is not None and b.branch is not None: + if a.branch == b.branch: + return a.branch + else: + raise 'Incompatible specifiers %s and %s for %s' % (a, b, tree.name) + + if a.revision is not None and a.at_least and b.revision is not None and b.at_least: + # Two 'at-least' revisions; check that they are on the same branch + # and pick the most recent + with TreeDirectory(tree): + a_branches = command_and_read('git branch --contains %s' % a.revision).readlines() + b_branches = command_and_read('git branch --contains %s' % b.revision).readlines() + + + + # # Tree # @@ -628,6 +689,19 @@ class Tree(object): with TreeDirectory(self): return self.cscript[function](self.target, *args) + def calculate_dependencies(self): + if 'dependencies' in self.cscript: + for d in self.cscript['dependencies'](self.target): + # Get any existing Tree + dep = globals.trees.get(d[0], self.target) + if dep is None: + # No existing tree; make one + globals.trees.add(Tree(d[0], d[1], self.target)) + else: + # Check that this specifier and the existing one are compatible, + # updating the existing one if required + dep.specifier = union(dep.specifier, d[1], d[0]) + def build(self, options={}): # Build any dependencies if 'dependencies' in self.cscript: @@ -950,8 +1024,9 @@ def main(): else: raise Error('invalid command %s' % globals.command) -try: - main() -except Error as e: - print >>sys.stderr,'cdist: %s' % str(e) - sys.exit(1) +if __name__ == '__main__': + try: + main() + except Error as e: + print >>sys.stderr,'cdist: %s' % str(e) + sys.exit(1) @@ -0,0 +1,10 @@ +import imp +import sys + +cdist = imp.load_source("cdist", "cdist") + +target = cdist.SourceTarget() +tree = cdist.Tree('dcpomatic', 'master', target) + +assert(cdist.union(None, None, tree) is None) +print cdist.union('master', 'master', tree) |
