harfbuzz: Update from 1.0.6 to 1.1.2
[termux-packages] / buildorder.py
index bb248a9..fa02f7a 100755 (executable)
@@ -4,13 +4,31 @@
 import os
 import sys
 
+from itertools import filterfalse
 
-def die(msg):
-    sys.exit('ERROR: ' + msg)
+
+# https://docs.python.org/3/library/itertools.html#itertools-recipes
+
+def unique_everseen(iterable, key=None):
+    "List unique elements, preserving order. Remember all elements ever seen."
+    # unique_everseen('AAAABBBCCDAABBB') --> A B C D
+    # unique_everseen('ABBCcAD', str.lower) --> A B C D
+    seen = set()
+    seen_add = seen.add
+    if key is None:
+        for element in filterfalse(seen.__contains__, iterable):
+            seen_add(element)
+            yield element
+    else:
+        for element in iterable:
+            k = key(element)
+            if k not in seen:
+                seen_add(k)
+                yield element
 
 
-if len(sys.argv) != 1:
-    die('buildorder.py takes no arguments')
+def die(msg):
+    sys.exit('ERROR: ' + msg)
 
 
 class TermuxBuildFile(object):
@@ -136,7 +154,9 @@ def populate():
             dep_pkg.needed_by.add(pkg)
 
 
-def buildorder():
+def generate_full_buildorder():
+    build_order = []
+
     # List of all TermuxPackages without dependencies
     leaf_pkgs = [pkg for name, pkg in pkgs_map.items() if not pkg.deps]
 
@@ -148,36 +168,27 @@ def buildorder():
     pkg_queue = sorted(leaf_pkgs, key=lambda p: '' if p.name == 'libandroid-support' else p.name)
 
     # Topological sorting
-    build_order = []
     visited = set()
 
     while pkg_queue:
         pkg = pkg_queue.pop(0)
         if pkg.name in visited:
             continue
-        visited.add(pkg.name)
 
         # print("Processing {}:".format(pkg.name), pkg.needed_by)
-
+        visited.add(pkg.name)
         build_order.append(pkg)
 
         for other_pkg in sorted(pkg.needed_by, key=lambda p: p.name):
-            # Mark this package as done
+            # Remove this pkg from deps
             remaining_deps[other_pkg.name].discard(pkg.name)
-
             # ... and all its subpackages
             remaining_deps[other_pkg.name].difference_update(
                 [subpkg.name for subpkg in pkg.subpkgs]
             )
 
-            if not remaining_deps[other_pkg.name]:  # all deps were pruned?
-                pkg_queue.append(other_pkg)
-
-    return build_order
-
-
-def generate_and_print_buildorder():
-    build_order = buildorder()
+            if not remaining_deps[other_pkg.name]:  # all deps were already appended?
+                pkg_queue.append(other_pkg)  # should be processed
 
     if set(pkgs_map.values()) != set(build_order):
         print("ERROR: Cycle exists. Remaining: ")
@@ -187,11 +198,34 @@ def generate_and_print_buildorder():
 
         sys.exit(1)
 
-    for pkg in build_order:
-        print(pkg.name)
+    return build_order
+
+
+def deps_then_me(pkg):
+    l = []
+
+    for dep in sorted(pkg.deps):
+        l += deps_then_me(pkgs_map[dep])
+    l += [pkg]
 
-    sys.exit(0)
+    return l
+
+
+def generate_targets_buildorder(targetnames):
+    buildorder = []
+
+    for pkgname in targetnames:
+        buildorder += deps_then_me(pkgs_map[pkgname])
+
+    return unique_everseen(buildorder)
 
 if __name__ == '__main__':
     populate()
-    generate_and_print_buildorder()
+
+    if len(sys.argv) == 1:
+        bo = generate_full_buildorder()
+    else:
+        bo = generate_targets_buildorder(sys.argv[1:])
+
+    for pkg in bo:
+        print(pkg.name)