release.py: order symbols list, preserve old symbols
authorMathieu Duponchelle <mathieu@centricular.com>
Thu, 2 Jul 2020 13:41:25 +0000 (15:41 +0200)
committerMathieu Duponchelle <mathieu@centricular.com>
Thu, 2 Jul 2020 13:41:25 +0000 (15:41 +0200)
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-docs/-/merge_requests/100>

scripts/release.py

index ca13ebb..d963244 100644 (file)
@@ -5,6 +5,89 @@ import shutil
 import sys
 import tarfile
 
+from collections.abc import MutableSet
+import json
+
+
+# Recipe from http://code.activestate.com/recipes/576694/
+
+
+class OrderedSet(MutableSet):
+    def __init__(self, iterable=None):
+        self.end = end = []
+        end += [None, end, end]         # sentinel node for doubly linked list
+        self.map = {}                   # key --> [key, prev, next]
+        if iterable is not None:
+            self |= iterable
+
+    def __len__(self):
+        return len(self.map)
+
+    def __contains__(self, key):
+        return key in self.map
+
+    # pylint: disable=arguments-differ
+    def add(self, key):
+        if key not in self.map:
+            end = self.end
+            curr = end[1]
+            curr[2] = end[1] = self.map[key] = [key, curr, end]
+
+    def __getstate__(self):
+        if not self:
+            # The state can't be an empty list.
+            # We need to return a truthy value, or else
+            # __setstate__ won't be run.
+            #
+            # This could have been done more gracefully by always putting
+            # the state in a tuple, but this way is backwards- and forwards-
+            # compatible with previous versions of OrderedSet.
+            return (None,)
+        return list(self)
+
+    def __setstate__(self, state):
+        if state == (None,):
+            self.__init__([])
+        else:
+            self.__init__(state)
+
+    def discard(self, key):
+        if key in self.map:
+            key, prev, nxt = self.map.pop(key)
+            prev[2] = nxt
+            nxt[1] = prev
+
+    def __iter__(self):
+        end = self.end
+        curr = end[2]
+        while curr is not end:
+            yield curr[0]
+            curr = curr[2]
+
+    def __reversed__(self):
+        end = self.end
+        curr = end[1]
+        while curr is not end:
+            yield curr[0]
+            curr = curr[1]
+
+    def pop(self, last=True):
+        if not self:
+            raise KeyError('set is empty')
+        key = self.end[1][0] if last else self.end[2][0]
+        self.discard(key)
+        return key
+
+    def __repr__(self):
+        if not self:
+            return '%s()' % (self.__class__.__name__,)
+        return '%s(%r)' % (self.__class__.__name__, list(self))
+
+    def __eq__(self, other):
+        if isinstance(other, OrderedSet):
+            return len(self) == len(other) and list(self) == list(other)
+        return set(self) == set(other)
+
 
 HERE = os.path.realpath(os.path.dirname(__file__))
 
@@ -32,10 +115,18 @@ if __name__ == "__main__":
         print("Updating symbols to new major version %s" % version_major_minor, file=sys.stderr)
 
         symbol_index_file = os.path.join(symbols_index_dir, 'symbol_index.json')
-        shutil.copyfile(os.path.join(builddir, "hotdoc-private-GStreamer", "symbol_index.json"),
-            symbol_index_file)
+        with open(symbol_index_file, 'r', encoding='utf-8') as _:
+            symbols = OrderedSet(json.load(_))
+
+        with open(os.path.join(builddir, "hotdoc-private-GStreamer", "symbol_index.json"), 'r', encoding='utf-8') as _:
+            new_symbols = OrderedSet(sorted(json.load(_)))
+
+        with open(symbol_index_file, 'w', encoding='utf-8') as _:
+            json.dump(sorted(list(symbols | new_symbols)), _, indent=2)
+
         with open(symbols_version_file, 'w') as sv:
             sv.write(version_major_minor)
+
         print("NOTE: YOU SHOULD COMMIT THE FOLLOWING FILES BEFORE PUBLISHING THE RELEASE:", file=sys.stderr)
         print(" - " + symbol_index_file, file=sys.stderr)
         print(" - " + symbols_version_file, file=sys.stderr)
@@ -47,4 +138,4 @@ if __name__ == "__main__":
     tar.add(files, release_name)
     os.chdir(os.path.dirname(readme))
     tar.add(os.path.basename(readme), os.path.join(release_name, os.path.basename(readme)))
-    tar.close()
\ No newline at end of file
+    tar.close()