Repository: dart-lang/pub-dev (dart)

Issue:
Retracted package should show the latest available one instead of the latest retracted one if they are not compatible between
Package: https://pub.dev/packages/ord_dart

I've retracted all v0.1 versions and published a v0.0.8 version. But the page still shows that the v0.1.0+2 has been retracted.

![image](https://github.com/dart-lang/pub-dev/assets/15884415/48f46505-d7d3-4189-afa5-02418a8bffa0)

Pull request description:
- Fixes #7852.
- I was able to create a reproduction of the bug, and it turns out it was not in the version update at retraction, it was at upload time, when all of the versions are retracted.

Patch:
diff --git a/app/lib/package/backend.dart b/app/lib/package/backend.dart
index e8aa1a4e0a..0e4ad07bed 100644
--- a/app/lib/package/backend.dart
+++ b/app/lib/package/backend.dart
@@ -1065,6 +1065,12 @@ class PackageBackend {
         lastKnownStable: toolStableFlutterSdkVersion);
     final existingPackage = await lookupPackage(newVersion.package);
     final isNew = existingPackage == null;
+    final existingLatestVersion = isNew
+        ? null
+        : await lookupPackageVersion(
+            existingPackage.name!, existingPackage.latestVersion!);
+    final existingLatestIsRetracted =
+        existingLatestVersion?.isRetracted ?? false;
 
     // check authorizations before the transaction
     await _requireUploadAuthorization(
@@ -1158,6 +1164,7 @@ class PackageBackend {
         newVersion,
         dartSdkVersion: currentDartSdk.semanticVersion,
         flutterSdkVersion: currentFlutterSdk.semanticVersion,
+        existingLatestIsRetracted: existingLatestIsRetracted,
       );
       package!.updated = clock.now().toUtc();
       package!.versionCount++;
diff --git a/app/lib/package/models.dart b/app/lib/package/models.dart
index 4a2105629c..8734bb948c 100644
--- a/app/lib/package/models.dart
+++ b/app/lib/package/models.dart
@@ -340,6 +340,7 @@ class Package extends db.ExpandoModel<String> {
     PackageVersion pv, {
     required Version dartSdkVersion,
     required Version flutterSdkVersion,
+    bool existingLatestIsRetracted = false,
   }) {
     final newVersion = pv.semanticVersion;
     final isOnStableSdk = !pv.pubspec!.isPreviewForCurrentSdk(
@@ -347,20 +348,23 @@ class Package extends db.ExpandoModel<String> {
       flutterSdkVersion: flutterSdkVersion,
     );
 
-    if (latestVersionKey == null ||
+    if (existingLatestIsRetracted ||
+        latestVersionKey == null ||
         (isNewer(latestSemanticVersion, newVersion, pubSorted: true) &&
             (latestSemanticVersion.isPreRelease || isOnStableSdk))) {
       latestVersionKey = pv.key;
       latestPublished = pv.created;
     }
 
-    if (latestPreviewVersionKey == null ||
+    if (existingLatestIsRetracted ||
+        latestPreviewVersionKey == null ||
         isNewer(latestPreviewSemanticVersion!, newVersion, pubSorted: true)) {
       latestPreviewVersionKey = pv.key;
       latestPreviewPublished = pv.created;
     }
 
-    if (latestPrereleaseVersionKey == null ||
+    if (existingLatestIsRetracted ||
+        latestPrereleaseVersionKey == null ||
         isNewer(latestPrereleaseSemanticVersion!, newVersion,
             pubSorted: false)) {
       latestPrereleaseVersionKey = pv.key;


Test patch:
diff --git a/app/test/package/retracted_test.dart b/app/test/package/retracted_test.dart
index 4d2d4f8c6b..53b37b0a89 100644
--- a/app/test/package/retracted_test.dart
+++ b/app/test/package/retracted_test.dart
@@ -14,6 +14,7 @@ import 'package:test/test.dart';
 import '../shared/handlers_test_utils.dart';
 import '../shared/test_models.dart';
 import '../shared/test_services.dart';
+import 'backend_test_utils.dart';
 
 void main() {
   group('Retractions', () {
@@ -301,4 +302,53 @@ void main() {
       expect(pkg6.lastVersionPublished, origLastVersionPublished);
     });
   });
+
+  group('different combinations', () {
+    final _testProfile = TestProfile(
+      packages: [
+        TestPackage(
+          name: 'pkg',
+          versions: [
+            TestVersion(version: '1.2.0'),
+            TestVersion(version: '1.3.0-dev'),
+            TestVersion(version: '2.0.0-dev'),
+          ],
+        ),
+        TestPackage(name: 'oxygen'),
+      ],
+      defaultUser: adminAtPubDevEmail,
+    );
+
+    testWithProfile(
+      'remove latest versions and then publish an old version number',
+      testProfile: _testProfile,
+      fn: () async {
+        final client =
+            await createFakeAuthPubApiClient(email: adminAtPubDevEmail);
+        await client.setVersionOptions(
+            'pkg', '1.2.0', VersionOptions(isRetracted: true));
+        final pkg1 = (await packageBackend.lookupPackage('pkg'))!;
+        expect(pkg1.latestVersion, '2.0.0-dev');
+
+        await client.setVersionOptions(
+            'pkg', '2.0.0-dev', VersionOptions(isRetracted: true));
+        final pkg2 = (await packageBackend.lookupPackage('pkg'))!;
+        expect(pkg2.latestVersion, '1.3.0-dev');
+
+        await client.setVersionOptions(
+            'pkg', '1.3.0-dev', VersionOptions(isRetracted: true));
+
+        final pkg3 = (await packageBackend.lookupPackage('pkg'))!;
+        expect(pkg3.latestVersion, '1.2.0');
+
+        final pubspecContent = generatePubspecYaml('pkg', '0.1.0');
+        await createPubApiClient(authToken: adminClientToken)
+            .uploadPackageBytes(
+                await packageArchiveBytes(pubspecContent: pubspecContent));
+
+        final pkg4 = (await packageBackend.lookupPackage('pkg'))!;
+        expect(pkg4.latestVersion, '0.1.0');
+      },
+    );
+  });
 }