blob: 1a544a787a209f25c27dcdef067d68208f926409 [file] [log] [blame]
// 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:args/command_runner.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/ide_config.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/template.dart';
import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/test_flutter_command_runner.dart';
void main() {
group('ide_config', () {
late Directory tempDir;
late Directory templateDir;
late Directory intellijDir;
late Directory toolsDir;
Map<String, String> getFilesystemContents([ Directory? root ]) {
final String tempPath = tempDir.absolute.path;
final List<String> paths =
(root ?? tempDir).listSync(recursive: true).map((FileSystemEntity entity) {
final String relativePath = globals.fs.path.relative(entity.path, from: tempPath);
return relativePath;
}).toList();
final Map<String, String> contents = <String, String>{};
for (final String path in paths) {
final String absPath = globals.fs.path.join(tempPath, path);
if (globals.fs.isDirectorySync(absPath)) {
contents[path] = 'dir';
} else if (globals.fs.isFileSync(absPath)) {
contents[path] = globals.fs.file(absPath).readAsStringSync();
}
}
return contents;
}
Map<String, String> getManifest(Directory base, String marker, { bool isTemplate = false }) {
final String basePath = globals.fs.path.relative(base.path, from: tempDir.absolute.path);
final String suffix = isTemplate ? Template.copyTemplateExtension : '';
return <String, String>{
globals.fs.path.join(basePath, '.idea'): 'dir',
globals.fs.path.join(basePath, '.idea', 'modules.xml$suffix'): 'modules $marker',
globals.fs.path.join(basePath, '.idea', 'vcs.xml$suffix'): 'vcs $marker',
globals.fs.path.join(basePath, '.idea', '.name$suffix'): 'codeStyleSettings $marker',
globals.fs.path.join(basePath, '.idea', 'runConfigurations'): 'dir',
globals.fs.path.join(basePath, '.idea', 'runConfigurations', 'hello_world.xml$suffix'): 'hello_world $marker',
globals.fs.path.join(basePath, 'flutter.iml$suffix'): 'flutter $marker',
globals.fs.path.join(basePath, 'packages', 'new', 'deep.iml$suffix'): 'deep $marker',
globals.fs.path.join(basePath, 'example', 'gallery', 'android.iml$suffix'): 'android $marker',
};
}
void populateDir(Map<String, String> manifest) {
for (final String key in manifest.keys) {
if (manifest[key] == 'dir') {
tempDir.childDirectory(key).createSync(recursive: true);
}
}
for (final String key in manifest.keys) {
if (manifest[key] != 'dir') {
tempDir.childFile(key)
..createSync(recursive: true)
..writeAsStringSync(manifest[key]!);
}
}
}
bool fileOrDirectoryExists(String path) {
final String absPath = globals.fs.path.join(tempDir.absolute.path, path);
return globals.fs.file(absPath).existsSync() || globals.fs.directory(absPath).existsSync();
}
Future<void> updateIdeConfig({
Directory? dir,
List<String> args = const <String>[],
Map<String, String> expectedContents = const <String, String>{},
List<String> unexpectedPaths = const <String>[],
}) async {
dir ??= tempDir;
Cache.flutterRoot = tempDir.absolute.path;
final IdeConfigCommand command = IdeConfigCommand();
final CommandRunner<void> runner = createTestCommandRunner(command);
await runner.run(<String>[
'ide-config',
...args,
]);
for (final String path in expectedContents.keys) {
final String absPath = globals.fs.path.join(tempDir.absolute.path, path);
expect(fileOrDirectoryExists(globals.fs.path.join(dir.path, path)), true,
reason: "$path doesn't exist");
if (globals.fs.file(absPath).existsSync()) {
expect(globals.fs.file(absPath).readAsStringSync(), equals(expectedContents[path]),
reason: "$path contents don't match");
}
}
for (final String path in unexpectedPaths) {
expect(fileOrDirectoryExists(globals.fs.path.join(dir.path, path)), false, reason: '$path exists');
}
}
setUpAll(() {
Cache.disableLocking();
});
setUp(() {
tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_tools_ide_config_test.');
final Directory packagesDir = tempDir.childDirectory('packages')..createSync(recursive: true);
toolsDir = packagesDir.childDirectory('flutter_tools')..createSync();
templateDir = toolsDir.childDirectory('ide_templates')..createSync();
intellijDir = templateDir.childDirectory('intellij')..createSync();
});
tearDown(() {
tryToDelete(tempDir);
});
testUsingContext("doesn't touch existing files without --overwrite", () async {
final Map<String, String> templateManifest = getManifest(
intellijDir,
'template',
isTemplate: true,
);
final Map<String, String> flutterManifest = getManifest(
tempDir,
'existing',
);
populateDir(templateManifest);
populateDir(flutterManifest);
final Map<String, String> expectedContents = getFilesystemContents();
return updateIdeConfig(
expectedContents: expectedContents,
);
});
testUsingContext('creates non-existent files', () async {
final Map<String, String> templateManifest = getManifest(
intellijDir,
'template',
isTemplate: true,
);
final Map<String, String> flutterManifest = getManifest(
tempDir,
'template',
);
populateDir(templateManifest);
final Map<String, String> expectedContents = <String, String>{
...templateManifest,
...flutterManifest,
};
return updateIdeConfig(
expectedContents: expectedContents,
);
});
testUsingContext('overwrites existing files with --overwrite', () async {
final Map<String, String> templateManifest = getManifest(
intellijDir,
'template',
isTemplate: true,
);
final Map<String, String> flutterManifest = getManifest(
tempDir,
'existing',
);
populateDir(templateManifest);
populateDir(flutterManifest);
final Map<String, String> overwrittenManifest = getManifest(
tempDir,
'template',
);
final Map<String, String> expectedContents = <String, String>{
...templateManifest,
...overwrittenManifest,
};
return updateIdeConfig(
args: <String>['--overwrite'],
expectedContents: expectedContents,
);
});
testUsingContext('only adds new templates without --overwrite', () async {
final Map<String, String> templateManifest = getManifest(
intellijDir,
'template',
isTemplate: true,
);
final String flutterIml = globals.fs.path.join(
'packages',
'flutter_tools',
'ide_templates',
'intellij',
'flutter.iml${Template.copyTemplateExtension}',
);
templateManifest.remove(flutterIml);
populateDir(templateManifest);
templateManifest[flutterIml] = 'flutter existing';
final Map<String, String> flutterManifest = getManifest(
tempDir,
'existing',
);
populateDir(flutterManifest);
final Map<String, String> expectedContents = <String, String>{
...flutterManifest,
...templateManifest,
};
return updateIdeConfig(
args: <String>['--update-templates'],
expectedContents: expectedContents,
);
});
testUsingContext('update all templates with --overwrite', () async {
final Map<String, String> templateManifest = getManifest(
intellijDir,
'template',
isTemplate: true,
);
populateDir(templateManifest);
final Map<String, String> flutterManifest = getManifest(
tempDir,
'existing',
);
populateDir(flutterManifest);
final Map<String, String> updatedTemplates = getManifest(
intellijDir,
'existing',
isTemplate: true,
);
final Map<String, String> expectedContents = <String, String>{
...flutterManifest,
...updatedTemplates,
};
return updateIdeConfig(
args: <String>['--update-templates', '--overwrite'],
expectedContents: expectedContents,
);
});
testUsingContext('removes deleted imls with --overwrite', () async {
final Map<String, String> templateManifest = getManifest(
intellijDir,
'template',
isTemplate: true,
);
populateDir(templateManifest);
final Map<String, String> flutterManifest = getManifest(
tempDir,
'existing',
);
flutterManifest.remove('flutter.iml');
populateDir(flutterManifest);
final Map<String, String> updatedTemplates = getManifest(
intellijDir,
'existing',
isTemplate: true,
);
final String flutterIml = globals.fs.path.join(
'packages',
'flutter_tools',
'ide_templates',
'intellij',
'flutter.iml${Template.copyTemplateExtension}',
);
updatedTemplates.remove(flutterIml);
final Map<String, String> expectedContents = <String, String>{
...flutterManifest,
...updatedTemplates,
};
return updateIdeConfig(
args: <String>['--update-templates', '--overwrite'],
expectedContents: expectedContents,
);
});
testUsingContext('removes deleted imls with --overwrite, including empty parent dirs', () async {
final Map<String, String> templateManifest = getManifest(
intellijDir,
'template',
isTemplate: true,
);
populateDir(templateManifest);
final Map<String, String> flutterManifest = getManifest(
tempDir,
'existing',
);
flutterManifest.remove(globals.fs.path.join('packages', 'new', 'deep.iml'));
populateDir(flutterManifest);
final Map<String, String> updatedTemplates = getManifest(
intellijDir,
'existing',
isTemplate: true,
);
String deepIml = globals.fs.path.join(
'packages',
'flutter_tools',
'ide_templates',
'intellij');
// Remove the all the dir entries too.
updatedTemplates.remove(deepIml);
deepIml = globals.fs.path.join(deepIml, 'packages');
updatedTemplates.remove(deepIml);
deepIml = globals.fs.path.join(deepIml, 'new');
updatedTemplates.remove(deepIml);
deepIml = globals.fs.path.join(deepIml, 'deep.iml');
updatedTemplates.remove(deepIml);
final Map<String, String> expectedContents = <String, String>{
...flutterManifest,
...updatedTemplates,
};
return updateIdeConfig(
args: <String>['--update-templates', '--overwrite'],
expectedContents: expectedContents,
);
});
});
}