feat: add boolean file system support
This commit is contained in:
parent
18aeef9e35
commit
77e60213f9
@ -2,42 +2,365 @@
|
||||
|
||||
A simple command-line application which allows to generate the template of a brick from a project which compiles.
|
||||
|
||||
With an entrypoint in `bin/`, library code in `lib/`.
|
||||
With an entrypoint in `bin/` , library code in `lib/` .
|
||||
|
||||
## How to use
|
||||
|
||||
|
||||
- Add your app in `apps/`.
|
||||
- Add `brick_config.yaml` in you app folder and add this fields:
|
||||
|
||||
> Here we have created `wyatt_feature_brick` app in `apps/`
|
||||
* Add your app in `apps/`.
|
||||
* Add `brickgen.yaml` in you app folder and add this fields:
|
||||
|
||||
```yaml
|
||||
name: wyatt_feature_brick
|
||||
description: New feature brick including state mananement
|
||||
path_to_brickify: lib/feature_name
|
||||
name: brick_name
|
||||
description: An awesome brick
|
||||
|
||||
version: 0.1.1
|
||||
version: 0.1.0
|
||||
|
||||
vars:
|
||||
feature_name:
|
||||
bundle_id:
|
||||
compilable: io.wyattapp.new
|
||||
type: string
|
||||
name: feature_name
|
||||
description: Name of the feature
|
||||
default: Dash
|
||||
prompt: What is the name of your new feature
|
||||
description: The bundle id used in Android and iOS
|
||||
default: io.wyattapp.new
|
||||
prompt: "What is the bundle id?"
|
||||
|
||||
flutter:
|
||||
type: boolean
|
||||
description: If this app is a Flutter or Dart project.
|
||||
default: false
|
||||
prompt: "Is it Flutter app ?"
|
||||
|
||||
brickgen:
|
||||
path_to_brickify: brick_folder
|
||||
ignore:
|
||||
- .env
|
||||
- node_modules/
|
||||
hooks: true
|
||||
boolean_file_system:
|
||||
flutter:
|
||||
folders:
|
||||
on_true:
|
||||
- android
|
||||
- ios
|
||||
on_false:
|
||||
- bin
|
||||
files:
|
||||
on_true:
|
||||
- l10n.yaml
|
||||
- trapeze.yaml
|
||||
|
||||
```
|
||||
|
||||
then run command with project path
|
||||
Project structure must be like:
|
||||
|
||||
```
|
||||
apps
|
||||
├── brick_name
|
||||
│ ├── brickgen.yaml
|
||||
│ ├── hooks
|
||||
│ │ └── pre_gen.dart
|
||||
│ ├── brick_folder
|
||||
│ │ └── ... compilable project
|
||||
```
|
||||
|
||||
Then run command with project path
|
||||
|
||||
```sh
|
||||
dart tools/brick_generator/bin/brick_generator.dart ./apps/wyatt_feature_brick
|
||||
dart ./tools/brick_generator/bin/brickgen.dart ./apps/brick_name
|
||||
```
|
||||
|
||||
## TODO
|
||||
|
||||
- [ ] bool variables
|
||||
- [ ] enum variables
|
||||
- [ ] array variables
|
||||
- [ ] pre hooks
|
||||
- [ ] post hooks
|
||||
* [ ] hooks
|
||||
- [x] post hooks
|
||||
- [x] pre hooks
|
||||
- [ ] add partial hooks
|
||||
* [ ] bool variables
|
||||
- [x] boolean file system
|
||||
- [ ] boolean mapping
|
||||
* [ ] enum variables
|
||||
* [ ] array variables
|
||||
|
||||
## Current specification
|
||||
|
||||
### File Structure
|
||||
|
||||
```
|
||||
apps
|
||||
├── <brick_name>
|
||||
│ ├── brickgen.yaml
|
||||
│ ├── hooks
|
||||
│ │ └── pre_gen.dart
|
||||
│ ├── <brick_folder>
|
||||
│ │ └── ... compilable project
|
||||
```
|
||||
|
||||
### Brick (Mason)
|
||||
|
||||
```yaml
|
||||
name: <brick_name>
|
||||
description: <brick_description>
|
||||
|
||||
version: 0.1.0
|
||||
|
||||
vars:
|
||||
...
|
||||
```
|
||||
|
||||
- name: the brick name (will be in `brick.yaml`)
|
||||
- description: the brick description (will be in `brick.yaml`)
|
||||
- version: the brick version (will be in `brick.yaml`)
|
||||
- vars: the brick variables (will be in `brick.yaml`)
|
||||
|
||||
#### String variable
|
||||
|
||||
```yaml
|
||||
name:
|
||||
compilable: <compilable>
|
||||
type: string
|
||||
description: <description>
|
||||
default: <default>
|
||||
prompt: <prompt>
|
||||
```
|
||||
|
||||
- name: the variable name (will be in `brick.yaml`)
|
||||
- compilable: the variable compilable name used in brickgen project
|
||||
- type: variable type, here string, (will be in `brick.yaml`)
|
||||
- default: default value (will be in `brick.yaml`)
|
||||
- prompt: the displayed prompt at the brick generation (will be in `brick.yaml`)
|
||||
|
||||
#### Boolean variable
|
||||
|
||||
```yaml
|
||||
name:
|
||||
type: boolean
|
||||
description: <description>
|
||||
default: <default>
|
||||
prompt: <prompt>
|
||||
```
|
||||
|
||||
- name: the variable name (will be in `brick.yaml`)
|
||||
- type: variable type, here string, (will be in `brick.yaml`)
|
||||
- default: default value (will be in `brick.yaml`)
|
||||
- prompt: the displayed prompt at the brick generation (will be in `brick.yaml`)
|
||||
|
||||
> Identical to Mason
|
||||
|
||||
### Brickgen
|
||||
|
||||
```yaml
|
||||
brickgen:
|
||||
path_to_brickify: <brick_folder>
|
||||
ignore:
|
||||
- ...
|
||||
hooks: true
|
||||
boolean_file_system:
|
||||
...
|
||||
```
|
||||
|
||||
- path_to_brickify: the path of the compilable project that will be brickified
|
||||
- ignore: list of the ignored files and folders.
|
||||
- be sure to add an `/` at the end of the folders name.
|
||||
- hooks: copy or not `hooks` folder
|
||||
- boolean_file_system: list of the boolean file system variables
|
||||
|
||||
#### Boolean File System
|
||||
|
||||
```yaml
|
||||
boolean_file_system:
|
||||
boolean:
|
||||
folders:
|
||||
on_true:
|
||||
- ...
|
||||
on_false:
|
||||
- ...
|
||||
files:
|
||||
on_true:
|
||||
- ...
|
||||
on_false:
|
||||
- ...
|
||||
```
|
||||
|
||||
- boolean: name of the `boolean` variable used.
|
||||
- folders
|
||||
- on_true: list of the folders includes if the variable is `true`
|
||||
- on_true: list of the folders includes if the variable is `false`
|
||||
- files
|
||||
- on_true: list of the files includes if the variable is `true`
|
||||
- on_true: list of the files includes if the variable is `false`
|
||||
|
||||
> `on_true` and `on_false` are optionnal. (You are allowed to set one or two of them).
|
||||
|
||||
## Specifications (WIP)
|
||||
|
||||
File structure:
|
||||
|
||||
```
|
||||
apps
|
||||
├── <brick_name>
|
||||
│ ├── brickgen.yaml
|
||||
│ ├── hooks
|
||||
│ │ └── pre_gen.dart
|
||||
│ ├── <brick_folder>
|
||||
│ │ └── ... compilable project
|
||||
```
|
||||
|
||||
Configuration: `brickgen.yaml`
|
||||
|
||||
```yaml
|
||||
name: <brick_name>
|
||||
description: <brick_description>
|
||||
|
||||
version: 0.1.0
|
||||
|
||||
vars:
|
||||
display_name:
|
||||
compilable: Display Name
|
||||
type: string
|
||||
description: The display name
|
||||
default: Display Name
|
||||
prompt: "What is the display name?"
|
||||
|
||||
project_name:
|
||||
compilable: wyatt_app_template
|
||||
type: string
|
||||
description: The project name
|
||||
default: wyatt_app
|
||||
prompt: "What is the project name?"
|
||||
|
||||
bundle_id:
|
||||
compilable: io.wyattapp.new
|
||||
type: string
|
||||
description: The bundle id used in Android and iOS
|
||||
default: io.wyattapp.new
|
||||
prompt: "What is the bundle id?"
|
||||
|
||||
flutter:
|
||||
type: boolean
|
||||
description: If this app is a Flutter or Dart project.
|
||||
default: false
|
||||
prompt: "Is it Flutter app ?"
|
||||
|
||||
brickgen:
|
||||
path_to_brickify: <brick_folder>
|
||||
ignore:
|
||||
- .env
|
||||
- node_modules/
|
||||
hooks: true
|
||||
boolean_mapping:
|
||||
flutter:
|
||||
folders:
|
||||
- "test":
|
||||
on_true: "test"
|
||||
on_false: "test_dart"
|
||||
files:
|
||||
- "pubspec.yaml":
|
||||
on_true: pubspec.yaml
|
||||
on_false: pubspec.dart.yaml
|
||||
boolean_file_system:
|
||||
flutter:
|
||||
folders:
|
||||
on_true:
|
||||
- android
|
||||
- ios
|
||||
on_false:
|
||||
- bin
|
||||
files:
|
||||
on_true:
|
||||
- l10n.yaml
|
||||
- trapeze.yaml
|
||||
```
|
||||
|
||||
Will generate:
|
||||
|
||||
```
|
||||
bricks
|
||||
├── <brick_name>
|
||||
│ ├── brick.yaml
|
||||
│ ├── hooks
|
||||
│ │ └── pre_gen.dart
|
||||
│ ├── __brick__
|
||||
│ │ └── <brick_folder>
|
||||
```
|
||||
|
||||
> It creates a sub folder in __brick__
|
||||
|
||||
|
||||
### How copy works
|
||||
|
||||
- Case 1
|
||||
|
||||
```
|
||||
apps
|
||||
├── brick_1
|
||||
│ ├── brickgen.yaml
|
||||
│ ├── hooks
|
||||
│ │ └── pre_gen.dart
|
||||
│ ├── brick_1
|
||||
│ │ ├── lib/
|
||||
│ │ └── pubspec.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
...
|
||||
name: awesome_brick_1
|
||||
brickgen:
|
||||
path_to_brickify: brick_1
|
||||
hooks: true
|
||||
...
|
||||
```
|
||||
|
||||
```sh
|
||||
dart ./tools/brick_generator/bin/brickgen.dart ./apps/brick_1
|
||||
```
|
||||
|
||||
Will generate:
|
||||
|
||||
```
|
||||
bricks
|
||||
├── awesome_brick_1
|
||||
│ ├── brick.yaml
|
||||
│ ├── hooks
|
||||
│ │ └── pre_gen.dart
|
||||
│ ├── __brick__
|
||||
│ │ ├── lib/
|
||||
│ │ └── pubspec.yaml
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
- Case 2
|
||||
|
||||
```
|
||||
apps
|
||||
├── brick_2
|
||||
│ ├── brickgen.yaml
|
||||
│ ├── hooks
|
||||
│ │ └── pre_gen.dart
|
||||
│ ├── brick_2
|
||||
│ │ ├── lib
|
||||
│ │ │ └── widget.dart
|
||||
│ │ └── pubspec.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
...
|
||||
name: awesome_brick_2
|
||||
brickgen:
|
||||
path_to_brickify: brick_2/lib
|
||||
hooks: false
|
||||
...
|
||||
```
|
||||
|
||||
```sh
|
||||
dart ./tools/brick_generator/bin/brickgen.dart ./apps/brick_2
|
||||
```
|
||||
|
||||
Will generate:
|
||||
|
||||
```
|
||||
bricks
|
||||
├── awesome_brick_2
|
||||
│ ├── brick.yaml
|
||||
│ ├── __brick__
|
||||
│ │ └── widget.dart
|
||||
```
|
@ -1,30 +0,0 @@
|
||||
name: <brick_name>
|
||||
description: <brick_description>
|
||||
|
||||
version: 0.1.0
|
||||
|
||||
vars:
|
||||
display_name:
|
||||
type: string
|
||||
description: The display name
|
||||
default: Display Name
|
||||
prompt: What is the display name?
|
||||
|
||||
project_name:
|
||||
type: string
|
||||
description: The project name
|
||||
default: wyatt_app
|
||||
prompt: What is the project name?
|
||||
|
||||
bundle_id:
|
||||
type: string
|
||||
description: The bundle id used in Android and iOS
|
||||
default: io.wyattapp.new
|
||||
prompt: What is the bundle id?
|
||||
|
||||
flutter:
|
||||
type: boolean
|
||||
description: If this app is a Flutter or Dart project.
|
||||
default: false
|
||||
prompt: Is it Flutter app ?
|
||||
|
@ -1,93 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:brick_generator/core/logger.dart';
|
||||
import 'package:brick_generator/core/shell.dart';
|
||||
import 'package:brick_generator/file_system_utils.dart';
|
||||
import 'package:brick_generator/models/brick_config.dart';
|
||||
import 'package:brick_generator/yaml_reader.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
// Constants
|
||||
const _bricks = 'bricks';
|
||||
const _brickFolderLabel = '__brick__';
|
||||
const _yamlFileName = 'brick_config.yaml';
|
||||
const _cfgFileName = 'brick.yaml';
|
||||
|
||||
Future<void> main(List<String> arguments) async {
|
||||
try {
|
||||
if (arguments.length != 1) {
|
||||
Logger.error('Please provide project path.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
final projectPath = arguments[0];
|
||||
|
||||
// Store options from yaml file
|
||||
final configs =
|
||||
YamlReader.readYamlFile(path.join(projectPath, _yamlFileName));
|
||||
final brickConfig = BrickConfig.from(configs);
|
||||
Logger.info('Config retrieved.');
|
||||
|
||||
brickConfig?.checkFormat();
|
||||
|
||||
// Define paths
|
||||
final sourcePath = path.join(
|
||||
projectPath,
|
||||
brickConfig!.pathToBrickify,
|
||||
);
|
||||
final cfgTarget = path.join(
|
||||
_bricks,
|
||||
brickConfig.name,
|
||||
_cfgFileName,
|
||||
);
|
||||
final targetPath = path.join(
|
||||
_bricks,
|
||||
brickConfig.name,
|
||||
_brickFolderLabel,
|
||||
);
|
||||
Logger.info('Path defined.');
|
||||
|
||||
// Remove previously generated files
|
||||
final targetDir = Directory(targetPath);
|
||||
if (targetDir.existsSync()) {
|
||||
await targetDir.delete(recursive: true);
|
||||
}
|
||||
|
||||
final cfgTargetFile = File(cfgTarget);
|
||||
if (cfgTargetFile.existsSync()) {
|
||||
await cfgTargetFile.delete();
|
||||
}
|
||||
|
||||
// create target folder
|
||||
await Shell.mkdir(targetPath);
|
||||
|
||||
// Copy project files
|
||||
await Shell.cp(sourcePath, targetPath);
|
||||
Logger.info('Files copied.');
|
||||
|
||||
// Remove ignored folders
|
||||
final brickPath = path.join(targetPath, brickConfig.pathToBrickify);
|
||||
await FileSystemUtils.deleteIgnoredFolders(brickConfig, brickPath);
|
||||
|
||||
// Convert values to variables
|
||||
await FileSystemUtils.convertValuesToVariablesInFolder(
|
||||
brickConfig,
|
||||
targetPath,
|
||||
);
|
||||
Logger.info('Values converted into variables.');
|
||||
|
||||
// Rename files and folders
|
||||
await FileSystemUtils.renamePathsInFolder(brickConfig, targetPath);
|
||||
Logger.info('Folders and files renamed.');
|
||||
|
||||
// Create config file
|
||||
cfgTargetFile.writeAsStringSync(brickConfig.toBrickYaml());
|
||||
Logger.info('brick.yml added.');
|
||||
|
||||
await FileSystemUtils.deleteEmptyFolders(targetPath);
|
||||
Logger.info('Empty folders removed');
|
||||
Logger.success('Brick template available at $targetPath');
|
||||
} catch (e) {
|
||||
Logger.error(e);
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ import 'package:path/path.dart';
|
||||
const _configurationFileName = 'brickgen.yaml';
|
||||
const _masonConfigurationFileName = 'brick.yaml';
|
||||
const _brickFolderName = '__brick__';
|
||||
const _hooksFolderName = 'hooks';
|
||||
|
||||
const _helpOption = 'help';
|
||||
const _verboseOption = 'verbose';
|
||||
@ -37,10 +38,12 @@ class Brickgen {
|
||||
final bool deleteEmptyFolders;
|
||||
|
||||
late String configPath;
|
||||
late String hooksInputPath;
|
||||
|
||||
String? toBrickifyPath;
|
||||
String? masonConfigPath;
|
||||
String? targetPath;
|
||||
String? hooksOutputPath;
|
||||
|
||||
Brickgen({
|
||||
required this.brickPath,
|
||||
@ -48,6 +51,7 @@ class Brickgen {
|
||||
required this.deleteEmptyFolders,
|
||||
}) {
|
||||
configPath = join(brickPath, _configurationFileName);
|
||||
hooksInputPath = join(brickPath, _hooksFolderName);
|
||||
}
|
||||
|
||||
Future<void> run() async {
|
||||
@ -70,6 +74,13 @@ class Brickgen {
|
||||
);
|
||||
Logger.debug('Define `masonConfigPath`: $masonConfigPath');
|
||||
|
||||
hooksOutputPath = FileSystem.joinRecreate(
|
||||
outputPath,
|
||||
config.name,
|
||||
_hooksFolderName,
|
||||
);
|
||||
Logger.debug('Define `hooksOutputPath`: $hooksOutputPath');
|
||||
|
||||
targetPath = FileSystem.joinRecreate(
|
||||
outputPath,
|
||||
config.name,
|
||||
@ -78,7 +89,8 @@ class Brickgen {
|
||||
Logger.debug('Define `targetPath`: $targetPath');
|
||||
|
||||
// Check paths
|
||||
if (toBrickifyPath == null || targetPath == null) {
|
||||
if (toBrickifyPath == null || targetPath == null
|
||||
|| masonConfigPath == null || hooksOutputPath == null) {
|
||||
throw Exception('An error occures during path definition.');
|
||||
}
|
||||
Logger.info('Paths defined.');
|
||||
@ -90,6 +102,11 @@ 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.');
|
||||
// TODO(wyatt): generate hook to handle boolean mapping.
|
||||
|
||||
// Convert compilable values -> variables (in files)
|
||||
FileSystem.convertCompilableVariablesInFolder(config, targetPath!);
|
||||
@ -109,17 +126,16 @@ class Brickgen {
|
||||
FileSystem.renameCompilableFilesInFolder(config, targetPath!);
|
||||
Logger.info('Files renamed with variables.');
|
||||
|
||||
// Take care of boolean mapping and boolean fs
|
||||
|
||||
// Create Mason config
|
||||
FileSystem.writeFile(masonConfigPath!, config.toMason());
|
||||
Logger.info('Mason `brick.yaml` generated.');
|
||||
|
||||
// Create gitkeep hook
|
||||
|
||||
// Copy custom hooks
|
||||
// Copy hooks
|
||||
await FileSystem.copyHooks(config, hooksInputPath, hooksOutputPath!);
|
||||
|
||||
// Success!
|
||||
Logger.success('Brick template available at $targetPath');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,7 +341,7 @@ abstract class FileSystem {
|
||||
if (toReplace != null && file.path.contains(toReplace)) {
|
||||
final newPath = file.path.replaceAll(
|
||||
toReplace,
|
||||
'{{${variable.name}.${syntax.id}}}',
|
||||
'{{${variable.name}.${syntax.id}()}}',
|
||||
);
|
||||
|
||||
File(newPath).createSync(recursive: true);
|
||||
@ -354,4 +354,124 @@ abstract class FileSystem {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static Future<void> copyHooks(
|
||||
BrickConfig config,
|
||||
String source,
|
||||
String targetPath,
|
||||
) async {
|
||||
if (!config.brickgenConfig.hooks) {
|
||||
Logger.debug('Ignore hooks');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FileSystemEntity.isDirectorySync(source)) {
|
||||
throw ArgumentError('Source must be a directory', 'source');
|
||||
}
|
||||
|
||||
if (!FileSystemEntity.isDirectorySync(targetPath)) {
|
||||
throw ArgumentError('Target must be a directory', 'targetPath');
|
||||
}
|
||||
|
||||
await copyFolder(source, targetPath);
|
||||
Logger.info('Hooks copied.');
|
||||
}
|
||||
|
||||
/// Apply boolean file system: create or not folders/files depending of
|
||||
/// a boolean variable.
|
||||
///
|
||||
/// Example
|
||||
/// ```yaml
|
||||
/// boolean_file_system:
|
||||
/// flutter:
|
||||
/// folders:
|
||||
/// on_true:
|
||||
/// - android
|
||||
/// - ios
|
||||
/// - assets
|
||||
/// on_false:
|
||||
/// - bin
|
||||
/// files:
|
||||
/// on_true:
|
||||
/// - l10n.yaml
|
||||
/// - trapeze.yaml
|
||||
/// ```
|
||||
///
|
||||
/// Creates some folders and files depending of `flutter` variable.
|
||||
static void applyBooleanFileSystem(
|
||||
BrickConfig config,
|
||||
String targetPath,
|
||||
) {
|
||||
for (final variable in config.brickgenConfig.booleanFileSystem) {
|
||||
final boolean = variable.booleanName;
|
||||
|
||||
String rename(
|
||||
String boolean,
|
||||
FileSystemEntity entity, {
|
||||
bool? onValue,
|
||||
}) {
|
||||
final entityPath = entity.path;
|
||||
final entityPathSplitted =
|
||||
(entityPath.split('/')..removeWhere((element) => element.isEmpty));
|
||||
final entityRenamed =
|
||||
'{{${(onValue ?? true) ? "#" : "^"}$boolean}}${entityPathSplitted.last}{{/$boolean}}';
|
||||
final entityNewPath =
|
||||
((entityPathSplitted..removeLast())..add(entityRenamed)).join('/');
|
||||
|
||||
Logger.debug('Apply boolean file system on $entityPath');
|
||||
|
||||
return entityNewPath;
|
||||
}
|
||||
|
||||
// Rename folders
|
||||
for (final folder in variable.folders.onTrueNames) {
|
||||
final directory = Directory(join(targetPath, folder));
|
||||
final newPath = rename(
|
||||
boolean,
|
||||
directory,
|
||||
onValue: true,
|
||||
);
|
||||
|
||||
Directory(newPath).createSync(recursive: true);
|
||||
directory.renameSync(newPath);
|
||||
}
|
||||
|
||||
for (final folder in variable.folders.onFalseNames) {
|
||||
final directory = Directory(join(targetPath, folder));
|
||||
final newPath = rename(
|
||||
boolean,
|
||||
directory,
|
||||
onValue: false,
|
||||
);
|
||||
|
||||
Directory(newPath).createSync(recursive: true);
|
||||
directory.renameSync(newPath);
|
||||
}
|
||||
|
||||
// Rename files
|
||||
for (final path in variable.files.onTrueNames) {
|
||||
final file = File(join(targetPath, path));
|
||||
final newPath = rename(
|
||||
boolean,
|
||||
file,
|
||||
onValue: true,
|
||||
);
|
||||
|
||||
File(newPath).createSync(recursive: true);
|
||||
file.renameSync(newPath);
|
||||
}
|
||||
|
||||
for (final path in variable.files.onFalseNames) {
|
||||
final file = File(join(targetPath, path));
|
||||
final newPath = rename(
|
||||
boolean,
|
||||
file,
|
||||
onValue: false,
|
||||
);
|
||||
|
||||
File(newPath).createSync(recursive: true);
|
||||
file.renameSync(newPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,26 @@
|
||||
// Copyright (C) 2023 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:yaml/yaml.dart';
|
||||
|
||||
class YamlReader {
|
||||
static YamlMap readYamlFile(String path) =>
|
||||
abstract class Reader {}
|
||||
|
||||
class YamlReader extends Reader {
|
||||
static YamlMap read(String path) =>
|
||||
loadYaml(File(path).readAsStringSync()) as YamlMap;
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
// Copyright (C) 2023 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:brick_generator/core/logger.dart';
|
||||
import 'package:brick_generator/core/shell.dart';
|
||||
import 'package:brick_generator/models/brick_config.dart';
|
||||
import 'package:brick_generator/models/variable_string_syntax.dart';
|
||||
import 'package:brick_generator/models/variable_type.dart';
|
||||
import 'package:path/path.dart';
|
||||
|
||||
class FileSystemUtils {
|
||||
static Future<void> convertValuesToVariablesInFolder(
|
||||
BrickConfig brickConfig,
|
||||
String path,
|
||||
) async {
|
||||
await Future.wait(
|
||||
Directory(path)
|
||||
.listSync(recursive: true)
|
||||
.whereType<File>()
|
||||
.map((f) async {
|
||||
var file = f;
|
||||
|
||||
try {
|
||||
var contents = await file.readAsString();
|
||||
|
||||
// Transform all values in variables
|
||||
if (brickConfig.variables != null) {
|
||||
for (final variable in brickConfig.variables!) {
|
||||
// Replace all string variables
|
||||
if (variable?.type == VariableType.string) {
|
||||
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}}}',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Logger.debug(
|
||||
'Variable `${variable?.name}` replaced in ${file.path}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Replace content
|
||||
file = await file.writeAsString(contents);
|
||||
} catch (e) {
|
||||
Logger.error(e);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
static Future<void> renamePathsInFolder(
|
||||
BrickConfig brickConfig,
|
||||
String path,
|
||||
) async {
|
||||
await Future.wait(
|
||||
Directory(path)
|
||||
.listSync(recursive: true)
|
||||
.whereType<File>()
|
||||
.map((_) async {
|
||||
final file = _;
|
||||
|
||||
// Rename file if needed
|
||||
if (brickConfig.variables != null) {
|
||||
for (final variable in brickConfig.variables!) {
|
||||
if (variable?.type == VariableType.string &&
|
||||
variable?.syntax?[VariableStringSyntax.snakeCase.mapKey] !=
|
||||
null) {
|
||||
final snake =
|
||||
variable!.syntax![VariableStringSyntax.snakeCase.mapKey];
|
||||
if (snake == null) {
|
||||
const err = 'Invalid snake_case syntax';
|
||||
Logger.throwError(ArgumentError(err), err);
|
||||
}
|
||||
final newPath = file.path.replaceAll(
|
||||
snake!,
|
||||
'{{${variable.name}.snakeCase()}}',
|
||||
);
|
||||
|
||||
await File(newPath).create(recursive: true);
|
||||
await file.rename(newPath);
|
||||
Logger.debug(
|
||||
'${file.path} renamed with variable `${variable.name}`',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
static Future<void> deleteEmptyFolders(String path) async {
|
||||
for (final dir in Directory(path).listSync(recursive: true).reversed) {
|
||||
if (dir is Directory) {
|
||||
if (dir.existsSync() && await dir.list().isEmpty) {
|
||||
await dir.delete(recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For the moment ignored files are copied, then deleted...
|
||||
static Future<void> deleteIgnoredFolders(
|
||||
BrickConfig brickConfig,
|
||||
String brickPath,
|
||||
) async {
|
||||
for (final String ignore in brickConfig.brickgenConfig.ignore.ignored) {
|
||||
final String toDelete = join(brickPath, ignore);
|
||||
if (FileSystemEntity.isDirectorySync(toDelete)) {
|
||||
await Shell.rm(toDelete, recursive: true);
|
||||
} else {
|
||||
await Shell.rm(toDelete);
|
||||
}
|
||||
Logger.debug('$toDelete ignored.');
|
||||
}
|
||||
}
|
||||
}
|
@ -14,9 +14,9 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:brick_generator/core/reader.dart';
|
||||
import 'package:brick_generator/models/brick_variable.dart';
|
||||
import 'package:brick_generator/models/brickgen_config.dart';
|
||||
import 'package:brick_generator/yaml_reader.dart';
|
||||
import 'package:yaml/yaml.dart';
|
||||
|
||||
const _nameKey = 'name';
|
||||
@ -62,7 +62,7 @@ class BrickConfig {
|
||||
throw ArgumentError.notNull('path');
|
||||
}
|
||||
|
||||
final config = YamlReader.readYamlFile(path);
|
||||
final config = YamlReader.read(path);
|
||||
|
||||
return BrickConfig.parse(config);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user