@@ -188,6 +188,58 @@ def template_to_file(template, plugin_root_path, relative_path, template_vars):
188188 destination_path .chmod (mode )
189189
190190
191+ def merge_gitleaks (template , plugin_root_path , relative_path , template_vars = {}):
192+ """
193+ Take values from .gitleaks.allowlist.j2 and insert them into the allowlist of
194+ an existing .gitleaks.toml file, or create said file otherwise.
195+ """
196+ basename , merge_key = relative_path .split (".toml." , maxsplit = 1 )
197+ # "allowlist" is all we recognize for gitleaks
198+ assert "allowlist" == merge_key
199+ # We aren't using template-vars *currently* - but may want to at some point.
200+ data = tomlkit .loads (template .render (** template_vars ))
201+ path = Path (plugin_root_path / f"{ basename } .toml" )
202+ if path .exists ():
203+ old_toml = tomlkit .load (path .open ())
204+ if merge_key not in old_toml :
205+ old_toml ["allowlist" ] = data ["allowlist" ]
206+ else :
207+ old_toml ["allowlist" ]["description" ] = data ["allowlist" ]["description" ]
208+ merge_sets ("paths" , data , old_toml )
209+ merge_sets ("regexes" , data , old_toml )
210+
211+ else :
212+ old_toml = data
213+ # Update MANIFEST.in to ignore the file we're about to create
214+ # (if we are only updating .gitleaks, we 'assume' it's already being ignored)
215+ manifest = Path (plugin_root_path / "MANIFEST.in" )
216+ if manifest .exists ():
217+ # MANIFEST.in is small enough to look at the whole thing at once
218+ manifest_contents = manifest .read_text ()
219+ if ".gitleaks.toml" not in manifest_contents :
220+ manifest .write_text (manifest_contents + "\n exclude .gitleaks.toml" )
221+ output = tomlkit .dumps (old_toml )
222+ if output [- 1 ] != "\n " :
223+ output = output + "\n "
224+ path .write_text (output )
225+
226+
227+ def merge_sets (key , data , old_toml ):
228+ """
229+ For a given key, merge any existing values and incoming new ones.
230+ Use set() to get rid of duplicates, use sorted() to enforce ordering.
231+ If incoming values are already a subset of the existing ones - nothing to do here.
232+ """
233+ if key in old_toml ["allowlist" ]:
234+ old_values = set (old_toml ["allowlist" ][key ])
235+ new_values = set (data ["allowlist" ][key ])
236+ if new_values .issubset (old_values ): # Everything we want to add is already there
237+ return
238+ old_toml ["allowlist" ][key ] = sorted (old_values .union (new_values ))
239+ else :
240+ old_toml ["allowlist" ][key ] = sorted (set (data ["allowlist" ][key ]))
241+
242+
191243def merge_toml (template , plugin_root_path , relative_path , template_vars ):
192244 """
193245 Template a file of the form 'basename.toml.merge_key' and combine its content beneath
0 commit comments