From 0b05a1847371184e82918ee853199891b2c7e0f5 Mon Sep 17 00:00:00 2001 From: kushalm Date: Sat, 4 Nov 2023 17:19:45 +0400 Subject: [PATCH] feat: Remove section added with test cases --- .dart_tool/package_config.json | 326 --------- CHANGELOG.md | 4 + README.md | 154 ++++- example/README.md | 154 ++++- example/_pubspec.yaml | 49 ++ example/pubspec_dev.yaml | 38 ++ example/pubspec_prod.yaml | 40 ++ lib/constants.dart | 29 +- lib/models/pubspec.dart | 12 +- lib/pubm.dart | 7 +- lib/src/configuration.dart | 20 +- lib/src/manage/manage_dependencies.dart | 39 ++ .../manage/manage_dependency_overrides.dart | 39 ++ lib/src/manage/manage_dev_dependencies.dart | 39 ++ lib/src/manage/manage_flutter_values.dart | 100 +++ lib/src/manage/manage_other_values.dart | 43 ++ lib/src/manage/pubspec_manage.dart | 211 ++++++ lib/src/manage/remove_values.dart | 220 ++++++ lib/src/manage/sort_all_dependencies.dart | 39 ++ lib/src/manage/update_actuap_pubspec.dart | 59 ++ lib/src/pubspec_manage.dart | 625 ------------------ pubspec.yaml | 2 +- test/helper.dart | 30 + test/mock_pubspec_manager.dart | 12 + test/pubm_test.dart | 388 ++++------- test/remove_value.dart | 116 ++++ test/test_constants.dart | 41 +- test/yaml_check.dart | 162 +++++ 28 files changed, 1733 insertions(+), 1265 deletions(-) delete mode 100644 .dart_tool/package_config.json create mode 100644 example/_pubspec.yaml create mode 100644 example/pubspec_dev.yaml create mode 100644 example/pubspec_prod.yaml create mode 100644 lib/src/manage/manage_dependencies.dart create mode 100644 lib/src/manage/manage_dependency_overrides.dart create mode 100644 lib/src/manage/manage_dev_dependencies.dart create mode 100644 lib/src/manage/manage_flutter_values.dart create mode 100644 lib/src/manage/manage_other_values.dart create mode 100644 lib/src/manage/pubspec_manage.dart create mode 100644 lib/src/manage/remove_values.dart create mode 100644 lib/src/manage/sort_all_dependencies.dart create mode 100644 lib/src/manage/update_actuap_pubspec.dart delete mode 100644 lib/src/pubspec_manage.dart create mode 100644 test/helper.dart create mode 100644 test/mock_pubspec_manager.dart create mode 100644 test/remove_value.dart create mode 100644 test/yaml_check.dart diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json deleted file mode 100644 index a6cbb82..0000000 --- a/.dart_tool/package_config.json +++ /dev/null @@ -1,326 +0,0 @@ -{ - "configVersion": 2, - "packages": [ - { - "name": "_fe_analyzer_shared", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/_fe_analyzer_shared-62.0.0", - "packageUri": "lib/", - "languageVersion": "3.0" - }, - { - "name": "analyzer", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/analyzer-6.0.0", - "packageUri": "lib/", - "languageVersion": "3.0" - }, - { - "name": "args", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/args-2.4.2", - "packageUri": "lib/", - "languageVersion": "2.19" - }, - { - "name": "async", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/async-2.11.0", - "packageUri": "lib/", - "languageVersion": "2.18" - }, - { - "name": "boolean_selector", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1", - "packageUri": "lib/", - "languageVersion": "2.17" - }, - { - "name": "cli_util", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/cli_util-0.4.0", - "packageUri": "lib/", - "languageVersion": "2.19" - }, - { - "name": "collection", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/collection-1.17.2", - "packageUri": "lib/", - "languageVersion": "2.18" - }, - { - "name": "convert", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/convert-3.1.1", - "packageUri": "lib/", - "languageVersion": "2.18" - }, - { - "name": "coverage", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/coverage-1.6.3", - "packageUri": "lib/", - "languageVersion": "2.18" - }, - { - "name": "crypto", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/crypto-3.0.3", - "packageUri": "lib/", - "languageVersion": "2.19" - }, - { - "name": "cupertino_icons", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/cupertino_icons-1.0.5", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "dart_internal", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/dart_internal-0.2.8", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "equatable", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/equatable-2.0.5", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "file", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/file-7.0.0", - "packageUri": "lib/", - "languageVersion": "3.0" - }, - { - "name": "frontend_server_client", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/frontend_server_client-3.2.0", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "get_it", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/get_it-7.6.0", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "glob", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/glob-2.1.2", - "packageUri": "lib/", - "languageVersion": "2.19" - }, - { - "name": "http_multi_server", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/http_multi_server-3.2.1", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "http_parser", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/http_parser-4.0.2", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "io", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/io-1.0.4", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "js", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/js-0.6.7", - "packageUri": "lib/", - "languageVersion": "2.19" - }, - { - "name": "json2yaml", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/json2yaml-3.0.1", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "lints", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/lints-2.1.1", - "packageUri": "lib/", - "languageVersion": "3.0" - }, - { - "name": "logging", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/logging-1.2.0", - "packageUri": "lib/", - "languageVersion": "2.19" - }, - { - "name": "matcher", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/matcher-0.12.16", - "packageUri": "lib/", - "languageVersion": "2.18" - }, - { - "name": "meta", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/meta-1.9.1", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "mime", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/mime-1.0.4", - "packageUri": "lib/", - "languageVersion": "2.18" - }, - { - "name": "node_preamble", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/node_preamble-2.0.2", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "package_config", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/package_config-2.1.0", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "path", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/path-1.8.3", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "pool", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/pool-1.5.1", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "pub_semver", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/pub_semver-2.1.4", - "packageUri": "lib/", - "languageVersion": "2.17" - }, - { - "name": "shelf", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/shelf-1.4.1", - "packageUri": "lib/", - "languageVersion": "2.17" - }, - { - "name": "shelf_packages_handler", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/shelf_packages_handler-3.0.2", - "packageUri": "lib/", - "languageVersion": "2.17" - }, - { - "name": "shelf_static", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/shelf_static-1.1.2", - "packageUri": "lib/", - "languageVersion": "2.17" - }, - { - "name": "shelf_web_socket", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/shelf_web_socket-1.0.4", - "packageUri": "lib/", - "languageVersion": "2.17" - }, - { - "name": "source_map_stack_trace", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/source_map_stack_trace-2.1.1", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "source_maps", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/source_maps-0.10.12", - "packageUri": "lib/", - "languageVersion": "2.18" - }, - { - "name": "source_span", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/source_span-1.9.1", - "packageUri": "lib/", - "languageVersion": "2.14" - }, - { - "name": "stack_trace", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/stack_trace-1.11.1", - "packageUri": "lib/", - "languageVersion": "2.18" - }, - { - "name": "stream_channel", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/stream_channel-2.1.2", - "packageUri": "lib/", - "languageVersion": "2.19" - }, - { - "name": "string_scanner", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/string_scanner-1.2.0", - "packageUri": "lib/", - "languageVersion": "2.18" - }, - { - "name": "term_glyph", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/term_glyph-1.2.1", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "test", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/test-1.24.4", - "packageUri": "lib/", - "languageVersion": "3.0" - }, - { - "name": "test_api", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/test_api-0.6.1", - "packageUri": "lib/", - "languageVersion": "3.0" - }, - { - "name": "test_core", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/test_core-0.5.4", - "packageUri": "lib/", - "languageVersion": "3.0" - }, - { - "name": "typed_data", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/typed_data-1.3.2", - "packageUri": "lib/", - "languageVersion": "2.17" - }, - { - "name": "vm_service", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/vm_service-11.7.2", - "packageUri": "lib/", - "languageVersion": "2.19" - }, - { - "name": "watcher", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/watcher-1.1.0", - "packageUri": "lib/", - "languageVersion": "3.0" - }, - { - "name": "web_socket_channel", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/web_socket_channel-2.4.0", - "packageUri": "lib/", - "languageVersion": "2.15" - }, - { - "name": "webkit_inspection_protocol", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/webkit_inspection_protocol-1.2.0", - "packageUri": "lib/", - "languageVersion": "2.12" - }, - { - "name": "yaml", - "rootUri": "file:///Users/kushalmahapatro/.pub-cache/hosted/pub.dev/yaml-3.1.2", - "packageUri": "lib/", - "languageVersion": "2.19" - }, - { - "name": "pubm", - "rootUri": "../", - "packageUri": "lib/", - "languageVersion": "3.0" - } - ], - "generated": "2023-09-04T20:08:02.720864Z", - "generator": "pub", - "generatorVersion": "3.1.0" -} diff --git a/CHANGELOG.md b/CHANGELOG.md index 72f1e84..3ed7623 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### 0.2.0 (2023-11-04) +#### Added +- Added support to remove values from pubspec.yaml file. + ### 0.1.1 (2023-09-19) #### Fixed - Deep check for other dependencies to avoid changes to pubspec.yaml file if the dependencies are same. diff --git a/README.md b/README.md index a93b2cf..1c138b5 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,9 @@ pubm -f -v # else dart run pubm:manage -f -v ``` -### 📋 Example: pubpsec_dev.yaml +### 📋 Example: pubspec_dev.yaml Here's an example of a flavor-specific pubspec.yaml file for a 'dev' flavor: -```console +```yaml description: dev version of pubspec.yaml version: 0.0.1-dev @@ -81,7 +81,7 @@ The above values present in the pubspec_.yaml file will be updated in th ### 📋 Example: pubspec.yaml Here's an example of the main pubspec.yaml file: -```console +```yaml name: pubm description: Actual description version: 0.0.1 @@ -129,7 +129,7 @@ dart run pubm:manage -f dev ``` ##### Output -```console +```yaml name: pubm description: dev version of pubspec.yaml version: 0.0.1-dev @@ -174,6 +174,140 @@ flutter: weight: 400 ``` +### 📋 Example: Removing values from pubspec.yaml +To remove a dependency from the pubspec.yaml file, add the following line to the pubspec_.yaml file: +The dependency name is only required, its respective version is not mandatory. + +To remove dependency from dependencies section: +add it to the dependencies section of the pubspec_.yaml file. + +the same with dev_dependencies and dependency_overrides section. + +Remove section should have the same format of the yaml file. + +After going through all the updating values, it will look for the remove section, +if found it will look into the data and remove respective form the actual pubspec.yaml file. + +### Actual pubspec.yaml file: +```yaml +name: pubm +description: test version of pubspec.yaml +version: 0.0.1 + +environment: + sdk: ^3.0.0 + +dependencies: + # normal dependencies + cupertino_icons: ^1.0.2 + example_dependency: ^0.0.1 + +dev_dependencies: + # normal dev_dependencies + lints: ^2.1.1 + example_dependency_dev: ^0.0.1 + +dependency_overrides: + # normal dependency_overrides + example_dependency_overrides: ^0.0.1 + +flutter: + uses-material-design: true + generate: true + + assets: + - assets/images/ + - assets/1.png + fonts: + - family: font1 + fonts: + - asset: dev/font1/700.ttf + weight: 700 + - asset: dev/font1/600.ttf + weight: 600 + - asset: dev/font1/500.ttf + weight: 500 + - asset: dev/font1/400.ttf + weight: 400 + - family: font2 + fonts: + - asset: dev/font2/700.ttf + weight: 700 + - asset: dev/font2/600.ttf + weight: 600 + - asset: dev/font2/500.ttf + weight: 500 + - asset: dev/font2/400.ttf + weight: 400 +any_other_section: + name: Name + version: 0.0.1 +``` + +### Example of pubspec_dev.yaml file: +```yaml +description: dev version of pubspec.yaml +version: 0.0.1-dev + +remove: + home_page: + + dependencies: + example_dependency: + + dev_dependencies: + example_dependency_dev: + + dependency_overrides: + example_dependency_overrides: + + flutter: + assets: + - assets/1.png + + fonts: + - family: font1 + + any_other_section: +``` + +### Output +```yaml +name: pubm +description: dev version of pubspec.yaml +version: 0.0.1-dev + +environment: + sdk: ^3.0.0 + +dependencies: + # normal dependencies + cupertino_icons: ^1.0.2 + +dev_dependencies: + # normal dev_dependencies + lints: ^2.1.1 + +flutter: + uses-material-design: true + generate: true + + assets: + - assets/images/ + + fonts: + - family: font2 + fonts: + - asset: dev/font2/700.ttf + weight: 700 + - asset: dev/font2/600.ttf + weight: 600 + - asset: dev/font2/500.ttf + weight: 500 + - asset: dev/font2/400.ttf + weight: 400 +``` + By default, this tool also sorts the dependencies and dev_dependencies in alphabetical order by category. The categories are as follows: 1. git related dependencies 2. path related dependencies @@ -181,14 +315,18 @@ By default, this tool also sorts the dependencies and dev_dependencies in alphab 4. hosted dependencies 5. sdk dependencies -## Support -This plugin is free to use and currently in its early stages of development. We plan to add many more features soon. Please visit the [Github Project](https://github.com/users/kushalmahapatro/projects/1) to know about the upcoming feature and fixes. If you encounter any issues or would like additional features, please raise an issue in the [GitHub repository](https://github.com/kushalmahapatro/pubspec_manager/issues). +## Contributors + + + - Feel free to contribute to this project by creating a pull request with a clear description of your changes. +Made with [contrib.rocks](https://contrib.rocks). +## Support +This plugin is free to use and currently in its early stages of development. We plan to add many more features soon. Please visit the [Github Project](https://github.com/users/kushalmahapatro/projects/1) to know about the upcoming feature and fixes. If you encounter any issues or would like additional features, please raise an issue in the [GitHub repository](https://github.com/kushalmahapatro/pubspec_manager/issues). +Feel free to contribute to this project by creating a pull request with a clear description of your changes. If this plugin was useful to you, helped you in any way, saved you a lot of time, or you just want to support the project, I would be very grateful if you buy me a cup of coffee. Your support helps maintain and improve this project. - Buy Me A Coffee diff --git a/example/README.md b/example/README.md index a93b2cf..56d2250 100644 --- a/example/README.md +++ b/example/README.md @@ -39,9 +39,9 @@ pubm -f -v # else dart run pubm:manage -f -v ``` -### 📋 Example: pubpsec_dev.yaml +### 📋 Example: pubspec_dev.yaml Here's an example of a flavor-specific pubspec.yaml file for a 'dev' flavor: -```console +```yaml description: dev version of pubspec.yaml version: 0.0.1-dev @@ -81,7 +81,7 @@ The above values present in the pubspec_.yaml file will be updated in th ### 📋 Example: pubspec.yaml Here's an example of the main pubspec.yaml file: -```console +```yaml name: pubm description: Actual description version: 0.0.1 @@ -129,7 +129,7 @@ dart run pubm:manage -f dev ``` ##### Output -```console +```yaml name: pubm description: dev version of pubspec.yaml version: 0.0.1-dev @@ -174,6 +174,140 @@ flutter: weight: 400 ``` +### 📋 Example: Removing values from pubspec.yaml +To remove a dependency from the pubspec.yaml file, add the following line to the pubspec_.yaml file: +The dependency name is only required, its respective version is not mandatory. + +To remove dependency from dependencies section: +add it to the dependencies section of the pubspec_.yaml file. + +the same with dev_dependencies and dependency_overrides section. + +Remove section should have the same format of the yaml file. + +After going through all the updating values, it will look for the remove section, +if found it will look into the data and remove respective form the actual pubspec.yaml file. + +### Actual pubspec.yaml file: +```yaml +name: pubm +description: test version of pubspec.yaml +version: 0.0.1 + +environment: + sdk: ^3.0.0 + +dependencies: + # normal dependencies + cupertino_icons: ^1.0.2 + example_dependency: ^0.0.1 + +dev_dependencies: + # normal dev_dependencies + lints: ^2.1.1 + example_dependency_dev: ^0.0.1 + +dependency_overrides: + # normal dependency_overrides + example_dependency_overrides: ^0.0.1 + +flutter: + uses-material-design: true + generate: true + + assets: + - assets/images/ + - assets/1.png + fonts: + - family: font1 + fonts: + - asset: dev/font1/700.ttf + weight: 700 + - asset: dev/font1/600.ttf + weight: 600 + - asset: dev/font1/500.ttf + weight: 500 + - asset: dev/font1/400.ttf + weight: 400 + - family: font2 + fonts: + - asset: dev/font2/700.ttf + weight: 700 + - asset: dev/font2/600.ttf + weight: 600 + - asset: dev/font2/500.ttf + weight: 500 + - asset: dev/font2/400.ttf + weight: 400 +any_other_section: + name: Name + version: 0.0.1 +``` + +### Example of pubspec_dev.yaml file: +```yaml +description: dev version of pubspec.yaml +version: 0.0.1-dev + +remove: + home_page: + + dependencies: + example_dependency: + + dev_dependencies: + example_dependency_dev: + + dependency_overrides: + example_dependency_overrides: + + flutter: + assets: + - assets/1.png + + fonts: + - family: font1 + + any_other_section: +``` + +### Output +```yaml +name: pubm +description: dev version of pubspec.yaml +version: 0.0.1-dev + +environment: + sdk: ^3.0.0 + +dependencies: + # normal dependencies + cupertino_icons: ^1.0.2 + +dev_dependencies: + # normal dev_dependencies + lints: ^2.1.1 + +flutter: + uses-material-design: true + generate: true + + assets: + - assets/images/ + + fonts: + - family: font2 + fonts: + - asset: dev/font2/700.ttf + weight: 700 + - asset: dev/font2/600.ttf + weight: 600 + - asset: dev/font2/500.ttf + weight: 500 + - asset: dev/font2/400.ttf + weight: 400 +``` + By default, this tool also sorts the dependencies and dev_dependencies in alphabetical order by category. The categories are as follows: 1. git related dependencies 2. path related dependencies @@ -181,14 +315,18 @@ By default, this tool also sorts the dependencies and dev_dependencies in alphab 4. hosted dependencies 5. sdk dependencies -## Support -This plugin is free to use and currently in its early stages of development. We plan to add many more features soon. Please visit the [Github Project](https://github.com/users/kushalmahapatro/projects/1) to know about the upcoming feature and fixes. If you encounter any issues or would like additional features, please raise an issue in the [GitHub repository](https://github.com/kushalmahapatro/pubspec_manager/issues). +## Contributors + + + - Feel free to contribute to this project by creating a pull request with a clear description of your changes. +Made with [contrib.rocks](https://contrib.rocks). +## Support +This plugin is free to use and currently in its early stages of development. We plan to add many more features soon. Please visit the [Github Project](https://github.com/users/kushalmahapatro/projects/1) to know about the upcoming feature and fixes. If you encounter any issues or would like additional features, please raise an issue in the [GitHub repository](https://github.com/kushalmahapatro/pubspec_manager/issues). +Feel free to contribute to this project by creating a pull request with a clear description of your changes. If this plugin was useful to you, helped you in any way, saved you a lot of time, or you just want to support the project, I would be very grateful if you buy me a cup of coffee. Your support helps maintain and improve this project. - Buy Me A Coffee diff --git a/example/_pubspec.yaml b/example/_pubspec.yaml new file mode 100644 index 0000000..3d3123c --- /dev/null +++ b/example/_pubspec.yaml @@ -0,0 +1,49 @@ +name: pubm +description: Actual description +version: 0.0.1 +homepage: https://test.homepage + +environment: + sdk: ^3.0.0 + +dependencies: + cupertino_icons: ^1.0.2 + unwanted_dependency: ^0.0.1 + +dev_dependencies: + flutter_lints: ^2.0.0 + unwanted_dependency: ^0.0.1-dev + +dependency_overrides: + flutter_lints: ^1.0.0 + unwanted_dependency: ^0.0.1-override + +flutter: + uses-material-design: true + generate: true + + assets: + - assets/dev/ + - assets/prod/ + + fonts: + - family: font1 + fonts: + - asset: actual/font1/700.ttf + weight: 700 + - asset: actual/font1/600.ttf + weight: 600 + - asset: actual/font1/500.ttf + weight: 500 + - asset: actual/font1/400.ttf + weight: 400 + - family: font + fonts: + - asset: actual/font2/700.ttf + weight: 700 + - asset: actual/font2/600.ttf + weight: 600 + - asset: actual/font2/500.ttf + weight: 500 + - asset: actual/font2/400.ttf + weight: 400 \ No newline at end of file diff --git a/example/pubspec_dev.yaml b/example/pubspec_dev.yaml new file mode 100644 index 0000000..49d8d8c --- /dev/null +++ b/example/pubspec_dev.yaml @@ -0,0 +1,38 @@ +description: prod version of pubspec.yaml +version: 0.0.1-prod + +dependencies: + example_dependency: + path: example/dependency + +dev_dependencies: + lints: ^2.1.1 + +flutter: + fonts: + - family: font + fonts: + - asset: dev/font2/700.ttf + weight: 700 + - asset: dev/font2/600.ttf + weight: 600 + - asset: dev/font2/500.ttf + weight: 500 + - asset: dev/font2/400.ttf + weight: 400 + +remove: + homepage: https://test.homepage + + dependencies: + unwanted_dependency: + + dev_dependencies: + dependency_overrides: + + flutter: + assets: + - assets/dev/ + + fonts: + - family: font1 \ No newline at end of file diff --git a/example/pubspec_prod.yaml b/example/pubspec_prod.yaml new file mode 100644 index 0000000..cabbfac --- /dev/null +++ b/example/pubspec_prod.yaml @@ -0,0 +1,40 @@ +description: prod version of pubspec.yaml +version: 0.0.1-prod +homepage: https://prod.homepage + +dependencies: + example_dependency: + path: example/dependency + +dev_dependencies: + lints: ^2.1.1 + +flutter: + fonts: + - family: font + fonts: + - asset: prod/font2/700.ttf + weight: 700 + - asset: prod/font2/600.ttf + weight: 600 + - asset: prod/font2/500.ttf + weight: 500 + - asset: prod/font2/400.ttf + weight: 400 + +remove: + dependencies: + unwanted_dependency: + + dev_dependencies: + dependency_overrides: + + dependency_overrides: + unwanted_dependency: ^0.0.1-override + + flutter: + assets: + - assets/dev/ + + fonts: + - family: font1 \ No newline at end of file diff --git a/lib/constants.dart b/lib/constants.dart index b8033b5..da5fb05 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -1,4 +1,25 @@ -abstract class Constants { - static const String comment = "Pubspec Manager Comment"; - static const String pubspecYamlPath = "pubspec.yaml"; -} +const String comment = "Pubspec Manager Comment"; +const String pubspecYamlPath = "pubspec.yaml"; + +/// Pubspec keys +const String name = 'name'; +const String description = 'description'; +const String version = 'version'; +const String homepage = 'homepage'; +const String repository = 'repository'; +const String issueTracker = 'issue_tracker'; +const String documentation = 'documentation'; +const String publishTo = 'publish_to'; +const String environment = 'environment'; +const String dependencies = 'dependencies'; +const String devDependencies = 'dev_dependencies'; +const String dependencyOverrides = 'dependency_overrides'; +const String flutter = 'flutter'; +const String useMaterialDesign = 'uses-material-design'; +const String assets = 'assets'; +const String generate = 'generate'; +const String fonts = 'fonts'; +const String family = 'family'; + +/// Flavored pubspec keys +const String remove = 'remove'; diff --git a/lib/models/pubspec.dart b/lib/models/pubspec.dart index ead3001..4f31a66 100644 --- a/lib/models/pubspec.dart +++ b/lib/models/pubspec.dart @@ -45,12 +45,12 @@ class Pubspec extends Equatable { return { if (name != null) 'name': name, if (description != null) 'description': description, + if (version != null) 'version': version, if (homepage != null) 'homepage': homepage, if (repository != null) 'repository': repository, if (issueTracker != null) 'issue_tracker': issueTracker, if (documentation != null) 'documentation': documentation, if (publishTo != null) 'publish_to': publishTo, - if (version != null) 'version': version, if (environment != null) 'environment': environment?.toMap(), if (dependencies != null) 'dependencies': dependencies?.toMap(addComments: addComments), @@ -185,34 +185,34 @@ class Dependencies extends Equatable { List> finalList = []; if (gitDependencies != null && gitDependencies!.isNotEmpty) { if (addComments) { - finalList.add({'${Constants.comment}1': 'git related dependencies'}); + finalList.add({'${comment}1': 'git related dependencies'}); } finalList += gitDependencies!.map((x) => x.toMap()).toList(); } if (pathDependencies != null && pathDependencies!.isNotEmpty) { if (addComments) { - finalList.add({'${Constants.comment}2': 'path related dependencies'}); + finalList.add({'${comment}2': 'path related dependencies'}); } finalList += pathDependencies!.map((x) => x.toMap()).toList(); } if (normalDependencies != null && normalDependencies!.isNotEmpty) { if (addComments) { - finalList.add({'${Constants.comment}3': 'normal dependencies'}); + finalList.add({'${comment}3': 'normal dependencies'}); } finalList += normalDependencies!.map((x) => x.toMap()).toList(); } if (hostedDependencies != null && hostedDependencies!.isNotEmpty) { if (addComments) { - finalList.add({'${Constants.comment}4': 'hosted dependencies'}); + finalList.add({'${comment}4': 'hosted dependencies'}); } finalList += hostedDependencies!.map((x) => x.toMap()).toList(); } if (sdkDependencies != null && sdkDependencies!.isNotEmpty) { if (addComments) { - finalList.add({'${Constants.comment}5': 'sdk dependencies'}); + finalList.add({'${comment}5': 'sdk dependencies'}); } finalList += sdkDependencies!.map((x) => x.toMap()).toList(); } diff --git a/lib/pubm.dart b/lib/pubm.dart index 1e563ae..38c7aaf 100644 --- a/lib/pubm.dart +++ b/lib/pubm.dart @@ -1,7 +1,7 @@ import 'package:cli_util/cli_logging.dart'; import 'package:get_it/get_it.dart'; import 'package:pubm/src/configuration.dart'; -import 'package:pubm/src/pubspec_manage.dart'; +import 'package:pubm/src/manage/pubspec_manage.dart'; class Pubm with PubspecManager { Pubm(List args) { @@ -30,8 +30,9 @@ class Pubm with PubspecManager { /// Register [Logger] and [Configuration] as singleton services void _setupSingletonServices(List args) { - GetIt.I.registerSingleton( - args.contains('-v') ? Logger.verbose() : Logger.standard(ansi: Ansi(true))); + GetIt.I.registerSingleton(args.contains('-v') + ? Logger.verbose() + : Logger.standard(ansi: Ansi(true))); GetIt.I.registerSingleton(Configuration(args)); } diff --git a/lib/src/configuration.dart b/lib/src/configuration.dart index 1035efd..40b77fa 100644 --- a/lib/src/configuration.dart +++ b/lib/src/configuration.dart @@ -17,8 +17,8 @@ class Configuration { late ArgResults _args; List? buildArgs; String flavor = ''; - File backupPubspecFile = File('backup_${Constants.pubspecYamlPath}'); - File pubspecFile = File(Constants.pubspecYamlPath); + File backupPubspecFile = File('backup_$pubspecYamlPath'); + File pubspecFile = File(pubspecYamlPath); File pubspecFlavorFile = File(''); /// Gets the configuration values from from [_arguments] or pubspec.yaml file @@ -27,7 +27,8 @@ class Configuration { dynamic pubspec = await _getPubspec(); dynamic yaml = pubspec['pubm_config'] ?? YamlMap(); - final String? buildArgsConfig = (_args['build-args'] ?? yaml['build_args'])?.toString(); + final String? buildArgsConfig = + (_args['build-args'] ?? yaml['build_args'])?.toString(); if (buildArgsConfig != null && buildArgsConfig.isNotEmpty) { CommandLineConverter commandLineConverter = CommandLineConverter(); buildArgs = commandLineConverter.convert(buildArgsConfig); @@ -40,13 +41,15 @@ class Configuration { if (_args['help']) { _logger.stdout('Usage: pubm -f '); - _logger.stdout('Usage: pubm -f -v (verbose) to enable verbose mode'); - _logger.stdout('Usage: pubm -h to get the list of available commands and how to use'); + _logger.stdout( + 'Usage: pubm -f -v (verbose) to enable verbose mode'); + _logger.stdout( + 'Usage: pubm -h to get the list of available commands and how to use'); return false; } - flavor = _args['flavor']?.toString() ?? 'test'; + flavor = _args['flavor']?.toString() ?? ''; if (flavor.isEmpty) { exitCode = 2; _logger.stderr('Usage: dart manage.dart -f '.red); @@ -59,7 +62,7 @@ class Configuration { /// Get pubspec.yaml content dynamic _getPubspec() async { - String pubspecString = await File(Constants.pubspecYamlPath).readAsString(); + String pubspecString = await File(pubspecYamlPath).readAsString(); dynamic pubspec = loadYaml(pubspecString); return pubspec; } @@ -69,7 +72,8 @@ class Configuration { _logger.trace('parsing cli arguments'); ArgParser parser = ArgParser() - ..addOption('flavor', abbr: 'f', help: 'flavor of YAML file (pubspec_/flavor/.yaml)') + ..addOption('flavor', + abbr: 'f', help: 'flavor of YAML file (pubspec_/flavor/.yaml)') ..addOption('build-args') ..addFlag('help', negatable: false, abbr: 'h'); diff --git a/lib/src/manage/manage_dependencies.dart b/lib/src/manage/manage_dependencies.dart new file mode 100644 index 0000000..f9d0d8a --- /dev/null +++ b/lib/src/manage/manage_dependencies.dart @@ -0,0 +1,39 @@ +import 'package:cli_util/cli_logging.dart'; +import 'package:pubm/constants.dart'; +import 'package:pubm/models/pubspec.dart'; +import 'package:pubm/src/helpers/pubspec_checker.dart'; + +/// Check and update the dependencies +void checkAndUpdateDependencies( + Pubspec actualPubspec, + Pubspec flavorPubspec, + Map finalMap, + Map map, + Logger logger, +) { + var dependencyCheck = PubspecChecker.checkDependencies( + actualPubspec, + flavorPubspec, + checkAll: true, + ); + + if (!dependencyCheck.hasMatch) { + if (dependencyCheck.update.isNotEmpty) { + for (var element in dependencyCheck.update) { + logger.trace('Updating dependency $element'); + } + } + + if (dependencyCheck.addition.isNotEmpty) { + for (var element in dependencyCheck.addition) { + logger.trace('Adding dependency $element'); + } + } + + /// Combine the dependencies from both pubspec.yaml and pubspec_flavor.yaml files + finalMap[dependencies] = { + if (finalMap[dependencies] != null) ...finalMap[dependencies], + if (map[dependencies] != null) ...map[dependencies], + }; + } +} diff --git a/lib/src/manage/manage_dependency_overrides.dart b/lib/src/manage/manage_dependency_overrides.dart new file mode 100644 index 0000000..a852f5d --- /dev/null +++ b/lib/src/manage/manage_dependency_overrides.dart @@ -0,0 +1,39 @@ +import 'package:cli_util/cli_logging.dart'; +import 'package:pubm/constants.dart'; +import 'package:pubm/models/pubspec.dart'; +import 'package:pubm/src/helpers/pubspec_checker.dart'; + +/// Check and update the dependency_overrides +void checkAndUpdateDependencyOverrides( + Pubspec actualPubspec, + Pubspec flavorPubspec, + Map finalMap, + Map map, + Logger logger, +) { + var dependencyOverrideCheck = PubspecChecker.checkDependencyOverride( + actualPubspec, + flavorPubspec, + checkAll: true, + ); + + if (!dependencyOverrideCheck.hasMatch) { + if (dependencyOverrideCheck.update.isNotEmpty) { + for (var element in dependencyOverrideCheck.update) { + logger.trace('Updating dependency_override $element'); + } + } + + if (dependencyOverrideCheck.addition.isNotEmpty) { + for (var element in dependencyOverrideCheck.addition) { + logger.trace('Adding dependency_override $element'); + } + } + + finalMap[dependencyOverrides] = { + if (finalMap[dependencyOverrides] != null) + ...finalMap[dependencyOverrides], + if (map[dependencyOverrides] != null) ...map[dependencyOverrides], + }; + } +} diff --git a/lib/src/manage/manage_dev_dependencies.dart b/lib/src/manage/manage_dev_dependencies.dart new file mode 100644 index 0000000..170897e --- /dev/null +++ b/lib/src/manage/manage_dev_dependencies.dart @@ -0,0 +1,39 @@ +import 'package:cli_util/cli_logging.dart'; +import 'package:pubm/constants.dart'; +import 'package:pubm/models/pubspec.dart'; +import 'package:pubm/src/helpers/pubspec_checker.dart'; + +/// Check and update the dev_dependencies +void checkAndUpdateDevDependencies( + Pubspec actualPubspec, + Pubspec flavorPubspec, + Map finalMap, + Map map, + Logger logger, +) { + var devDependencyCheck = PubspecChecker.checkDevDependencies( + actualPubspec, + flavorPubspec, + checkAll: true, + ); + + if (!devDependencyCheck.hasMatch) { + if (devDependencyCheck.update.isNotEmpty) { + for (var element in devDependencyCheck.update) { + logger.trace('Updating dev_dependency $element'); + } + } + + if (devDependencyCheck.addition.isNotEmpty) { + for (var element in devDependencyCheck.addition) { + logger.trace('Adding dev_dependency $element'); + } + } + + /// Combine the dev_dependencies from both pubspec.yaml and pubspec_flavor.yaml files + finalMap[devDependencies] = { + if (finalMap[devDependencies] != null) ...finalMap[devDependencies], + if (map[devDependencies] != null) ...map[devDependencies], + }; + } +} diff --git a/lib/src/manage/manage_flutter_values.dart b/lib/src/manage/manage_flutter_values.dart new file mode 100644 index 0000000..f278a37 --- /dev/null +++ b/lib/src/manage/manage_flutter_values.dart @@ -0,0 +1,100 @@ +import 'package:cli_util/cli_logging.dart'; +import 'package:collection/collection.dart'; +import 'package:pubm/constants.dart'; +import 'package:pubm/models/flutter_data.dart'; +import 'package:pubm/models/pubspec.dart'; + +/// Check and update the flutter related values +void checkAndUpdateFlutterRelatedValues( + Pubspec flavorPubspec, + Pubspec actualPubspec, + Map finalMap, + Logger logger, +) { + if (flavorPubspec.flutter != null) { + logger.trace('Updating $flutter values'); + + final flutterValues = actualPubspec.flutter?.toMap() ?? {}; + finalMap[flutter] = flavorPubspec.flutter?.toMap(); + if (actualPubspec.flutter != null) { + if (actualPubspec.flutter?.usesMaterialDesign != + flavorPubspec.flutter?.usesMaterialDesign) { + logger.trace('Updating $useMaterialDesign from ' + '${actualPubspec.flutter?.usesMaterialDesign} to ' + '${flavorPubspec.flutter?.usesMaterialDesign}'); + + flutterValues[useMaterialDesign] = + flavorPubspec.flutter?.usesMaterialDesign ?? + actualPubspec.flutter?.usesMaterialDesign; + } + + if (actualPubspec.flutter?.generate != flavorPubspec.flutter?.generate) { + logger.trace('Updating $generate from ' + '${actualPubspec.flutter?.generate} to ' + '${flavorPubspec.flutter?.generate}'); + flutterValues[generate] = + flavorPubspec.flutter?.generate ?? actualPubspec.flutter?.generate; + } + + final assetsValue = actualPubspec.flutter?.assets ?? []; + assetsValue.addAll(flavorPubspec.flutter?.assets ?? []); + flutterValues[assets] = assetsValue.toSet(); + + final finalFonts = {}; + for (final Font data in actualPubspec.flutter?.fonts ?? []) { + finalFonts.add(Font(family: data.family)); + } + for (final Font data in flavorPubspec.flutter?.fonts ?? []) { + finalFonts.add(Font(family: data.family)); + } + + var fontsSet = {}..addAll(finalFonts); + + for (final data in finalFonts) { + final actualFont = actualPubspec.flutter?.fonts + ?.firstWhereOrNull((element) => element.family == data.family); + + final flavorFont = flavorPubspec.flutter?.fonts + ?.firstWhereOrNull((element) => element.family == data.family); + + if (actualFont != null && flavorFont != null) { + final map = {}; + map[family] = actualFont.family; + final f = {}; + + for (final FontsData data in [ + ...actualFont.fonts ?? [], + ...flavorFont.fonts ?? [] + ]) { + final d = flavorFont.fonts + ?.firstWhereOrNull((element) => element.weight == data.weight); + if (d != null) { + f.add(d); + } else { + f.add(data); + } + } + map[fonts] = f.toList().map((e) => e.toMap()).toList(); + fontsSet.remove(data); + + logger.trace( + 'Updating $fonts from ${actualFont.family} to ${flavorFont.family} and associated fonts'); + fontsSet.add(Font.fromMap(map)); + } else if (actualFont != null && flavorFont == null) { + fontsSet.remove(data); + fontsSet.add(actualFont); + } else if (actualFont == null && flavorFont != null) { + fontsSet.remove(data); + + logger + .trace('Adding $fonts ${flavorFont.family} and associated fonts'); + fontsSet.add(flavorFont); + } + + flutterValues[fonts] = fontsSet.toList().map((e) => e.toMap()).toList(); + } + finalFonts.clear(); + } + finalMap[flutter] = flutterValues; + } +} diff --git a/lib/src/manage/manage_other_values.dart b/lib/src/manage/manage_other_values.dart new file mode 100644 index 0000000..b0da2c6 --- /dev/null +++ b/lib/src/manage/manage_other_values.dart @@ -0,0 +1,43 @@ +import 'dart:convert'; + +import 'package:cli_util/cli_logging.dart'; +import 'package:collection/collection.dart'; +import 'package:pubm/models/pubspec.dart'; + +/// Check and update the other values in the pubspec.yaml file. +void checkAndUpdateOtherValues( + Pubspec flavorPubspec, + Pubspec actualPubspec, + Map finalMap, + Logger logger, +) { + if (!DeepCollectionEquality() + .equals(flavorPubspec.others, actualPubspec.others)) { + logger.trace('Updating others values'); + Map others = {}; + if (actualPubspec.others != null) { + actualPubspec.others!.forEach((key, value) { + logger.trace('Updating $key'); + + if (value is Map || value is List) { + others[key] = jsonDecode(jsonEncode(value)); + } else { + others[key] = value; + } + }); + } + if (flavorPubspec.others != null) { + flavorPubspec.others!.forEach((key, value) { + logger.trace('Updating $key'); + + if (value is Map || value is List) { + others[key] = jsonDecode(jsonEncode(value)); + } else { + others[key] = value; + } + }); + } + + finalMap.addAll(others); + } +} diff --git a/lib/src/manage/pubspec_manage.dart b/lib/src/manage/pubspec_manage.dart new file mode 100644 index 0000000..0d01456 --- /dev/null +++ b/lib/src/manage/pubspec_manage.dart @@ -0,0 +1,211 @@ +import 'package:cli_util/cli_logging.dart'; +import 'package:pubm/constants.dart'; +import 'package:pubm/models/pubspec.dart'; +import 'package:pubm/src/configuration.dart'; +import 'package:pubm/src/extensions.dart'; +import 'package:pubm/src/helpers/pubspec_checker.dart'; +import 'package:pubm/src/manage/manage_dependencies.dart'; +import 'package:pubm/src/manage/manage_dependency_overrides.dart'; +import 'package:pubm/src/manage/manage_dev_dependencies.dart'; +import 'package:pubm/src/manage/manage_other_values.dart'; +import 'package:pubm/src/manage/remove_values.dart'; +import 'package:pubm/src/manage/sort_all_dependencies.dart'; +import 'package:pubm/src/manage/update_actuap_pubspec.dart'; +import 'package:yaml/yaml.dart'; + +import 'manage_flutter_values.dart'; + +mixin PubspecManager { + Logger get logger; + + Configuration get config; + + Future mergePubspec() async { + bool nameChanged = false; + if (!config.pubspecFlavorFile.existsSync()) { + logger.stderr('File does not exist: ${config.flavor}'.red); + return; + } + + // Read the YAML file + final String contents = config.pubspecFlavorFile.readAsStringSync(); + + // Parse the YAML contents + final dynamic yamlMap = loadYaml(contents); + final dynamic actualYamlMap = + loadYaml(config.pubspecFile.readAsStringSync()); + + if (checkIfItsOnlyRemove(yamlMap)) { + final Map? finalMap = await removeValuesFromPubspec( + logger: logger, + config: config, + ); + if (finalMap != null) { + /// Sort all the dependencies (dependencies, dev_dependencies, dependency_overrides) + sortAllDependencies( + finalMap, + logger, + ); + + /// Update the actual pubspec.yaml file + await updateActualPubspec( + finalMap, + nameChanged, + Pubspec.fromMap(actualYamlMap), + Pubspec.fromMap(yamlMap), + config, + logger, + ); + return; + } + } + + // Create a Pubspec object + final Pubspec actualPubspec = Pubspec.fromMap(actualYamlMap); + final Pubspec flavorPubspec = Pubspec.fromMap(yamlMap); + + final bool alreadyMerged = PubspecChecker.checkIfPubspecAlreadyMerged( + actualPubspec: actualPubspec, + flavorPubspec: flavorPubspec, + ); + + if (alreadyMerged) { + logger.stdout('Pubspec already merged.'.green); + return; + } + + // Update the Pubspec object + Map finalMap = actualPubspec.toMap(); + final Map map = flavorPubspec.toMap(); + + if (!PubspecChecker.checkName(actualPubspec, flavorPubspec)) { + logger.trace('Updating $name from ${actualPubspec.name} to ' + '${flavorPubspec.name}'); + nameChanged = true; + finalMap[name] = flavorPubspec.name; + } + + if (!PubspecChecker.checkDescription(actualPubspec, flavorPubspec)) { + logger.trace('Updating $description from ${actualPubspec.description} to ' + '${flavorPubspec.description}'); + finalMap[description] = flavorPubspec.description; + } + + if (!PubspecChecker.checkVersion(actualPubspec, flavorPubspec)) { + logger.trace('Updating $version from ${actualPubspec.version} to ' + '${flavorPubspec.version}'); + finalMap[version] = flavorPubspec.version; + } + + if (!PubspecChecker.checkHomepage(actualPubspec, flavorPubspec)) { + logger.trace('Updating $homepage from ${actualPubspec.homepage} to ' + '${flavorPubspec.homepage}'); + finalMap[homepage] = flavorPubspec.homepage; + } + + if (!PubspecChecker.checkRepository(actualPubspec, flavorPubspec)) { + logger.trace('Updating $repository from ${actualPubspec.repository} to ' + '${flavorPubspec.repository}'); + finalMap[repository] = flavorPubspec.repository; + } + + if (!PubspecChecker.checkIssueTracker(actualPubspec, flavorPubspec)) { + logger + .trace('Updating $issueTracker from ${actualPubspec.issueTracker} to ' + '${flavorPubspec.issueTracker}'); + finalMap[issueTracker] = flavorPubspec.issueTracker; + } + + if (!PubspecChecker.checkDocumentation(actualPubspec, flavorPubspec)) { + logger.trace( + 'Updating $documentation from ${actualPubspec.documentation} to ' + '${flavorPubspec.documentation}'); + finalMap[documentation] = flavorPubspec.documentation; + } + + if (!PubspecChecker.checkPublishTo(actualPubspec, flavorPubspec)) { + logger.trace('Updating $publishTo from ${actualPubspec.publishTo} to ' + '${flavorPubspec.publishTo}'); + finalMap[publishTo] = flavorPubspec.publishTo; + } + + if (!PubspecChecker.checkEnvironment(actualPubspec, flavorPubspec)) { + logger.trace('Updating $environment from ${actualPubspec.environment} to ' + '${flavorPubspec.environment}'); + final env = actualPubspec.environment?.toMap() ?? {}; + + env.addAll(flavorPubspec.environment!.toMap()); + finalMap[environment] = env; + } + + /// Check and update the dependencies + checkAndUpdateDependencies( + actualPubspec, + flavorPubspec, + finalMap, + map, + logger, + ); + + /// Check and update the dev_dependencies + checkAndUpdateDevDependencies( + actualPubspec, + flavorPubspec, + finalMap, + map, + logger, + ); + + /// Check and update the dependency_overrides + checkAndUpdateDependencyOverrides( + actualPubspec, + flavorPubspec, + finalMap, + map, + logger, + ); + + /// Other values which are not checked and might be from other plugins + checkAndUpdateOtherValues( + flavorPubspec, + actualPubspec, + finalMap, + logger, + ); + + /// Check and update the flutter related values + checkAndUpdateFlutterRelatedValues( + flavorPubspec, + actualPubspec, + finalMap, + logger, + ); + + /// Get the final map after removing the values mentioned in the pubspec_flavor.yaml + final Map? finalMapAfterRemoving = + await removeValuesFromPubspec( + logger: logger, + config: config, + ); + + if (finalMapAfterRemoving != null) { + finalMap = finalMapAfterRemoving; + } + + /// Sort all the dependencies (dependencies, dev_dependencies, dependency_overrides) + sortAllDependencies( + finalMap, + logger, + ); + + /// Update the actual pubspec.yaml file + await updateActualPubspec( + finalMap, + nameChanged, + actualPubspec, + flavorPubspec, + config, + logger, + ); + } +} diff --git a/lib/src/manage/remove_values.dart b/lib/src/manage/remove_values.dart new file mode 100644 index 0000000..dfe7265 --- /dev/null +++ b/lib/src/manage/remove_values.dart @@ -0,0 +1,220 @@ +import 'package:cli_util/cli_logging.dart'; +import 'package:pubm/constants.dart'; +import 'package:pubm/models/flutter_data.dart'; +import 'package:pubm/models/pubspec.dart'; +import 'package:pubm/src/configuration.dart'; +import 'package:pubm/src/extensions.dart'; +import 'package:yaml/yaml.dart'; + +/// Check if the pubspec_flavor.yaml file contains remove key +bool checkIfItsOnlyRemove(dynamic data) { + return data is Map && data.containsKey("remove") && data.keys.length == 1; +} + +bool checkIfItsContainsRemove(dynamic data) { + return data is Map && data.containsKey("remove"); +} + +/// Remove the values mentioned in the remove section of the pubspec_flavor.yaml +Future?> removeValuesFromPubspec({ + required Logger logger, + required Configuration config, +}) async { + if (!config.pubspecFlavorFile.existsSync()) { + logger.stderr('File does not exist: ${config.flavor}'.red); + return null; + } + + // Read the YAML file + final String contents = config.pubspecFlavorFile.readAsStringSync(); + + // Parse the YAML contents + final dynamic yamlMap = loadYaml(contents); + + /// Check if the pubspec_flavor.yaml file contains remove key + if (!checkIfItsContainsRemove(yamlMap)) { + logger.stdout( + 'No remove key found in pubspec_${config.flavor}.yaml'.emphasized, + ); + return null; + } + + final dynamic actualYamlMap = loadYaml(config.pubspecFile.readAsStringSync()); + + // Create a Pubspec object + final Pubspec actualPubspec = Pubspec.fromMap(actualYamlMap); + final Pubspec flavorPubspec = Pubspec.fromMap(yamlMap[remove]); + + // Update the Pubspec object + final Map finalMap = actualPubspec.toMap(); + final Map map = flavorPubspec.toMap(); + + //Remove name if name exists in flavor + if (map.containsKey(name)) { + logger.stderr( + 'Cannot remove $name: ${actualPubspec.name} from pubspec, as this will cause the project to break' + .red); + logger.stderr('Discarding removal of $name, and continuing ahead'); + } + + ///Remove description if description exists in flavor + if (map.containsKey(description)) { + logger.trace('Removing $description'); + finalMap.remove(description); + } + + ///Remove version if version exists in flavor + if (map.containsKey(version)) { + logger.trace('Removing $version'); + finalMap.remove(version); + } + + ///Remove homepage if homepage exists in flavor + if (map.containsKey(homepage)) { + logger.trace('Removing $homepage'); + finalMap.remove(homepage); + } + + ///Remove repository if repository exists in flavor + if (map.containsKey(repository)) { + logger.trace('Removing $repository'); + finalMap.remove(repository); + } + + ///Remove issueTracker if issueTracker exists in flavor + if (map.containsKey(issueTracker)) { + logger.trace('Removing $issueTracker'); + finalMap.remove(issueTracker); + } + + ///Remove documentation if documentation exists in flavor + if (map.containsKey(documentation)) { + logger.trace('Removing $documentation'); + finalMap.remove(documentation); + } + + ///Remove publish_to if publish_to exists in flavor + if (map.containsKey(publishTo)) { + logger.trace('Removing $publishTo'); + finalMap.remove(publishTo); + } + + ///Remove environment if environment exists in flavor + if (map.containsKey(environment)) { + logger.trace('Removing $environment'); + finalMap.remove(environment); + } + + ///Check if dependencies key exists if so then + ///Loop through all the dependencies and remove it. + if (map.containsKey(dependencies)) { + map[dependencies].forEach((key, value) { + if (finalMap[dependencies].containsKey(key)) { + logger.trace('Removing dependency $key'); + finalMap[dependencies].remove(key); + } + }); + if ((finalMap[dependencies] as Map).isEmpty) { + finalMap.remove(dependencies); + } + } + + ///Check if dev_dependencies key exists if so then + ///Loop through all the dev_dependencies and remove it. + if (map.containsKey(devDependencies)) { + map[devDependencies].forEach((key, value) { + if (finalMap[devDependencies].containsKey(key)) { + logger.trace('Deleting dev_dependency $key'); + finalMap[devDependencies].remove(key); + } + }); + if ((finalMap[devDependencies] as Map).isEmpty) { + finalMap.remove(devDependencies); + } + } + + ///Check if dependency_overrides key exists if so then + ///Loop through all the dependency_overrides and remove it. + if (map.containsKey(dependencyOverrides)) { + map[dependencyOverrides].forEach((key, value) { + if (finalMap[dependencyOverrides].containsKey(key)) { + logger.trace('Deleting dependency_override $key'); + finalMap[dependencyOverrides].remove(key); + } + }); + if ((finalMap[dependencyOverrides] as Map).isEmpty) { + finalMap.remove(dependencyOverrides); + } + } + + /// Other values which are not checked and might be from other plugins + if (flavorPubspec.others?.isNotEmpty ?? false) { + logger.trace('Removing others values'); + + if (flavorPubspec.others != null) { + flavorPubspec.others!.forEach((key, value) { + if (finalMap.containsKey(key)) { + logger.trace('Removing $key'); + finalMap.remove(key); + } + }); + } + } + + if (flavorPubspec.flutter != null) { + logger.trace('Removing flutter values'); + + final flutterValue = actualPubspec.flutter?.toMap() ?? {}; + final flavorFlutter = flavorPubspec.flutter?.toMap() ?? {}; + if (actualPubspec.flutter != null) { + if (flavorFlutter.containsKey(useMaterialDesign)) { + logger.trace('Removing flutter $useMaterialDesign'); + flutterValue.remove(useMaterialDesign); + } + if (flavorFlutter.containsKey(generate)) { + logger.trace('Removing flutter $generate'); + flutterValue.remove(generate); + } + + if (flavorFlutter.containsKey(assets)) { + logger.trace('Removing flutter $assets'); + final flavourAssets = flavorPubspec.flutter?.assets ?? []; + for (var item in flavourAssets) { + logger.trace('Removing flutter asset $item'); + actualPubspec.flutter?.assets?.remove(item); + } + final assetsValue = actualPubspec.flutter?.assets ?? []; + flutterValue[assets] = assetsValue.toList(); + } + + final finalFonts = actualPubspec.flutter?.fonts?.toList() ?? []; + + for (final Font finalFont in actualPubspec.flutter?.fonts ?? []) { + for (final Font flavoredFont in flavorPubspec.flutter?.fonts ?? []) { + if (flavoredFont.family == finalFont.family) { + logger.trace( + 'Removing flutter font family: ${finalFont.family} and the associated fonts'); + finalFonts.removeWhere( + (element) => element.family == finalFont.family, + ); + } + } + } + + var fontsValue = {}..addAll(finalFonts); + + flutterValue[fonts] = fontsValue.toList().map((e) => e.toMap()).toList(); + + if (finalFonts.isEmpty) { + flutterValue.remove(fonts); + } + } + + finalMap[flutter] = flutterValue; + if (flutterValue.isEmpty) { + finalMap.remove(flutter); + } + } + + return finalMap; +} diff --git a/lib/src/manage/sort_all_dependencies.dart b/lib/src/manage/sort_all_dependencies.dart new file mode 100644 index 0000000..d55bc15 --- /dev/null +++ b/lib/src/manage/sort_all_dependencies.dart @@ -0,0 +1,39 @@ +import 'dart:collection'; + +import 'package:cli_util/cli_logging.dart'; +import 'package:pubm/constants.dart'; + +/// Sort all the dependencies (dependencies, dev_dependencies, dependency_overrides) +void sortAllDependencies( + Map finalMap, + Logger logger, +) { + if (finalMap.containsKey(dependencies)) { + logger.trace('Sorting $dependencies'); + var sortedKeys = finalMap[dependencies].keys.toList(growable: false) + ..sort((k1, k2) => k1.toString().compareTo(k2.toString())); + LinkedHashMap sortedMap = LinkedHashMap.fromIterable(sortedKeys, + key: (k) => k, value: (k) => finalMap[dependencies][k]); + finalMap[dependencies] = sortedMap; + } + + if (finalMap.containsKey(devDependencies)) { + logger.trace('Sorting $devDependencies'); + var sortedDDKeys = finalMap[devDependencies].keys.toList(growable: false) + ..sort((k1, k2) => k1.toString().compareTo(k2.toString())); + LinkedHashMap sortedDDMap = LinkedHashMap.fromIterable(sortedDDKeys, + key: (k) => k, value: (k) => finalMap[devDependencies][k]); + finalMap[devDependencies] = sortedDDMap; + } + + if (finalMap.containsKey(dependencyOverrides)) { + logger.trace('Sorting $dependencyOverrides'); + var sortedDOKeys = finalMap[dependencyOverrides] + .keys + .toList(growable: false) + ..sort((k1, k2) => k1.toString().compareTo(k2.toString())); + LinkedHashMap sortedDOMap = LinkedHashMap.fromIterable(sortedDOKeys, + key: (k) => k, value: (k) => finalMap[dependencyOverrides][k]); + finalMap[dependencyOverrides] = sortedDOMap; + } +} diff --git a/lib/src/manage/update_actuap_pubspec.dart b/lib/src/manage/update_actuap_pubspec.dart new file mode 100644 index 0000000..9dc9d00 --- /dev/null +++ b/lib/src/manage/update_actuap_pubspec.dart @@ -0,0 +1,59 @@ +import 'package:cli_util/cli_logging.dart'; +import 'package:json2yaml/json2yaml.dart'; +import 'package:pubm/constants.dart'; +import 'package:pubm/models/pubspec.dart'; +import 'package:pubm/src/configuration.dart'; +import 'package:pubm/src/extensions.dart'; +import 'package:pubm/src/flutter_build.dart'; + +Future updateActualPubspec( + Map finalMap, + bool nameChanged, + Pubspec actualPubspec, + Pubspec flavorPubspec, + Configuration config, + Logger logger, +) async { + final finalPubspec = Pubspec.fromMap(finalMap); + + /// Convert the `finalMap` to String with pubspec.yaml format + final String string = json2yaml( + finalPubspec.toMap(addComments: true), + yamlStyle: YamlStyle.pubspecYaml, + ); + + /// If any of the value contains # then it will be converted to "#" + /// ex: hexCode #FFFFFF will be converted to "#FFFFFF" + String replacedText = + string.replaceAllMapped(RegExp("#(.*?)(?=\\s|\$)"), (Match m) { + return '"#${m.group(1)}"'; + }); + + /// This will replace the temp added comment string with # + /// [Constants.comment] -> "Pubspec Manager Comment:" will be replaced with "#" in the final pubspec.yaml + replacedText = replacedText + .replaceAllMapped(RegExp("$comment\\d+: (.*?)(?=\\s|\$)"), (Match m) { + return '# ${m.group(1)}'; + }); + + /// Save the updated YAML to the file + logger.trace('Creating a backup of pubspec.yaml to backup_pubspec.yaml'); + config.backupPubspecFile + .writeAsStringSync(config.pubspecFile.readAsStringSync()); + config.pubspecFile.writeAsStringSync(replacedText); + + logger.stdout('Merging of pubspec.yaml files completed successfully'.green); + + /// Error message when name is changed in the main pubspec.yaml from the flavor pubspec.yaml + if (nameChanged) { + logger.stderr( + 'The $name is changed from ${actualPubspec.name} to ${flavorPubspec.name} (as the the one mentioned in the pubspec_${config.flavor}.yaml'); + logger.stderr('This would cause errors in the project.'); + logger.stderr( + 'Fix for this would to refactor the places where the package name was used'); + logger.stderr( + "Refactor: import 'package:${actualPubspec.name}/ to import 'package:${flavorPubspec.name}/ "); + } + + await FlutterBuild().pubGet(); +} diff --git a/lib/src/pubspec_manage.dart b/lib/src/pubspec_manage.dart deleted file mode 100644 index 83f5865..0000000 --- a/lib/src/pubspec_manage.dart +++ /dev/null @@ -1,625 +0,0 @@ -import 'dart:collection'; -import 'dart:convert'; - -import 'package:cli_util/cli_logging.dart'; -import 'package:collection/collection.dart'; -import 'package:json2yaml/json2yaml.dart'; -import 'package:pubm/constants.dart'; -import 'package:pubm/models/flutter_data.dart'; -import 'package:pubm/models/pubspec.dart'; -import 'package:pubm/src/configuration.dart'; -import 'package:pubm/src/extensions.dart'; -import 'package:pubm/src/flutter_build.dart'; -import 'package:pubm/src/helpers/pubspec_checker.dart'; -import 'package:yaml/yaml.dart'; - -mixin PubspecManager { - Logger get logger; - - Configuration get config; - Future remove() async { - bool nameChanged = false; - if (!config.pubspecFlavorFile.existsSync()) { - logger.stderr('File does not exist: ${config.flavor}'.red); - return; - } - - // Read the YAML file - final String contents = config.pubspecFlavorFile.readAsStringSync(); - - // Parse the YAML contents - final dynamic yamlMap = loadYaml(contents); - final dynamic actualYamlMap = loadYaml(config.pubspecFile.readAsStringSync()); - - // Create a Pubspec object - final Pubspec actualPubspec = Pubspec.fromMap(actualYamlMap); - final Pubspec flavorPubspec = Pubspec.fromMap(yamlMap["remove"]); - - // Update the Pubspec object - final Map finalMap = actualPubspec.toMap(); - final Map map = flavorPubspec.toMap(); - - //Remove name if name exists in flavor - if (map.containsKey("name")) { - logger.trace('Updating name'); - nameChanged = true; - finalMap.remove("name"); - } - - ///Remove description if description exists in flavor - if (map.containsKey("description")) { - logger.trace('Delete description'); - finalMap.remove("description"); - } - - ///Remove version if version exists in flavor - if (map.containsKey("version")) { - logger.trace('Updating version'); - finalMap.remove("version"); - } - - ///Remove homepage if homepage exists in flavor - if (map.containsKey("homepage")) { - logger.trace('Updating homepage'); - finalMap.remove("homepage"); - } - - ///Remove repository if repository exists in flavor - if (map.containsKey("repository")) { - logger.trace('Updating repository'); - finalMap.remove("repository"); - } - - ///Remove issueTracker if issueTracker exists in flavor - if (map.containsKey("issueTracker")) { - logger.trace('Updating issueTracker'); - finalMap.remove("issueTracker"); - } - - ///Remove documentation if documentation exists in flavor - if (map.containsKey("documentation")) { - logger.trace('Deleting documentation'); - finalMap.remove("documentation"); - } - - ///Remove publish_to if publish_to exists in flavor - if (map.containsKey("publish_to")) { - logger.trace('Deleting publishTo'); - finalMap.remove("publish_to"); - } - - ///Remove environment if environment exists in flavor - if (map.containsKey("environment")) { - logger.trace('Deleting environment '); - finalMap.remove("environment"); - } - - ///Check if dependencies key exists if so then - ///Loop through all the dependencies and remove it. - if (map.containsKey("dependencies")) { - map['dependencies'].forEach((key, value) { - if (finalMap['dependencies'].containsKey(key)) { - logger.trace('Deleting dependency $key'); - finalMap['dependencies'].remove(key); - } - }); - if ((finalMap['dependencies'] as Map).isEmpty) { - finalMap.remove('dependencies'); - } - } - - ///Check if dev_dependencies key exists if so then - ///Loop through all the dev_dependencies and remove it. - if (map.containsKey("dev_dependencies")) { - map['dev_dependencies'].forEach((key, value) { - if (finalMap['dev_dependencies'].containsKey(key)) { - logger.trace('Deleting dev_dependencies $key'); - finalMap['dev_dependencies'].remove(key); - } - }); - if ((finalMap['dev_dependencies'] as Map).isEmpty) { - finalMap.remove('dev_dependencies'); - } - } - - ///Check if dependency_overrides key exists if so then - ///Loop through all the dependency_overrides and remove it. - if (map.containsKey("dependency_overrides")) { - map['dependency_overrides'].forEach((key, value) { - if (finalMap['dependency_overrides'].containsKey(key)) { - logger.trace('Deleting dependency_overrides $key'); - finalMap['dependency_overrides'].remove(key); - } - }); - if ((finalMap['dependency_overrides'] as Map).isEmpty) { - finalMap.remove('dependency_overrides'); - } - } - - if (finalMap.containsKey('dependencies')) { - logger.trace('Sorting dependencies'); - var sortedKeys = finalMap['dependencies'].keys.toList(growable: false) - ..sort((k1, k2) => k1.toString().compareTo(k2.toString())); - LinkedHashMap sortedMap = LinkedHashMap.fromIterable(sortedKeys, - key: (k) => k, value: (k) => finalMap['dependencies'][k]); - finalMap['dependencies'] = sortedMap; - } - - if (finalMap.containsKey('dev_dependencies')) { - logger.trace('Sorting dev_dependencies'); - var sortedDDKeys = finalMap['dev_dependencies'].keys.toList(growable: false) - ..sort((k1, k2) => k1.toString().compareTo(k2.toString())); - LinkedHashMap sortedDDMap = LinkedHashMap.fromIterable(sortedDDKeys, - key: (k) => k, value: (k) => finalMap['dev_dependencies'][k]); - finalMap['dev_dependencies'] = sortedDDMap; - } - - if (finalMap.containsKey('dependency_overrides')) { - logger.trace('Sorting dependency_overrides'); - var sortedDOKeys = finalMap['dependency_overrides'].keys.toList(growable: false) - ..sort((k1, k2) => k1.toString().compareTo(k2.toString())); - LinkedHashMap sortedDOMap = LinkedHashMap.fromIterable(sortedDOKeys, - key: (k) => k, value: (k) => finalMap['dependency_overrides'][k]); - finalMap['dependency_overrides'] = sortedDOMap; - } - - /// Other values which are not checked and might be from other plugins - if (DeepCollectionEquality().equals(flavorPubspec.others, actualPubspec.others)) { - logger.trace('Deleteing others values'); - - if (flavorPubspec.others != null) { - flavorPubspec.others!.forEach((key, value) { - if (finalMap.containsKey(key)) { - logger.trace('Deleting $key'); - finalMap.remove(key); - } - }); - } - } - - if (flavorPubspec.flutter != null) { - logger.trace('Deleting flutter values'); - - final flutter = actualPubspec.flutter?.toMap() ?? {}; - final flavorFlutter = flavorPubspec.flutter?.toMap() ?? {}; - //finalMap['flutter'] = flavorPubspec.flutter?.toMap(); - if (actualPubspec.flutter != null) { - if (flutter.containsKey('uses-material-design')) { - logger.trace('Deleting Flutter uses-material-design'); - flutter.remove('uses-material-design'); - } - if (flutter.containsKey('generate')) { - logger.trace('Deleting Flutter generate'); - flutter.remove('generate'); - } - - if (flavorFlutter.containsKey('assets')) { - logger.trace('Deleting Flutter Assets'); - final flavourAssets = flavorPubspec.flutter?.assets ?? []; - for (var item in flavourAssets) { - logger.trace('Deleting Flutter Assets $item'); - actualPubspec.flutter?.assets?.remove(item); - } - final assets = actualPubspec.flutter?.assets ?? []; - flutter['assets'] = assets.toList(); - } - - final finalFonts = actualPubspec.flutter?.fonts?.toList() ?? []; - - for (final Font dataI in actualPubspec.flutter?.fonts ?? []) { - for (final Font dataJ in flavorPubspec.flutter?.fonts ?? []) { - if (dataJ == dataI) { - finalFonts.remove(dataI); - } - } - } - - for (final Font dataI in finalFonts) { - for (final Font dataJ in flavorPubspec.flutter?.fonts ?? []) { - if (dataJ.family == dataI.family) { - for (FontsData item in dataJ.fonts ?? []) { - dataI.fonts?.removeWhere((element) => element == item); - } - } - } - } - var fonts = {}..addAll(finalFonts); - - flutter['fonts'] = fonts.toList().map((e) => e.toMap()).toList(); - - if (finalFonts.isEmpty) { - flutter.remove('fonts'); - } - // finalFonts.clear(); - } - - finalMap['flutter'] = flutter; - if (flutter.isEmpty) { - finalMap.remove('flutter'); - } - } - - final finalPubspec = Pubspec.fromMap(finalMap); - - /// Convert the `finalMap` to String with pubspec.yaml format - final String string = json2yaml( - finalPubspec.toMap(addComments: true), - yamlStyle: YamlStyle.pubspecYaml, - ); - - /// If any of the value contains # then it will be converted to "#" - /// ex: hexCode #FFFFFF will be converted to "#FFFFFF" - String replacedText = string.replaceAllMapped(RegExp("#(.*?)(?=\\s|\$)"), (Match m) { - return '"#${m.group(1)}"'; - }); - - /// This will replace the temp added comment string with # - /// [Constants.comment] -> "Pubspec Manager Comment:" will be replaced with "#" in the final pubspec.yaml - replacedText = replacedText - .replaceAllMapped(RegExp("${Constants.comment}\\d+: (.*?)(?=\\s|\$)"), (Match m) { - return '# ${m.group(1)}'; - }); - - /// Save the updated YAML to the file - logger.trace('Creating a backup of pubspec.yaml to backup_pubspec.yaml'); - config.backupPubspecFile.writeAsStringSync(config.pubspecFile.readAsStringSync()); - config.pubspecFile.writeAsStringSync(replacedText); - - logger.stdout('Merging of pubspec.yaml files completed successfully'.green); - - /// Error message when name is changed in the main pubspec.yaml from the flavor pubspec.yaml - if (nameChanged) { - logger.stderr( - 'The name is changed from ${actualPubspec.name} to ${flavorPubspec.name} (as the the one mentioned in the pubspec_${config.flavor}.yaml'); - logger.stderr('This would cause errors in the project.'); - logger.stderr('Fix for this would to refactor the places where the package name was used'); - logger.stderr( - "Refactor: import 'package:${actualPubspec.name}/ to import 'package:${flavorPubspec.name}/ "); - } - - await FlutterBuild().pubGet(); - } - - bool checkIfItsRemove(dynamic data) { - if (data is Map) { - Map result = data; - if (result.containsKey("remove")) { - return true; - } - } - return false; - } - - Future mergePubspec() async { - bool nameChanged = false; - if (!config.pubspecFlavorFile.existsSync()) { - logger.stderr('File does not exist: ${config.flavor}'.red); - return; - } - - // Read the YAML file - final String contents = config.pubspecFlavorFile.readAsStringSync(); - - // Parse the YAML contents - final dynamic yamlMap = loadYaml(contents); - final dynamic actualYamlMap = loadYaml(config.pubspecFile.readAsStringSync()); - if (checkIfItsRemove(yamlMap)) { - remove(); - return; - } - - // Create a Pubspec object - final Pubspec actualPubspec = Pubspec.fromMap(actualYamlMap); - final Pubspec flavorPubspec = Pubspec.fromMap(yamlMap); - - final bool alreadyMerged = PubspecChecker.checkIfPubspecAlreadyMerged( - actualPubspec: actualPubspec, - flavorPubspec: flavorPubspec, - ); - - if (alreadyMerged) { - logger.stdout('Pubspec already merged.'.green); - return; - } - - // Update the Pubspec object - final Map finalMap = actualPubspec.toMap(); - final Map map = flavorPubspec.toMap(); - - if (!PubspecChecker.checkName(actualPubspec, flavorPubspec)) { - logger.trace('Updating name from ${actualPubspec.name} to ' - '${flavorPubspec.name}'); - nameChanged = true; - finalMap['name'] = flavorPubspec.name; - } - - if (!PubspecChecker.checkDescription(actualPubspec, flavorPubspec)) { - logger.trace('Updating description from ${actualPubspec.description} to ' - '${flavorPubspec.description}'); - finalMap['description'] = flavorPubspec.description; - } - - if (!PubspecChecker.checkVersion(actualPubspec, flavorPubspec)) { - logger.trace('Updating version from ${actualPubspec.version} to ' - '${flavorPubspec.version}'); - finalMap['version'] = flavorPubspec.version; - } - - if (!PubspecChecker.checkHomepage(actualPubspec, flavorPubspec)) { - logger.trace('Updating homepage from ${actualPubspec.homepage} to ' - '${flavorPubspec.homepage}'); - finalMap['homepage'] = flavorPubspec.homepage; - } - - if (!PubspecChecker.checkRepository(actualPubspec, flavorPubspec)) { - logger.trace('Updating repository from ${actualPubspec.repository} to ' - '${flavorPubspec.repository}'); - finalMap['repository'] = flavorPubspec.repository; - } - - if (!PubspecChecker.checkIssueTracker(actualPubspec, flavorPubspec)) { - logger.trace('Updating issueTracker from ${actualPubspec.issueTracker} to ' - '${flavorPubspec.issueTracker}'); - finalMap['issueTracker'] = flavorPubspec.issueTracker; - } - - if (!PubspecChecker.checkDocumentation(actualPubspec, flavorPubspec)) { - logger.trace('Updating documentation from ${actualPubspec.documentation} to ' - '${flavorPubspec.documentation}'); - finalMap['documentation'] = flavorPubspec.documentation; - } - - if (!PubspecChecker.checkPublishTo(actualPubspec, flavorPubspec)) { - logger.trace('Updating publishTo from ${actualPubspec.publishTo} to ' - '${flavorPubspec.publishTo}'); - finalMap['publishTo'] = flavorPubspec.publishTo; - } - - if (!PubspecChecker.checkEnvironment(actualPubspec, flavorPubspec)) { - logger.trace('Updating environment from ${actualPubspec.environment} to ' - '${flavorPubspec.environment}'); - final env = actualPubspec.environment?.toMap() ?? {}; - - env.addAll(flavorPubspec.environment!.toMap()); - finalMap['environment'] = env; - } - - var dependencyCheck = - PubspecChecker.checkDependencies(actualPubspec, flavorPubspec, checkAll: true); - if (!dependencyCheck.hasMatch) { - if (dependencyCheck.update.isNotEmpty) { - for (var element in dependencyCheck.update) { - logger.trace('Updating dependency $element'); - } - } - - if (dependencyCheck.addition.isNotEmpty) { - for (var element in dependencyCheck.addition) { - logger.trace('Adding dependency $element'); - } - } - - finalMap['dependencies'] = { - if (finalMap['dependencies'] != null) ...finalMap['dependencies'], - if (map['dependencies'] != null) ...map['dependencies'], - }; - } - - var devDependencyCheck = - PubspecChecker.checkDevDependencies(actualPubspec, flavorPubspec, checkAll: true); - - if (!devDependencyCheck.hasMatch) { - if (devDependencyCheck.update.isNotEmpty) { - for (var element in devDependencyCheck.update) { - logger.trace('Updating dev_dependency $element'); - } - } - - if (devDependencyCheck.addition.isNotEmpty) { - for (var element in devDependencyCheck.addition) { - logger.trace('Adding dev_dependency $element'); - } - } - - finalMap['dev_dependencies'] = { - if (finalMap['dev_dependencies'] != null) ...finalMap['dev_dependencies'], - if (map['dev_dependencies'] != null) ...map['dev_dependencies'], - }; - } - - var dependencyOverrideCheck = - PubspecChecker.checkDependencyOverride(actualPubspec, flavorPubspec, checkAll: true); - - if (!dependencyOverrideCheck.hasMatch) { - if (dependencyOverrideCheck.update.isNotEmpty) { - for (var element in dependencyOverrideCheck.update) { - logger.trace('Updating dependency_overrides $element'); - } - } - - if (dependencyOverrideCheck.addition.isNotEmpty) { - for (var element in dependencyOverrideCheck.addition) { - logger.trace('Adding dependency_overrides $element'); - } - } - - finalMap['dependency_overrides'] = { - if (finalMap['dependency_overrides'] != null) ...finalMap['dependency_overrides'], - if (map['dependency_overrides'] != null) ...map['dependency_overrides'], - }; - } - - if (finalMap.containsKey('dependencies')) { - logger.trace('Sorting dependencies'); - var sortedKeys = finalMap['dependencies'].keys.toList(growable: false) - ..sort((k1, k2) => k1.toString().compareTo(k2.toString())); - LinkedHashMap sortedMap = LinkedHashMap.fromIterable(sortedKeys, - key: (k) => k, value: (k) => finalMap['dependencies'][k]); - finalMap['dependencies'] = sortedMap; - } - - if (finalMap.containsKey('dev_dependencies')) { - logger.trace('Sorting dev_dependencies'); - var sortedDDKeys = finalMap['dev_dependencies'].keys.toList(growable: false) - ..sort((k1, k2) => k1.toString().compareTo(k2.toString())); - LinkedHashMap sortedDDMap = LinkedHashMap.fromIterable(sortedDDKeys, - key: (k) => k, value: (k) => finalMap['dev_dependencies'][k]); - finalMap['dev_dependencies'] = sortedDDMap; - } - - if (finalMap.containsKey('dependency_overrides')) { - logger.trace('Sorting dependency_overrides'); - var sortedDOKeys = finalMap['dependency_overrides'].keys.toList(growable: false) - ..sort((k1, k2) => k1.toString().compareTo(k2.toString())); - LinkedHashMap sortedDOMap = LinkedHashMap.fromIterable(sortedDOKeys, - key: (k) => k, value: (k) => finalMap['dependency_overrides'][k]); - finalMap['dependency_overrides'] = sortedDOMap; - } - - /// Other values which are not checked and might be from other plugins - if (!DeepCollectionEquality().equals(flavorPubspec.others, actualPubspec.others)) { - logger.trace('Updating others values'); - Map others = {}; - if (actualPubspec.others != null) { - actualPubspec.others!.forEach((key, value) { - logger.trace('Updating $key'); - - if (value is Map || value is List) { - others[key] = jsonDecode(jsonEncode(value)); - } else { - others[key] = value; - } - }); - } - if (flavorPubspec.others != null) { - flavorPubspec.others!.forEach((key, value) { - logger.trace('Updating $key'); - - if (value is Map || value is List) { - others[key] = jsonDecode(jsonEncode(value)); - } else { - others[key] = value; - } - }); - } - - finalMap.addAll(others); - } - - if (flavorPubspec.flutter != null) { - logger.trace('Updating flutter values'); - - final flutter = actualPubspec.flutter?.toMap() ?? {}; - finalMap['flutter'] = flavorPubspec.flutter?.toMap(); - if (actualPubspec.flutter != null) { - if (actualPubspec.flutter?.usesMaterialDesign != - flavorPubspec.flutter?.usesMaterialDesign) { - logger.trace('Updating uses-material-design from ' - '${actualPubspec.flutter?.usesMaterialDesign} to ' - '${flavorPubspec.flutter?.usesMaterialDesign}'); - - flutter['uses-material-design'] = flavorPubspec.flutter?.usesMaterialDesign ?? - actualPubspec.flutter?.usesMaterialDesign; - } - - if (actualPubspec.flutter?.generate != flavorPubspec.flutter?.generate) { - logger.trace('Updating generate from ' - '${actualPubspec.flutter?.generate} to ' - '${flavorPubspec.flutter?.generate}'); - flutter['generate'] = flavorPubspec.flutter?.generate ?? actualPubspec.flutter?.generate; - } - - final assets = actualPubspec.flutter?.assets ?? []; - assets.addAll(flavorPubspec.flutter?.assets ?? []); - flutter['assets'] = assets.toSet(); - - final finalFonts = {}; - for (final Font data in actualPubspec.flutter?.fonts ?? []) { - finalFonts.add(Font(family: data.family)); - } - for (final Font data in flavorPubspec.flutter?.fonts ?? []) { - finalFonts.add(Font(family: data.family)); - } - - var fonts = {}..addAll(finalFonts); - - for (final data in finalFonts) { - final actualFont = actualPubspec.flutter?.fonts - ?.firstWhereOrNull((element) => element.family == data.family); - - final flavorFont = flavorPubspec.flutter?.fonts - ?.firstWhereOrNull((element) => element.family == data.family); - - if (actualFont != null && flavorFont != null) { - final map = {}; - map['family'] = actualFont.family; - final f = {}; - - for (final FontsData data in [...actualFont.fonts ?? [], ...flavorFont.fonts ?? []]) { - final d = - flavorFont.fonts?.firstWhereOrNull((element) => element.weight == data.weight); - if (d != null) { - f.add(d); - } else { - f.add(data); - } - } - map['fonts'] = f.toList().map((e) => e.toMap()).toList(); - fonts.remove(data); - fonts.add(Font.fromMap(map)); - } else if (actualFont != null && flavorFont == null) { - fonts.remove(data); - fonts.add(actualFont); - } else if (actualFont == null && flavorFont != null) { - fonts.remove(data); - fonts.add(flavorFont); - } - - flutter['fonts'] = fonts.toList().map((e) => e.toMap()).toList(); - } - finalFonts.clear(); - } - finalMap['flutter'] = flutter; - } - - final finalPubspec = Pubspec.fromMap(finalMap); - - /// Convert the `finalMap` to String with pubspec.yaml format - final String string = json2yaml( - finalPubspec.toMap(addComments: true), - yamlStyle: YamlStyle.pubspecYaml, - ); - - /// If any of the value contains # then it will be converted to "#" - /// ex: hexCode #FFFFFF will be converted to "#FFFFFF" - String replacedText = string.replaceAllMapped(RegExp("#(.*?)(?=\\s|\$)"), (Match m) { - return '"#${m.group(1)}"'; - }); - - /// This will replace the temp added comment string with # - /// [Constants.comment] -> "Pubspec Manager Comment:" will be replaced with "#" in the final pubspec.yaml - replacedText = replacedText - .replaceAllMapped(RegExp("${Constants.comment}\\d+: (.*?)(?=\\s|\$)"), (Match m) { - return '# ${m.group(1)}'; - }); - - /// Save the updated YAML to the file - logger.trace('Creating a backup of pubspec.yaml to backup_pubspec.yaml'); - config.backupPubspecFile.writeAsStringSync(config.pubspecFile.readAsStringSync()); - config.pubspecFile.writeAsStringSync(replacedText); - - logger.stdout('Merging of pubspec.yaml files completed successfully'.green); - - /// Error message when name is changed in the main pubspec.yaml from the flavor pubspec.yaml - if (nameChanged) { - logger.stderr( - 'The name is changed from ${actualPubspec.name} to ${flavorPubspec.name} (as the the one mentioned in the pubspec_${config.flavor}.yaml'); - logger.stderr('This would cause errors in the project.'); - logger.stderr('Fix for this would to refactor the places where the package name was used'); - logger.stderr( - "Refactor: import 'package:${actualPubspec.name}/ to import 'package:${flavorPubspec.name}/ "); - } - - await FlutterBuild().pubGet(); - } -} diff --git a/pubspec.yaml b/pubspec.yaml index a15b20e..01090c2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: pubm description: A Dart command line tool to help with managing pubspec dependencies. -version: 0.1.1 +version: 0.2.0 repository: https://github.com/kushalmahapatro/pubspec_manager homepage: https://github.com/kushalmahapatro/pubspec_manager topics: diff --git a/test/helper.dart b/test/helper.dart new file mode 100644 index 0000000..502b2dd --- /dev/null +++ b/test/helper.dart @@ -0,0 +1,30 @@ +import 'dart:io'; + +import 'package:cli_util/cli_logging.dart'; +import 'package:get_it/get_it.dart'; +import 'package:pubm/src/configuration.dart'; + +import 'pubm_test.dart'; + +Future testSetUp() async { + GetIt.I.registerSingleton(Logger.verbose()); + + final Configuration config = Configuration(['-f', 'test']) + ..pubspecFile = File(pubspecPath) + ..pubspecFlavorFile = File(pubspecFlavorPath) + ..backupPubspecFile = File(backupPubspecFlavorPath) + ..flavor = 'test'; + + GetIt.I.registerSingleton(config); + + await Directory(tempFolderPath).create(recursive: true); + return config; +} + +Future tearDownSetup() async { + GetIt.I.reset(); + + if (await Directory(tempFolderPath).exists()) { + await Directory(tempFolderPath).delete(recursive: true); + } +} diff --git a/test/mock_pubspec_manager.dart b/test/mock_pubspec_manager.dart new file mode 100644 index 0000000..8b77eab --- /dev/null +++ b/test/mock_pubspec_manager.dart @@ -0,0 +1,12 @@ +import 'package:cli_util/cli_logging.dart'; +import 'package:get_it/get_it.dart'; +import 'package:pubm/src/configuration.dart'; +import 'package:pubm/src/manage/pubspec_manage.dart'; + +class MockPubspecManager with PubspecManager { + @override + Configuration get config => GetIt.I(); + + @override + Logger get logger => GetIt.I(); +} diff --git a/test/pubm_test.dart b/test/pubm_test.dart index 06ba6d6..606dda9 100644 --- a/test/pubm_test.dart +++ b/test/pubm_test.dart @@ -1,54 +1,42 @@ import 'dart:io'; -import 'package:cli_util/cli_logging.dart'; -import 'package:get_it/get_it.dart'; import 'package:path/path.dart' as p; import 'package:pubm/models/pubspec.dart'; import 'package:pubm/src/configuration.dart'; import 'package:pubm/src/helpers/pubspec_checker.dart'; -import 'package:pubm/src/pubspec_manage.dart'; import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; +import 'helper.dart'; +import 'mock_pubspec_manager.dart'; import 'test_constants.dart'; +import 'yaml_check.dart'; const String flavor = 'test'; var tempFolderPath = p.join('test', 'configuration_temp'); var pubspecPath = p.join(tempFolderPath, 'pubspec.yaml'); var pubspecFlavorPath = p.join(tempFolderPath, 'pubspec_$flavor.yaml'); var backupPubspecFlavorPath = p.join(tempFolderPath, 'backup_pubspec.yaml'); +late Configuration config; +late MockPubspecManager testClass; +late YamlTest yamlTest; void main() { - late Configuration config; - late TestClass testClass; const flavorYamlContent = ''' - -name: testAppName_flavor - - '''; + name: testAppName_flavor + '''; setUp(() async { - GetIt.I.registerSingleton(Logger.verbose()); - - config = Configuration(['-f', 'test']) - ..pubspecFile = File(pubspecPath) - ..pubspecFlavorFile = File(pubspecFlavorPath) - ..backupPubspecFile = File(backupPubspecFlavorPath) - ..flavor = 'test'; - - GetIt.I.registerSingleton(config); - - await Directory(tempFolderPath).create(recursive: true); - testClass = TestClass(); + config = await testSetUp(); + testClass = MockPubspecManager(); + yamlTest = YamlTest( + yamlContent, + flavorYamlContent, + config, + ); }); - tearDown(() async { - GetIt.I.reset(); - - if (await Directory(tempFolderPath).exists()) { - await Directory(tempFolderPath).delete(recursive: true); - } - }); + tearDown(() => tearDownSetup()); group('config check:', () { test('should return false if help is passed', () async { @@ -78,136 +66,52 @@ name: testAppName_flavor expect(config.pubspecFlavorFile.existsSync(), true); }); - test('check if yaml(s) are same or not', () async { - await File(pubspecPath).writeAsString(yamlContent); - await File(pubspecFlavorPath).writeAsString(flavorYamlContent); - - final result = PubspecChecker.checkIfPubspecAlreadyMerged( - actualPubspec: - Pubspec.fromMap(loadYaml(config.pubspecFile.readAsStringSync())), - flavorPubspec: Pubspec.fromMap( - loadYaml(config.pubspecFlavorFile.readAsStringSync())), - ); - - expect(result, false); - - const content = ''' - -name: pubm - - '''; - - await File(pubspecFlavorPath).writeAsString(content); - final result1 = PubspecChecker.checkIfPubspecAlreadyMerged( - actualPubspec: - Pubspec.fromMap(loadYaml(config.pubspecFile.readAsStringSync())), - flavorPubspec: Pubspec.fromMap( - loadYaml(config.pubspecFlavorFile.readAsStringSync())), - ); - - expect(result1, true); - }); - - test('flavor yaml with existing dependency', () async { - const content2 = ''' + test( + 'Check if yaml are same or not', + () => yamlTest.checkSameYaml(), + ); -name: pubm + test( + 'flavor yaml with existing dependency', + () => yamlTest.checkExistingDependencies(), + ); -dependencies: - path_test2: - path: abc/xyz/2 - - '''; - await File(pubspecPath).writeAsString(yamlContent); - await File(pubspecFlavorPath).writeAsString(content2); - final result2 = PubspecChecker.checkIfPubspecAlreadyMerged( - actualPubspec: - Pubspec.fromMap(loadYaml(config.pubspecFile.readAsStringSync())), - flavorPubspec: Pubspec.fromMap( - loadYaml(config.pubspecFlavorFile.readAsStringSync())), - ); - - expect(result2, true); - }); - - test('flavor yaml with same fonts', () async { - const content2 = ''' - -name: pubm - -dependencies: - path_test2: - path: abc/xyz/2 - -flutter: - fonts: - - family: test - fonts: - - asset: a/a/700.ttf - weight: 700 - - asset: a/a/600.ttf - weight: 600 - - asset: a/a/500.ttf - weight: 500 - - asset: a/a/400.ttf - weight: 400 - - family: test2 - fonts: - - asset: a/b/700.ttf - weight: 700 - - asset: a/b/600.ttf - weight: 600 - - asset: a/b/500.ttf - weight: 500 - - asset: a/b/400.ttf - weight: 400 - - '''; - await File(pubspecPath).writeAsString(yamlContent); - await File(pubspecFlavorPath).writeAsString(content2); - final result2 = PubspecChecker.checkIfPubspecAlreadyMerged( - actualPubspec: - Pubspec.fromMap(loadYaml(config.pubspecFile.readAsStringSync())), - flavorPubspec: Pubspec.fromMap( - loadYaml(config.pubspecFlavorFile.readAsStringSync())), - ); - - expect(result2, true); - }); + test( + 'flavor yaml with same fonts', + () => yamlTest.sameFontsCheck(), + ); test('flavor yaml with new fonts', () async { const content2 = ''' - -name: pubm - -dependencies: - path_test2: - path: abc/xyz/2 - -flutter: - fonts: - - family: test - fonts: - - asset: b/a/700.ttf - weight: 700 - - asset: b/a/600.ttf - weight: 600 - - asset: b/a/500.ttf - weight: 500 - - asset: b/a/400.ttf - weight: 400 - - family: test2 - fonts: - - asset: b/b/700.ttf - weight: 700 - - asset: b/b/600.ttf - weight: 600 - - asset: b/b/500.ttf - weight: 500 - - asset: b/b/400.ttf - weight: 400 - - '''; + name: pubm + + dependencies: + path_test2: + path: abc/xyz/2 + + flutter: + fonts: + - family: test + fonts: + - asset: b/a/700.ttf + weight: 700 + - asset: b/a/600.ttf + weight: 600 + - asset: b/a/500.ttf + weight: 500 + - asset: b/a/400.ttf + weight: 400 + - family: test2 + fonts: + - asset: b/b/700.ttf + weight: 700 + - asset: b/b/600.ttf + weight: 600 + - asset: b/b/500.ttf + weight: 500 + - asset: b/b/400.ttf + weight: 400 + '''; await File(pubspecPath).writeAsString(yamlContent); await File(pubspecFlavorPath).writeAsString(content2); final result2 = PubspecChecker.checkIfPubspecAlreadyMerged( @@ -222,55 +126,53 @@ flutter: test('merge flavor pubspec to pubspec', () async { const content2 = ''' - -name: pubm_merge -version: 0.0.1 - -dependencies: - path_test2: - path: abc/def/2 - a: 1.0.0 - b: - git: - url: git://github.com/flutter/packages.git - ref: 1.0.0 - c: - sdk: flutter - e: - hosted: https://some-package-server.com - version: ^1.0.0 - f: - hosted: - name: some-package - url: https://some-package-server.com - version: ^1.0.0 - -flutter: - fonts: - - family: test - fonts: - - asset: b/a/700.ttf - weight: 700 - - asset: b/a/600.ttf - weight: 600 - - asset: b/a/500.ttf - weight: 500 - - asset: b/a/400.ttf - weight: 400 - - family: test2 - fonts: - - asset: b/b/700.ttf - weight: 700 - - asset: b/b/600.ttf - weight: 600 - - asset: b/b/500.ttf - weight: 500 - - asset: b/b/400.ttf - weight: 400 - - asset: b/b/300.ttf - weight: 300 - - '''; + name: pubm_merge + version: 0.0.1 + + dependencies: + path_test2: + path: abc/def/2 + a: 1.0.0 + b: + git: + url: git://github.com/flutter/packages.git + ref: 1.0.0 + c: + sdk: flutter + e: + hosted: https://some-package-server.com + version: ^1.0.0 + f: + hosted: + name: some-package + url: https://some-package-server.com + version: ^1.0.0 + + flutter: + fonts: + - family: test + fonts: + - asset: b/a/700.ttf + weight: 700 + - asset: b/a/600.ttf + weight: 600 + - asset: b/a/500.ttf + weight: 500 + - asset: b/a/400.ttf + weight: 400 + - family: test2 + fonts: + - asset: b/b/700.ttf + weight: 700 + - asset: b/b/600.ttf + weight: 600 + - asset: b/b/500.ttf + weight: 500 + - asset: b/b/400.ttf + weight: 400 + - asset: b/b/300.ttf + weight: 300 + '''; await File(pubspecPath).writeAsString(yamlContent); await File(pubspecFlavorPath).writeAsString(content2); await testClass.mergePubspec(); @@ -287,12 +189,11 @@ flutter: test('merge flavor pubspec to pubspec with git dependency with url', () async { const content2 = ''' - -dependencies: - b: - git: - url: git://github.com/flutter/packages.git - '''; + dependencies: + b: + git: + url: git://github.com/flutter/packages.git + '''; await File(pubspecPath).writeAsString(yamlContent); await File(pubspecFlavorPath).writeAsString(content2); await testClass.mergePubspec(); @@ -305,53 +206,30 @@ dependencies: expect(result2, true); }); - test('merge flavor pubspec to pubspec with other dependencies', () async { - const content2 = ''' -msix_config: - display_name: Flutter App - publisher_display_name: Company Name - identity_name: company.suite.flutterapp - msix_version: 1.0.0.0 - logo_path: C:\\path\\to\\logo.png - capabilities: internetClient, location, microphone, webcam - -flutter_launcher_icons: - android: "launcher_icon" - ios: true - image_path: "assets/icon/icon.png" - min_sdk_android: 21 # android min sdk min:16, default 21 - web: - generate: true - image_path: "path/to/image.png" - background_color: "#hexcode" - theme_color: "#hexcode" - windows: - generate: true - image_path: "path/to/image.png" - icon_size: 48 # min:48, max:256, default: 48 - macos: - generate: true - image_path: "path/to/image.png" - '''; - await File(pubspecPath).writeAsString(yamlContent); - await File(pubspecFlavorPath).writeAsString(content2); - await testClass.mergePubspec(); - final result2 = PubspecChecker.checkIfPubspecAlreadyMerged( - actualPubspec: - Pubspec.fromMap(loadYaml(config.pubspecFile.readAsStringSync())), - flavorPubspec: Pubspec.fromMap( - loadYaml(config.pubspecFlavorFile.readAsStringSync())), - ); - expect(result2, true); - }); + test( + 'merge flavor pubspec to pubspec with other dependencies', + () => yamlTest.otherDependenciesCheck(), + ); + + test( + 'remove name', + () => yamlTest.removeName(), + ); + + test( + 'remove dependencies', + () => yamlTest.removeDependency(), + ); + + test( + 'remove flutter values', + () => yamlTest.removeFlutterValues(), + ); + + test( + 'remove other values', + () => yamlTest.removeOtherValues(), + ); }); } - -class TestClass with PubspecManager { - @override - Configuration get config => GetIt.I(); - - @override - Logger get logger => GetIt.I(); -} diff --git a/test/remove_value.dart b/test/remove_value.dart new file mode 100644 index 0000000..3c72fda --- /dev/null +++ b/test/remove_value.dart @@ -0,0 +1,116 @@ +import 'dart:io'; + +import 'package:pubm/constants.dart'; +import 'package:pubm/models/pubspec.dart'; +import 'package:test/test.dart'; +import 'package:yaml/yaml.dart'; + +import 'pubm_test.dart'; + +void removeNameFromPubspec(String yamlContent) async { + const content2 = ''' + remove: + name: pubm_new + '''; + final actualPubspecFile = await File(pubspecPath).writeAsString(yamlContent); + final flavorPubspecFile = + await File(pubspecFlavorPath).writeAsString(content2); + await testClass.mergePubspec(); + + final dynamic yamlMap = loadYaml(actualPubspecFile.readAsStringSync()); + final dynamic yamlMap1 = loadYaml(flavorPubspecFile.readAsStringSync()); + expect(yamlMap[name] == yamlMap1[name], false); +} + +void removeDependencyFromPubspec(String yamlContent) async { + const content2 = ''' + remove: + dependencies: + cupertino_icons: ^1.0.2 + git_test2: + path_test: + + dev_dependencies: + test: + flutter_driver: + git_test_dev: + + dependency_overrides: + git_test_override: + '''; + final actualPubspecFile = await File(pubspecPath).writeAsString(yamlContent); + await File(pubspecFlavorPath).writeAsString(content2); + await testClass.mergePubspec(); + + final dynamic yamlMap = loadYaml(actualPubspecFile.readAsStringSync()); + + expect(((yamlMap[devDependencies] ?? {}) as Map).containsKey('git_test2'), + false); + expect(yamlMap[dependencies]?['git_test2'], null); + + expect(((yamlMap[devDependencies] ?? {}) as Map).containsKey('git_test2'), + false); + expect(yamlMap[dependencies]?['git_test2'], null); + + expect(((yamlMap[devDependencies] ?? {}) as Map).containsKey('path_test'), + false); + expect(yamlMap[dependencies]?['path_test'], null); + + expect(((yamlMap[devDependencies] ?? {}) as Map).containsKey('test'), false); + expect(yamlMap[devDependencies]?['test'], null); + + expect( + ((yamlMap[devDependencies] ?? {}) as Map).containsKey('flutter_driver'), + false); + expect(yamlMap[devDependencies]?['flutter_driver'], null); + + expect(((yamlMap[devDependencies] ?? {}) as Map).containsKey('git_test_dev'), + false); + expect(yamlMap[devDependencies]?['git_test_dev'], null); + + expect( + ((yamlMap[dependencyOverrides] ?? {}) as Map) + .containsKey('git_test_override'), + false); + expect(yamlMap[dependencyOverrides]?['git_test_override'], null); +} + +void removeFlutterValuesFromPubspec(String yamlContent) async { + const content2 = ''' + remove: + flutter: + fonts: + - family: test + assets: + - assets/my_icon.png + '''; + final actualPubspecFile = await File(pubspecPath).writeAsString(yamlContent); + await File(pubspecFlavorPath).writeAsString(content2); + await testClass.mergePubspec(); + final dynamic yamlMap = loadYaml(actualPubspecFile.readAsStringSync()); + + final finalPubspec = Pubspec.fromMap(yamlMap); + + expect( + finalPubspec.flutter?.fonts + ?.indexWhere((element) => element.family == 'test'), + -1, + ); + + expect(finalPubspec.flutter?.assets?.contains('assets/my_icon.png') ?? false, + false); +} + +void removeOtherValuesFromPubspec(String yamlContent) async { + const content2 = ''' + remove: + msix_config: + '''; + final actualPubspecFile = await File(pubspecPath).writeAsString(yamlContent); + await File(pubspecFlavorPath).writeAsString(content2); + await testClass.mergePubspec(); + final dynamic yamlMap = loadYaml(actualPubspecFile.readAsStringSync()); + + final finalPubspec = Pubspec.fromMap(yamlMap); + expect(finalPubspec.others?.containsKey('msix_config:') ?? false, false); +} diff --git a/test/test_constants.dart b/test/test_constants.dart index 261a40f..cb2ed95 100644 --- a/test/test_constants.dart +++ b/test/test_constants.dart @@ -1,5 +1,4 @@ const yamlContent = ''' - $name $description $version @@ -8,30 +7,23 @@ $dependencyContent $devDependencies $dependencyOverride $flutterContent +$otherContent '''; -const name = ''' -name: pubm - '''; +const name = 'name: pubm'; -const description = ''' -description: A command-line application to manage pubspec dependencies. - '''; +const description = + 'description: A command-line application to manage pubspec dependencies.'; -const version = ''' -version: 1.0.0 - '''; +const version = 'version: 1.0.0'; const environmentContent = ''' - environment: sdk: '>=3.0.0 <4.0.0' flutter: '3.10.0' - '''; const dependencyContent = ''' - dependencies: flutter: sdk: flutter @@ -53,11 +45,9 @@ dependencies: path: path2 args: ^2.4.2 cupertino_icons: ^1.0.2 - '''; const devDependencies = ''' - dev_dependencies: flutter_test: sdk: flutter @@ -70,26 +60,26 @@ dev_dependencies: path: path_dev test: any lints: ^2.1.1 - '''; const dependencyOverride = ''' - dependency_overrides: git_test_override: git: url: https://github.com/aa/override.git ref: 00000000000000override path: path_override - - '''; const flutterContent = ''' - flutter: uses-material-design: true generate: true + assets: + - assets/my_icon.png + - assets/background.png + - directory/ + - directory/subdirectory/ fonts: - family: test @@ -112,5 +102,14 @@ flutter: weight: 500 - asset: a/b/400.ttf weight: 400 - '''; + +const otherContent = ''' +msix_config: + display_name: Flutter App + publisher_display_name: Company Name + identity_name: company.suite.flutterapp + msix_version: 1.0.0.0 + logo_path: C:\\path\\to\\logo.png + capabilities: internetClient, location, microphone, webcam +'''; diff --git a/test/yaml_check.dart b/test/yaml_check.dart new file mode 100644 index 0000000..e76cca0 --- /dev/null +++ b/test/yaml_check.dart @@ -0,0 +1,162 @@ +import 'dart:io'; + +import 'package:pubm/models/pubspec.dart'; +import 'package:pubm/src/configuration.dart'; +import 'package:pubm/src/helpers/pubspec_checker.dart'; +import 'package:test/test.dart'; +import 'package:yaml/yaml.dart'; + +import 'pubm_test.dart'; +import 'remove_value.dart'; + +class YamlTest { + const YamlTest(this.yamlContent, this.flavorYamlContent, this.config); + + final Configuration config; + final String yamlContent; + final String flavorYamlContent; + + void checkSameYaml() async { + await File(pubspecPath).writeAsString(yamlContent); + await File(pubspecFlavorPath).writeAsString(flavorYamlContent); + + final result = PubspecChecker.checkIfPubspecAlreadyMerged( + actualPubspec: + Pubspec.fromMap(loadYaml(config.pubspecFile.readAsStringSync())), + flavorPubspec: Pubspec.fromMap( + loadYaml(config.pubspecFlavorFile.readAsStringSync())), + ); + + expect(result, false); + + const content = ''' + name: pubm + '''; + + await File(pubspecFlavorPath).writeAsString(content); + final result1 = PubspecChecker.checkIfPubspecAlreadyMerged( + actualPubspec: + Pubspec.fromMap(loadYaml(config.pubspecFile.readAsStringSync())), + flavorPubspec: Pubspec.fromMap( + loadYaml(config.pubspecFlavorFile.readAsStringSync())), + ); + + expect(result1, true); + } + + void checkExistingDependencies() async { + const content2 = ''' + + name: pubm + + dependencies: + path_test2: + path: abc/xyz/2 + + '''; + await File(pubspecPath).writeAsString(yamlContent); + await File(pubspecFlavorPath).writeAsString(content2); + final result2 = PubspecChecker.checkIfPubspecAlreadyMerged( + actualPubspec: + Pubspec.fromMap(loadYaml(config.pubspecFile.readAsStringSync())), + flavorPubspec: Pubspec.fromMap( + loadYaml(config.pubspecFlavorFile.readAsStringSync())), + ); + + expect(result2, true); + } + + void sameFontsCheck() async { + const content2 = ''' + + name: pubm + + dependencies: + path_test2: + path: abc/xyz/2 + + flutter: + fonts: + - family: test + fonts: + - asset: a/a/700.ttf + weight: 700 + - asset: a/a/600.ttf + weight: 600 + - asset: a/a/500.ttf + weight: 500 + - asset: a/a/400.ttf + weight: 400 + - family: test2 + fonts: + - asset: a/b/700.ttf + weight: 700 + - asset: a/b/600.ttf + weight: 600 + - asset: a/b/500.ttf + weight: 500 + - asset: a/b/400.ttf + weight: 400 + + '''; + await File(pubspecPath).writeAsString(yamlContent); + await File(pubspecFlavorPath).writeAsString(content2); + final result2 = PubspecChecker.checkIfPubspecAlreadyMerged( + actualPubspec: + Pubspec.fromMap(loadYaml(config.pubspecFile.readAsStringSync())), + flavorPubspec: Pubspec.fromMap( + loadYaml(config.pubspecFlavorFile.readAsStringSync())), + ); + + expect(result2, true); + } + + void otherDependenciesCheck() async { + const content2 = ''' + msix_config: + display_name: Flutter App + publisher_display_name: Company Name + identity_name: company.suite.flutterapp + msix_version: 1.0.0.0 + logo_path: C:\\path\\to\\logo.png + capabilities: internetClient, location, microphone, webcam + + flutter_launcher_icons: + android: "launcher_icon" + ios: true + image_path: "assets/icon/icon.png" + min_sdk_android: 21 # android min sdk min:16, default 21 + web: + generate: true + image_path: "path/to/image.png" + background_color: "#hexcode" + theme_color: "#hexcode" + windows: + generate: true + image_path: "path/to/image.png" + icon_size: 48 # min:48, max:256, default: 48 + macos: + generate: true + image_path: "path/to/image.png" + '''; + await File(pubspecPath).writeAsString(yamlContent); + await File(pubspecFlavorPath).writeAsString(content2); + await testClass.mergePubspec(); + final result = PubspecChecker.checkIfPubspecAlreadyMerged( + actualPubspec: Pubspec.fromMap( + loadYaml(config.pubspecFile.readAsStringSync()), + ), + flavorPubspec: Pubspec.fromMap( + loadYaml(config.pubspecFlavorFile.readAsStringSync()), + ), + ); + + expect(true, result); + } + + void removeName() => removeNameFromPubspec(yamlContent); + + void removeDependency() => removeDependencyFromPubspec(yamlContent); + void removeFlutterValues() => removeFlutterValuesFromPubspec(yamlContent); + void removeOtherValues() => removeOtherValuesFromPubspec(yamlContent); +}