26
26
import os
27
27
from io import BytesIO
28
28
import logging
29
+ from collections import defaultdict
29
30
30
31
31
32
# typing ------------------------------------------------------------------
@@ -335,8 +336,70 @@ def stats(self) -> Stats:
335
336
return Stats ._list_from_string (self .repo , text )
336
337
337
338
@property
338
- def trailers (self ) -> Dict :
339
- """Get the trailers of the message as dictionary
339
+ def trailers (self ) -> Dict [str , str ]:
340
+ """Get the trailers of the message as a dictionary
341
+
342
+ Git messages can contain trailer information that are similar to RFC 822
343
+ e-mail headers (see: https://git-scm.com/docs/git-interpret-trailers).
344
+
345
+ WARNING: This function only returns the latest instance of each trailer key
346
+ and will be deprecated soon. Please see either ``Commit.trailers_list`` or ``Commit.trailers_dict``.
347
+
348
+ :return:
349
+ Dictionary containing whitespace stripped trailer information.
350
+ Only the latest instance of each trailer key.
351
+ """
352
+ return {
353
+ k : v [0 ] for k , v in self .trailers_dict .items ()
354
+ }
355
+
356
+ @property
357
+ def trailers_list (self ) -> List [str ]:
358
+ """Get the trailers of the message as a list
359
+
360
+ Git messages can contain trailer information that are similar to RFC 822
361
+ e-mail headers (see: https://git-scm.com/docs/git-interpret-trailers).
362
+
363
+ This functions calls ``git interpret-trailers --parse`` onto the message
364
+ to extract the trailer information, returns the raw trailer data as a list.
365
+
366
+ Valid message with trailer::
367
+
368
+ Subject line
369
+
370
+ some body information
371
+
372
+ another information
373
+
374
+ key1: value1.1
375
+ key1: value1.2
376
+ key2 : value 2 with inner spaces
377
+
378
+
379
+ Returned list will look like this::
380
+
381
+ [
382
+ "key1: value1.1",
383
+ "key1: value1.2",
384
+ "key2 : value 2 with inner spaces",
385
+ ]
386
+
387
+
388
+ :return:
389
+ List containing whitespace stripped trailer information.
390
+ """
391
+ cmd = ["git" , "interpret-trailers" , "--parse" ]
392
+ proc : Git .AutoInterrupt = self .repo .git .execute (cmd , as_process = True , istream = PIPE ) # type: ignore
393
+ trailer : str = proc .communicate (str (self .message ).encode ())[0 ].decode ()
394
+ trailer = trailer .strip ()
395
+ if trailer :
396
+ return [t .strip () for t in trailer .split ("\n " )]
397
+
398
+ return []
399
+
400
+ @property
401
+ def trailers_dict (self ) -> Dict [str , List [str ]]:
402
+ """Get the trailers of the message as a dictionary
340
403
341
404
Git messages can contain trailer information that are similar to RFC 822
342
405
e-mail headers (see: https://git-scm.com/docs/git-interpret-trailers).
@@ -345,42 +408,36 @@ def trailers(self) -> Dict:
345
408
to extract the trailer information. The key value pairs are stripped of
346
409
leading and trailing whitespaces before they get saved into a dictionary.
347
410
348
- Valid message with trailer:
349
-
350
- .. code-block::
411
+ Valid message with trailer::
351
412
352
413
Subject line
353
414
354
415
some body information
355
416
356
417
another information
357
418
358
- key1: value1
419
+ key1: value1.1
420
+ key1: value1.2
359
421
key2 : value 2 with inner spaces
360
422
361
- dictionary will look like this:
362
423
363
- .. code-block ::
424
+ Returned dictionary will look like this ::
364
425
365
426
{
366
- "key1": "value1" ,
367
- "key2": "value 2 with inner spaces"
427
+ "key1": [ "value1.1", "value1.2"] ,
428
+ "key2": [ "value 2 with inner spaces"],
368
429
}
369
430
370
- :return: Dictionary containing whitespace stripped trailer information
371
431
432
+ :return:
433
+ Dictionary containing whitespace stripped trailer information.
434
+ Mapping trailer keys to a list of their corresponding values.
372
435
"""
373
- d = {}
374
- cmd = ["git" , "interpret-trailers" , "--parse" ]
375
- proc : Git .AutoInterrupt = self .repo .git .execute (cmd , as_process = True , istream = PIPE ) # type: ignore
376
- trailer : str = proc .communicate (str (self .message ).encode ())[0 ].decode ()
377
- if trailer .endswith ("\n " ):
378
- trailer = trailer [0 :- 1 ]
379
- if trailer != "" :
380
- for line in trailer .split ("\n " ):
381
- key , value = line .split (":" , 1 )
382
- d [key .strip ()] = value .strip ()
383
- return d
436
+ d = defaultdict (list )
437
+ for trailer in self .trailers_list :
438
+ key , value = trailer .split (":" , 1 )
439
+ d [key .strip ()].append (value .strip ())
440
+ return dict (d )
384
441
385
442
@classmethod
386
443
def _iter_from_process_or_stream (cls , repo : "Repo" , proc_or_stream : Union [Popen , IO ]) -> Iterator ["Commit" ]:
0 commit comments