diff --git a/src/blobset.nim b/src/blobset.nim index 9937ce0..879297f 100644 --- a/src/blobset.nim +++ b/src/blobset.nim @@ -218,7 +218,7 @@ proc getSet(env: Env; path: string): BlobSet= result = env.sets.getOrDefault(path) if result.isNil: result = newBlobSet() - result.insertPath(env.store, pcDir, path) + result.insertPath(env.store, path.getFileInfo.kind, path) if not result.isEmpty: env.sets[path] = result @@ -443,15 +443,10 @@ proc keyFunc(env: Env; args: NodeObj): NodeRef = args.atom.str.toKey.newAtom.newNode proc ingestFunc(env: Env; args: NodeObj): NodeRef = - let set = newBlobSet() + var bs = newBlobSet() for n in args.walk: - returnError n - let a = n.atom - case a.path.getFileInfo.kind - of pcFile, pcLinkToFile: - result = newNode(newAtomError("not a directory")) - of pcDir, pcLinkToDir: - result = newNode(newAtom(env.getSet(a.path))) + bs = env.store.union(bs, env.getSet(n.atom.path)) + result = bs.newAtom.newNode proc blobFunc(env: Env; args: NodeObj): NodeRef = assertArgCount(args, 1) diff --git a/src/blobsets.nim b/src/blobsets.nim index 94dc5ed..a97f09e 100644 --- a/src/blobsets.nim +++ b/src/blobsets.nim @@ -209,6 +209,20 @@ func compactIndex(t: BlobSet; x: Key): int = func masked(t: BlobSet; x: Key): bool = ((t.bitmap shr x.sparseIndex) and 1) != 0 +proc apply*(bs: BlobSet; cb: proc (leaf: BlobSet)) = + ## Apply a callback to each set element. + for node in bs.table: + case node.kind + of hotNode: + apply(node, cb) + of leafNode: + cb(node) + else: + raiseAssert("cannot apply to node type " & $node.kind) + +func isEmpty*(s: BlobSet): bool = s.bitmap == Key(0) + ## Test if a set is empty. + func nodeCount*(bs: BlobSet): int = ## Count of internal nodes in set. result = 1 @@ -266,13 +280,13 @@ func insert(t, l: BlobSet; depth: int) = t.bitmap = t.bitmap or (Key(1) shl key.sparseIndex) t.table.insert(l, t.compactIndex(key)) +func insert*(t, l: BlobSet) = insert(t, l, 0) + # Insert set node `t` into `l`. + func insert*(t: BlobSet; name: string; blob: BlobId; size: BiggestInt) = ## Insert a blob hash into a trie. let leaf = BlobSet(kind: leafNode, key: name.toKey, blob: blob, size: size) - insert(t, leaf, 0) - -func isEmpty*(s: BlobSet): bool = s.bitmap == Key(0) - ## Test if a set is empty. + insert(t, leaf) func toCbor*(x: BlobSet): CborNode = const diff --git a/src/blobsets/stores.nim b/src/blobsets/stores.nim index 61f43da..ac8d89c 100644 --- a/src/blobsets/stores.nim +++ b/src/blobsets/stores.nim @@ -259,10 +259,13 @@ proc commit*(store: BlobStore; bs: BlobSet): BlobSet = let (id, _) = finish stream result = BlobSet(kind: coldNode, setId: id) -proc union*(store: BlobStore; a, b: BlobSet): BlobSet = - ## Return the union of a set pair. - result = newBlobSet() - raiseAssert("not implemented") +proc union*(store: BlobStore; sets: varargs[BlobSet]): BlobSet = + ## Return the union of `sets`. + let fresh = newBlobSet() + result = fresh + proc freshInsert(leaf: BlobSet) = insert(fresh, leaf) + for bs in sets: + bs.apply(freshInsert) # Store implementations #