From 7eca345f27c6c314e0ac0aeddeb5d53798c2260b Mon Sep 17 00:00:00 2001
From: Sebastien Robin <seb@nexedi.com>
Date: Mon, 29 Apr 2019 11:41:48 +0200
Subject: [PATCH] testnode: handle cases of corrupted index files when updating
 git repositories

---
 erp5/tests/testERP5TestNode.py | 32 ++++++++++++++++++++++++++++++++
 erp5/util/testnode/testnode.py |  7 ++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/erp5/tests/testERP5TestNode.py b/erp5/tests/testERP5TestNode.py
index dc1241702e..34cd8628ad 100644
--- a/erp5/tests/testERP5TestNode.py
+++ b/erp5/tests/testERP5TestNode.py
@@ -437,6 +437,38 @@ shared = true
     rev_list = self.getAndUpdateFullRevisionList(test_node, node_test_suite)
     self.assertEqual(None, rev_list)
 
+  def test_05f_ResetCorruptedRepository(self):
+    """
+    It could happens that repository are corrupted, like when server is restarted
+    in the middle of a git checkout. So make sure testnode remove repositories
+    that are not working any longer.
+
+    Usual error is "index file smaller than expected".
+    We reproduce here a similar error "bad index file sha1 signature" which we
+    know how to reproduce
+    """
+    commit_dict = self.generateTestRepositoryList()
+    test_node = self.getTestNode()
+    node_test_suite = test_node.getNodeTestSuite('foo')
+    self.updateNodeTestSuiteData(node_test_suite)
+    rev_list = self.getAndUpdateFullRevisionList(test_node, node_test_suite)
+    self.assertTrue(rev_list is not None)
+    rep0_clone_path = [x['repository_path'] for x in \
+                   node_test_suite.vcs_repository_list \
+                   if x['repository_path'].endswith("rep0")][0]
+    # truncate index file to reproduce error
+    index_file = open(os.path.join(rep0_clone_path, '.git', 'index'), 'a')
+    index_file.seek(1,2)
+    index_file.truncate()
+    index_file.close()
+    # we get rev list with corrupted repository, we get None, but in the same
+    # time the bad repository is deleted
+    rev_list = self.getAndUpdateFullRevisionList(test_node, node_test_suite)
+    self.assertEqual(None, rev_list)
+    # So next update should go fine
+    rev_list = self.getAndUpdateFullRevisionList(test_node, node_test_suite)
+    self.assertTrue(rev_list is not None)
+
   def test_06_checkRevision(self):
     """
     Check if we are able to restore older commit hash if master decide so
diff --git a/erp5/util/testnode/testnode.py b/erp5/util/testnode/testnode.py
index 374f6b4a1b..518c89ff86 100644
--- a/erp5/util/testnode/testnode.py
+++ b/erp5/util/testnode/testnode.py
@@ -167,7 +167,12 @@ shared = true
            url=vcs_repository["url"])
         updater.checkout()
         revision_list.append((repository_id, updater.getRevision()))
-    except SubprocessError:
+    except SubprocessError as error:
+      # only limit to particular error, if we run that code for all errors,
+      # then if server having most repositories is down for some time, we would
+      # erase all repositories and facing later hours of downloads
+      if getattr(error, 'stderr', '').find('index file') >= 0:
+        rmtree(repository_path)
       logger.warning("Error while getting repository, ignoring this test suite",
                      exc_info=1)
       return False
-- 
2.30.9