Commit fa00c283 authored by Kirill Smelkov's avatar Kirill Smelkov

zodbcommit: Robustify copy handling

When zodbdump input says to copy an object, we first load that object.
However if object does not exist loadBefore raises POSKeyError, and when
object at copied-from revision was deleted loadBefore returns None.

-> Handle that explicitly to provide failure details to the user, so
that instead of cryptic

    === RUN   TestLoad/δstart=0285cbac75555580
    Traceback (most recent call last):
      File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
        "__main__", fname, loader, pkg_name)
      File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
        exec code in run_globals
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodb.py", line 133, in <module>
        main()
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodb.py", line 129, in main
        return command_module.main(argv)
      File "<decorator-gen-6>", line 2, in main
      File "/home/kirr/src/tools/go/pygolang/golang/__init__.py", line 103, in _
        return f(*argv, **kw)
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbrestore.py", line 94, in main
        zodbrestore(stor, asbinstream(sys.stdin), _)
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbrestore.py", line 43, in zodbrestore
        zodbcommit(stor, at, txn)
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbcommit.py", line 122, in zodbcommit
        _()
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbcommit.py", line 91, in _
        data, _, _ = stor.loadBefore(obj.oid, p64(u64(obj.copy_from)+1))
    TypeError: 'NoneType' object is not iterable
        xtesting.go:483: /tmp/demo009767458/δ0285cbac75555580/δ.fs: zpyrestore: exit status 1

it fails with something more understandable:

    === RUN   TestLoad/δstart=0285cbac75555580
    Traceback (most recent call last):
      File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
        "__main__", fname, loader, pkg_name)
      File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
        exec code in run_globals
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodb.py", line 133, in <module>
        main()
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodb.py", line 129, in main
        return command_module.main(argv)
      File "<decorator-gen-6>", line 2, in main
      File "/home/kirr/src/tools/go/pygolang/golang/__init__.py", line 103, in _
        return f(*argv, **kw)
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbrestore.py", line 94, in main
        zodbrestore(stor, asbinstream(sys.stdin), _)
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbrestore.py", line 43, in zodbrestore
        zodbcommit(stor, at, txn)
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbcommit.py", line 129, in zodbcommit
        _()
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbcommit.py", line 97, in _
        (stor.getName(), ashex(obj.oid), ashex(obj.copy_from)))
    ValueError: /tmp/demo358030847/δ0285cbac75555580/δ.fs: object 0000000000000003: copy from @0285cbac70a3d733: no data
        xtesting.go:483: /tmp/demo358030847/δ0285cbac75555580/δ.fs: zpyrestore: exit status 1

For the implementation it would be easier to use loadAt
(https://github.com/zopefoundation/ZODB/pull/323), but we don't have
that yet.

/reviewed-by @jerome
/reviewed-on nexedi/zodbtools!20
parent 4275f2e9
...@@ -88,7 +88,14 @@ def zodbcommit(stor, at, txn): ...@@ -88,7 +88,14 @@ def zodbcommit(stor, at, txn):
copy_from = None copy_from = None
if isinstance(obj, zodbdump.ObjectCopy): if isinstance(obj, zodbdump.ObjectCopy):
copy_from = obj.copy_from copy_from = obj.copy_from
data, _, _ = stor.loadBefore(obj.oid, p64(u64(obj.copy_from)+1)) try:
xdata = stor.loadBefore(obj.oid, p64(u64(obj.copy_from)+1))
except POSKeyError:
xdata = None
if xdata is None:
raise ValueError("%s: object %s: copy from @%s: no data" %
(stor.getName(), ashex(obj.oid), ashex(obj.copy_from)))
data, _, _ = xdata
elif isinstance(obj, zodbdump.ObjectDelete): elif isinstance(obj, zodbdump.ObjectDelete):
data = None data = None
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment