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
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
#
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:
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)