addDirectory method
Future<void>
addDirectory(
- Directory dir, {
- bool followLinks = true,
- bool includeDirName = true,
- ZipFileProgress? filter,
Implementation
Future<void> addDirectory(Directory dir,
{bool followLinks = true,
bool includeDirName = true,
ZipFileProgress? filter}) async {
Stream<FileSystemEntity> files() async* {
await for (final file
in dir.list(recursive: true, followLinks: followLinks)) {
if (file is File &&
await FileSystemEntity.identical(file.path, tarPath)) {
continue;
}
yield file;
}
}
// A filter is given a progress fraction, which needs the count up front,
// so the list is kept in that case, as it always was. Walking the tree
// twice instead would double the directory reads, and a file added or
// removed between the walks would put the fraction past 1 or short of it.
// Without a filter the entries are handled as they are listed.
final listed = filter != null ? await files().toList() : null;
final numFiles = listed?.length ?? 0;
final dirName = path.basename(dir.path);
var fileCount = 0;
await for (final file
in listed != null ? Stream.fromIterable(listed) : files()) {
final progress = numFiles == 0 ? 0.0 : ++fileCount / numFiles;
if (filter != null) {
final operation = filter(file, progress);
if (operation == ZipFileOperation.cancel) {
break;
}
if (operation == ZipFileOperation.skip) {
continue;
}
}
if (file is Directory) {
var filename = path.relative(file.path, from: dir.path);
filename = includeDirName ? '$dirName/$filename' : filename;
final af = ArchiveFile.directory('$filename/');
af.mode = (await file.stat()).mode;
_encoder.add(af);
} else if (file is File) {
final dirName = path.basename(dir.path);
final relPath = path.relative(file.path, from: dir.path);
await addFile(file, includeDirName ? '$dirName/$relPath' : relPath);
}
}
}