Add migration to git ignore SwiftPM build directories (#152766)

Opening a Swift package in Xcode generates `.build` and `.swiftpm` directories. These should be ignored as they contain intermediary build artifacts that aren't meant to be checked-in.

Part of https://github.com/flutter/flutter/issues/148018
This commit is contained in:
Loïc Sharma 2024-08-05 13:26:16 -07:00 committed by GitHub
parent 51646d091b
commit 29f332c822
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 206 additions and 0 deletions

View File

@ -24,6 +24,7 @@ import '../globals.dart' as globals;
import '../macos/cocoapod_utils.dart';
import '../macos/swift_package_manager.dart';
import '../macos/xcode.dart';
import '../migrations/swift_package_manager_gitignore_migration.dart';
import '../migrations/swift_package_manager_integration_migration.dart';
import '../migrations/xcode_project_object_version_migration.dart';
import '../migrations/xcode_script_build_phase_migration.dart';
@ -175,6 +176,7 @@ Future<XcodeBuildResult> buildXcodeProject({
fileSystem: globals.fs,
plistParser: globals.plistParser,
),
SwiftPackageManagerGitignoreMigration(project, globals.logger),
];
final ProjectMigration migration = ProjectMigration(migrators);

View File

@ -16,6 +16,7 @@ import '../convert.dart';
import '../globals.dart' as globals;
import '../ios/xcode_build_settings.dart';
import '../ios/xcodeproj.dart';
import '../migrations/swift_package_manager_gitignore_migration.dart';
import '../migrations/swift_package_manager_integration_migration.dart';
import '../migrations/xcode_project_object_version_migration.dart';
import '../migrations/xcode_script_build_phase_migration.dart';
@ -100,6 +101,7 @@ Future<void> buildMacOS({
fileSystem: globals.fs,
plistParser: globals.plistParser,
),
SwiftPackageManagerGitignoreMigration(flutterProject, globals.logger),
];
final ProjectMigration migration = ProjectMigration(migrators);

View File

@ -0,0 +1,63 @@
// Copyright 2014 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 '../base/file_system.dart';
import '../base/project_migrator.dart';
import '../project.dart';
const String _gitignoreBefore = '''
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
''';
const String _gitignoreAfter = '''
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/
''';
/// Adds `.build/` and `.swiftpm/` to the .gitignore file.
class SwiftPackageManagerGitignoreMigration extends ProjectMigrator {
SwiftPackageManagerGitignoreMigration(FlutterProject project, super.logger)
: _gitignoreFile = project.gitignoreFile;
final File _gitignoreFile;
@override
Future<void> migrate() async {
if (!_gitignoreFile.existsSync()) {
logger.printTrace(
'.gitignore file not found, skipping Swift Package Manager .gitignore migration.',
);
return;
}
final String originalContent = _gitignoreFile.readAsStringSync();
// Skip if .gitignore is already migrated.
if (originalContent.contains('.build/') && originalContent.contains('.swiftpm/')) {
return;
}
final String newContent = originalContent.replaceFirst(
_gitignoreBefore,
_gitignoreAfter,
);
if (newContent != originalContent) {
logger.printWarning(
'.gitignore does not ignore Swift Package Manager build directories, updating.',
);
_gitignoreFile.writeAsStringSync(newContent);
}
}
}

View File

@ -233,6 +233,9 @@ class FlutterProject {
/// which contains the dependencies each plugin depends on.
File get flutterPluginsDependenciesFile => directory.childFile('.flutter-plugins-dependencies');
/// The `.gitignore` file of this project.
File get gitignoreFile => directory.childFile('.gitignore');
/// The `.dart-tool` directory of this project.
Directory get dartTool => directory.childDirectory('.dart_tool');

View File

@ -5,9 +5,11 @@
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/
# IntelliJ related

View File

@ -5,9 +5,11 @@
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/
# IntelliJ related

View File

@ -0,0 +1,132 @@
// Copyright 2014 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:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/migrations/swift_package_manager_gitignore_migration.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:test/fake.dart';
import '../../src/common.dart';
void main() {
group('Swift Package Manager .gitignore migration', () {
late MemoryFileSystem memoryFileSystem;
late BufferLogger testLogger;
late FakeFlutterProject mockProject;
late File gitignoreFile;
setUp(() {
memoryFileSystem = MemoryFileSystem.test();
gitignoreFile = memoryFileSystem.file('.gitignore');
testLogger = BufferLogger(
terminal: Terminal.test(),
outputPreferences: OutputPreferences.test(),
);
mockProject = FakeFlutterProject(fileSystem: memoryFileSystem);
});
testWithoutContext('skipped if .gitignore file is missing', () {
final SwiftPackageManagerGitignoreMigration migration = SwiftPackageManagerGitignoreMigration(
mockProject,
testLogger,
);
migration.migrate();
expect(gitignoreFile.existsSync(), isFalse);
expect(
testLogger.traceText,
contains('.gitignore file not found, skipping Swift Package Manager .gitignore migration.'),
);
expect(testLogger.warningText, isEmpty);
});
testWithoutContext('skipped if nothing to migrate', () {
const String gitignoreFileContents = 'Nothing to migrate';
gitignoreFile.writeAsStringSync(gitignoreFileContents);
final DateTime updatedAt = gitignoreFile.lastModifiedSync();
final SwiftPackageManagerGitignoreMigration migration = SwiftPackageManagerGitignoreMigration(
mockProject,
testLogger,
);
migration.migrate();
expect(gitignoreFile.lastModifiedSync(), updatedAt);
expect(gitignoreFile.readAsStringSync(), gitignoreFileContents);
expect(testLogger.warningText, isEmpty);
});
testWithoutContext('skipped if already migrated', () {
const String gitignoreFileContents = '''
.build/
.swiftpm/
''';
gitignoreFile.writeAsStringSync(gitignoreFileContents);
final DateTime updatedAt = gitignoreFile.lastModifiedSync();
final SwiftPackageManagerGitignoreMigration migration = SwiftPackageManagerGitignoreMigration(
mockProject,
testLogger,
);
migration.migrate();
expect(gitignoreFile.lastModifiedSync(), updatedAt);
expect(gitignoreFile.readAsStringSync(), gitignoreFileContents);
expect(testLogger.warningText, isEmpty);
});
testWithoutContext('migrates project to ignore Swift Package Manager build directories', () {
gitignoreFile.writeAsStringSync(
'.DS_Store\n'
'.atom/\n'
'.buildlog/\n'
'.history\n'
'.svn/\n'
'migrate_working_dir/\n'
);
final SwiftPackageManagerGitignoreMigration migration = SwiftPackageManagerGitignoreMigration(
mockProject,
testLogger,
);
migration.migrate();
expect(
gitignoreFile.readAsStringSync(),
'.DS_Store\n'
'.atom/\n'
'.build/\n'
'.buildlog/\n'
'.history\n'
'.svn/\n'
'.swiftpm/\n'
'migrate_working_dir/\n'
);
expect(
testLogger.warningText,
contains('.gitignore does not ignore Swift Package Manager build directories, updating.'),
);
});
});
}
class FakeFlutterProject extends Fake implements FlutterProject {
FakeFlutterProject({
required MemoryFileSystem fileSystem,
}) : gitignoreFile = fileSystem.file('.gitignore');
@override
File gitignoreFile;
}