From 228c6bfa322385e710c5015a925e3ca0b9e8d550 Mon Sep 17 00:00:00 2001
From: Sergei Zharinov <zharinov@users.noreply.github.com>
Date: Sun, 25 Jun 2023 20:15:00 +0300
Subject: [PATCH] refactor: Extract `uniq` utility function (#22968)

---
 lib/modules/datasource/index.ts |  9 +++------
 lib/util/exec/docker/index.ts   |  8 +-------
 lib/util/uniq.spec.ts           | 17 +++++++++++++++++
 lib/util/uniq.ts                |  6 ++++++
 4 files changed, 27 insertions(+), 13 deletions(-)
 create mode 100644 lib/util/uniq.spec.ts
 create mode 100644 lib/util/uniq.ts

diff --git a/lib/modules/datasource/index.ts b/lib/modules/datasource/index.ts
index 33e7c7d17e..a9998eb83f 100644
--- a/lib/modules/datasource/index.ts
+++ b/lib/modules/datasource/index.ts
@@ -7,6 +7,7 @@ import * as memCache from '../../util/cache/memory';
 import * as packageCache from '../../util/cache/package';
 import { clone } from '../../util/clone';
 import { regEx } from '../../util/regex';
+import { uniq } from '../../util/uniq';
 import { trimTrailingSlash } from '../../util/url';
 import * as allVersioning from '../versioning';
 import datasources from './api';
@@ -394,12 +395,8 @@ export async function getPkgReleases(
     .sort((a, b) => version.sortVersions(a.version, b.version));
 
   // Filter versions for uniqueness
-  res.releases = res.releases.filter(
-    (filterRelease, filterIndex) =>
-      res.releases.findIndex(
-        (findRelease) => findRelease.version === filterRelease.version
-      ) === filterIndex
-  );
+  res.releases = uniq(res.releases, (x, y) => x.version === y.version);
+
   if (config?.constraintsFiltering === 'strict') {
     // Filter releases for compatibility
     for (const [constraintName, constraintValue] of Object.entries(
diff --git a/lib/util/exec/docker/index.ts b/lib/util/exec/docker/index.ts
index d20ccb9d02..a2106a302b 100644
--- a/lib/util/exec/docker/index.ts
+++ b/lib/util/exec/docker/index.ts
@@ -5,6 +5,7 @@ import { logger } from '../../../logger';
 import { getPkgReleases } from '../../../modules/datasource';
 import * as versioning from '../../../modules/versioning';
 import { newlineRegex, regEx } from '../../regex';
+import { uniq } from '../../uniq';
 import { ensureTrailingSlash } from '../../url';
 import { rawExec } from '../common';
 import type { DockerOptions, Opt, VolumeOption, VolumesPair } from '../types';
@@ -58,13 +59,6 @@ function volumesEql(x: VolumesPair, y: VolumesPair): boolean {
   return xFrom === yFrom && xTo === yTo;
 }
 
-function uniq<T = unknown>(
-  array: T[],
-  eql = (x: T, y: T): boolean => x === y
-): T[] {
-  return array.filter((x, idx, arr) => arr.findIndex((y) => eql(x, y)) === idx);
-}
-
 function prepareVolumes(volumes: VolumeOption[] = []): string[] {
   const expanded: (VolumesPair | null)[] = volumes.map(expandVolumeOption);
   const filtered: VolumesPair[] = expanded.filter(
diff --git a/lib/util/uniq.spec.ts b/lib/util/uniq.spec.ts
new file mode 100644
index 0000000000..fa2216a462
--- /dev/null
+++ b/lib/util/uniq.spec.ts
@@ -0,0 +1,17 @@
+import { uniq } from './uniq';
+
+describe('util/uniq', () => {
+  it('should return an array with unique elements', () => {
+    const input = [1, 2, 3, 2, 1, 4];
+    const expectedOutput = [1, 2, 3, 4];
+    expect(uniq(input)).toEqual(expectedOutput);
+  });
+
+  it('should use the provided equality function to compare elements', () => {
+    type T = { id: number };
+    const input: T[] = [{ id: 1 }, { id: 2 }, { id: 1 }];
+    const expectedOutput = [{ id: 1 }, { id: 2 }];
+    const eql = (x: T, y: T) => x.id === y.id;
+    expect(uniq(input, eql)).toEqual(expectedOutput);
+  });
+});
diff --git a/lib/util/uniq.ts b/lib/util/uniq.ts
new file mode 100644
index 0000000000..60079afa3c
--- /dev/null
+++ b/lib/util/uniq.ts
@@ -0,0 +1,6 @@
+export function uniq<T = unknown>(
+  array: T[],
+  eql = (x: T, y: T): boolean => x === y
+): T[] {
+  return array.filter((x, idx, arr) => arr.findIndex((y) => eql(x, y)) === idx);
+}
-- 
GitLab