blob: 0332b168c80f6c8845fdffbbdc60469e94ba1c43 [file] [log] [blame]
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
library quiver.io;
import 'dart:async';
import 'dart:convert';
import 'dart:io';
/// Converts a [Stream] of byte lists to a [String].
Future<String> byteStreamToString(Stream<List<int>> stream,
{Encoding encoding: utf8}) {
return stream.transform(encoding.decoder).join();
}
/// Gets the full path of [path] by using [File.fullPathSync].
String getFullPath(path) => new File(path).resolveSymbolicLinksSync();
/// Lists the sub-directories and files of this Directory, optionally recursing
/// into sub-directories based on the return value of [visit].
///
/// [visit] is called with a [File], [Directory] or [Link] to a directory,
/// never a Symlink to a File. If [visit] returns true, then its argument is
/// listed recursively.
Future visitDirectory(Directory dir, Future<bool> visit(FileSystemEntity f)) {
final completer = new Completer();
final directories = <String, bool>{dir.path: false};
void _list(Directory dir) {
directories.putIfAbsent(dir.path, () => false);
dir.list(followLinks: false).listen((FileSystemEntity entity) {
var future = visit(entity);
if (future != null) {
future.then((bool recurse) {
// recurse on directories, but not cyclic symlinks
if (entity is! File && recurse == true) {
if (entity is Link) {
if (FileSystemEntity.typeSync(entity.path, followLinks: true) ==
FileSystemEntityType.directory) {
var fullPath = getFullPath(entity.path).toString();
var dirFullPath = getFullPath(dir.path).toString();
if (!dirFullPath.startsWith(fullPath)) {
_list(new Directory(entity.path));
}
}
} else {
_list(entity);
}
}
});
}
}, onDone: () {
directories[dir.path] = true;
if (directories.values.every((v) => v)) {
completer.complete();
}
}, onError: (e) {
completer.completeError(e);
}, cancelOnError: true);
}
_list(dir);
return completer.future;
}