Partial work on deps. better-deps
authorCarl Hetherington <cth@carlh.net>
Tue, 8 Dec 2015 18:12:15 +0000 (18:12 +0000)
committerCarl Hetherington <cth@carlh.net>
Tue, 8 Dec 2015 18:12:15 +0000 (18:12 +0000)
cdist
test.py [new file with mode: 0644]

diff --git a/cdist b/cdist
index d0576e9a9a3af54c89c0558eea6d9e98bf3b2cbb..b56a8db556ff8fc1b403ee7ca598e299bbc3575f 100755 (executable)
--- a/cdist
+++ b/cdist
@@ -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)
diff --git a/test.py b/test.py
new file mode 100644 (file)
index 0000000..5ad5b47
--- /dev/null
+++ b/test.py
@@ -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)