From aaaa6a1cfeb24e17c0b194b41f162c6af6b58f4f Mon Sep 17 00:00:00 2001
From: Johannes Feichtner <Churro@users.noreply.github.com>
Date: Sun, 25 Sep 2022 16:31:11 +0200
Subject: [PATCH] refactor: extract getLockFileContentMap() into fs utils
 (#17962)

---
 lib/modules/manager/nuget/artifacts.spec.ts | 86 ++++++++++++++++-----
 lib/modules/manager/nuget/artifacts.ts      | 25 +-----
 lib/util/fs/index.spec.ts                   | 35 ++++++++-
 lib/util/fs/index.ts                        | 16 ++++
 4 files changed, 120 insertions(+), 42 deletions(-)

diff --git a/lib/modules/manager/nuget/artifacts.spec.ts b/lib/modules/manager/nuget/artifacts.spec.ts
index 7faf362b88..4ca73a78fb 100644
--- a/lib/modules/manager/nuget/artifacts.spec.ts
+++ b/lib/modules/manager/nuget/artifacts.spec.ts
@@ -50,6 +50,7 @@ describe('modules/manager/nuget/artifacts', () => {
   it('aborts if no lock file found', async () => {
     const execSnapshots = mockExecAll();
     fs.getSiblingFileName.mockReturnValueOnce('packages.lock.json');
+    fs.getFileContentMap.mockResolvedValueOnce({ 'packages.lock.json': null });
     expect(
       await nuget.updateArtifacts({
         packageFileName: 'project.csproj',
@@ -66,8 +67,13 @@ describe('modules/manager/nuget/artifacts', () => {
     fs.getSiblingFileName.mockReturnValueOnce(
       'path/with space/packages.lock.json'
     );
-    git.getFile.mockResolvedValueOnce('Current packages.lock.json');
-    fs.readLocalFile.mockResolvedValueOnce('Current packages.lock.json');
+    fs.getFileContentMap
+      .mockResolvedValueOnce({
+        'path/with space/packages.lock.json': 'Current packages.lock.json',
+      })
+      .mockResolvedValueOnce({
+        'path/with space/packages.lock.json': 'Current packages.lock.json',
+      });
     expect(
       await nuget.updateArtifacts({
         packageFileName: 'path/with space/project.csproj',
@@ -82,8 +88,13 @@ describe('modules/manager/nuget/artifacts', () => {
   it('updates lock file', async () => {
     const execSnapshots = mockExecAll();
     fs.getSiblingFileName.mockReturnValueOnce('packages.lock.json');
-    git.getFile.mockResolvedValueOnce('Current packages.lock.json');
-    fs.readLocalFile.mockResolvedValueOnce('New packages.lock.json');
+    fs.getFileContentMap
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'Current packages.lock.json',
+      })
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'New packages.lock.json',
+      });
     expect(
       await nuget.updateArtifacts({
         packageFileName: 'project.csproj',
@@ -98,8 +109,13 @@ describe('modules/manager/nuget/artifacts', () => {
   it('does not update lock file when non-proj file is changed', async () => {
     const execSnapshots = mockExecAll();
     fs.getSiblingFileName.mockReturnValueOnce('packages.lock.json');
-    git.getFile.mockResolvedValueOnce('Current packages.lock.json');
-    fs.readLocalFile.mockResolvedValueOnce('New packages.lock.json');
+    fs.getFileContentMap
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'Current packages.lock.json',
+      })
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'New packages.lock.json',
+      });
     expect(
       await nuget.updateArtifacts({
         packageFileName: 'otherfile.props',
@@ -114,8 +130,13 @@ describe('modules/manager/nuget/artifacts', () => {
   it('does not update lock file when no deps changed', async () => {
     const execSnapshots = mockExecAll();
     fs.getSiblingFileName.mockReturnValueOnce('packages.lock.json');
-    git.getFile.mockResolvedValueOnce('Current packages.lock.json');
-    fs.readLocalFile.mockResolvedValueOnce('New packages.lock.json');
+    fs.getFileContentMap
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'Current packages.lock.json',
+      })
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'New packages.lock.json',
+      });
     expect(
       await nuget.updateArtifacts({
         packageFileName: 'project.csproj',
@@ -130,8 +151,13 @@ describe('modules/manager/nuget/artifacts', () => {
   it('performs lock file maintenance', async () => {
     const execSnapshots = mockExecAll();
     fs.getSiblingFileName.mockReturnValueOnce('packages.lock.json');
-    git.getFile.mockResolvedValueOnce('Current packages.lock.json');
-    fs.readLocalFile.mockResolvedValueOnce('New packages.lock.json');
+    fs.getFileContentMap
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'Current packages.lock.json',
+      })
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'New packages.lock.json',
+      });
     expect(
       await nuget.updateArtifacts({
         packageFileName: 'project.csproj',
@@ -150,8 +176,13 @@ describe('modules/manager/nuget/artifacts', () => {
     GlobalConfig.set({ ...adminConfig, binarySource: 'docker' });
     const execSnapshots = mockExecAll();
     fs.getSiblingFileName.mockReturnValueOnce('packages.lock.json');
-    git.getFile.mockResolvedValueOnce('Current packages.lock.json');
-    fs.readLocalFile.mockResolvedValueOnce('New packages.lock.json');
+    fs.getFileContentMap
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'Current packages.lock.json',
+      })
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'New packages.lock.json',
+      });
     expect(
       await nuget.updateArtifacts({
         packageFileName: 'project.csproj',
@@ -167,8 +198,13 @@ describe('modules/manager/nuget/artifacts', () => {
     GlobalConfig.set({ ...adminConfig, binarySource: 'global' });
     const execSnapshots = mockExecAll();
     fs.getSiblingFileName.mockReturnValueOnce('packages.lock.json');
-    git.getFile.mockResolvedValueOnce('Current packages.lock.json');
-    fs.readLocalFile.mockResolvedValueOnce('New packages.lock.json');
+    fs.getFileContentMap
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'Current packages.lock.json',
+      })
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'New packages.lock.json',
+      });
     expect(
       await nuget.updateArtifacts({
         packageFileName: 'project.csproj',
@@ -182,7 +218,9 @@ describe('modules/manager/nuget/artifacts', () => {
 
   it('catches errors', async () => {
     fs.getSiblingFileName.mockReturnValueOnce('packages.lock.json');
-    git.getFile.mockResolvedValueOnce('Current packages.lock.json');
+    fs.getFileContentMap.mockResolvedValueOnce({
+      'packages.lock.json': 'Current packages.lock.json',
+    });
     fs.writeLocalFile.mockImplementationOnce(() => {
       throw new Error('not found');
     });
@@ -206,8 +244,13 @@ describe('modules/manager/nuget/artifacts', () => {
   it('authenticates at registries', async () => {
     const execSnapshots = mockExecAll();
     fs.getSiblingFileName.mockReturnValueOnce('packages.lock.json');
-    git.getFile.mockResolvedValueOnce('Current packages.lock.json');
-    fs.readLocalFile.mockResolvedValueOnce('New packages.lock.json');
+    fs.getFileContentMap
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'Current packages.lock.json',
+      })
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'New packages.lock.json',
+      });
     getConfiguredRegistries.mockResolvedValueOnce([
       {
         name: 'myRegistry',
@@ -240,8 +283,13 @@ describe('modules/manager/nuget/artifacts', () => {
   it('strips protocol version from feed url', async () => {
     const execSnapshots = mockExecAll();
     fs.getSiblingFileName.mockReturnValueOnce('packages.lock.json');
-    git.getFile.mockResolvedValueOnce('Current packages.lock.json');
-    fs.readLocalFile.mockResolvedValueOnce('New packages.lock.json');
+    fs.getFileContentMap
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'Current packages.lock.json',
+      })
+      .mockResolvedValueOnce({
+        'packages.lock.json': 'New packages.lock.json',
+      });
     getConfiguredRegistries.mockResolvedValueOnce([
       {
         name: 'myRegistry',
diff --git a/lib/modules/manager/nuget/artifacts.ts b/lib/modules/manager/nuget/artifacts.ts
index f1651d860d..a88dfdb95b 100644
--- a/lib/modules/manager/nuget/artifacts.ts
+++ b/lib/modules/manager/nuget/artifacts.ts
@@ -6,13 +6,12 @@ import { exec } from '../../../util/exec';
 import type { ExecOptions } from '../../../util/exec/types';
 import {
   ensureDir,
+  getFileContentMap,
   getSiblingFileName,
   outputCacheFile,
   privateCacheDir,
-  readLocalFile,
   writeLocalFile,
 } from '../../../util/fs';
-import { getFile } from '../../../util/git';
 import * as hostRules from '../../../util/host-rules';
 import { regEx } from '../../../util/regex';
 import { NugetDatasource } from '../../datasource/nuget';
@@ -96,21 +95,6 @@ async function runDotnetRestore(
   await exec(cmds, execOptions);
 }
 
-async function getLockFileContentMap(
-  lockFileNames: string[],
-  local = false
-): Promise<Record<string, string | null>> {
-  const lockFileContentMap: Record<string, string | null> = {};
-
-  for (const lockFileName of lockFileNames) {
-    lockFileContentMap[lockFileName] = local
-      ? await readLocalFile(lockFileName, 'utf8')
-      : await getFile(lockFileName);
-  }
-
-  return lockFileContentMap;
-}
-
 export async function updateArtifacts({
   packageFileName,
   newPackageFileContent,
@@ -159,7 +143,7 @@ export async function updateArtifacts({
     getSiblingFileName(f, 'packages.lock.json')
   );
 
-  const existingLockFileContentMap = await getLockFileContentMap(lockFileNames);
+  const existingLockFileContentMap = await getFileContentMap(lockFileNames);
 
   const hasLockFileContent = Object.values(existingLockFileContentMap).some(
     (val) => !!val
@@ -184,10 +168,7 @@ export async function updateArtifacts({
 
     await runDotnetRestore(packageFileName, packageFiles, config);
 
-    const newLockFileContentMap = await getLockFileContentMap(
-      lockFileNames,
-      true
-    );
+    const newLockFileContentMap = await getFileContentMap(lockFileNames, true);
 
     const retArray: UpdateArtifactsResult[] = [];
     for (const lockFileName of lockFileNames) {
diff --git a/lib/util/fs/index.spec.ts b/lib/util/fs/index.spec.ts
index 3670a58bdc..2594f7e024 100644
--- a/lib/util/fs/index.spec.ts
+++ b/lib/util/fs/index.spec.ts
@@ -2,7 +2,7 @@ import _findUp from 'find-up';
 import fs from 'fs-extra';
 import tmp, { DirectoryResult } from 'tmp-promise';
 import { join, resolve } from 'upath';
-import { mockedFunction } from '../../../test/util';
+import { git, mockedFunction } from '../../../test/util';
 import { GlobalConfig } from '../../config/global';
 import {
   cachePathExists,
@@ -14,6 +14,7 @@ import {
   ensureLocalDir,
   findLocalSiblingOrParent,
   findUpLocal,
+  getFileContentMap,
   getParentDir,
   getSiblingFileName,
   listCacheDir,
@@ -35,6 +36,7 @@ import {
 
 jest.mock('../exec/env');
 jest.mock('find-up');
+jest.mock('../git');
 
 const findUp = mockedFunction(_findUp);
 
@@ -461,4 +463,35 @@ describe('util/fs/index', () => {
       expect(await readSystemFile(path)).toEqual(Buffer.from('foobar'));
     });
   });
+
+  describe('getFileContentMap', () => {
+    it('reads list of files from local fs', async () => {
+      const fileContentMap = {
+        file1: 'foobar',
+        file2: 'foobar2',
+      };
+
+      await fs.outputFile(`${localDir}/file1`, fileContentMap.file1);
+      await fs.outputFile(`${localDir}/file2`, fileContentMap.file2);
+      const res = await getFileContentMap(Object.keys(fileContentMap), true);
+      expect(res).toStrictEqual(fileContentMap);
+    });
+
+    it('reads list of files from git', async () => {
+      const fileContentMap = {
+        file1: 'foobar',
+      };
+
+      git.getFile.mockResolvedValueOnce('foobar');
+      const res = await getFileContentMap(Object.keys(fileContentMap));
+      expect(res).toStrictEqual(fileContentMap);
+    });
+
+    it('returns null as content if file is not found', async () => {
+      const res = await getFileContentMap(['invalidfile'], true);
+      expect(res).toStrictEqual({
+        invalidfile: null,
+      });
+    });
+  });
 });
diff --git a/lib/util/fs/index.ts b/lib/util/fs/index.ts
index b029c41efe..ae659c8324 100644
--- a/lib/util/fs/index.ts
+++ b/lib/util/fs/index.ts
@@ -6,6 +6,7 @@ import fs from 'fs-extra';
 import upath from 'upath';
 import { GlobalConfig } from '../../config/global';
 import { logger } from '../../logger';
+import { getFile } from '../git';
 import { ensureCachePath, ensureLocalPath } from './util';
 
 export const pipeline = util.promisify(stream.pipeline);
@@ -285,3 +286,18 @@ export function readSystemFile(
 ): Promise<string | Buffer> {
   return encoding ? fs.readFile(fileName, encoding) : fs.readFile(fileName);
 }
+
+export async function getFileContentMap(
+  fileNames: string[],
+  local = false
+): Promise<Record<string, string | null>> {
+  const fileContentMap: Record<string, string | null> = {};
+
+  for (const fileName of fileNames) {
+    fileContentMap[fileName] = local
+      ? await readLocalFile(fileName, 'utf8')
+      : await getFile(fileName);
+  }
+
+  return fileContentMap;
+}
-- 
GitLab