From 4c8d1060304a4e793c5d813a1d925e7cf1fcccbd Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Fri, 17 Feb 2012 18:01:27 -0800 Subject: [PATCH] PreservedLibsRegistry: add JSON read/write Support serialization as JSON instead of pickle, so that /var/lib/portage/preserved_libs_registry is human readable/writable, for those rare cases where it may be useful. Currently, pickle is still used for writes. The plan is to migrate to JSON after JSON read has been supported for some time. --- .../util/_dyn_libs/PreservedLibsRegistry.py | 61 ++++++++++++++++--- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/pym/portage/util/_dyn_libs/PreservedLibsRegistry.py b/pym/portage/util/_dyn_libs/PreservedLibsRegistry.py index 510c390af..405a23a88 100644 --- a/pym/portage/util/_dyn_libs/PreservedLibsRegistry.py +++ b/pym/portage/util/_dyn_libs/PreservedLibsRegistry.py @@ -1,7 +1,8 @@ -# Copyright 1998-2011 Gentoo Foundation +# Copyright 1998-2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import errno +import json import logging import sys @@ -27,6 +28,19 @@ if sys.hexversion >= 0x3000000: class PreservedLibsRegistry(object): """ This class handles the tracking of preserved library objects """ + + # Enable this after JSON read has been supported for some time. + _json_write = False + + _json_write_opts = { + "ensure_ascii": False, + "indent": "\t", + "sort_keys": True + } + if sys.hexversion < 0x3020000: + # indent only supports int number of spaces + _json_write_opts["indent"] = 4 + def __init__(self, root, filename): """ @param root: root used to check existence of paths in pruneNonExisting @@ -56,17 +70,11 @@ class PreservedLibsRegistry(object): """ Reload the registry data from file """ self._data = None f = None + content = None try: f = open(_unicode_encode(self._filename, encoding=_encodings['fs'], errors='strict'), 'rb') - if os.fstat(f.fileno()).st_size == 0: - # ignore empty lock file - pass - else: - self._data = pickle.load(f) - except (AttributeError, EOFError, ValueError, pickle.UnpicklingError) as e: - writemsg_level(_("!!! Error loading '%s': %s\n") % \ - (self._filename, e), level=logging.ERROR, noiselevel=-1) + content = f.read() except EnvironmentError as e: if not hasattr(e, 'errno'): raise @@ -79,8 +87,33 @@ class PreservedLibsRegistry(object): finally: if f is not None: f.close() + + # content is empty if it's an empty lock file + if content: + try: + self._data = pickle.loads(content) + except SystemExit: + raise + except Exception as e: + try: + self._data = json.loads(_unicode_decode(content, + encoding=_encodings['repo.content'], errors='strict')) + except SystemExit: + raise + except Exception: + writemsg_level(_("!!! Error loading '%s': %s\n") % + (self._filename, e), level=logging.ERROR, + noiselevel=-1) + if self._data is None: self._data = {} + else: + for k, v in self._data.items(): + if isinstance(v, (list, tuple)) and len(v) == 3 and \ + isinstance(v[2], set): + # convert set to list, for write with JSONEncoder + self._data[k] = (v[0], v[1], list(v[2])) + self._data_orig = self._data.copy() self.pruneNonExisting() @@ -97,7 +130,12 @@ class PreservedLibsRegistry(object): return try: f = atomic_ofstream(self._filename, 'wb') - pickle.dump(self._data, f, protocol=2) + if self._json_write: + f.write(_unicode_encode( + json.dumps(self._data, **self._json_write_opts), + encoding=_encodings['repo.content'], errors='strict')) + else: + pickle.dump(self._data, f, protocol=2) f.close() except EnvironmentError as e: if e.errno != PermissionDenied.errno: @@ -138,6 +176,9 @@ class PreservedLibsRegistry(object): self._normalize_counter(self._data[cps][1]) == counter: del self._data[cps] elif len(paths) > 0: + if isinstance(paths, set): + # convert set to list, for write with JSONEncoder + paths = list(paths) self._data[cps] = (cpv, counter, paths) def unregister(self, cpv, slot, counter): -- 2.26.2