From 4d85eb6bf3c840f942895d888559c7377a17e418 Mon Sep 17 00:00:00 2001 From: Sigurd Meldgaard Date: Fri, 20 Jan 2023 15:16:07 +0000 Subject: [PATCH 1/2] Validate files don't differ in case --- lib/src/validator.dart | 2 ++ lib/src/validator/file_case.dart | 32 ++++++++++++++++++++++++++ test/validator/file_case_test.dart | 36 ++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 lib/src/validator/file_case.dart create mode 100644 test/validator/file_case_test.dart diff --git a/lib/src/validator.dart b/lib/src/validator.dart index 4336d4a08..5a03d7b71 100644 --- a/lib/src/validator.dart +++ b/lib/src/validator.dart @@ -19,6 +19,7 @@ import 'validator/dependency_override.dart'; import 'validator/deprecated_fields.dart'; import 'validator/directory.dart'; import 'validator/executable.dart'; +import 'validator/file_case.dart'; import 'validator/flutter_constraint.dart'; import 'validator/flutter_plugin_format.dart'; import 'validator/gitignore.dart'; @@ -136,6 +137,7 @@ abstract class Validator { required List errors, }) async { var validators = [ + FileCaseValidator(), AnalyzeValidator(), GitignoreValidator(), PubspecValidator(), diff --git a/lib/src/validator/file_case.dart b/lib/src/validator/file_case.dart new file mode 100644 index 000000000..ad73d47e7 --- /dev/null +++ b/lib/src/validator/file_case.dart @@ -0,0 +1,32 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:collection/collection.dart'; + +import '../validator.dart'; + +/// Validates that a package files all are unique even after case-normalization. +class FileCaseValidator extends Validator { + @override + Future validate() async { + final lowerCaseToFile = {}; + for (final file in files.sorted()) { + final lowerCase = file.toLowerCase(); + final existing = lowerCaseToFile[lowerCase]; + if (existing != null) { + errors.add(''' +The file $file and $existing only differ in capitalization. + +This is not supported across platforms. + +Try renaming one of them. +'''); + break; + } + lowerCaseToFile[lowerCase] = file; + } + } +} diff --git a/test/validator/file_case_test.dart b/test/validator/file_case_test.dart new file mode 100644 index 000000000..7a161f805 --- /dev/null +++ b/test/validator/file_case_test.dart @@ -0,0 +1,36 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. 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:pub/src/exit_codes.dart'; +import 'package:test/test.dart'; + +import '../descriptor.dart' as d; +import '../test_pub.dart'; + +Future expectValidation(error, int exitCode) async { + await runPub( + error: error, + args: ['publish', '--dry-run'], + workingDirectory: d.path(appPath), + exitCode: exitCode, + ); +} + +late d.DirectoryDescriptor fakeFlutterRoot; + +void main() { + test('Recognizes files that only differ in capitalization.', () async { + await d.validPackage.create(); + await d.dir(appPath, [d.file('Pubspec.yaml')]).create(); + await expectValidation( + allOf( + contains('Package validation found the following error:'), + contains( + 'The file ./pubspec.yaml and ./Pubspec.yaml only differ in capitalization.', + ), + ), + DATA, + ); + }); +} From 205948819d81a27c19961d1c865616527db61450 Mon Sep 17 00:00:00 2001 From: Sigurd Meldgaard Date: Mon, 23 Jan 2023 14:22:06 +0000 Subject: [PATCH 2/2] Skip tests on non-linux platforms --- test/validator/file_case_test.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/validator/file_case_test.dart b/test/validator/file_case_test.dart index 7a161f805..67d820039 100644 --- a/test/validator/file_case_test.dart +++ b/test/validator/file_case_test.dart @@ -2,6 +2,12 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +// These tests only work on case-sensitive file systems (ie. only on linux). +@OnPlatform({ + 'windows': Skip('Windows file system is case-insensitive'), + 'mac-os': Skip('MacOS file system is case-insensitive') +}) + import 'package:pub/src/exit_codes.dart'; import 'package:test/test.dart';