From 5145c044ffcc89b88efe2eb57e8c1a823e9106f8 Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Sun, 19 Apr 2020 11:41:21 +0200
Subject: [PATCH] refactor: manager extract readLocalFile instead of
 platform.getFile

---
 lib/manager/bundler/extract.spec.ts           | 18 ++++++-----
 lib/manager/bundler/extract.ts                |  4 +--
 lib/manager/composer/extract.spec.ts          | 10 +++---
 lib/manager/composer/extract.ts               |  4 +--
 lib/manager/gradle/index.spec.ts              |  9 +++---
 lib/manager/gradle/index.ts                   |  4 +--
 lib/manager/helm-requirements/extract.spec.ts | 21 ++++++------
 lib/manager/helm-requirements/extract.ts      |  8 ++---
 lib/manager/npm/extract/index.spec.ts         | 23 ++++++-------
 lib/manager/npm/extract/index.ts              | 32 +++++++++----------
 lib/manager/npm/extract/npm.spec.ts           | 12 ++++---
 lib/manager/npm/extract/npm.ts                |  4 +--
 lib/manager/npm/extract/yarn.spec.ts          | 10 +++---
 lib/manager/npm/extract/yarn.ts               |  4 +--
 .../repository/extract/manager-files.spec.ts  |  9 ++++--
 .../repository/extract/manager-files.ts       |  3 +-
 16 files changed, 93 insertions(+), 82 deletions(-)

diff --git a/lib/manager/bundler/extract.spec.ts b/lib/manager/bundler/extract.spec.ts
index b5f8ecc3b4..9f66f3f7d6 100644
--- a/lib/manager/bundler/extract.spec.ts
+++ b/lib/manager/bundler/extract.spec.ts
@@ -1,9 +1,11 @@
 import { readFileSync } from 'fs';
 import { extractPackageFile } from './extract';
-import { platform as _platform } from '../../platform';
 import { isValid } from '../../versioning/ruby';
+import * as _fs from '../../util/fs';
 
