Pub add/remove now remove dependencies key if it makes them empty (#2639)
* Pub add/remove now remove dependencies key if it makes them empty
* Modified tests
diff --git a/lib/src/command/add.dart b/lib/src/command/add.dart
index 73b8833..1ba0410 100644
--- a/lib/src/command/add.dart
+++ b/lib/src/command/add.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:pub_semver/pub_semver.dart';
+import 'package:yaml/yaml.dart';
import '../command.dart';
import '../entrypoint.dart';
@@ -391,11 +392,18 @@
/// Remove the package from dev_dependencies if we are adding it to
/// dependencies. Refer to [_addPackageToPubspec] for additional discussion.
- if (!isDevelopment &&
- yamlEditor.parseAt(['dev_dependencies', package.name],
- orElse: () => null) !=
- null) {
- yamlEditor.remove(['dev_dependencies', package.name]);
+ if (!isDevelopment) {
+ final devDependenciesNode =
+ yamlEditor.parseAt(['dev_dependencies'], orElse: () => null);
+
+ if (devDependenciesNode is YamlMap &&
+ devDependenciesNode.containsKey(package.name)) {
+ if (devDependenciesNode.length == 1) {
+ yamlEditor.remove(['dev_dependencies']);
+ } else {
+ yamlEditor.remove(['dev_dependencies', package.name]);
+ }
+ }
}
/// Windows line endings are already handled by [yamlEditor]
diff --git a/lib/src/command/remove.dart b/lib/src/command/remove.dart
index 94091c7..16aefbc 100644
--- a/lib/src/command/remove.dart
+++ b/lib/src/command/remove.dart
@@ -2,6 +2,8 @@
// 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:yaml/yaml.dart';
+
import '../command.dart';
import '../entrypoint.dart';
import '../io.dart';
@@ -97,9 +99,17 @@
/// There may be packages where the dependency is declared both in
/// dependencies and dev_dependencies.
for (final dependencyKey in ['dependencies', 'dev_dependencies']) {
- if (yamlEditor.parseAt([dependencyKey, package], orElse: () => null) !=
- null) {
- yamlEditor.remove([dependencyKey, package]);
+ final dependenciesNode =
+ yamlEditor.parseAt([dependencyKey], orElse: () => null);
+
+ if (dependenciesNode is YamlMap &&
+ dependenciesNode.containsKey(package)) {
+ if (dependenciesNode.length == 1) {
+ yamlEditor.remove([dependencyKey]);
+ } else {
+ yamlEditor.remove([dependencyKey, package]);
+ }
+
found = true;
}
}
diff --git a/test/add/common/add_test.dart b/test/add/common/add_test.dart
index 3b9f3af..cca9fd9 100644
--- a/test/add/common/add_test.dart
+++ b/test/add/common/add_test.dart
@@ -50,6 +50,37 @@
await d.appDir({'foo': '1.2.3'}).validate();
});
+ test(
+ 'does not remove empty dev_dependencies while adding to normal dependencies',
+ () async {
+ await servePackages((builder) {
+ builder.serve('foo', '1.2.3');
+ builder.serve('foo', '1.2.2');
+ });
+
+ await d.dir(appPath, [
+ YamlDescriptor('pubspec.yaml', '''
+ name: myapp
+ dependencies:
+
+ dev_dependencies:
+ ''')
+ ]).create();
+
+ await pubAdd(args: ['foo:1.2.3']);
+
+ await d.cacheDir({'foo': '1.2.3'}).validate();
+ await d.appPackagesFile({'foo': '1.2.3'}).validate();
+
+ await d.dir(appPath, [
+ d.pubspec({
+ 'name': 'myapp',
+ 'dependencies': {'foo': '1.2.3'},
+ 'dev_dependencies': null
+ })
+ ]).validate();
+ });
+
test('dry run does not actually add the package or modify the pubspec',
() async {
await servePackages((builder) => builder.serve('foo', '1.2.3'));
@@ -150,11 +181,13 @@
});
await d.dir(appPath, [
- d.pubspec({
- 'name': 'myapp',
- 'dependencies': {},
- 'dev_dependencies': {'foo': '1.2.2'}
- })
+ YamlDescriptor('pubspec.yaml', '''
+name: myapp
+dependencies:
+
+dev_dependencies:
+ foo: 1.2.2
+''')
]).create();
await pubAdd(
@@ -165,11 +198,11 @@
await d.cacheDir({'foo': '1.2.3'}).validate();
await d.appPackagesFile({'foo': '1.2.3'}).validate();
+
await d.dir(appPath, [
d.pubspec({
'name': 'myapp',
- 'dependencies': {'foo': '1.2.3'},
- 'dev_dependencies': {}
+ 'dependencies': {'foo': '1.2.3'}
})
]).validate();
});
@@ -758,17 +791,9 @@
await pubAdd(args: ['bar']);
- final finalPubspec = YamlDescriptor('pubspec.yaml', '''
- name: myapp
- dependencies:
- bar: ^1.0.0''');
- await d.dir(appPath, [finalPubspec]).validate();
- final fullPath = p.join(d.sandbox, appPath, 'pubspec.yaml');
-
- expect(File(fullPath).existsSync(), true);
-
- final contents = File(fullPath).readAsStringSync();
- expect(contents, await finalPubspec.read());
+ await d.dir(appPath, [
+ d.appPubspec({'bar': '^1.0.0'})
+ ]).validate();
});
test('preserves comments', () async {
@@ -790,20 +815,19 @@
await pubAdd(args: ['bar']);
- final finalPubspec = YamlDescriptor('pubspec.yaml', '''
- name: myapp
- dependencies: # comment A
- # comment B
- bar: ^1.0.0
- foo: 1.0.0 # comment C
- # comment D
- ''');
- await d.dir(appPath, [finalPubspec]).validate();
+ await d.appDir({'bar': '^1.0.0', 'foo': '1.0.0'}).validate();
final fullPath = p.join(d.sandbox, appPath, 'pubspec.yaml');
expect(File(fullPath).existsSync(), true);
final contents = File(fullPath).readAsStringSync();
- expect(contents, await finalPubspec.read());
+ expect(
+ contents,
+ allOf([
+ contains('# comment A'),
+ contains('# comment B'),
+ contains('# comment C'),
+ contains('# comment D')
+ ]));
});
}
diff --git a/test/remove/remove_test.dart b/test/remove/remove_test.dart
index 50dba5d..3691405 100644
--- a/test/remove/remove_test.dart
+++ b/test/remove/remove_test.dart
@@ -22,7 +22,39 @@
await d.cacheDir({}).validate();
await d.appPackagesFile({}).validate();
- await d.appDir({}).validate();
+ await d.appDir().validate();
+ });
+
+ test('removing a package from dependencies does not affect dev_dependencies',
+ () async {
+ await servePackages((builder) {
+ builder.serve('foo', '1.2.3');
+ builder.serve('foo', '1.2.2');
+ builder.serve('bar', '2.0.0');
+ });
+
+ await d.dir(appPath, [
+ YamlDescriptor('pubspec.yaml', '''
+name: myapp
+dependencies:
+ foo: 1.2.3
+
+dev_dependencies:
+ bar: 2.0.0
+''')
+ ]).create();
+
+ await pubRemove(args: ['foo']);
+
+ await d.cacheDir({'bar': '2.0.0'}).validate();
+ await d.appPackagesFile({'bar': '2.0.0'}).validate();
+
+ await d.dir(appPath, [
+ d.pubspec({
+ 'name': 'myapp',
+ 'dev_dependencies': {'bar': '2.0.0'}
+ })
+ ]).validate();
});
test('dry-run does not actually remove dependency', () async {
@@ -80,7 +112,7 @@
await d.appPackagesFile({}).validate();
await d.dir(appPath, [
- d.pubspec({'name': 'myapp', 'dev_dependencies': {}})
+ d.pubspec({'name': 'myapp'})
]).validate();
});
@@ -111,7 +143,6 @@
d.pubspec({
'name': 'myapp',
'dependencies': {'jfj': '0.2.1'},
- 'dev_dependencies': {}
})
]).validate();
});
@@ -199,6 +230,7 @@
await pubRemove(args: ['bar']);
+ await d.appDir({'foo': '1.0.0'}).validate();
final fullPath = p.join(d.sandbox, appPath, 'pubspec.yaml');
expect(File(fullPath).existsSync(), true);
final contents = File(fullPath).readAsStringSync();