From 36b9c4a960962757e58c03c78a9590f6d6dc7c7c Mon Sep 17 00:00:00 2001
From: Jamie Magee <JamieMagee@users.noreply.github.com>
Date: Fri, 4 Oct 2019 09:10:11 +0200
Subject: [PATCH] fix(storage): defer clone of submodules (#4550)

---
 lib/platform/git/storage.ts       | 41 +++++++++++++++++++------------
 test/platform/git/storage.spec.ts | 26 +++++++++++++++++++-
 2 files changed, 50 insertions(+), 17 deletions(-)

diff --git a/lib/platform/git/storage.ts b/lib/platform/git/storage.ts
index 77d4895e88..2ccd337524 100644
--- a/lib/platform/git/storage.ts
+++ b/lib/platform/git/storage.ts
@@ -110,10 +110,7 @@ export class Storage {
       const cloneStart = process.hrtime();
       try {
         // clone only the default branch
-        await this._git.clone(config.url, '.', [
-          '--depth=2',
-          '--recurse-submodules',
-        ]);
+        await this._git.clone(config.url, '.', ['--depth=2']);
       } catch (err) /* istanbul ignore next */ {
         logger.debug({ err }, 'git clone error');
         throw new Error('platform-failure');
@@ -123,6 +120,14 @@ export class Storage {
         10;
       logger.info({ cloneSeconds }, 'git clone completed');
     }
+    const submodules = await this.getSubmodules();
+    for (const submodule of submodules) {
+      try {
+        await this._git.submoduleUpdate(['--init', '--', submodule]);
+      } catch (err) {
+        logger.warn(`Unable to initialise git submodule at ${submodule}`);
+      }
+    }
     try {
       const latestCommitDate = (await this._git!.log({ n: 1 })).latest.date;
       logger.debug({ latestCommitDate }, 'latest commit');
@@ -244,18 +249,7 @@ export class Storage {
     if (!exists) {
       return [];
     }
-    const submodules: string[] = (
-      (await this._git!.raw([
-        'config',
-        '--file',
-        '.gitmodules',
-        '--get-regexp',
-        'path',
-      ])) || ''
-    )
-      .trim()
-      .split(/[\n\s]/)
-      .filter((_e: string, i: number) => i % 2);
+    const submodules = await this.getSubmodules();
     const files: string = await this._git!.raw([
       'ls-tree',
       '-r',
@@ -274,6 +268,21 @@ export class Storage {
       );
   }
 
+  async getSubmodules() {
+    return (
+      (await this._git!.raw([
+        'config',
+        '--file',
+        '.gitmodules',
+        '--get-regexp',
+        'path',
+      ])) || ''
+    )
+      .trim()
+      .split(/[\n\s]/)
+      .filter((_e: string, i: number) => i % 2);
+  }
+
   async branchExists(branchName: string) {
     // First check cache
     if (this._config.branchExists[branchName] !== undefined) {
diff --git a/test/platform/git/storage.spec.ts b/test/platform/git/storage.spec.ts
index ffc0574a8d..62a4f45a24 100644
--- a/test/platform/git/storage.spec.ts
+++ b/test/platform/git/storage.spec.ts
@@ -85,7 +85,7 @@ describe('platform/git/storage', () => {
       expect(await git.getFileList()).toMatchSnapshot();
     });
     it('should exclude submodules', async () => {
-      const repo = await Git(base.path).silent(true);
+      const repo = Git(base.path).silent(true);
       await repo.submoduleAdd(base.path, 'submodule');
       await repo.commit('Add submodule');
       await git.initRepo({
@@ -346,5 +346,29 @@ describe('platform/git/storage', () => {
       expect(await git.branchExists('renovate/test')).toBe(true);
       expect(await git.getBranchCommit('renovate/test')).not.toEqual(cid);
     });
+
+    it('should fail clone ssh submodule', async () => {
+      const repo = Git(base.path).silent(true);
+      await fs.writeFile(
+        base.path + '/.gitmodules',
+        '[submodule "test"]\npath=test\nurl=ssh://0.0.0.0'
+      );
+      await repo.add('.gitmodules');
+      await repo.raw([
+        'update-index',
+        '--add',
+        '--cacheinfo',
+        '160000',
+        '4b825dc642cb6eb9a060e54bf8d69288fbee4904',
+        'test',
+      ]);
+      await repo.commit('Add submodule');
+      await git.initRepo({
+        localDir: tmpDir.path,
+        url: base.path,
+      });
+      expect(await fs.exists(tmpDir.path + '/.gitmodules')).toBeTruthy();
+      repo.reset(['--hard', 'HEAD^']);
+    });
   });
 });
-- 
GitLab