UNPKG

ipfs-car

Version:

Convert files to content-addressed archives (.car) and back

51 lines (44 loc) 1.47 kB
import { CID } from 'multiformats/cid' import { sha256 } from 'multiformats/hashes/sha2' import { decode as blockDecode } from 'multiformats/block' import { Codecs } from './codec.js' /** * @param {import('@ipld/car/api').CarReader} reader * @param {object} [opts] * @param {string} [opts.root] */ export async function getRoots (reader, opts = {}) { let roots = opts.root ? [CID.parse(opts.root)] : await reader.getRoots() if (!roots.length) { roots = await findImplicitRoots(reader.blocks()) } if (roots.length > 1) { console.error(`Multiple roots found, use --root to specify which one to use:\n${roots.join('\n')}`) process.exit(1) } return roots } /** @param {AsyncIterable<import('@ipld/car/api').Block>} blocks */ export async function findImplicitRoots (blocks) { const notRoots = new Set() const roots = new Set() for await (const { cid, bytes } of blocks) { if (!notRoots.has(cid.toString())) { roots.add(cid.toString()) } const decoder = Codecs[cid.code] /* c8 ignore next 4 */ if (!decoder) { console.error(`Missing decoder: ${cid.code}`) process.exit(1) } const block = await blockDecode({ bytes, codec: decoder, hasher: sha256 }) for (const [, linkCID] of block.links()) { if (roots.has(linkCID.toString())) { roots.delete(linkCID.toString()) } notRoots.add(cid.toString()) } } return Array.from(roots).map(s => CID.parse(s)) }