| 1 | """Traversal of the exported document's referenced revisions.""" |
| 2 | import os |
| 3 | from pathlib import Path |
| 4 | import subprocess |
| 5 | |
| 6 | |
| 7 | def _exporter(): |
| 8 | """The document exporter, built for this run.""" |
| 9 | if 'ONESTORE_DOCUMENT' in os.environ: |
| 10 | return Path(os.environ['ONESTORE_DOCUMENT']) |
| 11 | root = Path(__file__).resolve().parent.parent |
| 12 | subprocess.run(['cargo', 'build', '--quiet', '-p', 'notebook', '--example', 'document'], |
| 13 | cwd=root, check=True) |
| 14 | return root / 'target/debug/examples/document' |
| 15 | |
| 16 | |
| 17 | EXPORTER = _exporter() |
| 18 | BRIDGE = Path(__file__).resolve().parent.parent / 'target/debug/onestore-diagnostic' |
| 19 | |
| 20 | DEFAULT_CONTEXT = '{00000000-0000-0000-0000-000000000000},0' |
| 21 | |
| 22 | |
| 23 | def view(document, sid, context=DEFAULT_CONTEXT): |
| 24 | space = document['spaces'][sid] |
| 25 | rid = space['contexts'][context] |
| 26 | return rid, space['revisions'][rid] |
| 27 | |
| 28 | |
| 29 | def ordered_pages(document): |
| 30 | _, root = view(document, document['root']) |
| 31 | section = root['nodes'][root['roots']['1']] |
| 32 | if section['kind']['type'] == 'Encrypted': |
| 33 | return |
| 34 | assert section['kind']['type'] == 'Section' |
| 35 | for series in section['children']: |
| 36 | for space in root['nodes'][series]['spaces']: |
| 37 | rid, page = view(document, space) |
| 38 | manifest = page['nodes'][page['roots']['1']] |
| 39 | assert manifest['kind']['type'] == 'Manifest' |
| 40 | for oid in manifest['content']: |
| 41 | assert page['nodes'][oid]['kind']['type'] == 'Page' |
| 42 | yield space, rid, page, oid |
| 43 | |
| 44 | |
| 45 | def version_pages(document, sid, revision): |
| 46 | manifest = revision['nodes'][revision['roots']['1']]['kind'] |
| 47 | context = manifest['history'] |
| 48 | # A page OneNote copied from a version names a history it never wrote. |
| 49 | if context not in document['spaces'][sid]['contexts']: |
| 50 | return |
| 51 | _, history = view(document, sid, context) |
| 52 | root = history['nodes'][history['roots']['1']] |
| 53 | assert root['kind']['type'] == 'VersionHistory' |
| 54 | for proxy_id in root['children']: |
| 55 | proxy = history['nodes'][proxy_id] |
| 56 | assert proxy['kind']['type'] == 'VersionProxy' |
| 57 | context = proxy['kind']['context'] |
| 58 | rid, revision = view(document, sid, context) |
| 59 | manifest = revision['nodes'][revision['roots']['1']] |
| 60 | assert manifest['kind']['type'] == 'Manifest' |
| 61 | for oid in manifest['content']: |
| 62 | assert revision['nodes'][oid]['kind']['type'] == 'Page' |
| 63 | yield context, rid, revision, oid, proxy |
| 64 | |
| 65 | |
| 66 | def walk(space, root): |
| 67 | pending = [root] |
| 68 | while pending: |
| 69 | oid = pending.pop() |
| 70 | node = space['nodes'][oid] |
| 71 | yield oid, node |
| 72 | pending.extend(reversed(node['structure'] + node['content'] + node['children'])) |