23
23
from macaron .config .global_config import global_config
24
24
from macaron .environment_variables import get_patched_env
25
25
from macaron .errors import CloneError , GitTagError
26
+ from macaron .util import BytesDecoder
26
27
27
28
logger : logging .Logger = logging .getLogger (__name__ )
28
29
@@ -412,7 +413,7 @@ def list_remote_references(arguments: list[str], repo: str) -> str | None:
412
413
logger .error ("Failed to retrieve remote references from repo: %s" , repo )
413
414
return None
414
415
415
- return result .stdout . decode ( "utf-8" )
416
+ return decode_git_tags ( result .stdout )
416
417
417
418
418
419
def resolve_local_path (start_dir : str , local_path : str ) -> str :
@@ -944,7 +945,7 @@ def is_commit_hash(value: str) -> bool:
944
945
return bool (re .match (pattern , value ))
945
946
946
947
947
- def get_tags_via_git_remote (repo : str ) -> dict [str , str ] | None :
948
+ def get_tags_via_git_remote (repo : str ) -> dict [str , str ]:
948
949
"""Retrieve all tags from a given repository using ls-remote.
949
950
950
951
Parameters
@@ -955,35 +956,14 @@ def get_tags_via_git_remote(repo: str) -> dict[str, str] | None:
955
956
Returns
956
957
-------
957
958
dict[str]
958
- A dictionary of tags mapped to their commits, or None if the operation failed. .
959
+ A dictionary of tags mapped to their commits.
959
960
"""
960
961
tag_data = list_remote_references (["--tags" ], repo )
961
962
if not tag_data :
962
- return None
963
- tags = {}
964
-
965
- for tag_line in tag_data .splitlines ():
966
- tag_line = tag_line .strip ()
967
- if not tag_line :
968
- continue
969
- split = tag_line .split ("\t " )
970
- if len (split ) != 2 :
971
- continue
972
- possible_tag = split [1 ]
973
- if possible_tag .endswith ("^{}" ):
974
- possible_tag = possible_tag [:- 3 ]
975
- elif possible_tag in tags :
976
- # If a tag already exists, it must be the annotated reference of an annotated tag.
977
- # In that case we skip the tag as it does not point to the proper source commit.
978
- # Note that this should only happen if the tags are received out of standard order.
979
- continue
980
- possible_tag = possible_tag .replace ("refs/tags/" , "" )
981
- if not possible_tag :
982
- continue
983
- tags [possible_tag ] = split [0 ]
963
+ return {}
984
964
965
+ tags = parse_git_tags (tag_data )
985
966
logger .debug ("Found %s tags via ls-remote of %s" , len (tags ), repo )
986
-
987
967
return tags
988
968
989
969
@@ -1055,3 +1035,61 @@ def find_highest_git_tag(tags: set[str]) -> str:
1055
1035
raise GitTagError ("No valid version tag found." )
1056
1036
1057
1037
return highest_tag
1038
+
1039
+
1040
+ def parse_git_tags (tag_data : str ) -> dict [str , str ]:
1041
+ """Parse the tags and commits found within the passed data.
1042
+
1043
+ Parameters
1044
+ ----------
1045
+ tag_data: str
1046
+ The tag data to parse.
1047
+
1048
+ Returns
1049
+ -------
1050
+ dict[str, str]
1051
+ A dictionary of tags mapped to commits.
1052
+ """
1053
+ tags = {}
1054
+ for tag_line in tag_data .splitlines ():
1055
+ tag_line = tag_line .strip ()
1056
+ if not tag_line :
1057
+ continue
1058
+ split = re .split ("[\t ]" , tag_line , maxsplit = 1 )
1059
+ if len (split ) != 2 :
1060
+ continue
1061
+ possible_tag = split [1 ]
1062
+ if possible_tag .endswith ("^{}" ):
1063
+ possible_tag = possible_tag [:- 3 ]
1064
+ elif possible_tag in tags :
1065
+ # If a tag already exists, it must be the annotated reference of an annotated tag.
1066
+ # In that case we skip the tag as it does not point to the proper source commit.
1067
+ # Note that this should only happen if the tags are received out of standard order.
1068
+ continue
1069
+ possible_tag = possible_tag .replace ("refs/tags/" , "" )
1070
+ if not possible_tag :
1071
+ continue
1072
+ tags [possible_tag ] = split [0 ]
1073
+
1074
+ return tags
1075
+
1076
+
1077
+ def decode_git_tags (data : bytes ) -> str | None :
1078
+ """Decode the passed Git tag data.
1079
+
1080
+ Parameters
1081
+ ----------
1082
+ data: bytes
1083
+ The data to decode.
1084
+
1085
+ Returns
1086
+ -------
1087
+ str | None
1088
+ The decoded data, or None if an error occurred.
1089
+ """
1090
+ try :
1091
+ return data .decode ("utf-8" )
1092
+ except UnicodeDecodeError as error :
1093
+ logger .debug ("Error decoding stdout as utf-8: %s" , error )
1094
+ # Try other character encodings.
1095
+ return BytesDecoder .decode (data )
0 commit comments