From 43b3df453f099406c88e391d138edfc273aa8fef Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Thu, 26 Jan 2023 22:37:34 +0100 Subject: [PATCH] fix: correct path on copy project --- tools/brick_generator/README.md | 6 +- tools/brick_generator/bin/brickgen.dart | 12 ++- .../brick_generator/lib/core/file_system.dart | 97 +++++++++++-------- .../lib/models/boolean_file_system.dart | 22 +++-- .../models/boolean_file_system_variable.dart | 5 + 5 files changed, 86 insertions(+), 56 deletions(-) diff --git a/tools/brick_generator/README.md b/tools/brick_generator/README.md index 7824b9b..8e01ef7 100644 --- a/tools/brick_generator/README.md +++ b/tools/brick_generator/README.md @@ -65,7 +65,7 @@ apps Then run command with project path ```sh -dart ./tools/brick_generator/bin/brickgen.dart ./apps/brick_name +dart ./tools/brick_generator/bin/brickgen.dart ./apps/brick_name ./bricks/ ``` Available options: @@ -318,7 +318,7 @@ brickgen: ``` ```sh -dart ./tools/brick_generator/bin/brickgen.dart ./apps/brick_1 +dart ./tools/brick_generator/bin/brickgen.dart ./apps/brick_1 ./bricks/ ``` Will generate: @@ -360,7 +360,7 @@ brickgen: ``` ```sh -dart ./tools/brick_generator/bin/brickgen.dart ./apps/brick_2 +dart ./tools/brick_generator/bin/brickgen.dart ./apps/brick_2 ./bricks/ ``` Will generate: diff --git a/tools/brick_generator/bin/brickgen.dart b/tools/brick_generator/bin/brickgen.dart index 80bd337..f8e9432 100644 --- a/tools/brick_generator/bin/brickgen.dart +++ b/tools/brick_generator/bin/brickgen.dart @@ -89,8 +89,10 @@ class Brickgen { Logger.debug('Define `targetPath`: $targetPath'); // Check paths - if (toBrickifyPath == null || targetPath == null - || masonConfigPath == null || hooksOutputPath == null) { + if (toBrickifyPath == null || + targetPath == null || + masonConfigPath == null || + hooksOutputPath == null) { throw Exception('An error occures during path definition.'); } Logger.info('Paths defined.'); @@ -102,7 +104,7 @@ class Brickgen { ignoreList: config.brickgenConfig.ignore, ); Logger.info('Project copied.'); - + // Take care of boolean mapping and boolean fs FileSystem.applyBooleanFileSystem(config, targetPath!); Logger.info('Boolean file system applied.'); @@ -125,7 +127,9 @@ class Brickgen { // Convert compilable values -> variables (files/folder names) FileSystem.renameCompilableFilesInFolder(config, targetPath!); Logger.info('Files renamed with variables.'); - + + // Clean empty folders created from copy/moves + FileSystem.removeEmptyFolders(targetPath!); // Create Mason config FileSystem.writeFile(masonConfigPath!, config.toMason()); diff --git a/tools/brick_generator/lib/core/file_system.dart b/tools/brick_generator/lib/core/file_system.dart index 11d43b6..9b987f9 100644 --- a/tools/brick_generator/lib/core/file_system.dart +++ b/tools/brick_generator/lib/core/file_system.dart @@ -53,7 +53,18 @@ abstract class FileSystem { throw ArgumentError('Path must be a directory', 'from'); } - final List copiedFolders = []; + Future cp(FileSystemEntity entity) async { + final absolutPath = entity.path; + final relativePath = absolutPath.replaceFirst(from, ''); + final newPath = ((to + relativePath).split('/')..removeLast()).join('/'); + + if (ignoreList != null && ignoreList.contains(from, absolutPath)) { + Logger.debug('Ignoring $absolutPath'); + } else { + Logger.debug('cp -Rf $absolutPath $newPath'); + await Shell.cp(absolutPath, newPath); + } + } // Copy folders await Future.wait( @@ -61,38 +72,14 @@ abstract class FileSystem { .listSync(recursive: true) .whereType() .map((directory) async { - final absolutPath = directory.path; - final name = absolutPath.split('/').last; - - if (ignoreList != null && ignoreList.contains(from, absolutPath)) { - Logger.debug('Ignoring $absolutPath'); - } else { - Logger.debug('cp -Rf $absolutPath $to/$name'); - copiedFolders.add(absolutPath); - await Shell.cp(absolutPath, '$to/$name'); - } + await cp(directory); }), ); - // Copy files + // Copy root files await Future.wait( - Directory(from) - .listSync(recursive: true) - .whereType() - .map((file) async { - final absolutPath = file.path; - final name = absolutPath.split('/').last; - - if (ignoreList != null && ignoreList.contains(from, absolutPath)) { - Logger.debug('Ignoring $absolutPath'); - } else { - if (copiedFolders.any(absolutPath.startsWith)) { - Logger.debug('$absolutPath already copied!'); - } else { - Logger.debug('cp -Rf $absolutPath $to/$name'); - await Shell.cp(absolutPath, '$to/$name'); - } - } + Directory(from).listSync().whereType().map((file) async { + await cp(file); }), ); } @@ -259,13 +246,17 @@ abstract class FileSystem { for (final syntax in VariableStringSyntax.values) { final toReplace = variable.syntax?[syntax.mapKey]; if (toReplace != null) { - contents = contents!.replaceAll( - toReplace, - '{{#${syntax.id}}}{{${variable.name}}}{{/${syntax.id}}}', - ); + if (contents?.contains(toReplace) ?? false) { + contents = contents!.replaceAll( + toReplace, + '{{#${syntax.id}}}{{${variable.name}}}{{/${syntax.id}}}', + ); + Logger.debug( + 'Variable `${variable.name}` replaced in ${file.path}', + ); + } } } - Logger.debug('Variable `${variable.name}` replaced in ${file.path}'); }); file.writeAsStringSync(contents!); @@ -289,21 +280,43 @@ abstract class FileSystem { }); } + /// Removes empty folder dynamically: + /// + /// For example, for this structure: + /// ``` + /// ./brick/__brick__/folder/empty1/ + /// ./brick/__brick__/folder/empty2/ + /// ./brick/__brick__/dummy.txt + /// ``` + /// it will delete `empty1` and `empty2`...then it will delete `folder`, + /// because by deleting his subfolders he's now empty too. + /// static void removeEmptyFolders(String targetPath) { if (!FileSystemEntity.isDirectorySync(targetPath)) { throw ArgumentError('Target must be a directory', 'targetPath'); } - Directory(targetPath) + bool containsEmptyFoldersFunction() => Directory(targetPath) .listSync(recursive: true) .whereType() - .forEach((directory) { - if (directory.existsSync() && - directory.listSync(recursive: true).isEmpty) { - directory.deleteSync(recursive: true); - Logger.debug('${directory.path} (empty) deleted.'); - } - }); + .any( + (directory) => + directory.existsSync() && + directory.listSync(recursive: true).isEmpty, + ); + + while (containsEmptyFoldersFunction()) { + Directory(targetPath) + .listSync(recursive: true) + .whereType() + .forEach((directory) { + if (directory.existsSync() && + directory.listSync(recursive: true).isEmpty) { + directory.deleteSync(recursive: true); + Logger.debug('${directory.path} (empty) deleted.'); + } + }); + } } /// Transforms compilable file/folder names: diff --git a/tools/brick_generator/lib/models/boolean_file_system.dart b/tools/brick_generator/lib/models/boolean_file_system.dart index f03f227..1af3c71 100644 --- a/tools/brick_generator/lib/models/boolean_file_system.dart +++ b/tools/brick_generator/lib/models/boolean_file_system.dart @@ -32,14 +32,22 @@ class BooleanFileSystem { if (source == null) { throw ArgumentError.notNull('source'); } - + final variableName = key; - final folders = BooleanFileSystemVariable.fromYaml( - source.nodes[_foldersKey] as YamlMap?, - ); - final files = BooleanFileSystemVariable.fromYaml( - source.nodes[_filesKey] as YamlMap?, - ); + + final foldersMap = source.nodes[_foldersKey] as YamlMap?; + final folders = (foldersMap != null) + ? BooleanFileSystemVariable.fromYaml( + source.nodes[_foldersKey] as YamlMap?, + ) + : BooleanFileSystemVariable.empty(); + + final filesMap = source.nodes[_filesKey] as YamlMap?; + final files = (filesMap != null) + ? BooleanFileSystemVariable.fromYaml( + source.nodes[_filesKey] as YamlMap?, + ) + : BooleanFileSystemVariable.empty(); return BooleanFileSystem( booleanName: variableName, diff --git a/tools/brick_generator/lib/models/boolean_file_system_variable.dart b/tools/brick_generator/lib/models/boolean_file_system_variable.dart index 6fa2eb2..2772edf 100644 --- a/tools/brick_generator/lib/models/boolean_file_system_variable.dart +++ b/tools/brick_generator/lib/models/boolean_file_system_variable.dart @@ -43,6 +43,11 @@ class BooleanFileSystemVariable { ); } + factory BooleanFileSystemVariable.empty() => BooleanFileSystemVariable( + onTrueNames: [], + onFalseNames: [], + ); + final List onTrueNames; final List onFalseNames;