From 73df75d0c028cebea01c69756f24bd8fe5016b0e Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Wed, 5 Sep 2018 21:51:39 +0200
Subject: [PATCH] feat(gitfs): reuse cloned git directory

Closes #2430
---
 lib/platform/git/storage.js       | 49 +++++++++++++++++++++----------
 lib/platform/github/index.js      |  1 +
 test/platform/git/storage.spec.js |  2 ++
 3 files changed, 37 insertions(+), 15 deletions(-)

diff --git a/lib/platform/git/storage.js b/lib/platform/git/storage.js
index 7383871c03..fedc14a54d 100644
--- a/lib/platform/git/storage.js
+++ b/lib/platform/git/storage.js
@@ -1,6 +1,7 @@
 const fs = require('fs-extra');
 const { join } = require('path');
-const tmp = require('tmp-promise');
+const os = require('os');
+const path = require('path');
 const Git = require('simple-git/promise');
 const convertHrtime = require('convert-hrtime');
 
@@ -32,14 +33,37 @@ class Storage {
       cleanRepo();
       logger.info('Initialising git repository');
       config = { ...args };
-      repoDir = await tmp.dir({ unsafeCleanup: true });
-      git = Git(repoDir.path).silent(true);
-      const cloneStart = process.hrtime();
-      await git.clone(config.url, '.', ['--depth=2', '--no-single-branch']);
-      const cloneSeconds = Math.round(
-        convertHrtime(process.hrtime(cloneStart)).seconds
+      repoDir = path.join(
+        process.env.RENOVATE_TMPDIR || os.tmpdir(),
+        config.platform,
+        config.repository
       );
-      logger.info({ cloneSeconds }, 'git clone completed');
+      let clone = true;
+      // istanbul ignore if
+      if (await fs.exists(repoDir)) {
+        try {
+          git = Git(repoDir).silent(true);
+          const fetchStart = process.hrtime();
+          await git.fetch(config.url, ['--depth=2', '--no-single-branch']);
+          const fetchSeconds = Math.round(
+            convertHrtime(process.hrtime(fetchStart)).seconds
+          );
+          logger.info({ fetchSeconds }, 'git fetch completed');
+          clone = false;
+        } catch (err) {
+          logger.error({ err }, 'git fetch error');
+        }
+      }
+      if (clone) {
+        await fs.emptyDir(repoDir);
+        git = Git(repoDir).silent(true);
+        const cloneStart = process.hrtime();
+        await git.clone(config.url, '.', ['--depth=2', '--no-single-branch']);
+        const cloneSeconds = Math.round(
+          convertHrtime(process.hrtime(cloneStart)).seconds
+        );
+        logger.info({ cloneSeconds }, 'git clone completed');
+      }
 
       if (config.gitAuthor) {
         await git.raw(['config', 'user.name', config.gitAuthor.name]);
@@ -183,7 +207,7 @@ class Storage {
       await git.checkout(['-B', branchName, 'origin/' + parentBranch]);
       for (const file of files) {
         await fs.writeFile(
-          join(repoDir.path, file.name),
+          join(repoDir, file.name),
           Buffer.from(file.contents)
         );
       }
@@ -192,12 +216,7 @@ class Storage {
       await git.push(['origin', branchName, '--force']);
     }
 
-    function cleanRepo() {
-      if (repoDir) {
-        repoDir.cleanup();
-        repoDir = null;
-      }
-    }
+    function cleanRepo() {}
   }
 }
 
diff --git a/lib/platform/github/index.js b/lib/platform/github/index.js
index 1afbc16352..435b5d8a52 100644
--- a/lib/platform/github/index.js
+++ b/lib/platform/github/index.js
@@ -108,6 +108,7 @@ async function initRepo({
   logger.debug('Resetting platform config');
   // config is used by the platform api itself, not necessary for the app layer to know
   cleanRepo();
+  config.platform = 'github';
   config.repository = repository;
   [config.repositoryOwner, config.repositoryName] = repository.split('/');
   if (gitAuthor) {
diff --git a/test/platform/git/storage.spec.js b/test/platform/git/storage.spec.js
index f32013fd51..8a49b87142 100644
--- a/test/platform/git/storage.spec.js
+++ b/test/platform/git/storage.spec.js
@@ -41,6 +41,8 @@ describe('platform/git/storage', () => {
     const repo = Git(origin.path);
     await repo.clone(base.path, '.', ['--bare']);
     await git.initRepo({
+      platform: 'github',
+      repository: 'owner/repo-name',
       url: origin.path,
       gitAuthor: {
         name: 'test',
-- 
GitLab