// 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:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/globals.dart' as globals; import 'package:flutter_tools/src/migrate/migrate_utils.dart'; import '../src/common.dart'; void main() { late BufferLogger logger; late FileSystem fileSystem; late Directory projectRoot; late String projectRootPath; late MigrateUtils utils; late ProcessUtils processUtils; setUpAll(() async { fileSystem = globals.localFileSystem; logger = BufferLogger.test(); utils = MigrateUtils( logger: logger, fileSystem: fileSystem, platform: globals.platform, processManager: globals.processManager, ); processUtils = ProcessUtils(processManager: globals.processManager, logger: logger); }); group('git', () { setUp(() async { projectRoot = fileSystem.systemTempDirectory.createTempSync('flutter_migrate_utils_test'); projectRoot.createSync(recursive: true); projectRootPath = projectRoot.path; }); tearDown(() async { tryToDelete(projectRoot); }); testWithoutContext('init', () async { expect(projectRoot.existsSync(), true); expect(projectRoot.childDirectory('.git').existsSync(), false); await utils.gitInit(projectRootPath); expect(projectRoot.childDirectory('.git').existsSync(), true); }); testWithoutContext('isGitIgnored', () async { expect(projectRoot.existsSync(), true); expect(projectRoot.childDirectory('.git').existsSync(), false); await utils.gitInit(projectRootPath); expect(projectRoot.childDirectory('.git').existsSync(), true); projectRoot.childFile('.gitignore') ..createSync() ..writeAsStringSync('ignored_file.dart', flush: true); expect(await utils.isGitIgnored('ignored_file.dart', projectRootPath), true); expect(await utils.isGitIgnored('other_file.dart', projectRootPath), false); }); testWithoutContext('isGitRepo', () async { expect(projectRoot.existsSync(), true); expect(projectRoot.childDirectory('.git').existsSync(), false); expect(await utils.isGitRepo(projectRootPath), false); await utils.gitInit(projectRootPath); expect(projectRoot.childDirectory('.git').existsSync(), true); expect(await utils.isGitRepo(projectRootPath), true); expect(await utils.isGitRepo(projectRoot.parent.path), false); }); testWithoutContext('hasUncommittedChanges false on clean repo', () async { expect(projectRoot.existsSync(), true); expect(projectRoot.childDirectory('.git').existsSync(), false); await utils.gitInit(projectRootPath); expect(projectRoot.childDirectory('.git').existsSync(), true); projectRoot.childFile('.gitignore') ..createSync() ..writeAsStringSync('ignored_file.dart', flush: true); await processUtils.run(<String>['git', 'add', '.'], workingDirectory: projectRootPath); await processUtils.run(<String>['git', 'commit', '-m', 'Initial commit'], workingDirectory: projectRootPath); expect(await utils.hasUncommittedChanges(projectRootPath), false); }); testWithoutContext('hasUncommittedChanges true on dirty repo', () async { expect(projectRoot.existsSync(), true); expect(projectRoot.childDirectory('.git').existsSync(), false); await utils.gitInit(projectRootPath); expect(projectRoot.childDirectory('.git').existsSync(), true); projectRoot.childFile('some_file.dart') ..createSync() ..writeAsStringSync('void main() {}', flush: true); expect(await utils.hasUncommittedChanges(projectRootPath), true); }); testWithoutContext('diffFiles', () async { expect(projectRoot.existsSync(), true); expect(projectRoot.childDirectory('.git').existsSync(), false); await utils.gitInit(projectRootPath); expect(projectRoot.childDirectory('.git').existsSync(), true); final File file1 = projectRoot.childFile('some_file.dart') ..createSync() ..writeAsStringSync('void main() {}\n', flush: true); final File file2 = projectRoot.childFile('some_other_file.dart'); DiffResult result = await utils.diffFiles(file1, file2); expect(result.diff, null); expect(result.diffType, DiffType.deletion); expect(result.exitCode, null); result = await utils.diffFiles(file2, file1); expect(result.diff, null); expect(result.diffType, DiffType.addition); expect(result.exitCode, null); file2.createSync(); file2.writeAsStringSync('void main() {}\n', flush: true); result = await utils.diffFiles(file1, file2); expect(result.diff, ''); expect(result.diffType, DiffType.command); expect(result.exitCode, 0); file2.writeAsStringSync('void main() {}\na second line\na third line\n', flush: true); result = await utils.diffFiles(file1, file2); expect(result.diff, contains('@@ -1 +1,3 @@\n void main() {}\n+a second line\n+a third line')); expect(result.diffType, DiffType.command); expect(result.exitCode, 1); }); testWithoutContext('merge', () async { expect(projectRoot.existsSync(), true); expect(projectRoot.childDirectory('.git').existsSync(), false); await utils.gitInit(projectRootPath); expect(projectRoot.childDirectory('.git').existsSync(), true); final File file1 = projectRoot.childFile('some_file.dart'); file1.createSync(); file1.writeAsStringSync('void main() {}\n\nline1\nline2\nline3\nline4\nline5\n', flush: true); final File file2 = projectRoot.childFile('some_other_file.dart'); file2.createSync(); file2.writeAsStringSync('void main() {}\n\nline1\nline2\nline3.0\nline3.5\nline4\nline5\n', flush: true); final File file3 = projectRoot.childFile('some_other_third_file.dart'); file3.createSync(); file3.writeAsStringSync('void main() {}\n\nline2\nline3\nline4\nline5\n', flush: true); StringMergeResult result = await utils.gitMergeFile( base: file1.path, current: file2.path, target: file3.path, localPath: 'some_file.dart', ) as StringMergeResult; expect(result.mergedString, 'void main() {}\n\nline2\nline3.0\nline3.5\nline4\nline5\n'); expect(result.hasConflict, false); expect(result.exitCode, 0); file3.writeAsStringSync('void main() {}\n\nline1\nline2\nline3.1\nline3.5\nline4\nline5\n', flush: true); result = await utils.gitMergeFile( base: file1.path, current: file2.path, target: file3.path, localPath: 'some_file.dart', ) as StringMergeResult; expect(result.mergedString, contains('line3.0\n=======\nline3.1\n>>>>>>>')); expect(result.hasConflict, true); expect(result.exitCode, 1); // Two way merge result = await utils.gitMergeFile( base: file1.path, current: file1.path, target: file3.path, localPath: 'some_file.dart', ) as StringMergeResult; expect(result.mergedString, 'void main() {}\n\nline1\nline2\nline3.1\nline3.5\nline4\nline5\n'); expect(result.hasConflict, false); expect(result.exitCode, 0); }); }); group('legacy app creation', () { testWithoutContext('clone and create', () async { projectRoot = fileSystem.systemTempDirectory.createTempSync('flutter_sdk_test'); const String revision = '5391447fae6209bb21a89e6a5a6583cac1af9b4b'; expect(await utils.cloneFlutter(revision, projectRoot.path), true); expect(projectRoot.childFile('README.md').existsSync(), true); final Directory appDir = fileSystem.systemTempDirectory.createTempSync('flutter_app'); await utils.createFromTemplates( projectRoot.childDirectory('bin').path, name: 'testapp', androidLanguage: 'java', iosLanguage: 'objc', outputDirectory: appDir.path, ); expect(appDir.childFile('pubspec.yaml').existsSync(), true); expect(appDir.childFile('.metadata').existsSync(), true); expect(appDir.childFile('.metadata').readAsStringSync(), contains(revision)); expect(appDir.childDirectory('android').existsSync(), true); expect(appDir.childDirectory('ios').existsSync(), true); expect(appDir.childDirectory('web').existsSync(), false); projectRoot.deleteSync(recursive: true); }); }); testWithoutContext('conflictsResolved', () async { expect(utils.conflictsResolved(''), true); expect(utils.conflictsResolved('hello'), true); expect(utils.conflictsResolved('hello\n'), true); expect(utils.conflictsResolved('hello\nwow a bunch of lines\n\nhi\n'), true); expect(utils.conflictsResolved('hello\nwow a bunch of lines\n>>>>>>>\nhi\n'), false); expect(utils.conflictsResolved('hello\nwow a bunch of lines\n=======\nhi\n'), false); expect(utils.conflictsResolved('hello\nwow a bunch of lines\n<<<<<<<\nhi\n'), false); expect(utils.conflictsResolved('hello\nwow a bunch of lines\n<<<<<<<\n=======\n<<<<<<<\nhi\n'), false); }); }