Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make file IO more robust #329

Merged
merged 3 commits into from
Jun 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/melos/lib/melos.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export 'src/commands/runner.dart'
ScriptNotFoundException,
ListOutputKind;
export 'src/common/exception.dart' show CancelledException, MelosException;
export 'src/common/io.dart' show IOException;
export 'src/common/validation.dart' show MelosConfigException;
export 'src/global_options.dart' show GlobalOptions;
export 'src/logging.dart' show MelosLogger, ToMelosLoggerExtension;
Expand Down
32 changes: 16 additions & 16 deletions packages/melos/lib/src/commands/bootstrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ mixin _BootstrapMixin on _CleanMixin {

// Load current pubspec_overrides.yaml.
final pubspecOverridesFile =
File(utils.pubspecOverridesPathForDirectory(Directory(package.path)));
final pubspecOverridesContents = pubspecOverridesFile.existsSync()
? await pubspecOverridesFile.readAsString()
utils.pubspecOverridesPathForDirectory(package.path);
final pubspecOverridesContents = fileExists(pubspecOverridesFile)
? await readTextFileAsync(pubspecOverridesFile)
: null;

// Write new version of pubspec_overrides.yaml if it has changed.
Expand All @@ -116,11 +116,12 @@ mixin _BootstrapMixin on _CleanMixin {
);
if (updatedPubspecOverridesContents != null) {
if (updatedPubspecOverridesContents.isEmpty) {
await pubspecOverridesFile.delete();
deleteEntry(pubspecOverridesFile);
} else {
await pubspecOverridesFile.create(recursive: true);
await pubspecOverridesFile
.writeAsString(updatedPubspecOverridesContents);
await writeTextFileAsync(
pubspecOverridesFile,
updatedPubspecOverridesContents,
);
}
}
}
Expand Down Expand Up @@ -382,14 +383,13 @@ Future<void> _generateTemporaryProjects(MelosWorkspace workspace) async {
...pathParts,
'${otherPackage.androidPluginClass!}$mainClassFileSuffix',
]);
File(destinationMainClassPath).createSync(recursive: true);
String? classPath;
if (hasJavaPluginClass) {
classPath = otherPackage.javaPluginClassPath;
} else if (hasKotlinPluginClass) {
classPath = otherPackage.kotlinPluginClassPath;
}
File(classPath!).copySync(destinationMainClassPath);
copyFile(classPath!, destinationMainClassPath, recursive: true);
}
}
}
Expand All @@ -398,21 +398,21 @@ Future<void> _generateTemporaryProjects(MelosWorkspace workspace) async {
final generatedPubspecYamlString =
'$header\n${toYamlString(pubspec.toJson())}';

final pubspecFile = File(
utils.pubspecPathForDirectory(Directory(packageTemporaryPath)),
await writeTextFileAsync(
utils.pubspecPathForDirectory(packageTemporaryPath),
generatedPubspecYamlString,
recursive: true,
);
pubspecFile.createSync(recursive: true);
pubspecFile.writeAsStringSync(generatedPubspecYamlString);

// Original pubspec.lock files should also be preserved in our packages
// mirror, if we don't then this makes melos bootstrap function the same
// as `dart pub upgrade` every time - which we don't want.
// See https://github.com/invertase/melos/issues/68
final originalPubspecLock = join(package.path, 'pubspec.lock');
if (File(originalPubspecLock).existsSync()) {
final pubspecLockContents = File(originalPubspecLock).readAsStringSync();
if (fileExists(originalPubspecLock)) {
final pubspecLockContents = await readTextFileAsync(originalPubspecLock);
final copiedPubspecLock = join(packageTemporaryPath, 'pubspec.lock');
File(copiedPubspecLock).writeAsStringSync(pubspecLockContents);
await writeTextFileAsync(copiedPubspecLock, pubspecLockContents);
}
}
}
Expand Down
26 changes: 10 additions & 16 deletions packages/melos/lib/src/commands/clean.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ mixin _CleanMixin on _Melos {
}

void cleanWorkspace(MelosWorkspace workspace) {
if (Directory(workspace.melosToolPath).existsSync()) {
Directory(workspace.melosToolPath).deleteSync(recursive: true);
}
deleteEntry(workspace.melosToolPath);
}

Future<void> _cleanPackage(Package package) async {
Expand All @@ -40,39 +38,35 @@ mixin _CleanMixin on _Melos {
];

for (final generatedPubFilePath in pathsToClean) {
final file = File(join(package.path, generatedPubFilePath));
if (file.existsSync()) {
await file.delete(recursive: true);
}
deleteEntry(join(package.path, generatedPubFilePath));
}

// Remove any Melos generated dependency overrides from
// `pubspec_overrides.yaml`.
final pubspecOverridesFile =
File(join(package.path, 'pubspec_overrides.yaml'));
if (pubspecOverridesFile.existsSync()) {
final contents = await pubspecOverridesFile.readAsString();
final pubspecOverridesFile = join(package.path, 'pubspec_overrides.yaml');
if (fileExists(pubspecOverridesFile)) {
final contents = await readTextFileAsync(pubspecOverridesFile);
final updatedContents = mergeMelosPubspecOverrides({}, contents);
if (updatedContents != null) {
if (updatedContents.isEmpty) {
await pubspecOverridesFile.delete();
deleteEntry(pubspecOverridesFile);
} else {
await pubspecOverridesFile.writeAsString(updatedContents);
await writeTextFileAsync(pubspecOverridesFile, updatedContents);
}
}
}
}

Future<void> cleanIntelliJ(MelosWorkspace workspace) async {
if (workspace.ide.intelliJ.runConfigurationsDir.existsSync()) {
if (dirExists(workspace.ide.intelliJ.runConfigurationsDir.path)) {
final melosXmlGlob = createGlob(
join(workspace.ide.intelliJ.runConfigurationsDir.path, 'melos_*.xml'),
currentDirectoryPath: workspace.path,
);

await for (final melosYmlFile
await for (final melosXmlFile
in melosXmlGlob.listFileSystem(const LocalFileSystem())) {
await melosYmlFile.delete();
deleteEntry(melosXmlFile.path);
}
}
}
Expand Down
17 changes: 8 additions & 9 deletions packages/melos/lib/src/commands/exec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,19 @@ mixin _ExecMixin on _Melos {

// TODO what if it's not called 'example'?
if (package.path.endsWith('example')) {
final exampleParentPackagePath = Directory(package.path).parent.path;
final exampleParentPubspecFile = File(
'$exampleParentPackagePath${currentPlatform.pathSeparator}pubspec.yaml',
);
final exampleParentPackagePath = p.normalize('${package.path}/..');
final exampleParentPubspecPath =
p.normalize('$exampleParentPackagePath/pubspec.yaml');

if (exampleParentPubspecFile.existsSync()) {
final exampleParentPackage =
await PubSpec.load(exampleParentPubspecFile.parent);
if (fileExists(exampleParentPubspecPath)) {
final exampleParentPackage = PubSpec.fromYamlString(
await readTextFileAsync(exampleParentPubspecPath),
);

environment['MELOS_PARENT_PACKAGE_NAME'] = exampleParentPackage.name!;
environment['MELOS_PARENT_PACKAGE_VERSION'] =
(exampleParentPackage.version ?? Version.none).toString();
environment['MELOS_PARENT_PACKAGE_PATH'] =
exampleParentPubspecFile.parent.path;
environment['MELOS_PARENT_PACKAGE_PATH'] = exampleParentPackagePath;
}
}
if (environment.containsKey('MELOS_TEST')) {
Expand Down
2 changes: 2 additions & 0 deletions packages/melos/lib/src/commands/runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:conventional_commit/conventional_commit.dart';
import 'package:file/local.dart';
import 'package:meta/meta.dart';
import 'package:mustache_template/mustache.dart';
import 'package:path/path.dart' as p;
import 'package:path/path.dart';
import 'package:pool/pool.dart';
import 'package:pub_semver/pub_semver.dart';
Expand All @@ -22,6 +23,7 @@ import '../common/exception.dart';
import '../common/git.dart';
import '../common/git_commit.dart';
import '../common/glob.dart';
import '../common/io.dart';
import '../common/pending_package_update.dart';
import '../common/platform.dart';
import '../common/utils.dart';
Expand Down
12 changes: 6 additions & 6 deletions packages/melos/lib/src/commands/version.dart
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,8 @@ mixin _VersionMixin on _RunMixin {
Package package,
Version version,
) async {
final pubspec = File(pubspecPathForDirectory(Directory(package.path)));
final contents = await pubspec.readAsString();
final pubspec = pubspecPathForDirectory(package.path);
final contents = await readTextFileAsync(pubspec);

final updatedContents =
contents.replaceAllMapped(versionReplaceRegex, (match) {
Expand All @@ -364,7 +364,7 @@ mixin _VersionMixin on _RunMixin {
return;
}

await pubspec.writeAsString(updatedContents);
await writeTextFileAsync(pubspec, updatedContents);
}

Future<void> _setDependentPackageVersionConstraint(
Expand Down Expand Up @@ -451,8 +451,8 @@ mixin _VersionMixin on _RunMixin {
return;
}

final pubspec = File(pubspecPathForDirectory(Directory(package.path)));
final contents = await pubspec.readAsString();
final pubspec = pubspecPathForDirectory(package.path);
final contents = await readTextFileAsync(pubspec);

final isExternalHostedReference = package
.pubSpec.dependencies[dependencyName] is ExternalHostedReference ||
Expand Down Expand Up @@ -493,7 +493,7 @@ mixin _VersionMixin on _RunMixin {
return;
}

await pubspec.writeAsString(updatedContents);
await writeTextFileAsync(pubspec, updatedContents);
}

void _logNewVersionTable(
Expand Down
10 changes: 4 additions & 6 deletions packages/melos/lib/src/common/changelog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,14 @@
*
*/

import 'dart:io';

import 'package:path/path.dart';
import 'package:pub_semver/pub_semver.dart';

import '../logging.dart';
import '../package.dart';
import 'git_commit.dart';
import 'git_repository.dart';
import 'io.dart';
import 'pending_package_update.dart';

class Changelog {
Expand All @@ -47,9 +46,8 @@ class Changelog {
}

Future<String> read() async {
final exists = File(path).existsSync();
if (exists) {
return File(path).readAsString();
if (fileExists(path)) {
return readTextFile(path);
}
return '';
}
Expand All @@ -65,7 +63,7 @@ class Changelog {
}
contents = '$markdown$contents';

await File(path).writeAsString(contents);
await writeTextFileAsync(path, contents);
}
}

Expand Down
10 changes: 4 additions & 6 deletions packages/melos/lib/src/common/intellij_project.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import 'package:path/path.dart' show join, joinAll;
import '../common/utils.dart' as utils;
import '../package.dart';
import '../workspace.dart';
import 'io.dart';
import 'platform.dart';

const String _kTemplatesDirName = 'templates';
Expand Down Expand Up @@ -131,19 +132,16 @@ class IntellijProject {
templatesRootPath = await pathTemplates;
}

final templateFile =
File(joinAll([templatesRootPath, '$fileName$_kTmplExtension']));
final template = await templateFile.readAsString();
final templateFile = join(templatesRootPath, '$fileName$_kTmplExtension');
final template = await readTextFileAsync(templateFile);

_cacheTemplates[fileName] = template;

return template;
}

Future<void> forceWriteToFile(String filePath, String fileContents) async {
final outputFile = File(filePath);
await outputFile.create(recursive: true);
await outputFile.writeAsString(fileContents);
await writeTextFileAsync(filePath, fileContents, recursive: true);
}

/// Create a .name file using the workspace name.
Expand Down
Loading