Skip to content

Commit

Permalink
fix: yield intermediate blocks when path is not found
Browse files Browse the repository at this point in the history
  • Loading branch information
Alan Shaw committed Aug 22, 2023
1 parent 3e69522 commit 9c3145e
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 4 deletions.
17 changes: 13 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,19 @@ export class Dagula {
return block.bytes
}
}
for await (const item of walkPath(cidPath, blockstore, { signal: options.signal })) {
base = item
yield * traversed
traversed = []
try {
for await (const item of walkPath(cidPath, blockstore, { signal: options.signal })) {
base = item
yield * traversed
traversed = []
}
} catch (err) {
// yield all traversed blocks even if the path was not found. This allows
// the caller to verify the path does not exist for themselves.
if (err.code === 'ERR_NOT_FOUND') {
yield * traversed
}
throw err
}
if (!base) throw new Error('walkPath did not yield an entry')

Expand Down
28 changes: 28 additions & 0 deletions test/getPath.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import { sha256 } from 'multiformats/hashes/sha2'
import { identity } from 'multiformats/hashes/identity'
import { CID } from 'multiformats/cid'
import * as Block from 'multiformats/block'
import { Dagula } from '../index.js'
import { getLibp2p, fromNetwork } from '../p2p.js'
import { startBitswapPeer } from './_libp2p.js'
import { MemoryBlockstore } from './helpers/blockstore.js'

test('should getPath', async t => {
// should return all blocks in path and all blocks for resolved target of path
Expand Down Expand Up @@ -543,6 +545,32 @@ test('should getPath through sharded hamt dir with dagScope=entity', async t =>
t.deepEqual(blocks.at(2).cid, fileLink.cid)
})

test('should yield intermediate blocks when last path component does not exist', async t => {
const { readable, writable } = new TransformStream()
const blockstore = new MemoryBlockstore()
const [fileLink] = await Promise.all([
(async () => {
const file = UnixFS.createFileWriter({ writer: writable.getWriter() })
await file.write(new TextEncoder().encode('DATA'))
return file.close({ closeWriter: true })
})(),
readable.pipeTo(new WritableStream({
write: block => blockstore.put(block.cid, block.bytes)
}))
])

const dagula = new Dagula(blockstore)
const blocks = []
await t.throwsAsync(async () => {
for await (const block of dagula.getPath(`${fileLink.cid}/foo`)) {
blocks.push(block)
}
}, { message: 'file does not exist' })

t.is(blocks.length, 1)
t.is(blocks[0].cid.toString(), fileLink.cid.toString())
})

/** @param {AsyncIterable} source */
async function collect (source) {
const blocks = []
Expand Down
18 changes: 18 additions & 0 deletions test/helpers/blockstore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export class MemoryBlockstore {
/** @type {Map<string, Uint8Array>} */
#blocks = new Map()

/** @param {import('multiformats').UnknownLink} cid */
async get (cid) {
const bytes = this.#blocks.get(cid.toString())
if (bytes) return { cid, bytes }
}

/**
* @param {import('multiformats').UnknownLink} cid
* @param {Uint8Array} bytes
*/
async put (cid, bytes) {
this.#blocks.set(cid.toString(), bytes)
}
}

0 comments on commit 9c3145e

Please sign in to comment.