+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()
+
+
+
+