| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:meta/meta.dart'; |
| import 'package:path/path.dart' as p; |
| |
| import 'repository_package.dart'; |
| |
| /// The state of a package on disk relative to git state. |
| @immutable |
| class PackageChangeState { |
| /// Creates a new immutable state instance. |
| const PackageChangeState({ |
| required this.hasChanges, |
| required this.hasChangelogChange, |
| required this.needsVersionChange, |
| }); |
| |
| /// True if there are any changes to files in the package. |
| final bool hasChanges; |
| |
| /// True if the package's CHANGELOG.md has been changed. |
| final bool hasChangelogChange; |
| |
| /// True if any changes in the package require a version change according |
| /// to repository policy. |
| final bool needsVersionChange; |
| } |
| |
| /// Checks [package] against [changedPaths] to determine what changes it has |
| /// and how those changes relate to repository policy about CHANGELOG and |
| /// version updates. |
| /// |
| /// [changedPaths] should be a list of POSIX-style paths from a common root, |
| /// and [relativePackagePath] should be the path to [package] from that same |
| /// root. Commonly these will come from `gitVersionFinder.getChangedFiles()` |
| /// and `getRelativePoixPath(package.directory, gitDir.path)` respectively; |
| /// they are arguments mainly to allow for caching the changed paths for an |
| /// entire command run. |
| PackageChangeState checkPackageChangeState( |
| RepositoryPackage package, { |
| required List<String> changedPaths, |
| required String relativePackagePath, |
| }) { |
| final String packagePrefix = relativePackagePath.endsWith('/') |
| ? relativePackagePath |
| : '$relativePackagePath/'; |
| |
| bool hasChanges = false; |
| bool hasChangelogChange = false; |
| bool needsVersionChange = false; |
| for (final String path in changedPaths) { |
| // Only consider files within the package. |
| if (!path.startsWith(packagePrefix)) { |
| continue; |
| } |
| final String packageRelativePath = path.substring(packagePrefix.length); |
| hasChanges = true; |
| |
| final List<String> components = p.posix.split(packageRelativePath); |
| if (components.isEmpty) { |
| continue; |
| } |
| final bool isChangelog = components.first == 'CHANGELOG.md'; |
| if (isChangelog) { |
| hasChangelogChange = true; |
| } |
| |
| if (!needsVersionChange && |
| !isChangelog && |
| // One of a few special files example will be shown on pub.dev, but for |
| // anything else in the example publishing has no purpose. |
| !(components.first == 'example' && |
| !<String>{'main.dart', 'readme.md', 'example.md'} |
| .contains(components.last.toLowerCase())) && |
| // Changes to tests don't need to be published. |
| !components.contains('test') && |
| !components.contains('androidTest') && |
| !components.contains('RunnerTests') && |
| !components.contains('RunnerUITests') && |
| // The top-level "tool" directory is for non-client-facing utility code, |
| // so doesn't need to be published. |
| components.first != 'tool' && |
| // Ignoring lints doesn't affect clients. |
| !components.contains('lint-baseline.xml')) { |
| needsVersionChange = true; |
| } |
| } |
| |
| return PackageChangeState( |
| hasChanges: hasChanges, |
| hasChangelogChange: hasChangelogChange, |
| needsVersionChange: needsVersionChange); |
| } |