rm method
Removes a file or directory at the given path.
force ignores missing paths and implies recursive for directories,
matching Kubo files rm --force.
Implementation
Future<void> rm(
String path, {
bool recursive = false,
bool force = false,
}) async {
final parts = _splitPath(path);
if (parts.isEmpty) throw Exception('Cannot remove root');
final parentParts = parts.sublist(0, parts.length - 1);
final nameToRemove = parts.last;
await _mutationLock.synchronized(() async {
await _modifyPath(parentParts, (parentCid) async {
if (parentCid == null) {
if (force) return null;
throw Exception('Parent path not found');
}
final parentBlock = await _blockStore.getBlock(parentCid.encode());
if (!parentBlock.found) {
if (force) return null;
throw Exception('Parent block not found');
}
final parentNode = PBNode.fromBuffer(parentBlock.block.data);
final newLinks = parentNode.links
.where((l) => l.name != nameToRemove)
.toList();
if (newLinks.length == parentNode.links.length) {
// Nothing removed
if (force) return parentCid;
throw Exception('Path not found: $path');
}
final removeDirs = recursive || force;
if (!removeDirs) {
final removedLink = parentNode.links.firstWhere(
(l) => l.name == nameToRemove,
);
final removedBlock = await _blockStore.getBlock(
CID.fromBytes(Uint8List.fromList(removedLink.hash)).encode(),
);
if (removedBlock.found) {
final removedNode = PBNode.fromBuffer(removedBlock.block.data);
final unixData = Data.fromBuffer(removedNode.data);
if (unixData.type == Data_DataType.Directory) {
throw Exception('Cannot remove directory without -r: $path');
}
}
}
parentNode.links.clear();
parentNode.links.addAll(newLinks);
final newData = marshalDagPBNode(parentNode);
final newCid = await CID.fromContent(newData, codec: 'dag-pb');
await _blockStore.putBlock(
Block(cid: newCid, data: newData, format: 'dag-pb'),
);
return newCid;
});
});
}