@@ -16,9 +16,11 @@ import 'common/output_utils.dart';
1616import 'common/package_command.dart' ;
1717import 'common/repository_package.dart' ;
1818
19- const int _kExitPackageMalformed = 2 ;
20- const int _kGitFailedToPush = 3 ;
19+ const int _kExitPackageMalformed = 3 ;
20+ const int _kGitFailedToPush = 4 ;
2121
22+ // The template file name used to draft a pending changelog file.
23+ // This file will not be picked up by the batch release process.
2224const String _kTemplateFileName = 'template.yaml' ;
2325
2426/// A command to create a remote branch with release changes for a single package.
@@ -46,7 +48,8 @@ class BranchForBatchReleaseCommand extends PackageCommand {
4648
4749 @override
4850 Future <void > run () async {
49- final String branchName = argResults! ['branch' ] as String ;
51+ final String branchName = getStringArg ('branch' );
52+ final String remoteName = getStringArg ('remote' );
5053
5154 final List <RepositoryPackage > packages = await getTargetPackages ()
5255 .map ((PackageEnumerationEntry e) => e.package)
@@ -60,7 +63,7 @@ class BranchForBatchReleaseCommand extends PackageCommand {
6063 final GitDir repository = await gitDir;
6164
6265 print ('Parsing package "${package .displayName }"...' );
63- final PendingChangelogs pendingChangelogs =
66+ final _PendingChangelogs pendingChangelogs =
6467 await _getPendingChangelogs (package);
6568 if (pendingChangelogs.entries.isEmpty) {
6669 print ('No pending changelogs found for ${package .displayName }.' );
@@ -69,7 +72,12 @@ class BranchForBatchReleaseCommand extends PackageCommand {
6972
7073 final Pubspec pubspec =
7174 Pubspec .parse (package.pubspecFile.readAsStringSync ());
72- final ReleaseInfo releaseInfo =
75+ if (pubspec.version == null || pubspec.version! .major < 1 ) {
76+ printError (
77+ 'This script only supports packages with version >= 1.0.0. Current version: ${pubspec .version }. Package: ${package .displayName }.' );
78+ throw ToolExit (_kExitPackageMalformed);
79+ }
80+ final _ReleaseInfo releaseInfo =
7381 _getReleaseInfo (pendingChangelogs.entries, pubspec.version! );
7482
7583 if (releaseInfo.newVersion == null ) {
@@ -78,17 +86,17 @@ class BranchForBatchReleaseCommand extends PackageCommand {
7886 return ;
7987 }
8088
81- print ('Creating and pushing release branch...' );
82- await _pushBranch (
89+ await _createReleaseBranch (
8390 git: repository,
8491 package: package,
8592 branchName: branchName,
8693 pendingChangelogFiles: pendingChangelogs.files,
8794 releaseInfo: releaseInfo,
95+ remoteName: remoteName,
8896 );
8997 }
9098
91- Future <PendingChangelogs > _getPendingChangelogs (
99+ Future <_PendingChangelogs > _getPendingChangelogs (
92100 RepositoryPackage package) async {
93101 final Directory pendingChangelogsDir =
94102 package.directory.childDirectory ('pending_changelogs' );
@@ -104,60 +112,47 @@ class BranchForBatchReleaseCommand extends PackageCommand {
104112 f.basename.endsWith ('.yaml' ) && f.basename != _kTemplateFileName)
105113 .toList ();
106114 try {
107- final List <PendingChangelogEntry > entries = pendingChangelogFiles
108- .map <PendingChangelogEntry >(
109- (File f) => PendingChangelogEntry .parse (f.readAsStringSync ()))
115+ final List <_PendingChangelogEntry > entries = pendingChangelogFiles
116+ .map <_PendingChangelogEntry >(
117+ (File f) => _PendingChangelogEntry .parse (f.readAsStringSync ()))
110118 .toList ();
111- return PendingChangelogs (entries, pendingChangelogFiles);
119+ return _PendingChangelogs (entries, pendingChangelogFiles);
112120 } on FormatException catch (e) {
113121 printError ('Malformed pending changelog file: $e ' );
114122 throw ToolExit (_kExitPackageMalformed);
115123 }
116124 }
117125
118- ReleaseInfo _getReleaseInfo (
119- List <PendingChangelogEntry > pendingChangelogEntries, Version oldVersion) {
126+ _ReleaseInfo _getReleaseInfo (
127+ List <_PendingChangelogEntry > pendingChangelogEntries,
128+ Version oldVersion) {
120129 final List <String > changelogs = < String > [];
121- int versionIndex = VersionChange .skip.index;
122- for (final PendingChangelogEntry entry in pendingChangelogEntries) {
130+ int versionIndex = _VersionChange .skip.index;
131+ for (final _PendingChangelogEntry entry in pendingChangelogEntries) {
123132 changelogs.add (entry.changelog);
124133 versionIndex = math.min (versionIndex, entry.version.index);
125134 }
126- final VersionChange effectiveVersionChange =
127- VersionChange .values[versionIndex];
128-
129- Version ? newVersion;
130- switch (effectiveVersionChange) {
131- case VersionChange .skip:
132- break ;
133- case VersionChange .major:
134- newVersion = Version (
135- oldVersion.major + 1 ,
136- 0 ,
137- 0 ,
138- );
139- case VersionChange .minor:
140- newVersion = Version (
141- oldVersion.major,
142- oldVersion.minor + 1 ,
143- 0 ,
144- );
145- case VersionChange .patch:
146- newVersion = Version (
147- oldVersion.major,
148- oldVersion.minor,
149- oldVersion.patch + 1 ,
150- );
151- }
152- return ReleaseInfo (newVersion, changelogs);
135+ final _VersionChange effectiveVersionChange =
136+ _VersionChange .values[versionIndex];
137+
138+ final Version ? newVersion = switch (effectiveVersionChange) {
139+ _VersionChange .skip => null ,
140+ _VersionChange .major => Version (oldVersion.major + 1 , 0 , 0 ),
141+ _VersionChange .minor =>
142+ Version (oldVersion.major, oldVersion.minor + 1 , 0 ),
143+ _VersionChange .patch =>
144+ Version (oldVersion.major, oldVersion.minor, oldVersion.patch + 1 ),
145+ };
146+ return _ReleaseInfo (newVersion, changelogs);
153147 }
154148
155- Future <void > _pushBranch ({
149+ Future <void > _createReleaseBranch ({
156150 required GitDir git,
157151 required RepositoryPackage package,
158152 required String branchName,
159153 required List <File > pendingChangelogFiles,
160- required ReleaseInfo releaseInfo,
154+ required _ReleaseInfo releaseInfo,
155+ required String remoteName,
161156 }) async {
162157 print (' Creating new branch "$branchName "...' );
163158 final io.ProcessResult checkoutResult =
@@ -168,16 +163,23 @@ class BranchForBatchReleaseCommand extends PackageCommand {
168163 throw ToolExit (_kGitFailedToPush);
169164 }
170165
171- print (' Updating pubspec.yaml to version ${releaseInfo .newVersion }...' );
172- // Update pubspec.yaml.
166+ _updatePubspec (package, releaseInfo.newVersion! );
167+ _updateChangelog (package, releaseInfo);
168+ await _removePendingChangelogs (git, pendingChangelogFiles);
169+ await _stageAndCommitChanges (git, package);
170+ await _pushBranch (git, remoteName, branchName);
171+ }
172+
173+ void _updatePubspec (RepositoryPackage package, Version newVersion) {
174+ print (' Updating pubspec.yaml to version $newVersion ...' );
173175 final YamlEditor editablePubspec =
174176 YamlEditor (package.pubspecFile.readAsStringSync ());
175- editablePubspec
176- .update (< String > ['version' ], releaseInfo.newVersion.toString ());
177+ editablePubspec.update (< String > ['version' ], newVersion.toString ());
177178 package.pubspecFile.writeAsStringSync (editablePubspec.toString ());
179+ }
178180
181+ void _updateChangelog (RepositoryPackage package, _ReleaseInfo releaseInfo) {
179182 print (' Updating CHANGELOG.md...' );
180- // Update CHANGELOG.md.
181183 final String newHeader = '## ${releaseInfo .newVersion }' ;
182184 final List <String > newEntries = releaseInfo.changelogs;
183185
@@ -191,7 +193,10 @@ class BranchForBatchReleaseCommand extends PackageCommand {
191193 newChangelog.write (oldChangelogContent);
192194
193195 package.changelogFile.writeAsStringSync (newChangelog.toString ());
196+ }
194197
198+ Future <void > _removePendingChangelogs (
199+ GitDir git, List <File > pendingChangelogFiles) async {
195200 print (' Removing pending changelog files...' );
196201 for (final File file in pendingChangelogFiles) {
197202 final io.ProcessResult rmResult =
@@ -201,7 +206,10 @@ class BranchForBatchReleaseCommand extends PackageCommand {
201206 throw ToolExit (_kGitFailedToPush);
202207 }
203208 }
209+ }
204210
211+ Future <void > _stageAndCommitChanges (
212+ GitDir git, RepositoryPackage package) async {
205213 print (' Staging changes...' );
206214 final io.ProcessResult addResult = await git.runCommand (
207215 < String > ['add' , package.pubspecFile.path, package.changelogFile.path]);
@@ -220,10 +228,13 @@ class BranchForBatchReleaseCommand extends PackageCommand {
220228 printError ('Failed to commit: ${commitResult .stderr }' );
221229 throw ToolExit (_kGitFailedToPush);
222230 }
231+ }
223232
233+ Future <void > _pushBranch (
234+ GitDir git, String remoteName, String branchName) async {
224235 print (' Pushing to remote...' );
225236 final io.ProcessResult pushResult =
226- await git.runCommand (< String > ['push' , 'origin' , branchName]);
237+ await git.runCommand (< String > ['push' , remoteName , branchName]);
227238 if (pushResult.exitCode != 0 ) {
228239 printError ('Failed to push to $branchName : ${pushResult .stderr }' );
229240 throw ToolExit (_kGitFailedToPush);
@@ -232,21 +243,21 @@ class BranchForBatchReleaseCommand extends PackageCommand {
232243}
233244
234245/// A data class for pending changelogs.
235- class PendingChangelogs {
246+ class _PendingChangelogs {
236247 /// Creates a new instance.
237- PendingChangelogs (this .entries, this .files);
248+ _PendingChangelogs (this .entries, this .files);
238249
239250 /// The parsed pending changelog entries.
240- final List <PendingChangelogEntry > entries;
251+ final List <_PendingChangelogEntry > entries;
241252
242253 /// The files that the pending changelog entries were parsed from.
243254 final List <File > files;
244255}
245256
246257/// A data class for processed release information.
247- class ReleaseInfo {
258+ class _ReleaseInfo {
248259 /// Creates a new instance.
249- ReleaseInfo (this .newVersion, this .changelogs);
260+ _ReleaseInfo (this .newVersion, this .changelogs);
250261
251262 /// The new version for the release, or null if there is no version change.
252263 final Version ? newVersion;
@@ -256,7 +267,7 @@ class ReleaseInfo {
256267}
257268
258269/// The type of version change for a release.
259- enum VersionChange {
270+ enum _VersionChange {
260271 /// A major version change (e.g., 1.2.3 -> 2.0.0).
261272 major,
262273
@@ -271,12 +282,12 @@ enum VersionChange {
271282}
272283
273284/// Represents a single entry in the pending changelog.
274- class PendingChangelogEntry {
285+ class _PendingChangelogEntry {
275286 /// Creates a new pending changelog entry.
276- PendingChangelogEntry ({required this .changelog, required this .version});
287+ _PendingChangelogEntry ({required this .changelog, required this .version});
277288
278289 /// Creates a PendingChangelogEntry from a YAML string.
279- factory PendingChangelogEntry .parse (String yamlContent) {
290+ factory _PendingChangelogEntry .parse (String yamlContent) {
280291 final dynamic yaml = loadYaml (yamlContent);
281292 if (yaml is ! YamlMap ) {
282293 throw FormatException (
@@ -294,18 +305,18 @@ class PendingChangelogEntry {
294305 if (versionString == null ) {
295306 throw const FormatException ('Missing "version" key.' );
296307 }
297- final VersionChange version = VersionChange .values.firstWhere (
298- (VersionChange e) => e.name == versionString,
308+ final _VersionChange version = _VersionChange .values.firstWhere (
309+ (_VersionChange e) => e.name == versionString,
299310 orElse: () =>
300311 throw FormatException ('Invalid version type: $versionString ' ),
301312 );
302313
303- return PendingChangelogEntry (changelog: changelog, version: version);
314+ return _PendingChangelogEntry (changelog: changelog, version: version);
304315 }
305316
306317 /// The changelog messages for this entry.
307318 final String changelog;
308319
309320 /// The type of version change for this entry.
310- final VersionChange version;
321+ final _VersionChange version;
311322}
0 commit comments