Skip to content

Commit 008518b

Browse files
committed
Merge branch 'kk/p4-client-name-encoding-fix' into next
"git p4" did not handle non-ASCII client name well, which has been corrected. * kk/p4-client-name-encoding-fix: git-p4: refactoring of p4CmdList()
2 parents c2fedd2 + d205483 commit 008518b

File tree

1 file changed

+42
-11
lines changed

1 file changed

+42
-11
lines changed

git-p4.py

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,42 @@ def isModeExecChanged(src_mode, dst_mode):
822822
return isModeExec(src_mode) != isModeExec(dst_mode)
823823

824824

825+
def p4KeysContainingNonUtf8Chars():
826+
"""Returns all keys which may contain non UTF-8 encoded strings
827+
for which a fallback strategy has to be applied.
828+
"""
829+
return ['desc', 'client', 'FullName']
830+
831+
832+
def p4KeysContainingBinaryData():
833+
"""Returns all keys which may contain arbitrary binary data
834+
"""
835+
return ['data']
836+
837+
838+
def p4KeyContainsFilePaths(key):
839+
"""Returns True if the key contains file paths. These are handled by decode_path().
840+
Otherwise False.
841+
"""
842+
return key.startswith('depotFile') or key in ['path', 'clientFile']
843+
844+
845+
def p4KeyWhichCanBeDirectlyDecoded(key):
846+
"""Returns True if the key can be directly decoded as UTF-8 string
847+
Otherwise False.
848+
849+
Keys which can not be encoded directly:
850+
- `data` which may contain arbitrary binary data
851+
- `desc` or `client` or `FullName` which may contain non-UTF8 encoded text
852+
- `depotFile[0-9]*`, `path`, or `clientFile` which may contain non-UTF8 encoded text, handled by decode_path()
853+
"""
854+
if key in p4KeysContainingNonUtf8Chars() or \
855+
key in p4KeysContainingBinaryData() or \
856+
p4KeyContainsFilePaths(key):
857+
return False
858+
return True
859+
860+
825861
def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False,
826862
errors_as_exceptions=False, *k, **kw):
827863

@@ -851,15 +887,13 @@ def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False,
851887
try:
852888
while True:
853889
entry = marshal.load(p4.stdout)
890+
854891
if bytes is not str:
855-
# Decode unmarshalled dict to use str keys and values, except for:
856-
# - `data` which may contain arbitrary binary data
857-
# - `desc` or `client` or `FullName` which may contain non-UTF8 encoded text handled below, eagerly converted to bytes
858-
# - `depotFile[0-9]*`, `path`, or `clientFile` which may contain non-UTF8 encoded text, handled by decode_path()
892+
# Decode unmarshalled dict to use str keys and values. Special cases are handled below.
859893
decoded_entry = {}
860894
for key, value in entry.items():
861895
key = key.decode()
862-
if isinstance(value, bytes) and not (key in ('data', 'desc', 'FullName', 'path', 'clientFile', 'client') or key.startswith('depotFile')):
896+
if isinstance(value, bytes) and p4KeyWhichCanBeDirectlyDecoded(key):
863897
value = value.decode()
864898
decoded_entry[key] = value
865899
# Parse out data if it's an error response
@@ -869,12 +903,9 @@ def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False,
869903
if skip_info:
870904
if 'code' in entry and entry['code'] == 'info':
871905
continue
872-
if 'desc' in entry:
873-
entry['desc'] = metadata_stream_to_writable_bytes(entry['desc'])
874-
if 'client' in entry:
875-
entry['client'] = metadata_stream_to_writable_bytes(entry['client'])
876-
if 'FullName' in entry:
877-
entry['FullName'] = metadata_stream_to_writable_bytes(entry['FullName'])
906+
for key in p4KeysContainingNonUtf8Chars():
907+
if key in entry:
908+
entry[key] = metadata_stream_to_writable_bytes(entry[key])
878909
if cb is not None:
879910
cb(entry)
880911
else:

0 commit comments

Comments
 (0)