From 915e5d15de390866f7f95b9cc5f83e8114b35f77 Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Wed, 13 May 2020 12:45:02 +0200
Subject: [PATCH] refactor: use readLocalFile instead of platform.getFile
 (#6219)

---
 lib/manager/bundler/artifacts.spec.ts   | 61 +++++++++++++------------
 lib/manager/bundler/artifacts.ts        |  4 +-
 lib/manager/cocoapods/artifacts.spec.ts | 18 ++++----
 lib/manager/cocoapods/artifacts.ts      |  4 +-
 lib/manager/composer/artifacts.spec.ts  | 20 ++++----
 lib/manager/composer/artifacts.ts       | 14 +++---
 lib/manager/gomod/artifacts.spec.ts     | 15 +++---
 lib/manager/gomod/artifacts.ts          |  4 +-
 lib/manager/mix/artifacts.spec.ts       |  9 ++--
 lib/manager/mix/artifacts.ts            |  4 +-
 lib/manager/pipenv/artifacts.spec.ts    | 12 ++---
 lib/manager/pipenv/artifacts.ts         |  3 +-
 lib/util/fs.ts                          |  8 ++--
 13 files changed, 88 insertions(+), 88 deletions(-)

diff --git a/lib/manager/bundler/artifacts.spec.ts b/lib/manager/bundler/artifacts.spec.ts
index e1dcc4b370..d5691118b6 100644
--- a/lib/manager/bundler/artifacts.spec.ts
+++ b/lib/manager/bundler/artifacts.spec.ts
@@ -1,5 +1,4 @@
 import { exec as _exec } from 'child_process';
-import _fs from 'fs-extra';
 import Git from 'simple-git/promise';
 import { join } from 'upath';
 import { envMock, mockExecAll } from '../../../test/execUtil';
@@ -10,6 +9,7 @@ import { setUtilConfig } from '../../util';
 import { BinarySource } from '../../util/exec/common';
 import { resetPrefetchedImages } from '../../util/exec/docker';
 import * as _env from '../../util/exec/env';
+import * as _fs from '../../util/fs';
 import * as _bundlerHostRules from './host-rules';
 import { updateArtifacts } from '.';
 
@@ -25,6 +25,7 @@ jest.mock('child_process');
 jest.mock('../../../lib/util/exec/env');
 jest.mock('../../../lib/platform');
 jest.mock('../../../lib/datasource/docker');
+jest.mock('../../../lib/util/fs');
 jest.mock('../../../lib/util/host-rules');
 jest.mock('./host-rules');
 jest.mock('../../util/exec/docker/index', () =>
@@ -63,13 +64,13 @@ describe('bundler.updateArtifacts()', () => {
     ).toBeNull();
   });
   it('returns null if Gemfile.lock was not changed', async () => {
-    platform.getFile.mockResolvedValueOnce('Current Gemfile.lock');
-    fs.outputFile.mockResolvedValueOnce(null as never);
+    fs.readLocalFile.mockResolvedValueOnce('Current Gemfile.lock');
+    fs.writeLocalFile.mockResolvedValueOnce(null as never);
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValueOnce({
       modified: [],
     } as Git.StatusResult);
-    fs.readFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
+    fs.readLocalFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
     expect(
       await updateArtifacts({
         packageFileName: 'Gemfile',
@@ -81,13 +82,14 @@ describe('bundler.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('works for default binarySource', async () => {
-    platform.getFile.mockResolvedValueOnce('Current Gemfile.lock');
-    fs.outputFile.mockResolvedValueOnce(null as never);
+    fs.readLocalFile.mockResolvedValueOnce('Current Gemfile.lock');
+    fs.writeLocalFile.mockResolvedValueOnce(null as never);
+    fs.readLocalFile.mockResolvedValueOnce(null);
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValueOnce({
       modified: ['Gemfile.lock'],
     } as Git.StatusResult);
-    fs.readFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
+    fs.readLocalFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
     expect(
       await updateArtifacts({
         packageFileName: 'Gemfile',
@@ -99,13 +101,14 @@ describe('bundler.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('works explicit global binarySource', async () => {
-    platform.getFile.mockResolvedValueOnce('Current Gemfile.lock');
-    fs.outputFile.mockResolvedValueOnce(null as never);
+    fs.readLocalFile.mockResolvedValueOnce('Current Gemfile.lock');
+    fs.writeLocalFile.mockResolvedValueOnce(null as never);
+    fs.readLocalFile.mockResolvedValueOnce(null);
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValueOnce({
       modified: ['Gemfile.lock'],
     } as Git.StatusResult);
-    fs.readFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
+    fs.readLocalFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
     expect(
       await updateArtifacts({
         packageFileName: 'Gemfile',
@@ -124,9 +127,9 @@ describe('bundler.updateArtifacts()', () => {
       await setUtilConfig({ ...config, binarySource: BinarySource.Docker });
     });
     it('.ruby-version', async () => {
-      platform.getFile.mockResolvedValueOnce('Current Gemfile.lock');
-      fs.outputFile.mockResolvedValueOnce(null as never);
-      platform.getFile.mockResolvedValueOnce('1.2.0');
+      fs.readLocalFile.mockResolvedValueOnce('Current Gemfile.lock');
+      fs.writeLocalFile.mockResolvedValueOnce(null as never);
+      fs.readLocalFile.mockResolvedValueOnce('1.2.0');
       datasource.getReleases.mockResolvedValueOnce({
         releases: [
           { version: '1.0.0' },
@@ -138,7 +141,7 @@ describe('bundler.updateArtifacts()', () => {
       platform.getRepoStatus.mockResolvedValueOnce({
         modified: ['Gemfile.lock'],
       } as Git.StatusResult);
-      fs.readFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
+      fs.readLocalFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
       expect(
         await updateArtifacts({
           packageFileName: 'Gemfile',
@@ -153,8 +156,8 @@ describe('bundler.updateArtifacts()', () => {
       expect(execSnapshots).toMatchSnapshot();
     });
     it('compatibility options', async () => {
-      platform.getFile.mockResolvedValueOnce('Current Gemfile.lock');
-      fs.outputFile.mockResolvedValueOnce(null as never);
+      fs.readLocalFile.mockResolvedValueOnce('Current Gemfile.lock');
+      fs.writeLocalFile.mockResolvedValueOnce(null as never);
       datasource.getReleases.mockResolvedValueOnce({
         releases: [
           { version: '1.0.0' },
@@ -166,7 +169,7 @@ describe('bundler.updateArtifacts()', () => {
       platform.getRepoStatus.mockResolvedValueOnce({
         modified: ['Gemfile.lock'],
       } as Git.StatusResult);
-      fs.readFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
+      fs.readLocalFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
       expect(
         await updateArtifacts({
           packageFileName: 'Gemfile',
@@ -186,8 +189,8 @@ describe('bundler.updateArtifacts()', () => {
       expect(execSnapshots).toMatchSnapshot();
     });
     it('invalid compatibility options', async () => {
-      platform.getFile.mockResolvedValueOnce('Current Gemfile.lock');
-      fs.outputFile.mockResolvedValueOnce(null as never);
+      fs.readLocalFile.mockResolvedValueOnce('Current Gemfile.lock');
+      fs.writeLocalFile.mockResolvedValueOnce(null as never);
       datasource.getReleases.mockResolvedValueOnce({
         releases: [
           { version: '1.0.0' },
@@ -199,7 +202,7 @@ describe('bundler.updateArtifacts()', () => {
       platform.getRepoStatus.mockResolvedValueOnce({
         modified: ['Gemfile.lock'],
       } as Git.StatusResult);
-      fs.readFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
+      fs.readLocalFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
       expect(
         await updateArtifacts({
           packageFileName: 'Gemfile',
@@ -220,9 +223,9 @@ describe('bundler.updateArtifacts()', () => {
     });
 
     it('injects bundler host configuration environment variables', async () => {
-      platform.getFile.mockResolvedValueOnce('Current Gemfile.lock');
-      fs.outputFile.mockResolvedValueOnce(null as never);
-      platform.getFile.mockResolvedValueOnce('1.2.0');
+      fs.readLocalFile.mockResolvedValueOnce('Current Gemfile.lock');
+      fs.writeLocalFile.mockResolvedValueOnce(null as never);
+      fs.readLocalFile.mockResolvedValueOnce('1.2.0');
       datasource.getReleases.mockResolvedValueOnce({
         releases: [
           { version: '1.0.0' },
@@ -246,7 +249,7 @@ describe('bundler.updateArtifacts()', () => {
       platform.getRepoStatus.mockResolvedValueOnce({
         modified: ['Gemfile.lock'],
       } as Git.StatusResult);
-      fs.readFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
+      fs.readLocalFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
       expect(
         await updateArtifacts({
           packageFileName: 'Gemfile',
@@ -265,8 +268,8 @@ describe('bundler.updateArtifacts()', () => {
     const execError = new Error();
     (execError as any).stdout = ' foo was resolved to';
     (execError as any).stderr = '';
-    platform.getFile.mockResolvedValueOnce('Current Gemfile.lock');
-    fs.outputFile.mockResolvedValueOnce(null as never);
+    fs.readLocalFile.mockResolvedValueOnce('Current Gemfile.lock');
+    fs.writeLocalFile.mockResolvedValueOnce(null as never);
     const execSnapshots = mockExecAll(exec, execError);
     platform.getRepoStatus.mockResolvedValueOnce({
       modified: ['Gemfile.lock'],
@@ -285,13 +288,13 @@ describe('bundler.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('performs lockFileMaintenance', async () => {
-    platform.getFile.mockResolvedValueOnce('Current Gemfile.lock');
-    fs.outputFile.mockResolvedValueOnce(null as never);
+    fs.readLocalFile.mockResolvedValueOnce('Current Gemfile.lock');
+    fs.writeLocalFile.mockResolvedValueOnce(null as never);
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValueOnce({
       modified: ['Gemfile.lock'],
     } as Git.StatusResult);
-    fs.readFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
+    fs.readLocalFile.mockResolvedValueOnce('Updated Gemfile.lock' as any);
     expect(
       await updateArtifacts({
         packageFileName: 'Gemfile',
diff --git a/lib/manager/bundler/artifacts.ts b/lib/manager/bundler/artifacts.ts
index 4fec0c0f75..af3c439cf6 100644
--- a/lib/manager/bundler/artifacts.ts
+++ b/lib/manager/bundler/artifacts.ts
@@ -37,7 +37,7 @@ async function getRubyConstraint(
       packageFileName,
       '.ruby-version'
     );
-    const rubyVersionFileContent = await platform.getFile(rubyVersionFile);
+    const rubyVersionFileContent = await readLocalFile(rubyVersionFile, 'utf8');
     if (rubyVersionFileContent) {
       logger.debug('Using ruby version specified in .ruby-version');
       rubyConstraint = rubyVersionFileContent
@@ -80,7 +80,7 @@ export async function updateArtifacts(
     throw new Error(existingError);
   }
   const lockFileName = `${packageFileName}.lock`;
-  const existingLockFileContent = await platform.getFile(lockFileName);
+  const existingLockFileContent = await readLocalFile(lockFileName, 'utf8');
   if (!existingLockFileContent) {
     logger.debug('No Gemfile.lock found');
     return null;
diff --git a/lib/manager/cocoapods/artifacts.spec.ts b/lib/manager/cocoapods/artifacts.spec.ts
index 9b4eb3fd7c..24156f3aaf 100644
--- a/lib/manager/cocoapods/artifacts.spec.ts
+++ b/lib/manager/cocoapods/artifacts.spec.ts
@@ -97,7 +97,7 @@ describe('.updateArtifacts()', () => {
   });
   it('returns null if unchanged', async () => {
     const execSnapshots = mockExecAll(exec);
-    platform.getFile.mockResolvedValueOnce('Current Podfile');
+    fs.readFile.mockResolvedValueOnce('Current Podfile' as any);
     platform.getRepoStatus.mockResolvedValueOnce({
       modified: [],
     } as Git.StatusResult);
@@ -115,7 +115,7 @@ describe('.updateArtifacts()', () => {
   it('returns updated Podfile', async () => {
     const execSnapshots = mockExecAll(exec);
     await setExecConfig({ ...config, binarySource: BinarySource.Docker });
-    platform.getFile.mockResolvedValueOnce('Old Podfile');
+    fs.readFile.mockResolvedValueOnce('Old Podfile' as any);
     platform.getRepoStatus.mockResolvedValueOnce({
       modified: ['Podfile.lock'],
     } as Git.StatusResult);
@@ -133,14 +133,14 @@ describe('.updateArtifacts()', () => {
   it('returns updated Podfile and Pods files', async () => {
     const execSnapshots = mockExecAll(exec);
     await setExecConfig({ ...config, binarySource: BinarySource.Docker });
-    platform.getFile.mockResolvedValueOnce('Old Podfile');
-    platform.getFile.mockResolvedValueOnce('Old Manifest.lock');
+    fs.readFile.mockResolvedValueOnce('Old Manifest.lock' as any);
+    fs.readFile.mockResolvedValueOnce('New Podfile' as any);
+    fs.readFile.mockResolvedValueOnce('Pods manifest' as any);
     platform.getRepoStatus.mockResolvedValueOnce({
       not_added: ['Pods/New'],
       modified: ['Podfile.lock', 'Pods/Manifest.lock'],
       deleted: ['Pods/Deleted'],
     } as Git.StatusResult);
-    fs.readFile.mockResolvedValueOnce('New Podfile' as any);
     expect(
       await updateArtifacts({
         packageFileName: 'Podfile',
@@ -153,7 +153,7 @@ describe('.updateArtifacts()', () => {
   });
   it('catches write error', async () => {
     const execSnapshots = mockExecAll(exec);
-    platform.getFile.mockResolvedValueOnce('Current Podfile');
+    fs.readFile.mockResolvedValueOnce('Current Podfile' as any);
     fs.outputFile.mockImplementationOnce(() => {
       throw new Error('not found');
     });
@@ -169,7 +169,7 @@ describe('.updateArtifacts()', () => {
   });
   it('returns pod exec error', async () => {
     const execSnapshots = mockExecAll(exec, new Error('exec exception'));
-    platform.getFile.mockResolvedValueOnce('Old Podfile.lock');
+    fs.readFile.mockResolvedValueOnce('Old Podfile.lock' as any);
     fs.outputFile.mockResolvedValueOnce(null as never);
     fs.readFile.mockResolvedValueOnce('Old Podfile.lock' as any);
     expect(
@@ -191,7 +191,7 @@ describe('.updateArtifacts()', () => {
       dockerUser: 'ubuntu',
     });
 
-    platform.getFile.mockResolvedValueOnce('COCOAPODS: 1.2.4');
+    fs.readFile.mockResolvedValueOnce('COCOAPODS: 1.2.4' as any);
 
     fs.readFile.mockResolvedValueOnce('New Podfile' as any);
 
@@ -216,7 +216,7 @@ describe('.updateArtifacts()', () => {
       dockerUser: 'ubuntu',
     });
 
-    platform.getFile.mockResolvedValueOnce('COCOAPODS: 1.2.4');
+    fs.readFile.mockResolvedValueOnce('COCOAPODS: 1.2.4' as any);
     datasource.getReleases.mockResolvedValueOnce({
       releases: [],
     });
diff --git a/lib/manager/cocoapods/artifacts.ts b/lib/manager/cocoapods/artifacts.ts
index 78879f7da9..7e7d291b4d 100644
--- a/lib/manager/cocoapods/artifacts.ts
+++ b/lib/manager/cocoapods/artifacts.ts
@@ -54,7 +54,7 @@ export async function updateArtifacts({
     ];
   }
 
-  const existingLockFileContent = await platform.getFile(lockFileName);
+  const existingLockFileContent = await readLocalFile(lockFileName, 'utf8');
   if (!existingLockFileContent) {
     logger.debug(`Lockfile not found: ${lockFileName}`);
     return null;
@@ -106,7 +106,7 @@ export async function updateArtifacts({
 
   const podsDir = join(dirname(packageFileName), 'Pods');
   const podsManifestFileName = join(podsDir, 'Manifest.lock');
-  if (await platform.getFile(podsManifestFileName)) {
+  if (await readLocalFile(podsManifestFileName, 'utf8')) {
     for (const f of status.modified.concat(status.not_added)) {
       if (f.startsWith(podsDir)) {
         res.push({
diff --git a/lib/manager/composer/artifacts.spec.ts b/lib/manager/composer/artifacts.spec.ts
index cb6082f8ce..09b55b48e3 100644
--- a/lib/manager/composer/artifacts.spec.ts
+++ b/lib/manager/composer/artifacts.spec.ts
@@ -55,7 +55,7 @@ describe('.updateArtifacts()', () => {
     ).toBeNull();
   });
   it('returns null if unchanged', async () => {
-    platform.getFile.mockResolvedValueOnce('Current composer.lock');
+    fs.readFile.mockResolvedValueOnce('Current composer.lock' as any);
     const execSnapshots = mockExecAll(exec);
     fs.readFile.mockReturnValueOnce('Current composer.lock' as any);
     platform.getRepoStatus.mockResolvedValue({ modified: [] } as StatusResult);
@@ -70,7 +70,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('uses hostRules to write auth.json', async () => {
-    platform.getFile.mockResolvedValueOnce('Current composer.lock');
+    fs.readFile.mockResolvedValueOnce('Current composer.lock' as any);
     const execSnapshots = mockExecAll(exec);
     fs.readFile.mockReturnValueOnce('Current composer.lock' as any);
     const authConfig = {
@@ -93,7 +93,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('returns updated composer.lock', async () => {
-    platform.getFile.mockResolvedValueOnce('Current composer.lock');
+    fs.readFile.mockResolvedValueOnce('Current composer.lock' as any);
     const execSnapshots = mockExecAll(exec);
     fs.readFile.mockReturnValueOnce('New composer.lock' as any);
     platform.getRepoStatus.mockResolvedValue({
@@ -110,7 +110,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('performs lockFileMaintenance', async () => {
-    platform.getFile.mockResolvedValueOnce('Current composer.lock');
+    fs.readFile.mockResolvedValueOnce('Current composer.lock' as any);
     const execSnapshots = mockExecAll(exec);
     fs.readFile.mockReturnValueOnce('New composer.lock' as any);
     platform.getRepoStatus.mockResolvedValue({
@@ -131,7 +131,7 @@ describe('.updateArtifacts()', () => {
   });
   it('supports docker mode', async () => {
     await setUtilConfig({ ...config, binarySource: BinarySource.Docker });
-    platform.getFile.mockResolvedValueOnce('Current composer.lock');
+    fs.readFile.mockResolvedValueOnce('Current composer.lock' as any);
 
     const execSnapshots = mockExecAll(exec);
 
@@ -147,7 +147,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('supports global mode', async () => {
-    platform.getFile.mockResolvedValueOnce('Current composer.lock');
+    fs.readFile.mockResolvedValueOnce('Current composer.lock' as any);
     const execSnapshots = mockExecAll(exec);
     fs.readFile.mockReturnValueOnce('New composer.lock' as any);
     expect(
@@ -164,7 +164,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('catches errors', async () => {
-    platform.getFile.mockResolvedValueOnce('Current composer.lock');
+    fs.readFile.mockResolvedValueOnce('Current composer.lock' as any);
     fs.outputFile.mockImplementationOnce(() => {
       throw new Error('not found');
     });
@@ -178,7 +178,7 @@ describe('.updateArtifacts()', () => {
     ).toMatchSnapshot();
   });
   it('catches unmet requirements errors', async () => {
-    platform.getFile.mockResolvedValueOnce('Current composer.lock');
+    fs.readFile.mockResolvedValueOnce('Current composer.lock' as any);
     fs.outputFile.mockImplementationOnce(() => {
       throw new Error(
         'fooYour requirements could not be resolved to an installable set of packages.bar'
@@ -194,7 +194,7 @@ describe('.updateArtifacts()', () => {
     ).toMatchSnapshot();
   });
   it('throws for disk space', async () => {
-    platform.getFile.mockResolvedValueOnce('Current composer.lock');
+    fs.readFile.mockResolvedValueOnce('Current composer.lock' as any);
     fs.outputFile.mockImplementationOnce(() => {
       throw new Error(
         'vendor/composer/07fe2366/sebastianbergmann-php-code-coverage-c896779/src/Report/Html/Renderer/Template/js/d3.min.js:  write error (disk full?).  Continue? (y/n/^C) '
@@ -210,7 +210,7 @@ describe('.updateArtifacts()', () => {
     ).rejects.toThrow();
   });
   it('disables ignorePlatformReqs', async () => {
-    platform.getFile.mockResolvedValueOnce('Current composer.lock');
+    fs.readFile.mockResolvedValueOnce('Current composer.lock' as any);
     const execSnapshots = mockExecAll(exec);
     fs.readFile.mockReturnValueOnce('New composer.lock' as any);
     platform.getRepoStatus.mockResolvedValue({
diff --git a/lib/manager/composer/artifacts.ts b/lib/manager/composer/artifacts.ts
index 097dccfc08..b856ee288c 100644
--- a/lib/manager/composer/artifacts.ts
+++ b/lib/manager/composer/artifacts.ts
@@ -12,6 +12,7 @@ import * as datasourcePackagist from '../../datasource/packagist';
 import { logger } from '../../logger';
 import { platform } from '../../platform';
 import { ExecOptions, exec } from '../../util/exec';
+import { deleteLocalFile, readLocalFile, writeLocalFile } from '../../util/fs';
 import * as hostRules from '../../util/host-rules';
 import { UpdateArtifact, UpdateArtifactsResult } from '../common';
 
@@ -30,7 +31,7 @@ export async function updateArtifacts({
   logger.debug(`Using composer cache ${cacheDir}`);
 
   const lockFileName = packageFileName.replace(/\.json$/, '.lock');
-  const existingLockFileContent = await platform.getFile(lockFileName);
+  const existingLockFileContent = await readLocalFile(lockFileName);
   if (!existingLockFileContent) {
     logger.debug('No composer.lock found');
     return null;
@@ -38,11 +39,9 @@ export async function updateArtifacts({
   const cwd = upath.join(config.localDir, upath.dirname(packageFileName));
   await fs.ensureDir(upath.join(cwd, 'vendor'));
   try {
-    const localPackageFileName = upath.join(config.localDir, packageFileName);
-    await fs.outputFile(localPackageFileName, newPackageFileContent);
-    const localLockFileName = upath.join(config.localDir, lockFileName);
+    await writeLocalFile(packageFileName, newPackageFileContent);
     if (config.isLockFileMaintenance) {
-      await fs.remove(localLockFileName);
+      await deleteLocalFile(lockFileName);
     }
     const authJson = {};
     let credentials = hostRules.find({
@@ -98,8 +97,7 @@ export async function updateArtifacts({
       logger.warn({ err }, 'Error setting registryUrls auth for composer');
     }
     if (authJson) {
-      const localAuthFileName = upath.join(cwd, 'auth.json');
-      await fs.outputFile(localAuthFileName, JSON.stringify(authJson));
+      await writeLocalFile('auth.json', JSON.stringify(authJson));
     }
     const execOptions: ExecOptions = {
       cwd,
@@ -137,7 +135,7 @@ export async function updateArtifacts({
       {
         file: {
           name: lockFileName,
-          contents: await fs.readFile(localLockFileName, 'utf8'),
+          contents: await readLocalFile(lockFileName),
         },
       },
     ];
diff --git a/lib/manager/gomod/artifacts.spec.ts b/lib/manager/gomod/artifacts.spec.ts
index 05136fad91..cbb15ef524 100644
--- a/lib/manager/gomod/artifacts.spec.ts
+++ b/lib/manager/gomod/artifacts.spec.ts
@@ -76,7 +76,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('returns null if unchanged', async () => {
-    platform.getFile.mockResolvedValueOnce('Current go.sum');
+    fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValueOnce({
       modified: [],
@@ -92,7 +92,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('returns updated go.sum', async () => {
-    platform.getFile.mockResolvedValueOnce('Current go.sum');
+    fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValueOnce({
       modified: ['go.sum'],
@@ -110,7 +110,7 @@ describe('.updateArtifacts()', () => {
   });
   it('supports docker mode without credentials', async () => {
     await setUtilConfig({ ...config, binarySource: BinarySource.Docker });
-    platform.getFile.mockResolvedValueOnce('Current go.sum');
+    fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValueOnce({
       modified: ['go.sum'],
@@ -130,7 +130,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('supports global mode', async () => {
-    platform.getFile.mockResolvedValueOnce('Current go.sum');
+    fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValueOnce({
       modified: ['go.sum'],
@@ -154,7 +154,7 @@ describe('.updateArtifacts()', () => {
     hostRules.find.mockReturnValueOnce({
       token: 'some-token',
     });
-    platform.getFile.mockResolvedValueOnce('Current go.sum');
+    fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValueOnce({
       modified: ['go.sum'],
@@ -178,12 +178,13 @@ describe('.updateArtifacts()', () => {
     hostRules.find.mockReturnValueOnce({
       token: 'some-token',
     });
-    platform.getFile.mockResolvedValueOnce('Current go.sum');
+    fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValueOnce({
       modified: ['go.sum'],
     } as StatusResult);
     fs.readFile.mockResolvedValueOnce('New go.sum 1' as any);
+    fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename
     fs.readFile.mockResolvedValueOnce('New go.sum 2' as any);
     fs.readFile.mockResolvedValueOnce('New go.sum 3' as any);
     try {
@@ -207,7 +208,7 @@ describe('.updateArtifacts()', () => {
   });
   it('catches errors', async () => {
     const execSnapshots = mockExecAll(exec);
-    platform.getFile.mockResolvedValueOnce('Current go.sum');
+    fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
     fs.outputFile.mockImplementationOnce(() => {
       throw new Error('This update totally doesnt work');
     });
diff --git a/lib/manager/gomod/artifacts.ts b/lib/manager/gomod/artifacts.ts
index ae27390e95..8b120171b9 100644
--- a/lib/manager/gomod/artifacts.ts
+++ b/lib/manager/gomod/artifacts.ts
@@ -41,7 +41,7 @@ export async function updateArtifacts({
   logger.debug(`Using GOPATH: ${goPath}`);
 
   const sumFileName = goModFileName.replace(/\.mod$/, '.sum');
-  const existingGoSumContent = await platform.getFile(sumFileName);
+  const existingGoSumContent = await readLocalFile(sumFileName);
   if (!existingGoSumContent) {
     logger.debug('No go.sum found');
     return null;
@@ -96,7 +96,7 @@ export async function updateArtifacts({
     const vendorDir = join(dirname(goModFileName), 'vendor/');
     const vendorModulesFileName = join(vendorDir, 'modules.txt');
     // istanbul ignore if
-    if (await platform.getFile(vendorModulesFileName)) {
+    if (await readLocalFile(vendorModulesFileName)) {
       args = 'mod vendor';
       logger.debug({ cmd, args }, 'go mod vendor command');
       await exec(`${cmd} ${args}`, execOptions);
diff --git a/lib/manager/mix/artifacts.spec.ts b/lib/manager/mix/artifacts.spec.ts
index 867d3bb866..f35afd6434 100644
--- a/lib/manager/mix/artifacts.spec.ts
+++ b/lib/manager/mix/artifacts.spec.ts
@@ -2,19 +2,16 @@ import { exec as _exec } from 'child_process';
 import _fs from 'fs-extra';
 import { envMock, mockExecAll } from '../../../test/execUtil';
 import { mocked } from '../../../test/util';
-import { platform as _platform } from '../../platform';
 import { BinarySource } from '../../util/exec/common';
 import * as _env from '../../util/exec/env';
 import { updateArtifacts } from '.';
 
 const fs: jest.Mocked<typeof _fs> = _fs as any;
 const exec: jest.Mock<typeof _exec> = _exec as any;
-const platform = mocked(_platform);
 const env = mocked(_env);
 
 jest.mock('fs-extra');
 jest.mock('child_process');
-jest.mock('../../platform');
 jest.mock('../../util/exec/env');
 
 const config = {
@@ -72,7 +69,7 @@ describe('.updateArtifacts()', () => {
     ).toBeNull();
   });
   it('returns null if unchanged', async () => {
-    platform.getFile.mockResolvedValueOnce('Current mix.lock');
+    fs.readFile.mockResolvedValueOnce('Current mix.lock' as any);
     const execSnapshots = mockExecAll(exec);
     fs.readFile.mockResolvedValueOnce('Current mix.lock' as any);
     expect(
@@ -86,7 +83,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('returns updated mix.lock', async () => {
-    platform.getFile.mockResolvedValueOnce('Old mix.lock');
+    fs.readFile.mockResolvedValueOnce('Old mix.lock' as any);
     const execSnapshots = mockExecAll(exec);
     fs.readFile.mockResolvedValueOnce('New mix.lock' as any);
     expect(
@@ -103,7 +100,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('catches errors', async () => {
-    platform.getFile.mockResolvedValueOnce('Current mix.lock');
+    fs.readFile.mockResolvedValueOnce('Current mix.lock' as any);
     fs.outputFile.mockImplementationOnce(() => {
       throw new Error('not found');
     });
diff --git a/lib/manager/mix/artifacts.ts b/lib/manager/mix/artifacts.ts
index 610d471f09..c037f01da1 100644
--- a/lib/manager/mix/artifacts.ts
+++ b/lib/manager/mix/artifacts.ts
@@ -2,9 +2,9 @@ import fs from 'fs-extra';
 import { quote } from 'shlex';
 import upath from 'upath';
 import { logger } from '../../logger';
-import { platform } from '../../platform';
 import { exec } from '../../util/exec';
 import { BinarySource } from '../../util/exec/common';
+import { readLocalFile } from '../../util/fs';
 import { UpdateArtifact, UpdateArtifactsResult } from '../common';
 
 export async function updateArtifacts({
@@ -41,7 +41,7 @@ export async function updateArtifacts({
     ];
   }
 
-  const existingLockFileContent = await platform.getFile(lockFileName);
+  const existingLockFileContent = await readLocalFile(lockFileName, 'utf8');
   if (!existingLockFileContent) {
     logger.debug('No mix.lock found');
     return null;
diff --git a/lib/manager/pipenv/artifacts.spec.ts b/lib/manager/pipenv/artifacts.spec.ts
index 691787cbeb..a9a89b5cbc 100644
--- a/lib/manager/pipenv/artifacts.spec.ts
+++ b/lib/manager/pipenv/artifacts.spec.ts
@@ -63,7 +63,7 @@ describe('.updateArtifacts()', () => {
   });
   it('returns null if unchanged', async () => {
     pipFileLock._meta.requires.python_full_version = '3.7.6';
-    platform.getFile.mockResolvedValueOnce(JSON.stringify(pipFileLock));
+    fs.readFile.mockResolvedValueOnce(JSON.stringify(pipFileLock) as any);
     const execSnapshots = mockExecAll(exec);
     fs.readFile.mockReturnValueOnce(JSON.stringify(pipFileLock) as any);
     expect(
@@ -77,7 +77,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('handles no constraint', async () => {
-    platform.getFile.mockResolvedValueOnce('unparseable pipfile lock');
+    fs.readFile.mockResolvedValueOnce('unparseable pipfile lock' as any);
     const execSnapshots = mockExecAll(exec);
     fs.readFile.mockReturnValueOnce('unparseable pipfile lock' as any);
     expect(
@@ -91,7 +91,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('returns updated Pipfile.lock', async () => {
-    platform.getFile.mockResolvedValueOnce('current pipfile.lock');
+    fs.readFile.mockResolvedValueOnce('current pipfile.lock' as any);
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValue({
       modified: ['Pipfile.lock'],
@@ -110,7 +110,7 @@ describe('.updateArtifacts()', () => {
   it('supports docker mode', async () => {
     await setUtilConfig(dockerConfig);
     pipFileLock._meta.requires.python_version = '3.7';
-    platform.getFile.mockResolvedValueOnce(JSON.stringify(pipFileLock));
+    fs.readFile.mockResolvedValueOnce(JSON.stringify(pipFileLock) as any);
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValue({
       modified: ['Pipfile.lock'],
@@ -127,7 +127,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('catches errors', async () => {
-    platform.getFile.mockResolvedValueOnce('Current Pipfile.lock');
+    fs.readFile.mockResolvedValueOnce('Current Pipfile.lock' as any);
     fs.outputFile.mockImplementationOnce(() => {
       throw new Error('not found');
     });
@@ -141,7 +141,7 @@ describe('.updateArtifacts()', () => {
     ).toMatchSnapshot();
   });
   it('returns updated Pipenv.lock when doing lockfile maintenance', async () => {
-    platform.getFile.mockResolvedValueOnce('Current Pipfile.lock');
+    fs.readFile.mockResolvedValueOnce('Current Pipfile.lock' as any);
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValue({
       modified: ['Pipfile.lock'],
diff --git a/lib/manager/pipenv/artifacts.ts b/lib/manager/pipenv/artifacts.ts
index 67c3a80762..9e33a4dd91 100644
--- a/lib/manager/pipenv/artifacts.ts
+++ b/lib/manager/pipenv/artifacts.ts
@@ -3,6 +3,7 @@ import { join } from 'upath';
 import { logger } from '../../logger';
 import { platform } from '../../platform';
 import { ExecOptions, exec } from '../../util/exec';
+import { readLocalFile } from '../../util/fs';
 import {
   UpdateArtifact,
   UpdateArtifactsConfig,
@@ -47,7 +48,7 @@ export async function updateArtifacts({
   logger.debug('Using pipenv cache ' + cacheDir);
 
   const lockFileName = pipfileName + '.lock';
-  const existingLockFileContent = await platform.getFile(lockFileName);
+  const existingLockFileContent = await readLocalFile(lockFileName, 'utf8');
   if (!existingLockFileContent) {
     logger.debug('No Pipfile.lock found');
     return null;
diff --git a/lib/util/fs.ts b/lib/util/fs.ts
index 0bcbd47dac..1a472d6502 100644
--- a/lib/util/fs.ts
+++ b/lib/util/fs.ts
@@ -1,4 +1,4 @@
-import { outputFile, readFile, remove } from 'fs-extra';
+import * as fs from 'fs-extra';
 import { join, parse } from 'upath';
 import { RenovateConfig } from '../config/common';
 import { logger } from '../logger';
@@ -32,7 +32,7 @@ export async function readLocalFile(
 ): Promise<string | Buffer> {
   const localFileName = join(localDir, fileName);
   try {
-    const fileContent = await readFile(localFileName, encoding);
+    const fileContent = await fs.readFile(localFileName, encoding);
     return fileContent;
   } catch (err) {
     logger.trace({ err }, 'Error reading local file');
@@ -45,9 +45,9 @@ export async function writeLocalFile(
   fileContent: string
 ): Promise<void> {
   const localFileName = join(localDir, fileName);
-  await outputFile(localFileName, fileContent);
+  await fs.outputFile(localFileName, fileContent);
 }
 
 export async function deleteLocalFile(fileName: string): Promise<void> {
-  await remove(fileName);
+  await fs.remove(fileName);
 }
-- 
GitLab