Validate that dependency names are valid package names (#3940)

diff --git a/lib/src/pubspec.dart b/lib/src/pubspec.dart
index 1b1e3b8..18b0e99 100644
--- a/lib/src/pubspec.dart
+++ b/lib/src/pubspec.dart
@@ -443,6 +443,9 @@
       if (name is! String) {
         _error('A dependency name must be a string.', nameNode.span);
       }
+      if (!packageNameRegExp.hasMatch(name)) {
+        _error('Not a valid package name.', nameNode.span);
+      }
       var spec = specNode.value;
       if (packageName != null && name == packageName) {
         _error('A package may not list itself as a dependency.', nameNode.span);
diff --git a/test/add/common/add_test.dart b/test/add/common/add_test.dart
index 8e958af..6c8daa3 100644
--- a/test/add/common/add_test.dart
+++ b/test/add/common/add_test.dart
@@ -13,7 +13,7 @@
 import '../../test_pub.dart';
 
 void main() {
-  test('URL encodes the package name', () async {
+  test('Validates the package name', () async {
     await servePackages();
 
     await d.appDir(dependencies: {}).create();
diff --git a/test/dependency_name_validation_test.dart b/test/dependency_name_validation_test.dart
new file mode 100644
index 0000000..ae924c6
--- /dev/null
+++ b/test/dependency_name_validation_test.dart
@@ -0,0 +1,25 @@
+// 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';
+import 'test_pub.dart';
+
+void main() {
+  test('Dependency names have to be valid package names', () async {
+    await appDir(dependencies: {'abc def': '1.0.0'}).create();
+    await pubGet(error: contains('Not a valid package name.'), exitCode: DATA);
+  });
+
+  test('Dev-dependency names have to be valid package names', () async {
+    await appDir(
+      pubspec: {
+        'dev_dependencies': {'abc def': '1.0.0'}
+      },
+    ).create();
+    await pubGet(error: contains('Not a valid package name.'), exitCode: DATA);
+  });
+}
diff --git a/test/get/hosted/get_test.dart b/test/get/hosted/get_test.dart
index c6141ab..5e90f9f 100644
--- a/test/get/hosted/get_test.dart
+++ b/test/get/hosted/get_test.dart
@@ -97,22 +97,6 @@
     });
   });
 
-  test('URL encodes the package name', () async {
-    await servePackages();
-
-    await d.appDir(dependencies: {'bad name!': '1.2.3'}).create();
-
-    await pubGet(
-      error: allOf([
-        contains(
-            "Because myapp depends on bad name! any which doesn't exist (could "
-            'not find package bad name! at http://localhost:'),
-        contains('), version solving failed.')
-      ]),
-      exitCode: exit_codes.UNAVAILABLE,
-    );
-  });
-
   test('gets a package from a non-default pub server', () async {
     // Make the default server serve errors. Only the custom server should
     // be accessed.