diff --git a/.github/workflows/pr_validation.yaml b/.github/workflows/pr_validation.yaml
index 85edfd5..da169fe 100644
--- a/.github/workflows/pr_validation.yaml
+++ b/.github/workflows/pr_validation.yaml
@@ -4,12 +4,10 @@ env:
dart_version: 2.19.2
on:
- push:
- branches:
- - main
pull_request:
branches:
- main
+ - develop
jobs:
pr_validation:
@@ -18,14 +16,33 @@ jobs:
timeout-minutes: 15
steps:
- - uses: actions/checkout@v3
+ - name: Checkout
+ uses: actions/checkout@v3
- - uses: dart-lang/setup-dart@v1
+ - name: Dart install
+ uses: dart-lang/setup-dart@v1
with:
sdk: ${{ env.dart_version }}
- name: Pub Get
run: dart pub get
+ - name: Validate Version Bump
+ run: dart run tool/validate_version_bump.dart
+
+ - name: Format
+ run: dart format --set-exit-if-changed .
+
+ - name: Run Tests
+ run: |
+ dart test --coverage=coverage
+ dart run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --report-on=lib
+
+ - name: Verify Test Coverage
+ uses: VeryGoodOpenSource/very_good_coverage@v2
+ with:
+ path: coverage/lcov.info
+ min_coverage: 70
+
- name: Publish dry run
run: dart pub publish --dry-run
diff --git a/.github/workflows/upload_coverage.yaml b/.github/workflows/publish.yaml
similarity index 80%
rename from .github/workflows/upload_coverage.yaml
rename to .github/workflows/publish.yaml
index 83121b2..9009141 100644
--- a/.github/workflows/upload_coverage.yaml
+++ b/.github/workflows/publish.yaml
@@ -1,4 +1,4 @@
-name: Upload Coverage
+name: Publish
env:
dart_version: 2.19.2
@@ -9,7 +9,7 @@ on:
- main
jobs:
- coverage:
+ publish:
runs-on: ubuntu-latest
timeout-minutes: 15
@@ -25,7 +25,10 @@ jobs:
- name: Run Tests
run: |
dart test --coverage=coverage
- dart run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib
+ dart run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --report-on=lib
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
+
+ - name: Publish to pub.dev
+ uses: dart pub publish
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..d03590f
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,8 @@
+{
+ "[dart]": {
+ "editor.rulers": [
+ 80,
+ ],
+ },
+ "dart.lineLength": 80,
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4f48619..d007363 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,2 +1,3 @@
-1. testing some changelog changes
-2. changelog changes
\ No newline at end of file
+# 0.1.0
+
+- initial release
\ No newline at end of file
diff --git a/CHANGELOG_BUBBLED.g.md b/CHANGELOG_BUBBLED.g.md
index 697cfe0..c5e802d 100644
--- a/CHANGELOG_BUBBLED.g.md
+++ b/CHANGELOG_BUBBLED.g.md
@@ -1,2245 +1,13 @@
-# Bubbled Changelog
-
-## This app
-changelog_bubbler | 0.1.0 -> 0.1.0
-
- CHANGELOG.md not found
-
-
-
-
-## Changed Dependencies
-
-
- pub.dev
-
-
- get_it | 7.4.1 -> 7.6.0 | direct main
-
- [7.6.0] - 09.05.2023
-* merged PR by lacopiroty https://github.com/fluttercommunity/get_it/pull/297 which now allows to access objects inside GetIt by runtime type too like
-```Dart
- getIt.registerSingleton(TestClass());
-
- final instance1 = getIt.get(type: TestClass);
-
- expect(instance1 is TestClass, true);
-```
-* fix for https://github.com/fluttercommunity/get_it/issues/299
-* fix for https://github.com/fluttercommunity/get_it/issues/300
-
-
-[7.5.0] - 07.05.2023
-
-* new function `dropScope(scopeName)` which allows to remove and dispose any named scope even if it's not the top one. Great PR by @olexale https://github.com/fluttercommunity/get_it/pull/292 which fixes sort of race conditions if you create scopes just for the life time of a widget.
-## [7.4.1]
-* PR from @dzziwny which fixed an edge case with LazySingletons https://github.com/fluttercommunity/get_it/pull/284
-* Changed an assertion in case that an object is not registered to an Exception that also will throw in real time so that you get meaningful errors based on https://github.com/fluttercommunity/get_it/issues/312
-
-## [7.4.0]
-* `registerSingleton` now returns the passed instance as a return value thanks to the PR by @Rexios80 https://github.com/fluttercommunity/get_it/pull/242
-* In some cases GetIt will print error messages to the debug output. Now this won't happen anymore in release mode and can be completely disabled by setting `GetIt.noDebugOutput=true` following the PR from @James1345
-## [7.3.0]
-
-New features:
-* `popScopeTil` got a new optional `inclusive` parameter so you can now decide if scope with the passed name should be popped too or only the ones above
-* PR by @jtdLab that adds to reset a LazySingleton by providing an existing instance
-* Fix for an internal state error by @ioantsaf
-* Fix for a rare edge case if you manually `signalReady`
-* Many PRs with improvements to spelling and grammar of readme, source documentation and even one assert message by @selcukguvel @isinghmitesh @UsamaKarim @nilsreichardt and Os-Prog
-@Ae-Mc
-
-
-## [7.2.0]
-
-* fix for https://github.com/fluttercommunity/get_it/issues/210
-* Parameters of factories are no longer needed to be casted because they are nullable
-* downgraded the dependency on `async` to 2.6 again
-* you couldn't push two Scopes without a name
-
-## [7.1.4]
-
-* fixed bug with manual synchronization of SingletonsWithDependencies
-https://github.com/fluttercommunity/get_it/issues/196
-
-## [7.1.3] - 07.05.2021
-
-* Fix for https://github.com/fluttercommunity/get_it/issues/186
-
-## [7.1.2] - 06.05.2021
-
-* Thanks to the clever PR https://github.com/fluttercommunity/get_it/pull/185 by @kmartins `unregister` and `resetLazySingleton` now only have to be awaited if you use an async disposal function.
-
-## [7.1.1] - 05.05.2021
-
-* `pushNewScope()` now got an optional `init` parameter where you can pass a function that registers new objects inside the newly pushed Scope. Doing the registration in this function ensures that the `onScopeChanged` call-back is called after the objects are registered.
-
-## [7.1.0] - 05.05.2021
-
-* The new `Disposable` interface had a typo that now got corrected. You could call this a breaking change but as the last version change is just three days old I guess not many people will be affected by this correction.
-
-#### Getting notified when a scope change happens
-
-When using scopes with objects that shadow other objects its important to give the UI a chance to rebuild and acquire references to the now active objects. For this you can register an call-back function in GetIt
-The getit_mixin has a matching `rebuiltOnScopeChange` method.
-
-```Dart
- /// Optional call-back that will get call whenever a change in the current scope happens
- /// This can be very helpful to update the UI in such a case to make sure it uses
- /// the correct Objects after a scope change
- void Function(bool pushed)? onScopeChanged;
-```
-## [7.0.0] - 02.05.2021
-
-This is a breaking change because there were some inconsistencies in the handling of the disposal functions that you can pass when registering an Object, pop a Scope or use `unregister()` `resetLazySingleton()`. Some of accepted a `FutureOr` method type, others just a `void` which meant you couldn't use async functions consistently. With this release you can use async functions in all disposal functions which unfortunately also required to change the signatures of the following functions:
-
-```dart
- Future reset({bool dispose = true});
-
- Future resetScope({bool dispose = true});
-
- Future popScope();
-
- Future popScopesTill(String name);
-
- FutureOr resetLazySingleton({
- Object? instance,
- String? instanceName,
- FutureOr Function(T)? disposingFunction,
- });
-
- FutureOr unregister({
- Object? instance,
- String? instanceName,
- FutureOr Function(T)? disposingFunction,
- });
-```
-
-Basically all functions that can possibly call a disposal functions should be awaited.
-#### Implementing the `Disposable` interface
-
-Instead of passing a disposing function on registration or when pushing a Scope from V7.0 on your objects `onDispose()` method will be called
-if the object that you register implements the `Disposable`´interface:
-
-```Dart
-abstract class Disposable {
- FutureOr onDispose();
-}
-```
-#### Getting notified about the shadowing state of an object
-In some cases it might be helpful to know if an Object gets shadowed by another one e.g. if it has some Stream subscriptions that it want to cancel before the shadowing object creates a new subscription. Also the other way round so that a shadowed Object gets notified when it's "active" again meaning when a shadowing object is removed.
-
-For this a class had to implement the `ShadowChangeHandlers` interface:
-
-```Dart
-abstract class ShadowChangeHandlers {
- void onGetShadowed(Object shadowing);
- void onLeaveShadow(Object shadowing);
-}
-```
-When the Object is shadowed its `onGetShadowed()` method is called with the object that is shadowing it. When this object is removed from GetIt `onLeaveShadow()` will be called.
-
-
- * Thanks to this PR https://github.com/fluttercommunity/get_it/pull/181 by @n3wtron you can now also make objects depend on other objects not only by type but also by type and name if you used a named registration
-
-## [6.1.1] - 13.04.2021
-
-* small fix in getAsync with parameters
-
-## [6.1.0] - 12.04.2021
-
-* Exceptions that occur during an async initialisation are now forwarded to the future that `allReady()` returns instead to get swallowed https://github.com/fluttercommunity/get_it/issues/148
-* Added a property `currentScopeName` to query the name of the currently active scope https://github.com/fluttercommunity/get_it/issues/153
-* `popScope` will know throw an Exception instead just an assert if you are already on the `baseScope` and you try to pop it.
-
-## [6.0.0] - 15.02.2021
-
-* Official null safety release
-
-## [5.0.2] - 08.12.2020
-
-* fixed https://github.com/fluttercommunity/get_it/issues/138 when calling `unRegister` the dispose function
-that can be passed when registering wasn't called.
-
-## [5.0.1] - 23.09.2020
-
-* fixed formatting in readme
-
-## [5.0.0-mixin-version] - 17.09.2020
-
-* experimental
-
-## [5.0.0] - 15.09.2020
-
-* New scope support for registration
-* optional dispose functions for registered objects
-* **Breaking change:** `reset()` now is async and returns a `Future` because it will call the new optional disposal functions that can be async
-* **Breaking change:** If you use names to register your objects you now have to provide a type too or at least make sure the compiler can infer the type. With this change it is now possible to use the same name for different types.
-
-## [5.0.0-alpha] - 11.09.2020
-
-* alpha version of V5.0
-
-## [4.0.4] - 22.07.2020
-
-* fixed linter errors
-
-## [4.0.3] - 22.07.2020
-
-* fixes of several typos thanks to PRs from @Bryanx, @sspatari
-* fixed error https://github.com/fluttercommunity/get_it/issues/92
-
-## [4.0.2] - 26.04.2020
-
-* removed too strong type check for passed factory parameter
-* fixed error message https://github.com/fluttercommunity/get_it/issues/69
-
-
-## [4.0.1] - 19.03.2020
-
-* overhauled readme
-* removed unnecessary print statement
-
-## [4.0.0] - 26.02.2020
-
-* Added abstract `WillSignalReady` class
-
-## [4.0.0-release-candidate] - 14.02.2020
-
-* Breaking changes in API!!!
-* Release candidate
-* New Async functions
-* Factories with parameters
-* Improved startup synchronisation
-
-## [3.0.2] - 23.10.2019
-
-* Bugfix when using named instances
-
-## [3.0.1] - 24.09.2019
-
-* Bugfix with https://github.com/fluttercommunity/get_it/pull/21
-
-## [3.0.0+1] - 07.09.2019
-
-* Small fix to make the analyser happy
-
-## [3.0.0] - 07.09.2019
-
-* Overhauled the signalling API because the way it was was not optimal. Now you can either signal globally or by passing the instance of the registered object that shall signal. This way it's ensured that you have to have access to the instance to signal, typically from within the instance with a `GetIt.instance.signalReady(this)`
-individual signalling from other places but the instance itself is probably an error.
-* Unregister of singletons /lazysingletons now possible also over a registered instance.
-* Most asserts have bin replaced with throwing `Error`objects.
-* The example now shows the ready signalling.
-
-## [2.1.0] - 26.08.2019
-
-* Added handy ready signal to make start-up logic a bit easier
-* Unregister of Objects now possible with optional disposing function
-
-## [2.0.3] - 26.08.2019
-
-* Small fix
-
-## [2.0.2] - 19.08.2019
-
-* Small fix
-
-## [2.0.1] - 19.08.2019
-
-* Small fix
-
-## [2.0.0] - 18.08.2019
-
-* **Breaking Change with V2.0.0**
-you no longer can directly create instances of the type `GetIt` because `GetIt` is now a singleton please see [README](README.md)
-
-## [1.1.0] - 18.08.2019
-
-* added named registration
-
-## [1.0.3+2] - 26.06.2019
-
-* updated logo in readme
-
-## [1.0.3+1] - 22.05.2019
-
-* updated authors
-
-## [1.0.3] - 01.03.2019
-
-* Small fix so that intellisense works now if you use the short calling form without using `.get()`
-
-## [1.0.2] - 22.06.2018
-
-* Moved package to [Flutter Community](https://github.com/fluttercommunity)
-
-## [1.0.1] - 20.06.2018
-
-* Added `reset()`method
-
-## [1.0.0] - 22.05.2018
-
-* Initial release
-
-
-
-
-
-process_run | ADDED | direct mainpubspec_lock_parse | ADDED | direct maincharcode | ADDED | transitive mainchecked_yaml | ADDED | transitive main
- collection | 1.17.1 -> 1.17.2 | direct main
-
- ## 1.17.2
-
-* Accept Dart SDK versions above 3.0.
-
-## 1.17.1
-
-* Require Dart 2.18.
-* Improve docs for `splitAfter` and `splitBefore`.
-
-## 1.17.0
-
-* Add `Iterable.elementAtOrNull` and `List.elementAtOrNull` extension methods.
-* Add a top-level `lastBy()` function that converts an `Iterable` to a `Map` by
- grouping its elements using a function, keeping the last element for each
- computed key. Also available as an extension method on `Iterable`.
-
-## 1.16.0
-
-* Add an `Iterable.slices` extension method.
-* Add `BoolList` class for space-efficient lists of boolean values.
-* Use a stable sort algorithm in the `IterableExtension.sortedBy` method.
-* Add `min`, `max`, `minOrNull` and `maxOrNull` getters to
- `IterableDoubleExtension`, `IterableNumberExtension` and
- `IterableIntegerExtension`
-* Change `UnorderedIterableEquality` and `SetEquality` to implement `Equality`
- with a non-nullable generic to allows assignment to variables with that type.
- Assignment to `Equality` with a nullable type is still allowed because of
- covariance. The `equals` and `hash` methods continue to accept nullable
- arguments.
-* Enable the `avoid_dynamic_calls` lint.
-
-## 1.15.0
-
-* Stable release for null safety.
-
-## 1.15.0-nullsafety.5
-
-* Fix typo in extension method `expandIndexed`.
-* Update sdk constraints to `>=2.12.0-0 <3.0.0` based on beta release
- guidelines.
-
-## 1.15.0-nullsafety.4
-
-* Allow prerelease versions of the `2.12.x` sdk.
-
-* Remove the unusable setter `UnionSetController.set=`. This was mistakenly
- added to the public API but could never be called.
-
-* Add extra optional `Random` argument to `shuffle`.
-
-* Add a large number of extension methods on `Iterable` and `List` types,
- and on a few other types.
- These either provide easy access to the operations from `algorithms.dart`,
- or provide convenience variants of existing `Iterable` and `List` methods
- like `singleWhereOrNull` or `forEachIndexed`.
-
-## 1.15.0-nullsafety.3
-
-* Allow 2.10 stable and 2.11.0 dev SDK versions.
-* Add `toUnorderedList` method on `PriorityQueue`.
-* Make `HeapPriorityQueue`'s `remove` and `contains` methods
- use `==` for equality checks.
- Previously used `comparison(a, b) == 0` as criteria, but it's possible
- to have multiple elements with the same priority in a queue, so that
- could remove the wrong element.
- Still requires that objects that are `==` also have the same priority.
-
-## 1.15.0-nullsafety.2
-
-Update for the 2.10 dev sdk.
-
-## 1.15.0-nullsafety.1
-
-* Allow the <=2.9.10 stable sdks.
-
-## 1.15.0-nullsafety
-
-Pre-release for the null safety migration of this package.
-
-Note that `1.15.0` may not be the final stable null safety release version,
-we reserve the right to release it as a `2.0.0` breaking change.
-
-This release will be pinned to only allow pre-release sdk versions starting
-from `2.9.0-dev.18.0`, which is the first version where this package will
-appear in the null safety allow list.
-
-## 1.14.13
-
-* Deprecate `mapMap`. The Map interface has a `map` call and map literals can
- use for-loop elements which supersede this method.
-
-## 1.14.12
-
-* Fix `CombinedMapView.keys`, `CombinedMapView.length`,
- `CombinedMapView.forEach`, and `CombinedMapView.values` to work as specified
- and not repeat duplicate items from the maps.
- * As a result of this fix the `length` getter now must iterate all maps in
- order to remove duplicates and return an accurate length, so it is no
- longer `O(maps)`.
-
-## 1.14.11
-
-* Set max SDK version to `<3.0.0`.
-
-## 1.14.10
-
-* Fix the parameter names in overridden methods to match the source.
-* Make tests Dart 2 type-safe.
-* Stop depending on SDK `retype` and deprecate methods.
-
-## 1.14.9
-
-* Fixed bugs where `QueueList`, `MapKeySet`, and `MapValueSet` did not adhere to
- the contract laid out by `List.cast`, `Set.cast` and `Map.cast` respectively.
- The returned instances of these methods now correctly forward to the existing
- instance instead of always creating a new copy.
-
-## 1.14.8
-
-* Deprecated `Delegating{Name}.typed` static methods in favor of the new Dart 2
- `cast` methods. For example, `DelegatingList.typed(list)` can now be
- written as `list.cast()`.
-
-## 1.14.7
-
-* Only the Dart 2 dev SDK (`>=2.0.0-dev.22.0`) is now supported.
-* Added support for all Dart 2 SDK methods that threw `UnimplementedError`.
-
-## 1.14.6
-
-* Make `DefaultEquality`'s `equals()` and `hash()` methods take any `Object`
- rather than objects of type `E`. This makes `const DefaultEquality()`
- usable as `Equality` for any `E`, which means it can be used in a const
- context which expects `Equality`.
-
- This makes the default arguments of various other const equality constructors
- work in strong mode.
-
-## 1.14.5
-
-* Fix issue with `EmptyUnmodifiableSet`'s stubs that were introduced in 1.14.4.
-
-## 1.14.4
-
-* Add implementation stubs of upcoming Dart 2.0 core library methods, namely
- new methods for classes that implement `Iterable`, `List`, `Map`, `Queue`,
- and `Set`.
-
-## 1.14.3
-
-* Fix `MapKeySet.lookup` to be a valid override in strong mode.
-
-## 1.14.2
-
-* Add type arguments to `SyntheticInvocation`.
-
-## 1.14.1
-
-* Make `Equality` implementations accept `null` as argument to `hash`.
-
-## 1.14.0
-
-* Add `CombinedListView`, a view of several lists concatenated together.
-* Add `CombinedIterableView`, a view of several iterables concatenated together.
-* Add `CombinedMapView`, a view of several maps concatenated together.
-
-## 1.13.0
-
-* Add `EqualityBy`
-
-## 1.12.0
-
-* Add `CaseInsensitiveEquality`.
-
-* Fix bug in `equalsIgnoreAsciiCase`.
-
-## 1.11.0
-
-* Add `EqualityMap` and `EqualitySet` classes which use `Equality` objects for
- key and element equality, respectively.
-
-## 1.10.1
-
-* `Set.difference` now takes a `Set
-
-
-json_annotation | ADDED | transitive mainsynchronized | ADDED | transitive mainmocktail | ADDED | direct dev
- _fe_analyzer_shared | 59.0.0 -> 60.0.0 | transitive dev
-
- ## 5.12.0
-* Deprecated `DartType.isDynamic`, use `is DynamicType` instead.
-* Updated `NamedType` to use `importPrefix` and `name2` token.
- The deprecated `name` node is still visited in this version, but will stop
- in the next major version.
-* Updated `ExtensionOverride` to use `importPrefix` and `name` token.
- The deprecated `extensionName` node is still visited in this version, but
- will stop in the next major version.
-* Deprecated the default `AnalysisError` constructor, use `tmp` constructor,
- with names formal parameters. Theoretically no clients should use either,
- but practically there are two uses currently.
-* Added `InvalidType`, used when a named type cannot be resolved, or a
- property cannot be resolved, etc. Previously `DynamicType` was used.
- In the future `DynamicType` will be used only when specified explicitly,
- or a property is resolved against a dynamic target. The clients should
- prepare by checking also for `InvalidType` in addition to `DynamicType`.
-
-## 5.11.1
-* Restore previously published `finalKeyword`, `interfaceKeyword` and
- `sealedKeyword` of `MixinElement`. We added them preliminary while
- working on the class modifiers feature, but eventually decided to remove.
- See https://github.com/dart-lang/sdk/issues/52159 for details.
-
-## 5.11.0
-* Removed `@experimental` from AST nodes and elements for records and patterns.
-* Deprecated `IfStatement.condition`, use `expression` instead.
-* Added `NamedType.importPrefix`, `NamedType.name2`, and `NamedType.element`.
- Deprecated `NamedType.name`. Currently `Identifier` is an expression, and
- an expression as a name of a type does not make sense. So, instead we model
- it as a name token, the `Element` that it references, and an optional import
- library prefix reference.
-
-## 5.10.0
-* Added `DartType.isDartCoreType`.
-
-## 5.9.0
-* Deprecated `FunctionBody.isPotentiallyMutatedInClosure`, not used by clients.
-* Fix for `FunctionBody.isPotentiallyMutatedInScope` and pattern assignment.
-
-## 5.8.0
-* Deprecated `DartType.isVoid`, use `is VoidType` instead.
-* `records`, `patterns`, and `class-modifiers` features enabled by default.
-
-## 5.7.1
-* Require SDK `>=2.19.0 <3.0.0` to use `PathNotFoundException` from `dart:io`.
-
-## 5.7.0
-* Work on `class-modifiers` feature.
-* Work on `patterns` feature.
-* Support for primitive equality.
-
-## 5.6.0
-* Fixes for patterns parsing.
-* Implemented `DartPattern.precedence`.
-
-## 5.5.0
-* Rename `RecordPatternField` to `PatternField`.
-* Rename `RecordPatternFieldName` to `PatternFieldName`.
-
-## 5.4.0
-* Bug fixes: 50660
-
-## 5.3.1
-* Require `collection: ^1.17.0` because we use `elementAtOrNull`.
-
-## 5.3.0
-* Use `3.0.0` as the current language version.
-
-## 5.2.0
-* Deprecated `Element.enclosingElement3`, use `enclosingElement` instead.
-* Deprecated `Directive.element2`, use `element` instead.
-* Deprecated `CatchClause.exceptionParameter2`, use `exceptionParameter` instead.
-* Deprecated `CatchClause.stackTraceParameter2`, use `stackTraceParameter` instead.
-* Deprecated `DartType.element2`, use `element` instead.
-* Deprecated `Element.isAccessibleIn2()`, use `isAccessibleIn()` instead.
-* Deprecated `CompilationUnitElement.enums2`, use `enums` instead.
-* Deprecated `CompilationUnitElement.getEnum2()`, use `getEnum()` instead.
-* Deprecated `CompilationUnitElement.mixins2`, use `mixins` instead.
-* Deprecated `LibraryElement.parts2`, use `parts` instead.
-* Deprecated `ImportElement.imports2`, use `imports` instead.
-* Add `AnalysisDriverForPackageBuild.sdkLibraryUris`.
-* Deprecated `buildSdkSummary2()`, use `buildSdkSummary()` instead.
-
-## 5.1.0
-* Deprecated `AstNode.name2`, use `name` instead.
-* Deprecated `AstNode.declaredElement2`, use `declaredElement` instead.
-
-## 5.0.0
-* Removed deprecated methods from AST.
-* Removed deprecated `DiagnosticMessage.message`.
-* Removed deprecated `LibraryElement.getImportsWithPrefix()`.
-* Removed deprecated `ParameterElement.isNotOptional`.
-* Removed deprecated `DartType.displayName`.
-* Removed deprecated methods from `AnalysisDriver`.
-* Removed deprecated `ClassOrMixinDeclaration`.
-* Removed deprecated `Declaration.declaredElement`.
-* Removed deprecated `Element.enclosingElement` and `enclosingElement2`.
-* Removed deprecated `ExportElement`, `ImportElement`.
-* Removed deprecated `NamedCompilationUnitMember.name`.
-* Removed deprecated `Declaration.declaredElement`.
-* Removed deprecated `DartType.element`.
-
-## 4.7.0
-* Add missing `addXyz` to `NodeLintRegistry`.
-* Add `lookUpInheritedConcreteX()` to `InterfaceElement`.
-
-## 4.6.0
-* Added `DartType.element2`, so that `InterfaceType.element2` overrides it.
-
-## 4.5.0
-* Update deprecation message for `FormalParameter.identifier`.
-* Deprecated `ClassOrMixinDeclaration`, use `ClassDeclaration` and `MixinDeclaration` directly.
-* Deprecated `Declaration.declaredElement`, use `declaredElement2` instead.
- This is necessary to separate `ClassElement`, `EnumElement`, and `MixinElement`.
- And, in the future, augmentations like `ClassAugmentationElement`, etc.
-* Deprecated `TypeSystem.instantiateToBounds2()`, use `instantiateInterfaceToBounds()` or
- `instantiateTypeAliasToBounds()` instead.
-
-## 4.4.0
-* Deprecated `ClassDeclaration.isAbstract`, use `abstractKeyword` instead.
-* Deprecated `ClassTypeAlias.isAbstract`, use `abstractKeyword` instead.
-* Deprecated `ClassOrMixinDeclaration.getField`, filter `members` instead.
-* Deprecated `ClassOrMixinDeclaration.getMethod`, filter `members` instead.
-* Deprecated `ClassDeclaration.getConstructor`, filter `members` instead.
-* Deprecated `Directive.element`, use `element2` instead.
-* Deprecated `ClassElement.hasStaticMember`, it is not useful for clients.
-* Deprecated `NamespaceDirective.uriElement`, use `element2.uri` with `DirectiveUriWithLibrary` instead.
-* Deprecated `UriBasedDirective.uriContent`, `UriBasedDirective.uriElement`, `UriBasedDirective.uriSource`.
- Use `Directive.element2.uri` instead.
-* Deprecated `NamespaceDirective.selectedSource`, use `element2.uri` with `DirectiveUriWithSource` instead.
-* Deprecated `Configuration.uriSource`, use `resolvedUri` instead.
-* Deprecated `CatchClause.exceptionParameter` and `CatchClause.stackTraceParameter`.
- Use `exceptionParameter2` and `stackTraceParameter2` instead.
-* Added `FileResult.isAugmentation` and `isLibrary` to complement `isPart`.
-* Deprecated 'XyzDeclaration.name' in AST, use `name2` and `declaredElement` instead.
-* Deprecated `Element.enclosingElement2`, use `enclosingElement3` instead. The meaningful change is that
- `ConstructorElement.enclosingElement3` returns now `InterfaceElement`, not `ClassElement`.
-* Deprecated `get enums/mixin`, use `get enums2/mixins2` instead.
-* Deprecated `DartType.element`, check for `InterfaceType`, `TypeParameterType`, and then ask the element.
-* Deprecated `ClassElement.isEnum` and `isMixin`. Check for `is EnumElement` and `is MixinElement` instead.
-* Deprecated `LibraryElement.getType()` use `getClass()` instead.
-
-## 4.3.1
-* Fix `identifier` for `LibraryExportElement` and `LibraryImportElement`.
-
-## 4.3.0
-* Deprecated `Directive.keyword`, use corresponding `xyzToken` in specific directives.
-* Deprecated `LibraryElement.parts`, use `parts2` instead.
-* Deprecated `LibraryElement.exports`, use `libraryExports` instead.
-* Deprecated `LibraryElement.imports`, use `libraryImports` instead.
-* Deprecated `Element.enclosingElement`, use `enclosingElement2` instead.
-* `Member` is not equal to `ElementImpl`, use `Element.declaration`.
-
-## 4.2.0
-* Update SDK constraints to `>=2.17.0 <3.0.0`.
-* Deprecated `ImportDirective.COMPARATOR`, use appropriate custom logic, if necessary.
-* Deprecated `Element.isAccessibleIn()`, use `isAccessibleIn2()` instead.
-* Bug fixes: 49225.
-
-## 4.1.0
-* Deprecated `ParameterElement.isNotOptional`, use `isRequired` instead.
-* Deprecated `ResourceProviderMixin.newFile2`, use `newFile` instead.
-* Deprecated `ResourceProviderMixin.newAnalysisOptionsYamlFile2`, use `newAnalysisOptionsYamlFile` instead.
-* Deprecated `DartType.resolveToBound`, use `TypeSystem.resolveToBound` instead.
-* Deprecated `LibraryElement.getImportsWithPrefix`, use `PrefixElement.imports` instead.
-* Fix for `AnalysisSession.getFile()` to return updated content after `applyPendingFileChanges`.
-
-## 4.0.0
-* Removed deprecated `UriKind` and `Source.uriKind`.
-* Removed deprecated `LibraryElement.hasExtUri`.
-* Removed deprecated `LibraryElement.hasLoadLibraryFunction`.
-* Removed deprecated `ImportElement.prefixOffset`.
-* Removed deprecated `CompilationUnitElement.types`.
-* Removed deprecated `Source.encoding`.
-* Removed deprecated `Source.isInSystemLibrary`.
-* Removed deprecated `Source.modificationStamp`.
-* Removed deprecated `stamp` in `MemoryResourceProvider`.
-* Removed deprecated `SourceFactory.restoreUri`, use `pathToUri` instead.
-* Removed deprecated `AnalysisContext.workspace`.
-* The `isNonNullableByDefault` parameter in `ErrorReporter` is now required.
-* Removed `Element.SORT_BY_OFFSET`, it is not used.
-* Changed synchronous `AnalysisSession.getFile` and `getParsedUnit` to fail
- if there are pending file changes, instead of reading. As for any other
- `AnalysisSession` method, await `AnalysisContext.applyPendingFileChanges()`.
-* Removed `Token.copy()` and `copyComments()`.
-* Removed `CommentToken.remove()`.
-* Removed deprecated `astFactory` and `AstFactory`.
-* Removed `AnalysisOptions.signature` and `signaturesEqual`.
-* Removed deprecated `buildSdkSummary()`.
-
-## 3.4.1
-* Remove checks for consistency after operations in `AnalysisSession`.
-
-## 3.4.0
-* Deprecated `Resource.parent2`, use `parent` instead.
-* Deprecated `astFactory`, clients should not create AST nodes manually.
-* Changed `CompilationUnit.lineInfo` to be non-nullable.
-* Changed `CompilationUnitElement.lineInfo` to be non-nullable.
-* Deprecated `ResourceProviderMixin.newFile`, use `newFile2` instead.
-* Deprecated `ResourceProviderMixin.newAnalysisOptionsYamlFile`.
-* Added `AnalysisContext.changeFile` and `AnalysisContext.applyPendingFileChanges`.
-* Deprecated `buildSdkSummary`, use asynchronous `buildSdkSummary2` instead.
-
-## 3.3.1
-* Report HintCode.OVERRIDE_ON_NON_OVERRIDING_xyz on enum.
-
-## 3.3.0
-* Added `getField` to `ExtensionElement`.
-* Added `isGenerative` to `ConstructorElement`.
-* Added `isDartCoreEnum` to `ClassElement` and `DartType`.
-* Deprecated `superclass2`, `mixinTypes2`, etc. Use `superclass`, `mixinTypes`, etc.
-* APIs for `enhanced-enums` language feature.
-
-## 3.2.0
-* Deprecated `changes` getter in `File` and `Folder`, use `watch()` instead.
-
-## 3.1.0
-* New internal API for `package:dart_style`.
-* Removed deprecated non-API `MockSdk` class.
-* Removed deprecated `AnalysisDriver` constructor.
-* Updated the current language version to `2.17`.
-
-## 3.0.0
-* Removed deprecated `DartType.aliasElement/aliasArguments`.
-* Removed deprecated constructors from `FeatureSet`.
-* Removed `UnitElementResult.signature` - unused by clients.
-* Removed deprecated `AnalysisError.withNamedArguments`.
-* Removed deprecated `ErrorReporter.reportErrorMessage`.
-* Removed deprecated `ResourceProvider.getModificationTimes()`.
-* Removed deprecated `MemoryResourceProvider.newDummyLink()`.
-* Removed deprecated `MemoryResourceProvider.updateFile()`.
-* Removed deprecated `Resource.parent`.
-* Removed deprecated `ResultState` and `AnalysisResult.state`.
-* Removed deprecated `summary_file_builder` library.
-* Removed deprecated `message` and `correction` from `ErrorCode`.
-* Removed deprecated `lookUp` methods from `InterfaceType`.
-* Removed deprecated `InterfaceType.getSmartLeastUpperBound`.
-* Removed deprecated `path` and `uri` from `AnalysisResult`.
-* Removed deprecated methods from `AnalysisSession`.
-* Removed `TypeName` and corresponding methods.
-* Removed deprecated methods from `TypeProvider`.
-
-## 2.8.0
-* Deprecations and renames for `getXyz` methods in `AnalysisDriver`.
-* Removed uppercase named constants from `double` in mock SDK.
-* Deprecated `path` and `uri` from `AnalysisResult`.
-* Deprecated `UriResolver.restoreAbsolute`, use `pathToUri` instead.
-* Deprecated `SourceFactory.restoreAbsolute`, use `pathToUri` instead.
-* Deprecated `UriKind` and `Source.uriKind`.
-* Deprecated `Source.modificationStamp`.
-* Deprecated `Source.isInSystemLibrary`, use `uri.isScheme('dart')` instead.
-* Fixed #47715.
-
-## 2.7.0
-* Updated `ConstructorElement.displayName` to either `Class` or `Class.constructor`.
-* Deprecated `InterfaceType.getSmartLeastUpperBound`, use `TypeSystem.leastUpperBound` instead.
-* Deprecated `MockSdk`, use `createMockSdk` and `FolderBasedDartSdk` instead.
-
-## 2.6.0
-* Deprecated `AnalysisResult.state`, check for specific valid or invalid subtypes.
-* Deprecated `ResultState`.
-* Deprecated `LibraryElement.hasExtUri`, FFI should be used instead.
-
-## 2.5.0
-* Updated `MockSdk` to include more declarations.
-
-## 2.4.0
-* Deprecated `ResourceProvider.getModificationTimes()`.
-* Deprecated `MemoryResourceProvider.newDummyLink()`.
-* Deprecated `MemoryResourceProvider.updateFile()`.
-* Deprecated `TypeName`, use `NamedType` instead.
-* Override `AstVisitor.visitNamedType()` instead of `visitTypeName()`.
-* Deprecated `ClassTypeAlias.superclass`, use `superclass2` instead.
-* Deprecated `ConstructorName.type`, use `type2` instead.
-* Deprecated `ExtendsClause.superclass`, use `superclass2` instead.
-* Deprecated `ImplementsClause.interfaces`, use `interfaces2` instead.
-* Deprecated `OnClause.superclassConstraints`, use `superclassConstraints2` instead.
-* Deprecated `TypeLiteral.typeName`, use `type` instead.
-* Deprecated `WithClause.mixinTypes`, use `mixinTypes2` instead.
-* Deprecated `AstFactory.typeName()`, use `namedType()` instead.
-
-## 2.3.0
-* Enable `constructor-tearoffs` feature by default in `2.15`.
-* Improvements in constructors tear-off implementation.
-
-## 2.2.0
-* Improvements in constructors tear-off implementation.
-
-## 2.1.0
-* Changed `AnalysisResult.path` to be non-nullable.
-* Changed `ParsedLibraryResult.units` to be non-nullable.
-* Changed `ResolvedLibraryResult.element` to be non-nullable.
-* Changed `ResolvedLibraryResult.units` to be non-nullable.
-* Changed `ResolvedUnitResult.content` to be non-nullable.
-* Changed `ResolvedUnitResult.unit` to be non-nullable.
-* Deprecated and renamed `AnalysisSession.getXyz2()` into `getXyz()`.
-* Changed `AnalysisDriver.results` to `Stream
- ## 1.3.2
-
-* Added package topics to the pubspec file.
-* Require Dart 2.17.
-
-## 1.3.1
-
-* Switch to using `package:lints`.
-* Populate the pubspec `repository` field.
-
-## 1.3.0
-
-* Stable release for null safety.
-* Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release
- guidelines.
-
-## 1.2.0
-
-* Add typed queue classes such as `Uint8Queue`. These classes implement both
- `Queue` and `List` with a highly-efficient typed-data-backed implementation.
- Their `sublist()` methods also return typed data classes.
-* Update min Dart SDK to `2.4.0`.
-
-## 1.1.6
-
-* Set max SDK version to `<3.0.0`, and adjust other dependencies.
-
-## 1.1.5
-
-* Undo unnecessary SDK version constraint tweak.
-
-## 1.1.4
-
-* Expand the SDK version constraint to include `<2.0.0-dev.infinity`.
-
-## 1.1.3
-
-* Fix all strong-mode warnings.
-
-## 1.1.2
-
-* Fix a bug where `TypedDataBuffer.insertAll` could fail to insert some elements
- of an `Iterable`.
-
-## 1.1.1
-
-* Optimize `insertAll` with an `Iterable` argument and no end-point.
-
-## 1.1.0
-
-* Add `start` and `end` parameters to the `addAll()` and `insertAll()` methods
- for the typed data buffer classes. These allow efficient concatenation of
- slices of existing typed data.
-
-* Make `addAll()` for typed data buffer classes more efficient for lists,
- especially typed data lists.
-
-## 1.0.0
-
-* ChangeLog starts here
-
-
- ## 11.6.0
-- Update to version `4.7` of the spec.
-- Add deprecation notice to `Stack.awaiterFrames`.
-- Add deprecation notice to `FrameKind.kAsyncActivation`.
-
-
-
-
-
-
-
-
+ CHANGELOG.md did not contain changes
+
-
- github.com/dart-lang/pubspec_parse
-
- pubspec_parse | ADDED | direct main
-
-
-
-
-
+## Changed Dependencies
+
+No changed dependencies
+
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..b11ae88
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,61 @@
+# Contributing guide
+
+
+
+## Contribution Steps
+1. Make sure you are up to date with `main`
+1. Run all tests: `flutter test`
+1. Set up an alias to run commands locally (see below for instructions)
+1. Hack away! Test your changes locally, and add unit tests to cover everything
+1. Bump the version in the pubspec.yaml
+1. Commit your changes
+1. Make your PR!!! `gh pr create --fill`
+
+## Run commands locally during development
+```
+dart <-path to this repo->/bin/changelog_bubbler.dart --help
+```
+example:
+```
+dart /Users/micaiah.skolnick/Repos/changelog_bubbler/bin/changelog_bubbler.dart --help
+```
+
+Pro-tip:
+
+> You can create an alias to make it easier to develop locally.
+---
+
+### Mac:
+
+1. Add an alias to your bash profile (default is .zshrc)
+
+ ```
+ alias local_bubbler='dart /Users/micaiah.skolnick/Repos/changelog_bubbler/bin/changelog_bubbler.dart'
+ ```
+1. Open a new terminal window
+---
+
+### Windows:
+
+Add a function to your powershell profile.
+1. Create a file named `profile.ps1` at your powershell directory. eg: `C:\Users\micaiah.skolnick\Documents\WindowsPowerShell\profile.ps1`
+1. Add the following function to your profile. **Replace the path with the path to the repository on your machine
+ ```
+ Function local_bubbler {
+ dart run C:\Users\micaiah.skolnick\Repos\changelog_bubbler/bin/changelog_bubbler.dart $args
+ }
+ ```
+1. Open a new Powershell window
+
+---
+
+> Now you can run commands from anywhere like so:
+```
+local_bubbler --help
+```
+
+### To test
+General testing:
+```
+flutter test
+```
diff --git a/README.md b/README.md
index b1b04ab..ac5a457 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,3 @@
-
UNDER DEVELOPMENT - NOT READY FOR USE
Changelog Bubbler
@@ -15,30 +14,26 @@
## Overview
-The goal of this package is to automate the process of creating a changelog diff for flutter and dart applications. This package not only gathers the changelog diff from the current package. It also analyzes every sub-package and bubbles up their changelogs as well.
+The goal of this package is to automate the process of creating a changelog diff for flutter and dart applications. This package not only gathers the changelog diff from the current package. It also analyzes every changed sub-package and bubbles up their changelogs as well.
### How it Works
-This package generates a single CHANGELOG_BUBBLES.md file which contains the changelog diff from this application and every depended on dart application.
+This package generates a single CHANGELOG_BUBBLED.md file which contains the changelog diff from this application and every depended on dart application.
This builder works as follows:
-1. Read passed in args (ie.. ref to compare with current)
+1. Read passed in args (ie.. see args by running `dart pub run changelog_bubbler --help`)
1. Copy source Repo into temp folder and check out at specified ref
1. Gather info of repo in states current and previous
1. Run pub get
1. Read pubspec lock
1. Build dep list based on pubspec lock and pub_cache
1. Store path to pub_cache in dependency class for later reference
-1. Build release notes
- 1. Private Hosted - Direct
- 1. Private Hosted - Transitive
- 1. pub.dev - Direct
- 1. pub.dev - Transitive
-1. Release note section building
- 1. Only changed deps
+1. Build list of changed dependencies
+ 1. Group by Host URL (ie.. pub.dev, git, or hosted refs)
+ 1. Only gather changed deps
1. Print:
1. name 1.0.0 -> 2.0.0
- 1. Changelog new lines
+ 1. Changelog diff from package
1. Create a file with the information gathered above
@@ -59,11 +54,9 @@ This builder works as follows:
1. `CHANGELOG_BUBBLED.g.md` will be generated with content:
```
-# Bubbled Changelog
-
Example app
-## Hosted - Direct
+## pub.dev
my_app_core 1.0.0 - 1.1.0
@@ -102,7 +95,7 @@ If you are using this in Github Actions, you will need to set the fetch-depth of
### Previous Ref
By default the changelog will be generated based on a diff between the current git state and the previous tag.
-To specify your own ref, pass a flag named `previous-ref` with your desired git ref.
+To specify your own ref to compare with the current state, pass a flag named `previous-ref` with your desired git ref.
example:
```
@@ -121,9 +114,21 @@ example:
dart pub run changelog_bubbler --output MY_COOL_CHANGELOG_NAME.md
```
+### Templates
+All output is built based on templates found in the [Template Folder][template_folder].
+
+Any of the templates can be overriden by passing a path option.
+
+example:
+```
+dart pub run changelog_bubbler --changelog-template-path '/Users/micaiah.skolnick/Repos/alkami/changelog_bubbler/asset_test/changelog_template.html'
+```
+
+Run `dart pub run changelog_bubbler --help` to see a list of all possible path overrides.
## Maintainers
- [Micaiah Skolnick](https://github.com/m-skolnick)
-[example_app_output]: https://github.com/m-skolnick/changelog_bubbler/blob/main/example/my_output_file.md
\ No newline at end of file
+[example_app_output]: https://github.com/m-skolnick/changelog_bubbler/blob/main/example/my_output_file.md
+[template_folder]: https://github.com/m-skolnick/changelog_bubbler/blob/main/template/
\ No newline at end of file
diff --git a/bin/changelog_bubbler.dart b/bin/changelog_bubbler.dart
index e558882..6d34530 100644
--- a/bin/changelog_bubbler.dart
+++ b/bin/changelog_bubbler.dart
@@ -13,5 +13,6 @@ Future main(List args) async {
/// exited already. This is useful to prevent Future chains from proceeding
/// after you've decided to exit.
Future _flushThenExit(int status) {
- return Future.wait([stdout.close(), stderr.close()]).then((_) => exit(status));
+ return Future.wait([stdout.close(), stderr.close()])
+ .then((_) => exit(status));
}
diff --git a/lib/src/change_manager.dart b/lib/src/change_manager.dart
new file mode 100644
index 0000000..a1ddcb9
--- /dev/null
+++ b/lib/src/change_manager.dart
@@ -0,0 +1,70 @@
+import 'package:changelog_bubbler/src/dependency_pair.dart';
+import 'package:changelog_bubbler/src/dependency_parser.dart';
+import 'package:changelog_bubbler/src/dependency_type.dart';
+import 'package:collection/collection.dart';
+
+class ChangeManager {
+ /// Holds the parsed dependencies for the repo in the current state
+ final DependencyParser current;
+
+ /// Holds the parsed dependencies for the repo in the previous state
+ final DependencyParser previous;
+
+ /// All of the dependencies that have changed between the previous and current version
+ late final List changedDeps;
+
+ /// Changed deps grouped by hosted url
+ late final Map> groups;
+
+ ChangeManager({
+ required this.current,
+ required this.previous,
+ }) {
+ changedDeps = _getChangedDeps();
+ groups = _buildGroups();
+ }
+
+ List _getChangedDeps() {
+ final allDeps = {...current.dependencies, ...previous.dependencies};
+
+ final changedDeps = allDeps.values.where((e) =>
+ previous.dependencies[e.name]?.sameVersion(e) != true ||
+ current.dependencies[e.name]?.sameVersion(e) != true);
+
+ final changedDepNames = changedDeps.map((e) => e.name).toList();
+ final sortedChangedDeps = changedDepNames..sort((a, b) => a.compareTo(b));
+
+ return sortedChangedDeps
+ .map((e) => DependencyPair(
+ current: current.dependencies[e],
+ previous: previous.dependencies[e],
+ ))
+ .toList();
+ }
+
+ Map> _buildGroups() {
+ final Map> groups = {};
+
+ // Groups are built by section
+ // Each section will be for a separate hosted location
+ // Gather the unique urls for hosted dependencies
+ final urlSet = changedDeps.map((e) => e.trimmedUrl).whereNotNull().toSet();
+
+ // Loop through the groups and locate the pairs of previous and current dep
+ // which belong to that group
+ for (final groupUrl in urlSet) {
+ final depsInGroup = changedDeps.where((e) => e.trimmedUrl == groupUrl);
+
+ // Inside of the group, sort dependencies by dependency type
+ for (final dependencyType in DependencyType.sorted) {
+ final depsOfDepType =
+ depsInGroup.where((e) => e.dependencyType == dependencyType);
+
+ for (final dep in depsOfDepType) {
+ groups[groupUrl] = (groups[groupUrl] ?? [])..add(dep);
+ }
+ }
+ }
+ return groups;
+ }
+}
diff --git a/lib/src/change_type.dart b/lib/src/change_type.dart
new file mode 100644
index 0000000..f583cbf
--- /dev/null
+++ b/lib/src/change_type.dart
@@ -0,0 +1,14 @@
+enum ChangeType {
+ added('ADDED'),
+ removed('REMOVED'),
+ updated('UPDATED');
+
+ const ChangeType(this.name);
+ final String name;
+
+ static const sorted = [
+ ChangeType.added,
+ ChangeType.removed,
+ ChangeType.updated,
+ ];
+}
diff --git a/lib/src/changelog_bubbler.dart b/lib/src/changelog_bubbler.dart
index 43640cf..8eb17b2 100644
--- a/lib/src/changelog_bubbler.dart
+++ b/lib/src/changelog_bubbler.dart
@@ -1,12 +1,16 @@
+import 'dart:async';
import 'dart:io';
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
+import 'package:changelog_bubbler/src/bubbler_shell.dart';
+import 'package:changelog_bubbler/src/change_manager.dart';
+import 'package:changelog_bubbler/src/changelog_builder.dart';
import 'package:changelog_bubbler/src/dependency_parser.dart';
-import 'package:changelog_bubbler/src/diff_builder.dart';
import 'package:changelog_bubbler/src/global_dependencies.dart';
+import 'package:changelog_bubbler/src/logger.dart';
import 'package:changelog_bubbler/src/repository_preparer.dart';
-import 'package:io/ansi.dart';
+import 'package:changelog_bubbler/src/template_manager.dart';
import 'package:io/io.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
@@ -32,6 +36,31 @@ class ChangelogBubbler extends CommandRunner {
help: 'The name of the changelog to search for',
defaultsTo: 'CHANGELOG.md',
);
+ argParser.addOption(
+ 'changelog-template-path',
+ help: 'The path of the root changelog template',
+ defaultsTo: 'changelog_template.html',
+ );
+ argParser.addOption(
+ 'dependency-group-template-path',
+ help: 'The path of the root changelog template',
+ defaultsTo: 'dependency_group_template.html',
+ );
+ argParser.addOption(
+ 'dependency-changed-template-path',
+ help: 'The path of the root changelog template',
+ defaultsTo: 'dependency_changed_template.html',
+ );
+ argParser.addOption(
+ 'dependency-added-or-removed-template-path',
+ help: 'The path of the root changelog template',
+ defaultsTo: 'dependency_added_or_removed_template.html',
+ );
+ argParser.addOption(
+ 'no-changed-dependencies-template-path',
+ help: 'The path of the root changelog template',
+ defaultsTo: 'no_changed_dependencies_template.html',
+ );
argParser.addFlag(
'dev',
help: 'Include dev dependencies in output',
@@ -62,21 +91,41 @@ class ChangelogBubbler extends CommandRunner {
return ExitCode.usage.code;
}
// Define the tempDir where this repo will be copied to and set to the state to compare
- final tempDir = Directory.systemTemp.createTempSync('temp_changelog_bubbler_dir');
+ final tempDir =
+ Directory.systemTemp.createTempSync('temp_changelog_bubbler_dir');
+ final stopwatch = Stopwatch()..start();
try {
final prevousRefArg = argResults['previous-ref'] as String?;
final changelogName = argResults['changelog-name'] as String;
final outputArg = argResults['output'] as String;
final shouldIncludeDevArg = argResults['dev'] as bool;
final shouldIncludeTransitiveArg = argResults['transitive'] as bool;
+ final changelogTemplatePath =
+ argResults['changelog-template-path'] as String;
+ final dependencyGroupTemplatePath =
+ argResults['dependency-group-template-path'] as String;
+ final dependencyChangedTemplatePath =
+ argResults['dependency-changed-template-path'] as String;
+ final dependencyAddedOrRemovedTemplatePath =
+ argResults['dependency-added-or-removed-template-path'] as String;
+ final noChangedDependenciesTemplate =
+ argResults['no-changed-dependencies-template-path'] as String;
- print('Ensuring the working directory is a dart git repo...');
+ var prompt = 'Ensuring the working directory is a git repo';
+ Logger.progressStart(prompt);
await validateWorkingDir();
+ Logger.progressSuccess(prompt);
+
+ prompt = 'Running pub get';
+ Logger.progressStart(prompt);
+ await runPubGet();
+ Logger.progressSuccess(prompt);
- print('Copying the current repo to a tempDir...');
+ prompt = 'Copying the current repo to a tempDir';
+ Logger.progressStart(prompt);
await copyPath(workingDir, tempDir.path);
+ Logger.progressSuccess(prompt);
- print('In temp dir: Cleaning git state, checking out previous ref, running a pub get...');
await RepositoryPreparer(
repoPath: tempDir.path,
passedRef: prevousRefArg,
@@ -84,28 +133,48 @@ class ChangelogBubbler extends CommandRunner {
final parserPrevious = DependencyParser(repoPath: tempDir.path);
final parserCurrent = DependencyParser(repoPath: workingDir);
- print('In temp dir: Parsing dependencies from pubspec.lock');
+
+ prompt = 'Copying the current repo to a tempDir';
+ Logger.progressStart(prompt);
+ prompt = 'In temp dir: Parsing dependencies from pubspec.lock';
parserPrevious.parseDependencies(
includeTransitive: shouldIncludeTransitiveArg,
includeDev: shouldIncludeDevArg,
);
- print('In current: Parsing dependencies from pubspec.lock...');
+ Logger.progressSuccess(prompt);
+
+ prompt = 'In current dir: Parsing dependencies from pubspec.lock';
+ Logger.progressStart(prompt);
parserCurrent.parseDependencies(
includeTransitive: shouldIncludeTransitiveArg,
includeDev: shouldIncludeDevArg,
);
+ Logger.progressSuccess(prompt);
- print('Building diff...');
- final diff = await DiffBuilder(
- previous: parserPrevious,
- current: parserCurrent,
+ prompt = 'Building diff';
+ Logger.progressStart(prompt);
+ final diff = await ChangelogBuilder(
changelogName: changelogName,
- ).buildDiff();
+ changeManager: ChangeManager(
+ previous: parserPrevious,
+ current: parserCurrent,
+ ),
+ changelogTemplate: TemplateManager(changelogTemplatePath),
+ depGroupTemplate: TemplateManager(dependencyGroupTemplatePath),
+ depChangedTemplate: TemplateManager(dependencyChangedTemplatePath),
+ depAddedOrRemovedTemplate:
+ TemplateManager(dependencyAddedOrRemovedTemplatePath),
+ noChangedDependenciesTemplate:
+ TemplateManager(noChangedDependenciesTemplate),
+ ).buildChangelogFromTemplates();
+ Logger.progressSuccess(prompt);
- print('Writing diff to file ...');
+ prompt = 'Writing diff to file';
+ Logger.progressStart(prompt);
final outputFile = File(outputArg);
outputFile.writeAsStringSync(diff);
- print('${lightGreen.wrap('✓')} Diff written to ${outputFile.absolute}');
+ Logger.progressSuccess(prompt);
+ Logger.progressSuccess('Diff written to ${outputFile.absolute}');
} on UsageException catch (e) {
print(e.message);
print('');
@@ -117,27 +186,44 @@ class ChangelogBubbler extends CommandRunner {
return ExitCode.unavailable.code;
} finally {
- print('Deleting temp dir...');
+ final prompt = 'Deleting temp dir';
+ Logger.progressStart(prompt);
tempDir.deleteSync(recursive: true);
+ Logger.progressSuccess(prompt);
+ print('(${stopwatch.elapsed.inSeconds}s)');
}
return ExitCode.success.code;
}
- /// Ensure the working directory is a dart git repo
+ /// Ensure the working directory is a git repo
///
- /// * Check if current dir is a dart project
- /// * Error out of it is not a git dir and does not contain a pubspec.yaml
- /// * We don't want users to accidentally run this in a folder that doesn't contain a flutter project
+ /// * Error out of it is not a git dir
@visibleForTesting
Future validateWorkingDir() async {
- final pubspecYamlExists = File(p.join(workingDir, 'pubspec.yaml')).existsSync();
- if (!pubspecYamlExists) {
- throw (Exception('pubspec.yaml not found. Program must be run from a dart repository'));
- }
final isGitDir = Directory(p.join(workingDir, '.git')).existsSync();
if (!isGitDir) {
- throw (Exception('.git folder found. Program must be run from a git repository'));
+ throw (Exception(
+ '.git folder not found. Program must be run from a git repository'));
+ }
+ }
+
+ /// Run a pub get to make sure pubspec.lock exists
+ /// This also ensures the working directory is a dart repo
+ ///
+ /// * We don't want users to accidentally run this in a folder that doesn't contain a dart project
+ @visibleForTesting
+ Future runPubGet() async {
+ final shell = getDep();
+
+ try {
+ await shell.run(
+ 'dart pub get',
+ workingDir: workingDir,
+ );
+ } catch (e) {
+ throw (Exception(
+ '`dart pub get` errored out. Program must be run from the root of a dart project. Error: $e'));
}
}
}
diff --git a/lib/src/changelog_builder.dart b/lib/src/changelog_builder.dart
new file mode 100644
index 0000000..8aa7c02
--- /dev/null
+++ b/lib/src/changelog_builder.dart
@@ -0,0 +1,122 @@
+import 'dart:io';
+
+import 'package:changelog_bubbler/src/change_manager.dart';
+import 'package:changelog_bubbler/src/dependency_pair.dart';
+import 'package:changelog_bubbler/src/template_manager.dart';
+import 'package:path/path.dart' as p;
+
+class ChangelogBuilder {
+// Manages the differences between the previous dependencies and current
+ final ChangeManager changeManager;
+
+ /// The name of the changelog we should be searching for
+ /// This can be a value passed by the user. Check CLI input for defaults.
+ final String changelogName;
+
+ /// The top level template
+ final TemplateManager changelogTemplate;
+
+ /// Second level template used for dependency groups
+ final TemplateManager depGroupTemplate;
+
+ /// Lowest level template used for templating a changed dependency
+ final TemplateManager depChangedTemplate;
+
+ /// Lowest level template used for templating an added or deleted dependency
+ final TemplateManager depAddedOrRemovedTemplate;
+
+ /// Used when the app update had no dependency changes
+ final TemplateManager noChangedDependenciesTemplate;
+
+ ChangelogBuilder({
+ required this.changeManager,
+ required this.changelogName,
+ required this.changelogTemplate,
+ required this.depGroupTemplate,
+ required this.depChangedTemplate,
+ required this.depAddedOrRemovedTemplate,
+ required this.noChangedDependenciesTemplate,
+ });
+
+ Future buildChangelogFromTemplates() async {
+ return changelogTemplate.replaceAll({
+ '{{root_package_name}}': changeManager.previous.pubspec.name,
+ '{{root_previous_version}}':
+ changeManager.previous.pubspec.version.toString(),
+ '{{root_current_version}}':
+ changeManager.current.pubspec.version.toString(),
+ '{{root_changelog_diff}}': _getChangelogDiff(
+ currentPath: changeManager.current.repoPath,
+ previousPath: changeManager.previous.repoPath,
+ ),
+ '{{dependency_groups}}': _buildGroupsFromTemplate(),
+ });
+ }
+
+ String _buildGroupsFromTemplate() {
+ final stringBuffer = StringBuffer();
+
+ if (changeManager.groups.isEmpty) {
+ return noChangedDependenciesTemplate.unalteredTemplate;
+ }
+
+ for (final group in changeManager.groups.entries) {
+ final dependencyListBuffer = StringBuffer();
+ for (final depPair in group.value) {
+ dependencyListBuffer.write(_buildInvidualDepFromTemplate(depPair));
+ }
+ final substitutedTemplate = depGroupTemplate.replaceAll({
+ '{{group_name}}': group.key,
+ '{{changed_dependencies}}': dependencyListBuffer.toString(),
+ });
+
+ stringBuffer.write(substitutedTemplate);
+ }
+
+ return stringBuffer.toString();
+ }
+
+ String _buildInvidualDepFromTemplate(DependencyPair depPair) {
+ final current = depPair.current;
+ final previous = depPair.previous;
+
+ if (current != null && previous != null) {
+ return depChangedTemplate.replaceAll({
+ '{{package_name}}': depPair.name,
+ '{{previous_version}}': previous.version.toString(),
+ '{{current_version}}': current.version.toString(),
+ '{{dependency_type}}': depPair.dependencyType.name,
+ '{{changelog_diff}}': _getChangelogDiff(
+ previousPath: previous.getPubCachePath(),
+ currentPath: current.getPubCachePath(),
+ ),
+ });
+ }
+
+ return depAddedOrRemovedTemplate.replaceAll({
+ '{{package_name}}': depPair.name,
+ '{{change_type}}': depPair.changeType.name,
+ '{{dependency_type}}': depPair.dependencyType.name,
+ });
+ }
+
+ String _getChangelogDiff({
+ required String previousPath,
+ required String currentPath,
+ }) {
+ final previousChangelog = File(p.join(previousPath, changelogName));
+ final currentChangelog = File(p.join(currentPath, changelogName));
+
+ if (!previousChangelog.existsSync() || !currentChangelog.existsSync()) {
+ return '$changelogName not found';
+ }
+ final previousString = previousChangelog.readAsStringSync();
+ final currentString = currentChangelog.readAsStringSync();
+ final diff = currentString.replaceFirst(previousString, '');
+ if (diff.isEmpty) {
+ return '$changelogName did not contain changes';
+ }
+
+ return diff;
+ }
+}
diff --git a/lib/src/dependency_pair.dart b/lib/src/dependency_pair.dart
new file mode 100644
index 0000000..a4e1f26
--- /dev/null
+++ b/lib/src/dependency_pair.dart
@@ -0,0 +1,29 @@
+import 'package:changelog_bubbler/src/change_type.dart';
+import 'package:changelog_bubbler/src/dependency_type.dart';
+import 'package:changelog_bubbler/src/package_wrapper.dart';
+
+class DependencyPair {
+ final PackageWrapper? previous;
+ final PackageWrapper? current;
+
+ DependencyPair({
+ this.previous,
+ this.current,
+ }) : assert(previous != null || current != null,
+ 'Either previous or current must not be null');
+
+ ChangeType get changeType {
+ if (previous == null) {
+ return ChangeType.added;
+ }
+ if (current == null) {
+ return ChangeType.removed;
+ }
+ return ChangeType.updated;
+ }
+
+ String get name => (previous?.name ?? current?.name)!;
+ String? get trimmedUrl => previous?.trimmedUrl ?? current?.trimmedUrl;
+ DependencyType get dependencyType =>
+ (previous?.dependencyType ?? current?.dependencyType)!;
+}
diff --git a/lib/src/dependency_parser.dart b/lib/src/dependency_parser.dart
index e4cd110..b4c7331 100644
--- a/lib/src/dependency_parser.dart
+++ b/lib/src/dependency_parser.dart
@@ -17,7 +17,8 @@ class DependencyParser {
final _shell = getDep();
DependencyParser({required this.repoPath}) {
- final pubspecString = File(p.join(repoPath, 'pubspec.yaml')).readAsStringSync();
+ final pubspecString =
+ File(p.join(repoPath, 'pubspec.yaml')).readAsStringSync();
pubspec = Pubspec.parse(pubspecString);
}
@@ -26,44 +27,52 @@ class DependencyParser {
required bool includeTransitive,
}) {
// Get all of the dependencies from the pubspec.lock
- final lockString = File(p.join(repoPath, 'pubspec.lock')).readAsStringSync();
+ final lockString =
+ File(p.join(repoPath, 'pubspec.lock')).readAsStringSync();
final lockfile = PubspecLock.parse(lockString);
- final allDeps = lockfile.packages.map((key, value) => MapEntry(key, PackageWrapper(key, value)));
+ final devDeps = _isolateDevDeps(lockfile.packages.keys);
- final devDeps = _isolateDevDeps(allDeps.keys);
- var filteredDeps = allDeps;
+ final wrappedDeps = lockfile.packages.map((key, value) => MapEntry(
+ key,
+ PackageWrapper(
+ key,
+ value,
+ _determineDependencyType(key, value, devDeps),
+ )));
+
+ var filteredDeps = wrappedDeps;
if (!includeDev) {
filteredDeps = _filterDevDeps(filteredDeps, devDeps);
}
if (!includeTransitive) {
filteredDeps = _filterTransitiveDeps(filteredDeps);
}
-
- filteredDeps = _labelDependencyTypes(filteredDeps, devDeps);
dependencies = filteredDeps;
}
- Map _filterDevDeps(Map deps, Set devDeps) {
+ Map _filterDevDeps(
+ Map deps, Set devDeps) {
return {...deps}..removeWhere((key, value) => devDeps.contains(key));
}
- Map _filterTransitiveDeps(Map deps) {
- return {...deps}..removeWhere((key, value) => value.package.dependency == 'transitive');
+ Map _filterTransitiveDeps(
+ Map deps) {
+ return {...deps}
+ ..removeWhere((key, value) => value.package.dependency == 'transitive');
}
- Map _labelDependencyTypes(Map deps, Set devDeps) {
- return deps.map((key, value) {
- if (value.package.dependency == 'transitive') {
- if (devDeps.contains(key)) {
- return MapEntry(key, value..dependencyType = DependencyType.transitiveDev);
- }
- return MapEntry(key, value..dependencyType = DependencyType.transitiveMain);
- }
- if (devDeps.contains(key)) {
- return MapEntry(key, value..dependencyType = DependencyType.directDev);
+ DependencyType _determineDependencyType(
+ String name, Package package, Set devDepNames) {
+ if (package.dependency == 'transitive') {
+ if (devDepNames.contains(name)) {
+ return DependencyType.transitiveDev;
}
- return MapEntry(key, value..dependencyType = DependencyType.directMain);
- });
+ return DependencyType.transitiveMain;
+ }
+ if (devDepNames.contains(name)) {
+ return DependencyType.directDev;
+ }
+ return DependencyType.directMain;
}
/// The pubspec.lock does not distinguish "transitive dev" from "transitive main" they are all labeled "transitive"
diff --git a/lib/src/diff_builder.dart b/lib/src/diff_builder.dart
deleted file mode 100644
index 1929cb5..0000000
--- a/lib/src/diff_builder.dart
+++ /dev/null
@@ -1,227 +0,0 @@
-import 'dart:io';
-
-import 'package:changelog_bubbler/src/dependency_parser.dart';
-import 'package:changelog_bubbler/src/dependency_type.dart';
-import 'package:changelog_bubbler/src/package_wrapper.dart';
-import 'package:collection/collection.dart';
-import 'package:path/path.dart' as p;
-
-class DiffBuilder {
- /// Holds the parsed dependencies for the repo in the current state
- final DependencyParser current;
-
- /// Holds the parsed dependencies for the repo in the previous state
- final DependencyParser previous;
-
- /// The name of the changelog we should be searching for
- /// This can be a value passed by the user. Check CLI input for defaults.
- final String changelogName;
-
- DiffBuilder({
- required this.previous,
- required this.current,
- required this.changelogName,
- });
-
- Future buildDiff() async {
- return _fullOutputStr(
- mainApp: _buildMainAppSection(),
- dependencyGroups: _buildGroups(),
- );
- }
-
- String _buildGroups() {
- // Find the packages that have changed
- final changedDeps = {...current.dependencies, ...previous.dependencies}.entries.where((e) {
- return previous.dependencies[e.key]?.sameVersion(e.value) != true ||
- current.dependencies[e.key]?.sameVersion(e.value) != true;
- });
- final sortedDeps = changedDeps.toList()..sort((a, b) => a.key.compareTo(b.key));
- // We will build the diff by section
- // Each section will be for a separate hosted location
- // Gather the unique urls for hosted dependencies
- final urlSet = sortedDeps.map((e) => e.value.trimmedUrl).whereNotNull().toSet();
-
- final groupsBySection = StringBuffer();
- for (final groupUrl in urlSet) {
- final depsInGroup = sortedDeps.where((e) => e.value.trimmedUrl == groupUrl);
- if (depsInGroup.isEmpty) {
- continue;
- }
- final groupBuffer = StringBuffer();
- for (final dependencyType in DependencyType.sorted) {
- final depsOfDepType = depsInGroup.where((e) => e.value.dependencyType == dependencyType);
- if (depsOfDepType.isEmpty) {
- continue;
- }
- for (final dep in depsOfDepType) {
- final previousDep = previous.dependencies.entries.firstWhereOrNull((e) => e.key == dep.key);
- final currentDep = current.dependencies.entries.firstWhereOrNull((e) => e.key == dep.key);
-
- groupBuffer.write(_buildPackageDiff(
- previous: previousDep,
- current: currentDep,
- ));
- }
- }
- groupsBySection.write(
- _groupStr(
- groupName: groupUrl,
- packagesInGroup: groupBuffer.toString(),
- ),
- );
- }
-
- if (groupsBySection.isEmpty) {
- return _emptyDependencyStr();
- }
-
- return groupsBySection.toString();
- }
-
- String _buildMainAppSection() {
- return _mainPackageDiffStr(
- packageName: previous.pubspec.name,
- previousVersion: previous.pubspec.version.toString(),
- currentVersion: current.pubspec.version.toString(),
- changelogDiff: _getChangelogDiff(
- currentPath: current.repoPath,
- previousPath: previous.repoPath,
- ),
- );
- }
-
- String _buildPackageDiff({
- required MapEntry? previous,
- required MapEntry? current,
- }) {
- assert(previous != null || current != null, 'Either previous or current must not be null');
- if (previous == null) {
- return _depAddedOrRemovedStr(
- packageName: current!.key,
- dependencyType: current.value.dependencyType.name,
- changeType: 'ADDED',
- );
- }
- if (current == null) {
- return _depAddedOrRemovedStr(
- packageName: previous.key,
- dependencyType: previous.value.dependencyType.name,
- changeType: 'REMOVED',
- );
- }
-
- return _depDiffStr(
- packageName: previous.key,
- previousVersion: previous.value.version.toString(),
- currentVersion: current.value.version.toString(),
- dependencyType: current.value.dependencyType.name,
- changelogDiff: _getChangelogDiff(
- previousPath: previous.value.getPubCachePath(),
- currentPath: current.value.getPubCachePath(),
- ),
- );
- }
-
- String _getChangelogDiff({
- required String previousPath,
- required String currentPath,
- }) {
- final previousChangelog = File(p.join(previousPath, changelogName));
- final currentChangelog = File(p.join(currentPath, changelogName));
-
- if (!previousChangelog.existsSync() || !currentChangelog.existsSync()) {
- return '$changelogName not found';
- }
- final previousString = previousChangelog.readAsStringSync();
- final currentString = currentChangelog.readAsStringSync();
- final diff = currentString.replaceFirst(previousString, '');
- if (diff.isEmpty) {
- return '$changelogName did not contain changes';
- }
-
- return diff;
- }
-
- String _fullOutputStr({
- required String mainApp,
- required String dependencyGroups,
- }) {
- return '''
-# Bubbled Changelog
-
-## This app
-$mainApp
-
-## Changed Dependencies
-$dependencyGroups
-''';
- }
-
- String _groupStr({
- required String groupName,
- required String packagesInGroup,
- }) {
- return _collapsibleStr(
- header: groupName,
- body: packagesInGroup,
- );
- }
-
- String _emptyDependencyStr() {
- return _paddedDivStr(body: 'No changed dependencies');
- }
-
- String _mainPackageDiffStr({
- required String packageName,
- required String previousVersion,
- required String currentVersion,
- required String changelogDiff,
- }) {
- return '''
-$packageName | $previousVersion -> $currentVersion
-${_paddedDivStr(body: changelogDiff)}
-''';
- }
-
- String _depDiffStr({
- required String packageName,
- required String previousVersion,
- required String currentVersion,
- required String dependencyType,
- required String changelogDiff,
- }) {
- return _collapsibleStr(
- header: '$packageName | $previousVersion -> $currentVersion | $dependencyType',
- body: changelogDiff,
- );
- }
-
- String _depAddedOrRemovedStr({
- required String packageName,
- required String changeType,
- required String dependencyType,
- }) {
- return '$packageName | $changeType | $dependencyType';
- }
-
- String _collapsibleStr({
- required String header,
- required String body,
- }) {
- return '''
-
- $header
- ${_paddedDivStr(body: body)}
-
-''';
- }
-
- String _paddedDivStr({required String body}) {
- return '''
-
- $body
-
-''';
- }
-}
diff --git a/lib/src/logger.dart b/lib/src/logger.dart
new file mode 100644
index 0000000..69265bd
--- /dev/null
+++ b/lib/src/logger.dart
@@ -0,0 +1,15 @@
+import 'dart:io';
+
+import 'package:io/ansi.dart';
+
+class Logger {
+ static final _greenCheck = '${lightGreen.wrap('✓')}';
+
+ static void progressStart(String prompt) {
+ stdout.write('$prompt...');
+ }
+
+ static void progressSuccess(String prompt) {
+ stdout.write('\r$_greenCheck $prompt \n');
+ }
+}
diff --git a/lib/src/package_wrapper.dart b/lib/src/package_wrapper.dart
index 35c45ff..0709096 100644
--- a/lib/src/package_wrapper.dart
+++ b/lib/src/package_wrapper.dart
@@ -1,19 +1,21 @@
import 'package:changelog_bubbler/src/dependency_type.dart';
import 'package:changelog_bubbler/src/global_dependencies.dart';
import 'package:changelog_bubbler/src/platform_wrapper.dart';
+import 'package:meta/meta.dart';
import 'package:pubspec_lock_parse/pubspec_lock_parse.dart';
import 'package:path/path.dart' as p;
class PackageWrapper {
final Package package;
final String name;
- late final DependencyType dependencyType;
+ final DependencyType dependencyType;
- PackageWrapper(this.name, this.package);
+ PackageWrapper(this.name, this.package, this.dependencyType);
String get version {
if (package.description is GitPackageDescription) {
- final resolvedRef = (package.description as GitPackageDescription).resolvedRef;
+ final resolvedRef =
+ (package.description as GitPackageDescription).resolvedRef;
return resolvedRef.substring(0, 7);
}
@@ -33,7 +35,8 @@ class PackageWrapper {
path = p.join(path, 'hosted', formattedUrl, '$name-${package.version}');
}
if (package.description is GitPackageDescription) {
- final resolvedRef = (package.description as GitPackageDescription).resolvedRef;
+ final resolvedRef =
+ (package.description as GitPackageDescription).resolvedRef;
path = p.join(path, 'git', '$name-$resolvedRef');
}
@@ -42,14 +45,16 @@ class PackageWrapper {
String? get trimmedUrl {
final scheme = 'https://';
- final url = _url;
- if (url?.startsWith(scheme) == true) {
- return url?.replaceFirst(scheme, '');
+ // ignore: no_leading_underscores_for_local_identifiers
+ final _url = url;
+ if (_url?.startsWith(scheme) == true) {
+ return _url?.replaceFirst(scheme, '');
}
- return url;
+ return _url;
}
- String? get _url {
+ @visibleForTesting
+ String? get url {
if (package.description is HostedPackageDescription) {
return (package.description as HostedPackageDescription).url;
}
diff --git a/lib/src/platform_wrapper.dart b/lib/src/platform_wrapper.dart
index 3e62625..381deb1 100644
--- a/lib/src/platform_wrapper.dart
+++ b/lib/src/platform_wrapper.dart
@@ -1,3 +1,5 @@
+// coverage:ignore-file
+
import 'dart:io';
class PlatformWrapper {
diff --git a/lib/src/repository_preparer.dart b/lib/src/repository_preparer.dart
index 7048396..b830e28 100644
--- a/lib/src/repository_preparer.dart
+++ b/lib/src/repository_preparer.dart
@@ -1,3 +1,4 @@
+import 'package:changelog_bubbler/src/logger.dart';
import 'package:process_run/process_run.dart';
import 'package:changelog_bubbler/src/bubbler_shell.dart';
@@ -21,9 +22,20 @@ class RepositoryPreparer {
/// * Check out ref
/// * Get dependencies
Future prepareTempRepo() async {
+ var prompt = 'In temp dir: Cleaning git state';
+ Logger.progressStart(prompt);
await _cleanGitState();
+ Logger.progressSuccess(prompt);
+
+ prompt = 'In temp dir: Checking out previous ref';
+ Logger.progressStart(prompt);
await _checkOutRef();
+ Logger.progressSuccess(prompt);
+
+ prompt = 'In temp dir: Running a pub get';
+ Logger.progressStart(prompt);
await _getDependencies();
+ Logger.progressSuccess(prompt);
}
Future _cleanGitState() async {
@@ -45,7 +57,8 @@ class RepositoryPreparer {
Future _checkOutRef() async {
final shell = getDep();
- final ref = passedRef ?? await _getPreviousTag() ?? await _getPreviousCommit();
+ final ref =
+ passedRef ?? await _getPreviousTag() ?? await _getPreviousCommit();
await shell.run(
'git checkout $ref',
diff --git a/lib/src/template_manager.dart b/lib/src/template_manager.dart
new file mode 100644
index 0000000..b6cb8e4
--- /dev/null
+++ b/lib/src/template_manager.dart
@@ -0,0 +1,37 @@
+import 'dart:io';
+import 'package:path/path.dart' as p;
+
+class TemplateManager {
+ final String filePath;
+ String? _unalteredTemplate;
+ String get unalteredTemplate {
+ if (_unalteredTemplate != null) {
+ return _unalteredTemplate!;
+ }
+ var path = '';
+ // If the file path is absolute, we assume the user passed in a path override
+ if (p.isAbsolute(filePath)) {
+ path = filePath;
+ } else {
+ // Here we assume the path to the template is the default
+ // So we do some manipulation to resolve the uri to the asset folder
+ // inside the changelog_bubbler package
+ final basePackagePath = File(Platform.script.toFilePath()).parent.parent;
+ path = p.join(basePackagePath.path, 'template', filePath);
+ }
+ final templateFile = File(path);
+ return _unalteredTemplate ??= templateFile.readAsStringSync();
+ }
+
+ TemplateManager(this.filePath, {String? templateForTesting})
+ : _unalteredTemplate = templateForTesting;
+
+ String replaceAll(Map replacements) {
+ var substitutedTemplate = unalteredTemplate;
+ for (final replacement in replacements.entries) {
+ substitutedTemplate =
+ substitutedTemplate.replaceFirst(replacement.key, replacement.value);
+ }
+ return substitutedTemplate;
+ }
+}
diff --git a/pubspec.lock b/pubspec.lock
index 40df3f0..d2574b0 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -129,6 +129,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.1"
+ http:
+ dependency: transitive
+ description:
+ name: http
+ sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.13.6"
http_multi_server:
dependency: transitive
description:
@@ -233,6 +241,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.2"
+ oauth2:
+ dependency: transitive
+ description:
+ name: oauth2
+ sha256: "1e8376c222651904caf7785fd2fa01b1e2be608c94bec842a94e116deca88f13"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.1"
package_config:
dependency: transitive
description:
@@ -265,6 +281,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.13.0"
+ pub_api_client:
+ dependency: "direct dev"
+ description:
+ name: pub_api_client
+ sha256: d4bc6c9ec778da1a79675eab41bde456b392973216acd783156afaee69230e22
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.0"
pub_semver:
dependency: "direct main"
description:
@@ -273,6 +297,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
+ pubspec:
+ dependency: transitive
+ description:
+ name: pubspec
+ sha256: f534a50a2b4d48dc3bc0ec147c8bd7c304280fff23b153f3f11803c4d49d927e
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.0"
pubspec_lock_parse:
dependency: "direct main"
description:
@@ -289,6 +321,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.3"
+ quiver:
+ dependency: transitive
+ description:
+ name: quiver
+ sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.1"
shelf:
dependency: transitive
description:
@@ -417,14 +457,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
- test_process:
- dependency: "direct dev"
- description:
- name: test_process
- sha256: b0e6702f58272d459d5b80b88696483f86eac230dab05ecf73d0662e305d005e
- url: "https://pub.dev"
- source: hosted
- version: "2.0.3"
typed_data:
dependency: transitive
description:
@@ -433,6 +465,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.2"
+ uri:
+ dependency: transitive
+ description:
+ name: uri
+ sha256: "889eea21e953187c6099802b7b4cf5219ba8f3518f604a1033064d45b1b8268a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.0"
vm_service:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 487ff0e..bce1d67 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: changelog_bubbler
version: 0.1.0
-description: Compiles changelogs from this package and every sub-package between specified refs
+description: Compiles changelogs from this package and every sub-package (between specified refs)
repository: https://github.com/m-skolnick/changelog_bubbler.dart
environment:
sdk: '>=2.18.0 <3.0.0'
@@ -24,9 +24,9 @@ dependencies:
dev_dependencies:
lints: ^2.0.0
mocktail: ^0.3.0
+ pub_api_client: ^2.4.0
test: ^1.24.2
test_descriptor: ^2.0.0
- test_process: ^2.0.0
executables:
changelog_bubbler: changelog_bubbler
\ No newline at end of file
diff --git a/template/changelog_template.html b/template/changelog_template.html
new file mode 100644
index 0000000..d33ead2
--- /dev/null
+++ b/template/changelog_template.html
@@ -0,0 +1,11 @@
+
+
+ {{root_package_name}} | {{root_previous_version}} -> {{root_current_version}}
+
+
+ {{root_changelog_diff}}
+
+
+
+## Changed Dependencies
+{{dependency_groups}}
\ No newline at end of file
diff --git a/template/dependency_added_or_removed_template.html b/template/dependency_added_or_removed_template.html
new file mode 100644
index 0000000..cd1e262
--- /dev/null
+++ b/template/dependency_added_or_removed_template.html
@@ -0,0 +1 @@
+{{package_name}} | {{change_type}} | {{dependency_type}}
\ No newline at end of file
diff --git a/template/dependency_changed_template.html b/template/dependency_changed_template.html
new file mode 100644
index 0000000..67e0ed4
--- /dev/null
+++ b/template/dependency_changed_template.html
@@ -0,0 +1,6 @@
+
+ {{package_name}} | {{previous_version}} -> {{current_version}} | {{dependency_type}}
+
+ {{changelog_diff}}
+
+
\ No newline at end of file
diff --git a/template/dependency_group_template.html b/template/dependency_group_template.html
new file mode 100644
index 0000000..873f6f9
--- /dev/null
+++ b/template/dependency_group_template.html
@@ -0,0 +1,6 @@
+
+ {{group_name}}
+
+ {{changed_dependencies}}
+
+
\ No newline at end of file
diff --git a/template/no_changed_dependencies_template.html b/template/no_changed_dependencies_template.html
new file mode 100644
index 0000000..f0f67ee
--- /dev/null
+++ b/template/no_changed_dependencies_template.html
@@ -0,0 +1,3 @@
+