build: generate_template script + workflow (#11)
This commit is contained in:
parent
6791e7e613
commit
b6e0a6e7c9
44
.github/workflows/generate_template.yaml
vendored
Normal file
44
.github/workflows/generate_template.yaml
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
name: generate_template
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- tool/generator/**
|
||||||
|
- app/**
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: dart-lang/setup-dart@v1
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
working-directory: tool/generator
|
||||||
|
run: dart pub get
|
||||||
|
|
||||||
|
- name: Generate Template
|
||||||
|
run: dart ./tool/generator/main.dart
|
||||||
|
|
||||||
|
- name: Config Git User
|
||||||
|
run: |
|
||||||
|
git config user.name VGV Bot
|
||||||
|
git config user.email vgvbot@users.noreply.github.com
|
||||||
|
|
||||||
|
- name: Create Pull Request
|
||||||
|
uses: peter-evans/create-pull-request@v3.6.0
|
||||||
|
with:
|
||||||
|
base: main
|
||||||
|
branch: chore/generate-template
|
||||||
|
commit-message: "chore: generate template"
|
||||||
|
title: "chore: generate template"
|
||||||
|
body: Please squash and merge me!
|
||||||
|
labels: bot
|
||||||
|
author: VGV Bot <vgvbot@users.noreply.github.com>
|
||||||
|
assignees: vgvbot
|
||||||
|
reviewers: felangel
|
||||||
|
committer: VGV Bot <vgvbot@users.noreply.github.com>
|
3
analysis_options.yaml
Normal file
3
analysis_options.yaml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
analyzer:
|
||||||
|
exclude:
|
||||||
|
- brick/**
|
53
brick/brick.yaml
Normal file
53
brick/brick.yaml
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
name: very_good_flutter_plugin
|
||||||
|
description: A very good federated Flutter plugin.
|
||||||
|
version: 0.1.0+1
|
||||||
|
|
||||||
|
environment:
|
||||||
|
mason: ">=0.1.0-dev <0.1.0"
|
||||||
|
|
||||||
|
vars:
|
||||||
|
project_name:
|
||||||
|
type: string
|
||||||
|
description: The name of the flutter plugin
|
||||||
|
default: my_plugin
|
||||||
|
prompt: What is the name of the plugin?
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
description: A short description of the plugin
|
||||||
|
default: A very good plugin
|
||||||
|
prompt: Please enter the plugin description.
|
||||||
|
org_name:
|
||||||
|
type: string
|
||||||
|
description: The organization name
|
||||||
|
default: com.example.verygood.plugin
|
||||||
|
prompt: What is the organization name?
|
||||||
|
android:
|
||||||
|
type: boolean
|
||||||
|
description: Whether the plugin will support Android
|
||||||
|
default: true
|
||||||
|
prompt: Do you want to include Android support?
|
||||||
|
ios:
|
||||||
|
type: boolean
|
||||||
|
description: Whether the plugin will support iOS
|
||||||
|
default: true
|
||||||
|
prompt: Do you want to include iOS support?
|
||||||
|
web:
|
||||||
|
type: boolean
|
||||||
|
description: Whether the plugin will support Web
|
||||||
|
default: true
|
||||||
|
prompt: Do you want to include Web support?
|
||||||
|
linux:
|
||||||
|
type: boolean
|
||||||
|
description: Whether the plugin will support Linux
|
||||||
|
default: true
|
||||||
|
prompt: Do you want to include Linux support?
|
||||||
|
macos:
|
||||||
|
type: boolean
|
||||||
|
description: Whether the plugin will support MacOS
|
||||||
|
default: true
|
||||||
|
prompt: Do you want to include MacOS support?
|
||||||
|
windows:
|
||||||
|
type: boolean
|
||||||
|
description: Whether the plugin will support Windows
|
||||||
|
default: true
|
||||||
|
prompt: Do you want to include Windows support?
|
48
src/.gitignore
vendored
Normal file
48
src/.gitignore
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
.DS_Store
|
||||||
|
.atom/
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
.packages
|
||||||
|
.pub/
|
||||||
|
.dart_tool/
|
||||||
|
pubspec.lock
|
||||||
|
flutter_export_environment.sh
|
||||||
|
coverage/
|
||||||
|
|
||||||
|
Podfile.lock
|
||||||
|
Pods/
|
||||||
|
.symlinks/
|
||||||
|
**/Flutter/App.framework/
|
||||||
|
**/Flutter/ephemeral/
|
||||||
|
**/Flutter/Flutter.podspec
|
||||||
|
**/Flutter/Flutter.framework/
|
||||||
|
**/Flutter/Generated.xcconfig
|
||||||
|
**/Flutter/flutter_assets/
|
||||||
|
|
||||||
|
ServiceDefinitions.json
|
||||||
|
xcuserdata/
|
||||||
|
**/DerivedData/
|
||||||
|
|
||||||
|
local.properties
|
||||||
|
keystore.properties
|
||||||
|
.gradle/
|
||||||
|
gradlew
|
||||||
|
gradlew.bat
|
||||||
|
gradle-wrapper.jar
|
||||||
|
.flutter-plugins-dependencies
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
generated_plugin_registrant.cc
|
||||||
|
generated_plugin_registrant.h
|
||||||
|
generated_plugin_registrant.dart
|
||||||
|
GeneratedPluginRegistrant.java
|
||||||
|
GeneratedPluginRegistrant.h
|
||||||
|
GeneratedPluginRegistrant.m
|
||||||
|
GeneratedPluginRegistrant.swift
|
||||||
|
build/
|
||||||
|
.flutter-plugins
|
||||||
|
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.settings
|
21
src/LICENSE
Normal file
21
src/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Very Good Ventures
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
26
src/README.md
Normal file
26
src/README.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# my_plugin
|
||||||
|
|
||||||
|
[![Very Good Ventures][logo_white]][very_good_ventures_link_dark]
|
||||||
|
[![Very Good Ventures][logo_black]][very_good_ventures_link_light]
|
||||||
|
|
||||||
|
Developed with 💙 by [Very Good Ventures][very_good_ventures_link] 🦄
|
||||||
|
|
||||||
|
![coverage][coverage_badge]
|
||||||
|
[![style: very good analysis][very_good_analysis_badge]][very_good_analysis_link]
|
||||||
|
[![License: MIT][license_badge]][license_link]
|
||||||
|
|
||||||
|
A Very Good Flutter Federated Plugin created by the [Very Good Ventures Team][very_good_ventures_link].
|
||||||
|
|
||||||
|
Generated by the [Very Good CLI][very_good_cli_link] 🤖
|
||||||
|
|
||||||
|
[coverage_badge]: app/coverage_badge.svg
|
||||||
|
[license_badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
||||||
|
[license_link]: https://opensource.org/licenses/MIT
|
||||||
|
[logo_black]: https://raw.githubusercontent.com/VGVentures/very_good_brand/main/styles/README/vgv_logo_black.png#gh-light-mode-only
|
||||||
|
[logo_white]: https://raw.githubusercontent.com/VGVentures/very_good_brand/main/styles/README/vgv_logo_white.png#gh-dark-mode-only
|
||||||
|
[very_good_analysis_badge]: https://img.shields.io/badge/style-very_good_analysis-B22C89.svg
|
||||||
|
[very_good_analysis_link]: https://pub.dev/packages/very_good_analysis
|
||||||
|
[very_good_cli_link]: https://github.com/VeryGoodOpenSource/very_good_cli
|
||||||
|
[very_good_ventures_link]: https://verygood.ventures/?utm_source=github&utm_medium=banner&utm_campaign=core
|
||||||
|
[very_good_ventures_link_dark]: https://verygood.ventures/?utm_source=github&utm_medium=banner&utm_campaign=core#gh-dark-mode-only
|
||||||
|
[very_good_ventures_link_light]: https://verygood.ventures/?utm_source=github&utm_medium=banner&utm_campaign=core#gh-light-mode-only
|
@ -43,7 +43,7 @@ android {
|
|||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
applicationId "dev.flutter.plugins.example"
|
applicationId "com.example.my_plugin.example"
|
||||||
minSdkVersion flutter.minSdkVersion
|
minSdkVersion flutter.minSdkVersion
|
||||||
targetSdkVersion flutter.targetSdkVersion
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="dev.flutter.plugins.example">
|
package="com.example.my_plugin.example">
|
||||||
<!-- Flutter needs it to communicate with the running application
|
<!-- Flutter needs it to communicate with the running application
|
||||||
to allow setting breakpoints, to provide hot reload, etc.
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
-->
|
-->
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="dev.flutter.plugins.example">
|
package="com.example.my_plugin.example">
|
||||||
<application
|
<application
|
||||||
android:label="example"
|
android:label="example"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package dev.flutter.plugins.example
|
package com.example.my_plugin.example
|
||||||
|
|
||||||
import io.flutter.embedding.android.FlutterActivity
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="dev.flutter.plugins.example">
|
package="com.example.my_plugin">
|
||||||
<!-- Flutter needs it to communicate with the running application
|
<!-- Flutter needs it to communicate with the running application
|
||||||
to allow setting breakpoints, to provide hot reload, etc.
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
-->
|
-->
|
||||||
|
@ -363,7 +363,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.example;
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.my_plugin;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
@ -492,7 +492,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.example;
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.my_plugin;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
@ -515,7 +515,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.example;
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.my_plugin;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
PRODUCT_NAME = example
|
PRODUCT_NAME = example
|
||||||
|
|
||||||
// The application's bundle identifier
|
// The application's bundle identifier
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.example
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.my_plugin
|
||||||
|
|
||||||
// The copyright displayed in application information
|
// The copyright displayed in application information
|
||||||
PRODUCT_COPYRIGHT = Copyright © 2022 dev.flutter.plugins. All rights reserved.
|
PRODUCT_COPYRIGHT = Copyright © 2022 dev.flutter.plugins. All rights reserved.
|
||||||
|
222
tool/generator/main.dart
Normal file
222
tool/generator/main.dart
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
|
final _githubPath = path.join('.github');
|
||||||
|
final _sourcePath = path.join('src');
|
||||||
|
final _targetPath = path.join('brick', '__brick__');
|
||||||
|
final _androidPath = path.join(_targetPath, 'my_plugin_android', 'android');
|
||||||
|
final _androidKotlinPath = path.join(_androidPath, 'src', 'main', 'kotlin');
|
||||||
|
final _sourceMyPluginKtPath = path.join(
|
||||||
|
_androidKotlinPath,
|
||||||
|
'com',
|
||||||
|
'example',
|
||||||
|
'my_plugin',
|
||||||
|
'MyPluginPlugin.kt',
|
||||||
|
);
|
||||||
|
final _targetMyPluginKtPath = path.join(
|
||||||
|
_androidKotlinPath,
|
||||||
|
'{{#pathCase}}{{org_name}}{{/pathCase}}',
|
||||||
|
'{{#pascalCase}}{{project_name}}{{/pascalCase}}Plugin.kt',
|
||||||
|
);
|
||||||
|
final year = DateTime.now().year;
|
||||||
|
final copyrightHeader = '''
|
||||||
|
// Copyright (c) $year, Very Good Ventures
|
||||||
|
// https://verygood.ventures
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file or at
|
||||||
|
// https://opensource.org/licenses/MIT.
|
||||||
|
''';
|
||||||
|
|
||||||
|
final excludedFiles = [
|
||||||
|
path.join(
|
||||||
|
_targetPath,
|
||||||
|
'.github',
|
||||||
|
'workflows',
|
||||||
|
'generate_template.yaml',
|
||||||
|
),
|
||||||
|
path.join(_targetPath, '.github', 'CODEOWNERS'),
|
||||||
|
];
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
// Remove Previously Generated Files
|
||||||
|
final targetDir = Directory(_targetPath);
|
||||||
|
if (targetDir.existsSync()) {
|
||||||
|
await targetDir.delete(recursive: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy Project Files
|
||||||
|
await Future.wait([
|
||||||
|
Shell.cp(_sourcePath, _targetPath),
|
||||||
|
Shell.cp(_githubPath, path.join(_targetPath)),
|
||||||
|
() async {
|
||||||
|
await Shell.mkdir(File(_targetMyPluginKtPath).parent.path);
|
||||||
|
await Shell.cp(_sourceMyPluginKtPath, _targetMyPluginKtPath);
|
||||||
|
await Shell.rm(File(_sourceMyPluginKtPath).parent.parent.path);
|
||||||
|
}()
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Remove excluded files
|
||||||
|
await Future.wait(
|
||||||
|
excludedFiles.map((file) => File(file).delete(recursive: true)),
|
||||||
|
);
|
||||||
|
|
||||||
|
await Future.wait(
|
||||||
|
Directory(_targetPath)
|
||||||
|
.listSync(recursive: true)
|
||||||
|
.whereType<File>()
|
||||||
|
.map((_) async {
|
||||||
|
var file = _;
|
||||||
|
if (!file.existsSync()) return;
|
||||||
|
|
||||||
|
// Add copyright header to all .dart files
|
||||||
|
if (path.extension(file.path) == '.dart') {
|
||||||
|
final contents = await file.readAsString();
|
||||||
|
file = await file.writeAsString('$copyrightHeader\n$contents');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Template File Contents
|
||||||
|
final contents =
|
||||||
|
file.isAsset() ? await file.readAsBytes() : await file.readAsString();
|
||||||
|
final templatedContents = (contents is String)
|
||||||
|
? contents
|
||||||
|
.replaceAll(
|
||||||
|
'com.example.my_plugin',
|
||||||
|
'{{#dotCase}}{{org_name}}{{/dotCase}}',
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
'my_plugin',
|
||||||
|
'{{#snakeCase}}{{project_name}}{{/snakeCase}}',
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
'my-plugin',
|
||||||
|
'{{#paramCase}}{{project_name}}{{/paramCase}}',
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
'MyPlugin',
|
||||||
|
'{{#pascalCase}}{{project_name}}{{/pascalCase}}',
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
'A very good Flutter federated plugin',
|
||||||
|
'{{{description}}}',
|
||||||
|
)
|
||||||
|
: contents;
|
||||||
|
file = templatedContents is String
|
||||||
|
? await file.writeAsString(templatedContents)
|
||||||
|
: await file.writeAsBytes(templatedContents as List<int>);
|
||||||
|
|
||||||
|
/// Template file paths
|
||||||
|
final fileSegments = file.path.split('/').sublist(2);
|
||||||
|
if (fileSegments
|
||||||
|
.any((e) => e.contains('my_plugin') || e.contains('MyPlugin'))) {
|
||||||
|
final newSegments = fileSegments.map((e) {
|
||||||
|
return e
|
||||||
|
.replaceAll(
|
||||||
|
'MyPlugin',
|
||||||
|
'{{#pascalCase}}{{project_name}}{{/pascalCase}}',
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
'my_plugin',
|
||||||
|
'{{#snakeCase}}{{project_name}}{{/snakeCase}}',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
final newPathSegment = newSegments.join('/');
|
||||||
|
final newPath = path.join(_targetPath, newPathSegment);
|
||||||
|
final newFile = File(newPath)..createSync(recursive: true);
|
||||||
|
templatedContents is String
|
||||||
|
? newFile.writeAsStringSync(templatedContents)
|
||||||
|
: newFile.writeAsBytesSync(templatedContents as List<int>);
|
||||||
|
file = newFile;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Clean up top-level directories
|
||||||
|
const topLevelDirs = [
|
||||||
|
'my_plugin',
|
||||||
|
'my_plugin_android',
|
||||||
|
'my_plugin_ios',
|
||||||
|
'my_plugin_linux',
|
||||||
|
'my_plugin_macos',
|
||||||
|
'my_plugin_platform_interface',
|
||||||
|
'my_plugin_web',
|
||||||
|
'my_plugin_windows',
|
||||||
|
];
|
||||||
|
for (final dir in topLevelDirs) {
|
||||||
|
Directory(path.join(_targetPath, dir)).deleteSync(recursive: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Shell {
|
||||||
|
static Future<void> cp(String source, String destination) {
|
||||||
|
return _Cmd.run('cp', ['-rf', source, destination]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> rm(String source) {
|
||||||
|
return _Cmd.run('rm', ['-rf', source]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> mkdir(String destination) {
|
||||||
|
return _Cmd.run('mkdir', ['-p', destination]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _Cmd {
|
||||||
|
static Future<ProcessResult> run(
|
||||||
|
String cmd,
|
||||||
|
List<String> args, {
|
||||||
|
bool throwOnError = true,
|
||||||
|
String? processWorkingDir,
|
||||||
|
}) async {
|
||||||
|
final result = await Process.run(cmd, args,
|
||||||
|
workingDirectory: processWorkingDir, runInShell: true);
|
||||||
|
|
||||||
|
if (throwOnError) {
|
||||||
|
_throwIfProcessFailed(result, cmd, args);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _throwIfProcessFailed(
|
||||||
|
ProcessResult pr,
|
||||||
|
String process,
|
||||||
|
List<String> args,
|
||||||
|
) {
|
||||||
|
if (pr.exitCode != 0) {
|
||||||
|
final values = {
|
||||||
|
'Standard out': pr.stdout.toString().trim(),
|
||||||
|
'Standard error': pr.stderr.toString().trim()
|
||||||
|
}..removeWhere((k, v) => v.isEmpty);
|
||||||
|
|
||||||
|
String message;
|
||||||
|
if (values.isEmpty) {
|
||||||
|
message = 'Unknown error';
|
||||||
|
} else if (values.length == 1) {
|
||||||
|
message = values.values.single;
|
||||||
|
} else {
|
||||||
|
message = values.entries.map((e) => '${e.key}\n${e.value}').join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ProcessException(process, args, message, pr.exitCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension on File {
|
||||||
|
bool isAsset() {
|
||||||
|
const extensions = {
|
||||||
|
'.png',
|
||||||
|
'.ico',
|
||||||
|
'.svg',
|
||||||
|
'.jpg',
|
||||||
|
'.jpeg',
|
||||||
|
'.mov',
|
||||||
|
'.mp4',
|
||||||
|
'mp3',
|
||||||
|
'.wav',
|
||||||
|
'.ttf'
|
||||||
|
};
|
||||||
|
final ext = path.extension(this.path);
|
||||||
|
return extensions.contains(ext);
|
||||||
|
}
|
||||||
|
}
|
9
tool/generator/pubspec.yaml
Normal file
9
tool/generator/pubspec.yaml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
name: generator
|
||||||
|
description: A template generator for Very Good Flutter Plugin.
|
||||||
|
publish_to: none
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: ">=2.12.0 <3.0.0"
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
path: ^1.8.0
|
Reference in New Issue
Block a user