From af1297ff0f54ad7982bfc2e544bca451a4fe3a97 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9rome=20Perrin?= <jerome@nexedi.com>
Date: Wed, 21 Feb 2024 10:11:20 +0100
Subject: [PATCH] TemplateTool: install business templates in deterministic
 order

When a business template has multiple dependencies, these dependencies
were installed in an order defined by iteration in dictionaries, which
is not deterministic when using a random PYTHONHASHSEED on python2.

As an example, when we have business template "b" depending on "b1" and
"b2", the only guarantee was that "b" would be installed after "b1" and
"b2", but which one of "b1" and "b2" is installed first was undefined,
now it is stable, "b1" should be installed before "b2", because we added
a sort. In practice it should not matter, because if in that example
"b2" really needs to be installed after "b1", then "b2" should declare a
dependency on "b1".

test_resolveBusinessTemplateListDependency was failing on python3
because the order on python3 was different from the one using
PYTHONHASHSEED=0 on python2.
---
 product/ERP5/Tool/TemplateTool.py | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/product/ERP5/Tool/TemplateTool.py b/product/ERP5/Tool/TemplateTool.py
index 605b122764..6f90802d7d 100644
--- a/product/ERP5/Tool/TemplateTool.py
+++ b/product/ERP5/Tool/TemplateTool.py
@@ -909,7 +909,7 @@ class TemplateTool (BaseTool):
       repository_dict = {}
       undependent_list = []
 
-      for repository, bt_id in bt_list:
+      for repository, bt_id in sorted(bt_list):
         bt = [x for x in self.repository_dict[repository] \
               if x['id'] == bt_id][0]
         bt_title = bt['title']
@@ -924,7 +924,7 @@ class TemplateTool (BaseTool):
 
       # Calculate the reverse dependency graph
       reverse_dependency_dict = {}
-      for bt_id, dependency_id_list in dependency_dict.items():
+      for bt_id, dependency_id_list in sorted(dependency_dict.items()):
         update_dependency_id_list = []
         for dependency_id in dependency_id_list:
 
@@ -934,10 +934,7 @@ class TemplateTool (BaseTool):
           update_dependency_id_list.append(dependency_id)
 
           # Fill incoming edge dict
-          if dependency_id in reverse_dependency_dict:
-            reverse_dependency_dict[dependency_id].append(bt_id)
-          else:
-            reverse_dependency_dict[dependency_id] = [bt_id]
+          reverse_dependency_dict.setdefault(dependency_id, []).append(bt_id)
 
           # Remove from free node list
           try:
-- 
2.30.9