-const platform: any = _platform;
+jest.mock('../../util/fs');
+
+const fs: any = _fs;
 
 const railsGemfile = readFileSync(
   'lib/manager/bundler/__fixtures__/Gemfile.rails',
@@ -72,7 +74,7 @@ describe('lib/manager/bundler/extract', () => {
       expect(await extractPackageFile('nothing here', 'Gemfile')).toBeNull();
     });
     it('parses rails Gemfile', async () => {
-      platform.getFile.mockReturnValueOnce(railsGemfileLock);
+      fs.readLocalFile.mockReturnValueOnce(railsGemfileLock);
       const res = await extractPackageFile(railsGemfile, 'Gemfile');
       expect(res).toMatchSnapshot();
       // couple of dependency of ruby rails are not present in the lock file. Filter out those before processing
@@ -96,7 +98,7 @@ describe('lib/manager/bundler/extract', () => {
       validateGems(sourceGroupGemfile, res);
     });
     it('parse webpacker Gemfile', async () => {
-      platform.getFile.mockReturnValueOnce(webPackerGemfileLock);
+      fs.readLocalFile.mockReturnValueOnce(webPackerGemfileLock);
       const res = await extractPackageFile(webPackerGemfile, 'Gemfile');
       expect(res).toMatchSnapshot();
       expect(
@@ -110,7 +112,7 @@ describe('lib/manager/bundler/extract', () => {
       validateGems(webPackerGemfile, res);
     });
     it('parse mastodon Gemfile', async () => {
-      platform.getFile.mockReturnValueOnce(mastodonGemfileLock);
+      fs.readLocalFile.mockReturnValueOnce(mastodonGemfileLock);
       const res = await extractPackageFile(mastodonGemfile, 'Gemfile');
       expect(res).toMatchSnapshot();
       expect(
@@ -128,7 +130,7 @@ describe('lib/manager/bundler/extract', () => {
       validateGems(mastodonGemfile, res);
     });
     it('parse Ruby CI Gemfile', async () => {
-      platform.getFile.mockReturnValueOnce(rubyCIGemfileLock);
+      fs.readLocalFile.mockReturnValueOnce(rubyCIGemfileLock);
       const res = await extractPackageFile(rubyCIGemfile, 'Gemfile');
       expect(res).toMatchSnapshot();
       expect(
@@ -143,7 +145,7 @@ describe('lib/manager/bundler/extract', () => {
     });
   });
   it('parse Gitlab Foss Gemfile', async () => {
-    platform.getFile.mockReturnValueOnce(gitlabFossGemfileLock);
+    fs.readLocalFile.mockReturnValueOnce(gitlabFossGemfileLock);
     const res = await extractPackageFile(gitlabFossGemfile, 'Gemfile');
     expect(res).toMatchSnapshot();
     expect(
@@ -158,7 +160,7 @@ describe('lib/manager/bundler/extract', () => {
   });
 
   it('parse source blocks with spaces in Gemfile', async () => {
-    platform.getFile.mockReturnValueOnce(sourceBlockWithNewLinesGemfileLock);
+    fs.readLocalFile.mockReturnValueOnce(sourceBlockWithNewLinesGemfileLock);
     const res = await extractPackageFile(
       sourceBlockWithNewLinesGemfile,
       'Gemfile'
diff --git a/lib/manager/bundler/extract.ts b/lib/manager/bundler/extract.ts
index b486c73a8a..225def6ef0 100644
--- a/lib/manager/bundler/extract.ts
+++ b/lib/manager/bundler/extract.ts
@@ -1,10 +1,10 @@
 import { logger } from '../../logger';
 import { PackageFile, PackageDependency } from '../common';
-import { platform } from '../../platform';
 import { regEx } from '../../util/regex';
 import { extractLockFileEntries } from './locked-version';
 import * as datasourceRubygems from '../../datasource/rubygems';
 import { SkipReason } from '../../types';
+import { readLocalFile } from '../../util/fs';
 
 export async function extractPackageFile(
   content: string,
@@ -186,7 +186,7 @@ export async function extractPackageFile(
 
   if (fileName) {
     const gemfileLock = fileName + '.lock';
-    const lockContent = await platform.getFile(gemfileLock);
+    const lockContent = await readLocalFile(gemfileLock, 'utf8');
     if (lockContent) {
       logger.debug({ packageFile: fileName }, 'Found Gemfile.lock file');
       const lockedEntries = extractLockFileEntries(lockContent);
diff --git a/lib/manager/composer/extract.spec.ts b/lib/manager/composer/extract.spec.ts
index a05394e49d..c1b8884b25 100644
--- a/lib/manager/composer/extract.spec.ts
+++ b/lib/manager/composer/extract.spec.ts
@@ -1,8 +1,10 @@
 import { readFileSync } from 'fs';
 import { extractPackageFile } from './extract';
-import { platform as _platform, Platform } from '../../platform';
+import * as _fs from '../../util/fs';
 
-const platform: jest.Mocked<Platform> = _platform as any;
+jest.mock('../../util/fs');
+
+const fs: any = _fs;
 
 const requirements1 = readFileSync(
   'lib/manager/composer/__fixtures__/composer1.json',
@@ -61,13 +63,13 @@ describe('lib/manager/composer/extract', () => {
       expect(res.registryUrls).toHaveLength(2);
     });
     it('extracts object repositories and registryUrls with lock file', async () => {
-      platform.getFile.mockResolvedValue(requirements5Lock);
+      fs.readLocalFile.mockResolvedValue(requirements5Lock);
       const res = await extractPackageFile(requirements5, packageFile);
       expect(res).toMatchSnapshot();
       expect(res.registryUrls).toHaveLength(2);
     });
     it('extracts dependencies with lock file', async () => {
-      platform.getFile.mockResolvedValue('some content');
+      fs.readLocalFile.mockResolvedValue('some content');
       const res = await extractPackageFile(requirements1, packageFile);
       expect(res).toMatchSnapshot();
     });
diff --git a/lib/manager/composer/extract.ts b/lib/manager/composer/extract.ts
index a75ca4ac7a..8ca405e7ae 100644
--- a/lib/manager/composer/extract.ts
+++ b/lib/manager/composer/extract.ts
@@ -2,10 +2,10 @@ import is from '@sindresorhus/is';
 import { logger } from '../../logger';
 import { api as semverComposer } from '../../versioning/composer';
 import { PackageFile, PackageDependency } from '../common';
-import { platform } from '../../platform';
 import { SkipReason } from '../../types';
 import * as datasourceGitTags from '../../datasource/git-tags';
 import * as datasourcePackagist from '../../datasource/packagist';
+import { readLocalFile } from '../../util/fs';
 
 interface Repo {
   name?: string;
@@ -102,7 +102,7 @@ export async function extractPackageFile(
 
   // handle lockfile
   const lockfilePath = fileName.replace(/\.json$/, '.lock');
-  const lockContents = await platform.getFile(lockfilePath);
+  const lockContents = await readLocalFile(lockfilePath, 'utf8');
   let lockParsed;
   if (lockContents) {
     logger.debug({ packageFile: fileName }, 'Found composer lock file');
diff --git a/lib/manager/gradle/index.spec.ts b/lib/manager/gradle/index.spec.ts
index 577cff377e..2bea9a27d8 100644
--- a/lib/manager/gradle/index.spec.ts
+++ b/lib/manager/gradle/index.spec.ts
@@ -4,7 +4,7 @@ import * as upath from 'upath';
 import { exec as _exec } from 'child_process';
 import * as _os from 'os';
 import tmp, { DirectoryResult } from 'tmp-promise';
-import { platform as _platform } from '../../platform';
+import * as _utilfs from '../../util/fs';
 import { envMock, mockExecAll } from '../../../test/execUtil';
 import * as _env from '../../util/exec/env';
 import { BinarySource } from '../../util/exec/common';
@@ -45,17 +45,16 @@ async function setupMocks() {
 
   jest.mock('child_process');
   jest.mock('../../util/exec/env');
-  jest.mock('../../platform');
+  jest.mock('../../util/fs');
   jest.mock('os');
 
   const os: jest.Mocked<typeof _os> = require('os');
-  const platform: jest.Mocked<typeof _platform> = require('../../platform')
-    .platform;
+  const utilfs: jest.Mocked<typeof _utilfs> = require('../../util/fs');
   const env: jest.Mocked<typeof _env> = require('../../util/exec/env');
   const exec: jest.Mock<typeof _exec> = require('child_process').exec;
   const util: jest.Mocked<typeof _util> = require('../../util');
 
-  platform.getFile.mockResolvedValue('some content');
+  utilfs.readLocalFile.mockResolvedValue('some content');
   env.getChildProcessEnv.mockReturnValue(envMock.basic);
   await util.setUtilConfig(baseConfig);
 
diff --git a/lib/manager/gradle/index.ts b/lib/manager/gradle/index.ts
index f693d1a05d..42621f6947 100644
--- a/lib/manager/gradle/index.ts
+++ b/lib/manager/gradle/index.ts
@@ -11,7 +11,7 @@ import {
   UpdateDependencyConfig,
   Upgrade,
 } from '../common';
-import { platform } from '../../platform';
+import { readLocalFile } from '../../util/fs';
 import { LANGUAGE_JAVA } from '../../constants/languages';
 import * as datasourceMaven from '../../datasource/maven';
 import { DatasourceError } from '../../datasource';
@@ -161,7 +161,7 @@ export async function extractAllPackageFiles(
 
   const gradleFiles: PackageFile[] = [];
   for (const packageFile of packageFiles) {
-    const content = await platform.getFile(packageFile);
+    const content = await readLocalFile(packageFile, 'utf8');
     if (content) {
       gradleFiles.push({
         packageFile,
diff --git a/lib/manager/helm-requirements/extract.spec.ts b/lib/manager/helm-requirements/extract.spec.ts
index cd9ccef805..8e51f8c719 100644
--- a/lib/manager/helm-requirements/extract.spec.ts
+++ b/lib/manager/helm-requirements/extract.spec.ts
@@ -1,15 +1,16 @@
 import { extractPackageFile } from './extract';
-import { platform as _platform } from '../../platform';
+import * as _fs from '../../util/fs';
 
-const platform: any = _platform;
+const fs: any = _fs;
 
 describe('lib/manager/helm-requirements/extract', () => {
   describe('extractPackageFile()', () => {
     beforeEach(() => {
       jest.resetAllMocks();
+      fs.readLocalFile = jest.fn();
     });
     it('skips invalid registry urls', async () => {
-      platform.getFile.mockReturnValueOnce(`
+      fs.readLocalFile.mockResolvedValueOnce(`
       apiVersion: v1
       appVersion: "1.0"
       description: A Helm chart for Kubernetes
@@ -38,7 +39,7 @@ describe('lib/manager/helm-requirements/extract', () => {
       expect(result.deps.every((dep) => dep.skipReason));
     });
     it('parses simple requirements.yaml correctly', async () => {
-      platform.getFile.mockReturnValueOnce(`
+      fs.readLocalFile.mockResolvedValueOnce(`
       apiVersion: v1
       appVersion: "1.0"
       description: A Helm chart for Kubernetes
@@ -64,7 +65,7 @@ describe('lib/manager/helm-requirements/extract', () => {
       expect(result).toMatchSnapshot();
     });
     it('parses simple requirements.yaml but skips if necessary fields missing', async () => {
-      platform.getFile.mockReturnValueOnce(`
+      fs.readLocalFile.mockResolvedValueOnce(`
       apiVersion: v1
       appVersion: "1.0"
       description: A Helm chart for Kubernetes
@@ -79,7 +80,7 @@ describe('lib/manager/helm-requirements/extract', () => {
       expect(result).toBeNull();
     });
     it('resolves aliased registry urls', async () => {
-      platform.getFile.mockReturnValueOnce(`
+      fs.readLocalFile.mockResolvedValueOnce(`
       apiVersion: v1
       appVersion: "1.0"
       description: A Helm chart for Kubernetes
@@ -103,7 +104,7 @@ describe('lib/manager/helm-requirements/extract', () => {
       expect(result.deps.every((dep) => dep.skipReason));
     });
     it("doesn't fail if Chart.yaml is invalid", async () => {
-      platform.getFile.mockReturnValueOnce(`
+      fs.readLocalFile.mockResolvedValueOnce(`
       Invalid Chart.yaml content.
       arr:
       [
@@ -126,7 +127,7 @@ describe('lib/manager/helm-requirements/extract', () => {
       expect(result).toBeNull();
     });
     it('skips local dependencies', async () => {
-      platform.getFile.mockReturnValueOnce(`
+      fs.readLocalFile.mockResolvedValueOnce(`
       apiVersion: v1
       appVersion: "1.0"
       description: A Helm chart for Kubernetes
@@ -152,7 +153,7 @@ describe('lib/manager/helm-requirements/extract', () => {
       expect(result).toMatchSnapshot();
     });
     it('returns null if no dependencies', async () => {
-      platform.getFile.mockReturnValueOnce(`
+      fs.readLocalFile.mockResolvedValueOnce(`
       apiVersion: v1
       appVersion: "1.0"
       description: A Helm chart for Kubernetes
@@ -171,7 +172,7 @@ describe('lib/manager/helm-requirements/extract', () => {
       expect(result).toBeNull();
     });
     it('returns null if requirements.yaml is invalid', async () => {
-      platform.getFile.mockReturnValueOnce(`
+      fs.readLocalFile.mockResolvedValueOnce(`
       apiVersion: v1
       appVersion: "1.0"
       description: A Helm chart for Kubernetes
diff --git a/lib/manager/helm-requirements/extract.ts b/lib/manager/helm-requirements/extract.ts
index 89122f3ceb..b0e2ee4d9b 100644
--- a/lib/manager/helm-requirements/extract.ts
+++ b/lib/manager/helm-requirements/extract.ts
@@ -1,11 +1,10 @@
 import is from '@sindresorhus/is';
-import upath from 'upath';
 import yaml from 'js-yaml';
 import { SkipReason } from '../../types';
 import { logger } from '../../logger';
 import { PackageFile, PackageDependency, ExtractConfig } from '../common';
-import { platform } from '../../platform';
 import * as datasourceHelm from '../../datasource/helm';
+import { readLocalFile, getSiblingFileName } from '../../util/fs';
 
 export async function extractPackageFile(
   content: string,
@@ -13,9 +12,8 @@ export async function extractPackageFile(
   config: ExtractConfig
 ): Promise<PackageFile> {
   try {
-    const baseDir = upath.parse(fileName).dir;
-    const chartFileName = upath.join(baseDir, 'Chart.yaml');
-    const chartContents = await platform.getFile(chartFileName);
+    const chartFileName = getSiblingFileName(fileName, 'Chart.yaml');
+    const chartContents = await readLocalFile(chartFileName, 'utf8');
     if (!chartContents) {
       logger.debug({ fileName }, 'Failed to find helm Chart.yaml');
       return null;
diff --git a/lib/manager/npm/extract/index.spec.ts b/lib/manager/npm/extract/index.spec.ts
index ff35d47658..75c7e96d27 100644
--- a/lib/manager/npm/extract/index.spec.ts
+++ b/lib/manager/npm/extract/index.spec.ts
@@ -2,11 +2,12 @@ import fs from 'fs';
 import path from 'path';
 import * as npmExtract from '.';
 import { getConfig } from '../../../config/defaults';
-import { platform as _platform } from '../../../../test/util';
+import * as _fs from '../../../util/fs';
+
+const utilfs: any = _fs;
 
 // TODO: fix types
 const defaultConfig = getConfig();
-const platform: any = _platform;
 
 function readFixture(fixture: string) {
   return fs.readFileSync(
@@ -24,7 +25,7 @@ const invalidNameContent = readFixture('invalid-name.json');
 describe('manager/npm/extract', () => {
   describe('.extractPackageFile()', () => {
     beforeEach(() => {
-      platform.getFile.mockReturnValue(null);
+      utilfs.readLocalFile = jest.fn(() => null);
     });
     it('returns null if cannot parse', async () => {
       const res = await npmExtract.extractPackageFile(
@@ -84,7 +85,7 @@ describe('manager/npm/extract', () => {
       expect(res).toMatchSnapshot();
     });
     it('finds a lock file', async () => {
-      platform.getFile = jest.fn((fileName) => {
+      utilfs.readLocalFile = jest.fn((fileName) => {
         if (fileName === 'yarn.lock') {
           return '# yarn.lock';
         }
@@ -98,7 +99,7 @@ describe('manager/npm/extract', () => {
       expect(res).toMatchSnapshot();
     });
     it('finds and filters .npmrc', async () => {
-      platform.getFile = jest.fn((fileName) => {
+      utilfs.readLocalFile = jest.fn((fileName) => {
         if (fileName === '.npmrc') {
           return 'save-exact = true\npackage-lock = false\n';
         }
@@ -112,7 +113,7 @@ describe('manager/npm/extract', () => {
       expect(res.npmrc).toBeDefined();
     });
     it('finds and discards .npmrc', async () => {
-      platform.getFile = jest.fn((fileName) => {
+      utilfs.readLocalFile = jest.fn((fileName) => {
         if (fileName === '.npmrc') {
           // eslint-disable-next-line
           return '//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}\n';
@@ -127,7 +128,7 @@ describe('manager/npm/extract', () => {
       expect(res.npmrc).toBeUndefined();
     });
     it('finds lerna', async () => {
-      platform.getFile = jest.fn((fileName) => {
+      utilfs.readLocalFile = jest.fn((fileName) => {
         if (fileName === 'lerna.json') {
           return '{}';
         }
@@ -141,7 +142,7 @@ describe('manager/npm/extract', () => {
       expect(res).toMatchSnapshot();
     });
     it('finds "npmClient":"npm" in lerna.json', async () => {
-      platform.getFile = jest.fn((fileName) => {
+      utilfs.readLocalFile = jest.fn((fileName) => {
         if (fileName === 'lerna.json') {
           return '{ "npmClient": "npm" }';
         }
@@ -155,7 +156,7 @@ describe('manager/npm/extract', () => {
       expect(res).toMatchSnapshot();
     });
     it('finds "npmClient":"yarn" in lerna.json', async () => {
-      platform.getFile = jest.fn((fileName) => {
+      utilfs.readLocalFile = jest.fn((fileName) => {
         if (fileName === 'lerna.json') {
           return '{ "npmClient": "yarn" }';
         }
@@ -169,7 +170,7 @@ describe('manager/npm/extract', () => {
       expect(res).toMatchSnapshot();
     });
     it('finds simple yarn workspaces', async () => {
-      platform.getFile = jest.fn((fileName) => {
+      utilfs.readLocalFile = jest.fn((fileName) => {
         if (fileName === 'lerna.json') {
           return '{}';
         }
@@ -183,7 +184,7 @@ describe('manager/npm/extract', () => {
       expect(res).toMatchSnapshot();
     });
     it('finds complex yarn workspaces', async () => {
-      platform.getFile = jest.fn((fileName) => {
+      utilfs.readLocalFile = jest.fn((fileName) => {
         if (fileName === 'lerna.json') {
           return '{}';
         }
diff --git a/lib/manager/npm/extract/index.ts b/lib/manager/npm/extract/index.ts
index 9b701e2ee8..892af5efd4 100644
--- a/lib/manager/npm/extract/index.ts
+++ b/lib/manager/npm/extract/index.ts
@@ -1,6 +1,4 @@
-import { remove } from 'fs-extra';
 import { dirname } from 'path';
-import { join } from 'upath';
 import validateNpmPackageName from 'validate-npm-package-name';
 import is from '@sindresorhus/is';
 import { logger } from '../../../logger';
@@ -16,11 +14,15 @@ import {
   NpmLockFiles,
 } from '../../common';
 import { NpmPackage, NpmPackageDependeny } from './common';
-import { platform } from '../../../platform';
 import { CONFIG_VALIDATION } from '../../../constants/error-messages';
 import * as nodeVersioning from '../../../versioning/node';
 import * as datasourceNpm from '../../../datasource/npm';
 import * as datasourceGithubTags from '../../../datasource/github-tags';
+import {
+  readLocalFile,
+  getSiblingFileName,
+  deleteLocalFile,
+} from '../../../util/fs';
 
 function parseDepName(depType: string, key: string): string {
   if (depType !== 'resolutions') {
@@ -81,8 +83,8 @@ export async function extractPackageFile(
   };
 
   for (const [key, val] of Object.entries(lockFiles)) {
-    const filePath = join(dirname(fileName), val);
-    if (await platform.getFile(filePath)) {
+    const filePath = getSiblingFileName(fileName, val);
+    if (await readLocalFile(filePath, 'utf8')) {
       lockFiles[key] = filePath;
     } else {
       lockFiles[key] = undefined;
@@ -94,13 +96,12 @@ export async function extractPackageFile(
 
   let npmrc: string;
   let ignoreNpmrcFile: boolean;
-  const npmrcFileName = join(dirname(fileName), '.npmrc');
-  const npmrcFileNameLocal = join(config.localDir || '', npmrcFileName);
+  const npmrcFileName = getSiblingFileName(fileName, '.npmrc');
   // istanbul ignore if
   if (config.ignoreNpmrcFile) {
-    await remove(npmrcFileNameLocal);
+    await deleteLocalFile(npmrcFileName);
   } else {
-    npmrc = await platform.getFile(npmrcFileName);
+    npmrc = await readLocalFile(npmrcFileName, 'utf8');
     if (npmrc && npmrc.includes('package-lock')) {
       logger.debug('Stripping package-lock setting from npmrc');
       npmrc = npmrc.replace(/(^|\n)package-lock.*?(\n|$)/g, '\n');
@@ -110,14 +111,14 @@ export async function extractPackageFile(
         logger.debug('Discarding .npmrc file with variables');
         ignoreNpmrcFile = true;
         npmrc = undefined;
-        await remove(npmrcFileNameLocal);
+        await deleteLocalFile(npmrcFileName);
       }
     } else {
       npmrc = undefined;
     }
   }
-  const yarnrc =
-    (await platform.getFile(join(dirname(fileName), '.yarnrc'))) || undefined;
+  const yarnrcFileName = getSiblingFileName(fileName, '.yarnrc');
+  const yarnrc = (await readLocalFile(yarnrcFileName, 'utf8')) || undefined;
 
   let lernaDir: string;
   let lernaPackages: string[];
@@ -125,9 +126,8 @@ export async function extractPackageFile(
   let hasFileRefs = false;
   let lernaJson: { packages: string[]; npmClient: string };
   try {
-    lernaJson = JSON.parse(
-      await platform.getFile(join(dirname(fileName), 'lerna.json'))
-    );
+    const lernaJsonFileName = getSiblingFileName(fileName, 'lerna.json');
+    lernaJson = JSON.parse(await readLocalFile(lernaJsonFileName, 'utf8'));
   } catch (err) /* istanbul ignore next */ {
     logger.warn({ err }, 'Could not parse lerna.json');
   }
@@ -365,7 +365,7 @@ export async function extractAllPackageFiles(
 ): Promise<PackageFile[]> {
   const npmFiles: PackageFile[] = [];
   for (const packageFile of packageFiles) {
-    const content = await platform.getFile(packageFile);
+    const content = await readLocalFile(packageFile, 'utf8');
     if (content) {
       const deps = await extractPackageFile(content, packageFile, config);
       if (deps) {
diff --git a/lib/manager/npm/extract/npm.spec.ts b/lib/manager/npm/extract/npm.spec.ts
index 463bc74e0b..ac83637edf 100644
--- a/lib/manager/npm/extract/npm.spec.ts
+++ b/lib/manager/npm/extract/npm.spec.ts
@@ -1,13 +1,15 @@
 import { readFileSync } from 'fs';
 import { getNpmLock } from './npm';
-import { platform as _platform } from '../../../platform';
+import * as _fs from '../../../util/fs';
 
-const platform: any = _platform;
+jest.mock('../../../util/fs');
+
+const fs: any = _fs;
 
 describe('manager/npm/extract/npm', () => {
   describe('.getNpmLock()', () => {
     it('returns empty if failed to parse', async () => {
-      platform.getFile.mockReturnValueOnce('abcd');
+      fs.readLocalFile.mockReturnValueOnce('abcd');
       const res = await getNpmLock('package.json');
       expect(Object.keys(res)).toHaveLength(0);
     });
@@ -15,13 +17,13 @@ describe('manager/npm/extract/npm', () => {
       const plocktest1Lock = readFileSync(
         'lib/manager/npm/__fixtures__/plocktest1/package-lock.json'
       );
-      platform.getFile.mockReturnValueOnce(plocktest1Lock);
+      fs.readLocalFile.mockReturnValueOnce(plocktest1Lock);
       const res = await getNpmLock('package.json');
       expect(res).toMatchSnapshot();
       expect(Object.keys(res)).toHaveLength(7);
     });
     it('returns empty if no deps', async () => {
-      platform.getFile.mockResolvedValueOnce('{}');
+      fs.readLocalFile.mockResolvedValueOnce('{}');
       const res = await getNpmLock('package.json');
       expect(Object.keys(res)).toHaveLength(0);
     });
diff --git a/lib/manager/npm/extract/npm.ts b/lib/manager/npm/extract/npm.ts
index e3c4f31ae3..e3df86163f 100644
--- a/lib/manager/npm/extract/npm.ts
+++ b/lib/manager/npm/extract/npm.ts
@@ -1,11 +1,11 @@
 import { logger } from '../../../logger';
 import { LockFileEntry } from './common';
-import { platform } from '../../../platform';
+import { readLocalFile } from '../../../util/fs';
 
 export async function getNpmLock(
   filePath: string
 ): Promise<Record<string, string>> {
-  const lockRaw = await platform.getFile(filePath);
+  const lockRaw = await readLocalFile(filePath, 'utf8');
   try {
     const lockParsed = JSON.parse(lockRaw);
     const lockFile: Record<string, string> = {};
diff --git a/lib/manager/npm/extract/yarn.spec.ts b/lib/manager/npm/extract/yarn.spec.ts
index 01e39e4e7f..1da2d88571 100644
--- a/lib/manager/npm/extract/yarn.spec.ts
+++ b/lib/manager/npm/extract/yarn.spec.ts
@@ -1,13 +1,15 @@
 import { readFileSync } from 'fs';
 import { getYarnLock } from './yarn';
-import { platform as _platform } from '../../../platform';
+import * as _fs from '../../../util/fs';
 
-const platform: any = _platform;
+jest.mock('../../../util/fs');
+
+const fs: any = _fs;
 
 describe('manager/npm/extract/yarn', () => {
   describe('.getYarnLock()', () => {
     it('returns empty if exception parsing', async () => {
-      platform.getFile.mockReturnValueOnce('abcd');
+      fs.readLocalFile.mockReturnValueOnce('abcd');
       const res = await getYarnLock('package.json');
       expect(Object.keys(res)).toHaveLength(0);
     });
@@ -16,7 +18,7 @@ describe('manager/npm/extract/yarn', () => {
         'lib/manager/npm/__fixtures__/plocktest1/yarn.lock',
         'utf8'
       );
-      platform.getFile.mockReturnValueOnce(plocktest1Lock);
+      fs.readLocalFile.mockReturnValueOnce(plocktest1Lock);
       const res = await getYarnLock('package.json');
       expect(res).toMatchSnapshot();
       expect(Object.keys(res)).toHaveLength(7);
diff --git a/lib/manager/npm/extract/yarn.ts b/lib/manager/npm/extract/yarn.ts
index 839dec733f..075f1cfeef 100644
--- a/lib/manager/npm/extract/yarn.ts
+++ b/lib/manager/npm/extract/yarn.ts
@@ -1,14 +1,14 @@
 import { parse } from '@yarnpkg/lockfile';
 import { logger } from '../../../logger';
 import { LockFileEntry } from './common';
-import { platform } from '../../../platform';
+import { readLocalFile } from '../../../util/fs';
 
 export type YarnLock = Record<string, string> & {
   '@renovate_yarn_integrity'?: boolean;
 };
 
 export async function getYarnLock(filePath: string): Promise<YarnLock> {
-  const yarnLockRaw = await platform.getFile(filePath);
+  const yarnLockRaw = await readLocalFile(filePath, 'utf8');
   try {
     const yarnLockParsed = parse(yarnLockRaw);
     // istanbul ignore if
diff --git a/lib/workers/repository/extract/manager-files.spec.ts b/lib/workers/repository/extract/manager-files.spec.ts
index 39559c944e..c10d9e178b 100644
--- a/lib/workers/repository/extract/manager-files.spec.ts
+++ b/lib/workers/repository/extract/manager-files.spec.ts
@@ -1,12 +1,15 @@
 import { getManagerPackageFiles } from './manager-files';
 import * as _fileMatch from './file-match';
 import * as _html from '../../../manager/html';
-import { mocked, platform, getConfig } from '../../../../test/util';
+import { mocked, getConfig } from '../../../../test/util';
 import { RenovateConfig } from '../../../config';
+import * as _fs from '../../../util/fs';
 
 jest.mock('./file-match');
 jest.mock('../../../manager/html');
+jest.mock('../../../util/fs');
 
+const fs: any = _fs;
 const fileMatch = mocked(_fileMatch);
 const html = mocked(_html);
 
@@ -37,7 +40,7 @@ describe('workers/repository/extract/manager-files', () => {
     it('returns files with extractPackageFile', async () => {
       const managerConfig = { manager: 'html', enabled: true };
       fileMatch.getMatchingFiles.mockReturnValue(['Dockerfile']);
-      platform.getFile.mockResolvedValue('some content');
+      fs.readLocalFile.mockResolvedValueOnce('some content');
       html.extractPackageFile = jest.fn(() => ({
         deps: [{}, { replaceString: 'abc' }],
       })) as never;
@@ -47,7 +50,7 @@ describe('workers/repository/extract/manager-files', () => {
     it('returns files with extractAllPackageFiles', async () => {
       const managerConfig = { manager: 'npm', enabled: true };
       fileMatch.getMatchingFiles.mockReturnValue(['package.json']);
-      platform.getFile.mockResolvedValueOnce(
+      fs.readLocalFile.mockResolvedValueOnce(
         '{"dependencies":{"chalk":"2.0.0"}}'
       );
       const res = await getManagerPackageFiles(managerConfig);
diff --git a/lib/workers/repository/extract/manager-files.ts b/lib/workers/repository/extract/manager-files.ts
index e9a7c0c1c6..b9f53c4125 100644
--- a/lib/workers/repository/extract/manager-files.ts
+++ b/lib/workers/repository/extract/manager-files.ts
@@ -12,6 +12,7 @@ import {
   getMatchingFiles,
 } from './file-match';
 import { PackageFile } from '../../../manager/common';
+import { readLocalFile } from '../../../util/fs';
 
 export async function getManagerPackageFiles(config): Promise<PackageFile[]> {
   const { manager, enabled, includePaths, ignorePaths } = config;
@@ -52,7 +53,7 @@ export async function getManagerPackageFiles(config): Promise<PackageFile[]> {
   }
   const packageFiles = [];
   for (const packageFile of matchedFiles) {
-    const content = await platform.getFile(packageFile);
+    const content = await readLocalFile(packageFile, 'utf8');
     if (content) {
       const res = await extractPackageFile(
         manager,
-- 
GitLab