git-p4: handle "Translation of file content failed"

A P4 repository can get into a state where it contains a file with type UTF-16 that does not contain a valid UTF-16 BOM. If git-p4 attempts to retrieve the file then the process crashes with a "Translation of file content failed" error. More info here: http://answers.perforce.com/articles/KB/3117 Fix this by detecting this error and retrieving the file as binary instead. The result in Git is the same. Known issue: This works only if git-p4 is executed in verbose mode. In normal mode no exceptions are thrown and git-p4 just exits. Signed-off-by: Lars Schneider <larsxschneider@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Lars Schneider committed Sep 21, 2015 at 12:01 UTC 1f5f3907117021961545e42097829001b58288db
2 files changed +17 -12
git-p4.py
+16 -11
@@ -134,13 +134,11 @@ def read_pipe(c, ignore_error=False):
134 sys.stderr.write('Reading pipe: %s\n' % str(c))
135
136 expand = isinstance(c,basestring)
137 - p = subprocess.Popen(c, stdout=subprocess.PIPE, shell=expand)
138 - pipe = p.stdout
139 - val = pipe.read()
140 - if p.wait() and not ignore_error:
141 - die('Command failed: %s' % str(c))
142 -
143 - return val
137 + p = subprocess.Popen(c, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=expand)
138 + (out, err) = p.communicate()
139 + if p.returncode != 0 and not ignore_error:
140 + die('Command failed: %s\nError: %s' % (str(c), err))
141 + return out
142
143 def p4_read_pipe(c, ignore_error=False):
144 real_cmd = p4_build_cmd(c)
@@ -2193,10 +2191,17 @@ class P4Sync(Command, P4UserMap):
2191 # them back too. This is not needed to the cygwin windows version,
2192 # just the native "NT" type.
2193 #
2196 - text = p4_read_pipe(['print', '-q', '-o', '-', "%s@%s" % (file['depotFile'], file['change']) ])
2197 - if p4_version_string().find("/NT") >= 0:
2198 - text = text.replace("\r\n", "\n")
2199 - contents = [ text ]
2194 + try:
2195 + text = p4_read_pipe(['print', '-q', '-o', '-', '%s@%s' % (file['depotFile'], file['change'])])
2196 + except Exception as e:
2197 + if 'Translation of file content failed' in str(e):
2198 + type_base = 'binary'
2199 + else:
2200 + raise e
2201 + else:
2202 + if p4_version_string().find('/NT') >= 0:
2203 + text = text.replace('\r\n', '\n')
2204 + contents = [ text ]
2205
2206 if type_base == "apple":
2207 # Apple filetype files will be streamed as a concatenation of
t/t9825-git-p4-handle-utf16-without-bom.sh
+1 -1
@@ -29,7 +29,7 @@ test_expect_success 'init depot with UTF-16 encoded file and artificially remove
29 )
30 '
31
32 -test_expect_failure 'clone depot with invalid UTF-16 file in verbose mode' '
32 +test_expect_success 'clone depot with invalid UTF-16 file in verbose mode' '
33 git p4 clone --dest="$git" --verbose //depot &&
34 test_when_finished cleanup_git &&
35 (