Class: Oxygene::CARRepo
- Inherits:
-
CARArchive
- Object
- CARArchive
- Oxygene::CARRepo
- Defined in:
- lib/oxygene/car_repo.rb
Overview
A CAR archive containing an account's ATProto repository, as returned by the
com.atproto.sync.getRepo PDS endpoint.
Oxygene currently supports repositories in the v3 format version.
Related specifications:
Instance Attribute Summary collapse
-
#commit_section ⇒ CARSection
readonly
Returns the CAR archive section containing the repository's root commit.
Attributes inherited from CARArchive
Instance Method Summary collapse
-
#commit ⇒ Hash
Returns the repository commit data.
-
#initialize(data) ⇒ CARRepo
constructor
Creates an ATProto repository reader from an in-memory CAR file.
-
#walk_all_nodes(starting_node_cid = nil) {|key, cid| ... } ⇒ Object
Walks through the repository MST tree, running the passed block for each record in the repo in alphabetical key order.
Methods inherited from CARArchive
convert_data, #inspect, make_bytes, make_cid_link, #parsed_sections, #section_with_cid, #sections
Constructor Details
#initialize(data) ⇒ CARRepo
Creates an ATProto repository reader from an in-memory CAR file.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/oxygene/car_repo.rb', line 30 def initialize(data) super raise DecodeError, "CAR repository has no root commit" if roots.empty? @commit_section = section_with_cid(roots.first, use_map: true, return_body: false) raise DecodeError, "Root commit not found in the archive: #{roots.first.inspect}" if @commit_section.nil? commit_body = @commit_section.decoded_body raise DecodeError, "Commit object should be a hash" unless commit_body.is_a?(Hash) repo_version = commit_body['version'] raise UnsupportedError, "Unexpected repository version: #{repo_version.inspect}" unless repo_version == 3 end |
Instance Attribute Details
#commit_section ⇒ CARSection (readonly)
Returns the CAR archive section containing the repository's root commit.
22 23 24 |
# File 'lib/oxygene/car_repo.rb', line 22 def commit_section @commit_section end |
Instance Method Details
#commit ⇒ Hash
Returns the repository commit data.
The commit is decoded from the body of the #commit_section. The data is
returned in the ATProto JSON representation – CID links and binary strings
are represented using $link and $bytes objects respectively. Use
#commit_section to access the original CBOR bytes or decoded CBOR values
without conversion.
See the ATProto repository spec for what fields the commit object is expected to contain.
58 59 60 |
# File 'lib/oxygene/car_repo.rb', line 58 def commit commit_section.json_body end |
#walk_all_nodes(starting_node_cid = nil) {|key, cid| ... } ⇒ Object
Walks through the repository MST tree, running the passed block for each record in the repo in alphabetical key order.
Records are stored in the Merkle Search Tree structure in nodes with assigned keys,
where each key is a record path (NSID collection + rkey, e.g.
app.bsky.feed.post/3juhznhw65225). The iterator returns all records one by one
sorted alphabetically, so the list is sorted by collection first and then by rkey
within a collection. The callback is passed the path key and the Oxygene::CID of the section
which contains the actual record data, The CID can be used to extract the data
through a call to Oxygene::CARArchive#section_with_cid (you almost certainly want to pass
use_map: true).
Normally you can skip the starting_node_cid parameter, in which case the tree
traversal begins at the repository root referenced by the CAR header and covers the
entire tree. If a starting CID is passed, the traversal will start from a given node
covering only a subtree.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/oxygene/car_repo.rb', line 87 def walk_all_nodes(starting_node_cid = nil, &block) if starting_node_cid.nil? commit = commit_section.decoded_body tree_top_cid = commit['data'].value return walk_all_nodes(tree_top_cid, &block) end data = section_with_cid(starting_node_cid, use_map: true, return_body: false)&.decoded_body raise DecodeError, "MST node not found in the archive: #{starting_node_cid.inspect}" if data.nil? if data['l'] walk_all_nodes(data['l'].value, &block) end previous = nil (data['e'] || []).each do |e| if previous key = previous[0...e['p']] key << e['k'] else key = e['k'] end previous = key block.call(key, CID.from_cbor_tag(e['v'])) if e['t'] walk_all_nodes(e['t'].value, &block) end end end |