expand static method

List<File> expand(
  1. String pattern, {
  2. Directory? from,
})

Every existing file matching pattern, newest first.

Returns an empty list when nothing matches; the caller decides whether that is an error, because a dry run legitimately has nothing to match yet.

Implementation

static List<File> expand(String pattern, {Directory? from}) {
  final normalized = pattern.replaceAll('\\', '/');
  final segments = normalized.split('/');

  // Everything before the first magic segment is a real directory to start
  // from; listing the whole tree from the working directory would be absurd
  // for a pattern that named one folder.
  final fixed = <String>[];
  var index = 0;
  while (index < segments.length && !hasMagic(segments[index])) {
    fixed.add(segments[index]);
    index++;
  }
  if (index == segments.length) {
    // No magic after all — resolve it as the plain path it is, still
    // relative to `from` so the two branches agree.
    final literal = from == null ? pattern : path.join(from.path, pattern);
    final file = File(literal);
    return file.existsSync() ? [file] : const [];
  }

  final rootPath = fixed.isEmpty
      ? (from?.path ?? '.')
      : (from == null
          ? fixed.join(Platform.pathSeparator)
          : path.join(from.path, fixed.join(Platform.pathSeparator)));

  final root = Directory(rootPath);
  if (!root.existsSync()) return const [];

  final remainder = segments.sublist(index).join('/');
  final matcher = _toRegExp(remainder);
  final recursive = remainder.contains('**') || remainder.contains('/');

  final matches = <File>[];
  for (final entity in root.listSync(recursive: recursive)) {
    if (entity is! File) continue;
    final relative =
        path.relative(entity.path, from: root.path).replaceAll('\\', '/');
    if (matcher.hasMatch(relative)) matches.add(entity);
  }

  matches.sort(
    (a, b) => b.lastModifiedSync().compareTo(a.lastModifiedSync()),
  );
  return matches;
}