diff options
author | Sebastian Thiel <sebastian.thiel@icloud.com> | 2023-04-23 19:22:49 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-23 19:22:49 +0200 |
commit | e3bc5d10629ada4d61fdf61353668a58c5610d6b (patch) | |
tree | a1adfd6a7fa392cb39b16865caea7e6aef70666c /git/objects/commit.py | |
parent | 61ed7ecac2f53ea512fdfbcbb260d4cd49423f22 (diff) | |
parent | 9ef07a731caf39684891bce5cc92c4e91829138d (diff) | |
download | gitpython-e3bc5d10629ada4d61fdf61353668a58c5610d6b.tar.gz |
Merge pull request #1576 from itsluketwist/fix-trailers
Fix up the commit trailers functionality
Diffstat (limited to 'git/objects/commit.py')
-rw-r--r-- | git/objects/commit.py | 102 |
1 files changed, 80 insertions, 22 deletions
diff --git a/git/objects/commit.py b/git/objects/commit.py index 547e8fe8..138db0af 100644 --- a/git/objects/commit.py +++ b/git/objects/commit.py @@ -26,6 +26,7 @@ from time import time, daylight, altzone, timezone, localtime import os from io import BytesIO import logging +from collections import defaultdict # typing ------------------------------------------------------------------ @@ -335,8 +336,72 @@ class Commit(base.Object, TraversableIterableObj, Diffable, Serializable): return Stats._list_from_string(self.repo, text) @property - def trailers(self) -> Dict: - """Get the trailers of the message as dictionary + def trailers(self) -> Dict[str, str]: + """Get the trailers of the message as a dictionary + + :note: This property is deprecated, please use either ``Commit.trailers_list`` or ``Commit.trailers_dict``. + + :return: + Dictionary containing whitespace stripped trailer information. + Only contains the latest instance of each trailer key. + """ + return { + k: v[0] for k, v in self.trailers_dict.items() + } + + @property + def trailers_list(self) -> List[Tuple[str, str]]: + """Get the trailers of the message as a list + + Git messages can contain trailer information that are similar to RFC 822 + e-mail headers (see: https://git-scm.com/docs/git-interpret-trailers). + + This functions calls ``git interpret-trailers --parse`` onto the message + to extract the trailer information, returns the raw trailer data as a list. + + Valid message with trailer:: + + Subject line + + some body information + + another information + + key1: value1.1 + key1: value1.2 + key2 : value 2 with inner spaces + + + Returned list will look like this:: + + [ + ("key1", "value1.1"), + ("key1", "value1.2"), + ("key2", "value 2 with inner spaces"), + ] + + + :return: + List containing key-value tuples of whitespace stripped trailer information. + """ + cmd = ["git", "interpret-trailers", "--parse"] + proc: Git.AutoInterrupt = self.repo.git.execute(cmd, as_process=True, istream=PIPE) # type: ignore + trailer: str = proc.communicate(str(self.message).encode())[0].decode("utf8") + trailer = trailer.strip() + + if not trailer: + return [] + + trailer_list = [] + for t in trailer.split("\n"): + key, val = t.split(":", 1) + trailer_list.append((key.strip(), val.strip())) + + return trailer_list + + @property + def trailers_dict(self) -> Dict[str, List[str]]: + """Get the trailers of the message as a dictionary Git messages can contain trailer information that are similar to RFC 822 e-mail headers (see: https://git-scm.com/docs/git-interpret-trailers). @@ -345,9 +410,7 @@ class Commit(base.Object, TraversableIterableObj, Diffable, Serializable): to extract the trailer information. The key value pairs are stripped of leading and trailing whitespaces before they get saved into a dictionary. - Valid message with trailer: - - .. code-block:: + Valid message with trailer:: Subject line @@ -355,32 +418,27 @@ class Commit(base.Object, TraversableIterableObj, Diffable, Serializable): another information - key1: value1 + key1: value1.1 + key1: value1.2 key2 : value 2 with inner spaces - dictionary will look like this: - .. code-block:: + Returned dictionary will look like this:: { - "key1": "value1", - "key2": "value 2 with inner spaces" + "key1": ["value1.1", "value1.2"], + "key2": ["value 2 with inner spaces"], } - :return: Dictionary containing whitespace stripped trailer information + :return: + Dictionary containing whitespace stripped trailer information. + Mapping trailer keys to a list of their corresponding values. """ - d = {} - cmd = ["git", "interpret-trailers", "--parse"] - proc: Git.AutoInterrupt = self.repo.git.execute(cmd, as_process=True, istream=PIPE) # type: ignore - trailer: str = proc.communicate(str(self.message).encode())[0].decode() - if trailer.endswith("\n"): - trailer = trailer[0:-1] - if trailer != "": - for line in trailer.split("\n"): - key, value = line.split(":", 1) - d[key.strip()] = value.strip() - return d + d = defaultdict(list) + for key, val in self.trailers_list: + d[key].append(val) + return dict(d) @classmethod def _iter_from_process_or_stream(cls, repo: "Repo", proc_or_stream: Union[Popen, IO]) -> Iterator["Commit"]: |