mkdir method
Creates a directory at the given path.
parents and recursive are aliases for creating intermediate
directories and succeeding when the directory already exists — matching
Kubo's ipfs files mkdir --parents. Without them an existing path is an
error, as is a path whose parent does not exist.
mode, mtimeSecs and mtimeNsecs store optional UnixFS 1.5 metadata
on the created directory.
Implementation
Future<void> mkdir(
String path, {
bool recursive = false,
bool parents = false,
int? cidVersion,
String? hash,
int? mode,
int? mtimeSecs,
int? mtimeNsecs,
}) async {
final createMissing = recursive || parents;
final parts = _splitPath(path);
if (parts.isEmpty) {
// `mkdir /` is a no-op only when parents is requested.
if (createMissing) return;
throw Exception('file already exists: $path');
}
await _mutationLock.synchronized(() async {
await _modifyPath(
parts,
(currentCid) async {
if (currentCid != null) {
final existingType = await _unixfsType(currentCid);
if (createMissing && existingType == Data_DataType.Directory) {
// Directory already exists: `mkdir -p` is idempotent.
return currentCid;
}
throw Exception('file already exists: $path');
}
final dirManager = IPFSDirectoryManager();
if (mode != null) dirManager.setMode(mode);
if (mtimeSecs != null) {
dirManager.setModificationTime(
DateTime.fromMillisecondsSinceEpoch(
mtimeSecs * 1000,
isUtc: true,
),
);
}
final node = dirManager.build();
if (mtimeNsecs != null) {
final unixData = Data.fromBuffer(node.data)
..mtimeNsecs = mtimeNsecs;
node.data = unixData.writeToBuffer();
}
final data = marshalDagPBNode(node);
final cid = await CID.fromContent(
data,
codec: 'dag-pb',
hashType: hash ?? 'sha2-256',
version: cidVersion ?? 0,
);
await _blockStore.putBlock(
Block(cid: cid, data: data, format: 'dag-pb'),
);
return cid;
},
recursive: createMissing,
isDirectory: true,
);
});
}