1- // Copyright 2025 The Flutter Authors. All rights reserved.
1+ // Copyright 2025 The Flutter Authors.
22// Use of this source code is governed by a BSD-style license that can be
33// found in the LICENSE file.
44
@@ -19,7 +19,6 @@ Future<int> fixCopyrights(
1919 required bool force,
2020 required String year,
2121 required List <String > paths,
22- bool skipSubmodules = true ,
2322 ProcessManager processManager = const LocalProcessManager (),
2423 LogFunction ? log,
2524 LogFunction ? error,
@@ -32,47 +31,43 @@ Future<int> fixCopyrights(
3231 (error ?? stderr.writeln as LogFunction ).call (message);
3332
3433 final Set <String > submodulePaths;
35- if (skipSubmodules) {
36- final gitRootResult = await processManager.run ([
34+ final gitRootResult = await processManager.run ([
35+ 'git' ,
36+ 'rev-parse' ,
37+ '--show-toplevel' ,
38+ ]);
39+ if (gitRootResult.exitCode != 0 ) {
40+ stdErr ('Warning: not a git repository. Cannot check for submodules.' );
41+ submodulePaths = < String > {};
42+ } else {
43+ final repoRoot = gitRootResult.stdout.toString ().trim ();
44+ final result = await processManager.run ([
3745 'git' ,
38- 'rev-parse' ,
39- '--show-toplevel' ,
40- ]);
41- if (gitRootResult.exitCode != 0 ) {
42- stdErr ('Warning: not a git repository. Cannot check for submodules.' );
43- submodulePaths = < String > {};
46+ 'submodule' ,
47+ 'status' ,
48+ '--recursive' ,
49+ ], workingDirectory: repoRoot);
50+ if (result.exitCode == 0 ) {
51+ submodulePaths = result.stdout
52+ .toString ()
53+ .split ('\n ' )
54+ .where ((line) => line.trim ().isNotEmpty)
55+ .map ((line) {
56+ final parts = line.trim ().split (RegExp (r'\s+' ));
57+ if (parts.length > 1 ) {
58+ return path.canonicalize (path.join (repoRoot, parts[1 ]));
59+ }
60+ return null ;
61+ })
62+ .whereType <String >()
63+ .toSet ();
4464 } else {
45- final repoRoot = gitRootResult.stdout.toString ().trim ();
46- final result = await processManager.run ([
47- 'git' ,
48- 'submodule' ,
49- 'status' ,
50- '--recursive' ,
51- ], workingDirectory: repoRoot);
52- if (result.exitCode == 0 ) {
53- submodulePaths = result.stdout
54- .toString ()
55- .split ('\n ' )
56- .where ((line) => line.trim ().isNotEmpty)
57- .map ((line) {
58- final parts = line.trim ().split (RegExp (r'\s+' ));
59- if (parts.length > 1 ) {
60- return path.canonicalize (path.join (repoRoot, parts[1 ]));
61- }
62- return null ;
63- })
64- .whereType <String >()
65- .toSet ();
66- } else {
67- submodulePaths = < String > {};
68- stdErr (
69- 'Warning: could not get submodule status. '
70- 'Not skipping any submodules.' ,
71- );
72- }
65+ submodulePaths = < String > {};
66+ stdErr (
67+ 'Warning: could not get submodule status. '
68+ 'Not skipping any submodules.' ,
69+ );
7370 }
74- } else {
75- submodulePaths = < String > {};
7671 }
7772
7873 String getExtension (File file) {
@@ -85,8 +80,7 @@ Future<int> fixCopyrights(
8580 final directories = < Directory > [dir];
8681 while (directories.isNotEmpty) {
8782 final currentDir = directories.removeAt (0 );
88- if (skipSubmodules &&
89- submodulePaths.contains (path.canonicalize (currentDir.path))) {
83+ if (submodulePaths.contains (path.canonicalize (currentDir.path))) {
9084 stdLog ('Skipping submodule: ${currentDir .path }' );
9185 continue ;
9286 }
@@ -161,6 +155,8 @@ Future<int> fixCopyrights(
161155 }
162156 }
163157
158+ contents = contents.trimLeft ();
159+
164160 // If a sort-of correct copyright is there, but just doesn't have the
165161 // right case, date, spacing, license type or trailing newline, then
166162 // remove it.
@@ -171,7 +167,7 @@ Future<int> fixCopyrights(
171167 contents = contents.trimLeft ();
172168 var newContents = '' ;
173169 if (fileHeader != null ) {
174- final String copyrightBlock =
170+ final copyrightBlock =
175171 '${info .copyright }${info .trailingBlank ? '\n\n ' : '\n ' }' ;
176172 newContents = '$fileHeader $copyrightBlock $contents ' ;
177173 } else {
@@ -226,6 +222,7 @@ class CopyrightInfo {
226222 return RegExp (
227223 '^(?:${headerPattern ?? (header != null ? RegExp .escape (header !) : '' )})?'
228224 '${RegExp .escape (copyright )}\n ${trailingBlank ? r'\n' : '' }' ,
225+ multiLine: true ,
229226 );
230227 }
231228
@@ -254,7 +251,7 @@ Map<String, CopyrightInfo> _generateExtensionMap(String year) {
254251 String suffix = '' ,
255252 required bool isParagraph,
256253 }) {
257- return '''${prefix }Copyright $year The Flutter Authors. All rights reserved. ${isParagraph ? '' : suffix }
254+ return '''${prefix }Copyright $year The Flutter Authors.${isParagraph ? '' : suffix }
258255${isParagraph ? '' : prefix }Use of this source code is governed by a BSD-style license that can be${isParagraph ? '' : suffix }
259256${isParagraph ? '' : prefix }found in the LICENSE file.$suffix ''' ;
260257 }
@@ -267,7 +264,7 @@ ${isParagraph ? '' : prefix}found in the LICENSE file.$suffix''';
267264 final escapedSuffix = RegExp .escape (suffix);
268265
269266 return '($escapedPrefix '
270- r'Copyright (\d+) ([\w ]+)\.?\s+ All rights reserved.'
267+ r'Copyright (\d+) ([\w ]+)\.?(?:\s* All rights reserved.)? '
271268 '(?:$escapedSuffix )?\\ n'
272269 '(?:$escapedPrefix )?'
273270 r'Use of this source code is governed by a [-\w]+ license that can be'
@@ -311,7 +308,7 @@ ${isParagraph ? '' : prefix}found in the LICENSE file.$suffix''';
311308 'cc' : generateInfo (prefix: '// ' ),
312309 'cmake' : generateInfo (prefix: '# ' ),
313310 'cpp' : generateInfo (prefix: '// ' ),
314- 'dart' : generateInfo (prefix: '// ' ),
311+ 'dart' : generateInfo (prefix: '// ' , headerPattern : r'(?<header>#!.*\n?)' ),
315312 'gn' : generateInfo (prefix: '# ' ),
316313 'gradle' : generateInfo (prefix: '// ' ),
317314 'h' : generateInfo (prefix: '// ' ),
@@ -321,7 +318,7 @@ ${isParagraph ? '' : prefix}found in the LICENSE file.$suffix''';
321318 isParagraph: true ,
322319 trailingBlank: false ,
323320 header: '<!DOCTYPE HTML>\n ' ,
324- headerPattern: r'(?<header><!DOCTYPE\s+HTML[^>]*>\n)?' ,
321+ headerPattern: r'(?<header><!DOCTYPE\s+HTML[^>]*>\n? )?' ,
325322 ),
326323 'js' : generateInfo (prefix: '// ' ),
327324 'java' : generateInfo (prefix: '// ' ),
@@ -336,7 +333,7 @@ ${isParagraph ? '' : prefix}found in the LICENSE file.$suffix''';
336333 suffix: ' -->' ,
337334 isParagraph: true ,
338335 headerPattern:
339- r'''(?<header><\?xml\s+(?:version="1.0"\s+encoding="utf-8"|encoding="utf-8"\s+version="1.0")[^>]*\?>\n|)''' ,
336+ r'''(?<header><\?xml\s+(?:version="1.0"\s+encoding="utf-8"|encoding="utf-8"\s+version="1.0")[^>]*\?>\n? |)''' ,
340337 ),
341338 'yaml' : generateInfo (prefix: '# ' ),
342339 };
0 commit comments