Skip to content

Commit 78189be

Browse files
Pete Wyckoffgitster
authored andcommitted
git p4: catch p4 errors when streaming file contents
Error messages that arise during the "p4 print" phase of generating commits were silently ignored. Catch them, abort the fast-import, and exit. Without this fix, the sync/clone appears to work, but files that are inaccessible by the p4d server will still be imported to git, although without the proper contents. Instead the errant files will contain a p4 error message, such as "Librarian checkout //depot/path failed". Signed-off-by: Pete Wyckoff <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 249da4c commit 78189be

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

git-p4.py

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2139,6 +2139,29 @@ def streamOneP4Deletion(self, file):
21392139
# handle another chunk of streaming data
21402140
def streamP4FilesCb(self, marshalled):
21412141

2142+
# catch p4 errors and complain
2143+
err = None
2144+
if "code" in marshalled:
2145+
if marshalled["code"] == "error":
2146+
if "data" in marshalled:
2147+
err = marshalled["data"].rstrip()
2148+
if err:
2149+
f = None
2150+
if self.stream_have_file_info:
2151+
if "depotFile" in self.stream_file:
2152+
f = self.stream_file["depotFile"]
2153+
# force a failure in fast-import, else an empty
2154+
# commit will be made
2155+
self.gitStream.write("\n")
2156+
self.gitStream.write("die-now\n")
2157+
self.gitStream.close()
2158+
# ignore errors, but make sure it exits first
2159+
self.importProcess.wait()
2160+
if f:
2161+
die("Error from p4 print for %s: %s" % (f, err))
2162+
else:
2163+
die("Error from p4 print: %s" % err)
2164+
21422165
if marshalled.has_key('depotFile') and self.stream_have_file_info:
21432166
# start of a new file - output the old one first
21442167
self.streamOneP4File(self.stream_file, self.stream_contents)
@@ -2900,12 +2923,13 @@ def run(self, args):
29002923

29012924
self.tz = "%+03d%02d" % (- time.timezone / 3600, ((- time.timezone % 3600) / 60))
29022925

2903-
importProcess = subprocess.Popen(["git", "fast-import"],
2904-
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
2905-
stderr=subprocess.PIPE);
2906-
self.gitOutput = importProcess.stdout
2907-
self.gitStream = importProcess.stdin
2908-
self.gitError = importProcess.stderr
2926+
self.importProcess = subprocess.Popen(["git", "fast-import"],
2927+
stdin=subprocess.PIPE,
2928+
stdout=subprocess.PIPE,
2929+
stderr=subprocess.PIPE);
2930+
self.gitOutput = self.importProcess.stdout
2931+
self.gitStream = self.importProcess.stdin
2932+
self.gitError = self.importProcess.stderr
29092933

29102934
if revision:
29112935
self.importHeadRevision(revision)
@@ -2965,7 +2989,7 @@ def run(self, args):
29652989
self.importP4Labels(self.gitStream, missingP4Labels)
29662990

29672991
self.gitStream.close()
2968-
if importProcess.wait() != 0:
2992+
if self.importProcess.wait() != 0:
29692993
die("fast-import failed: %s" % self.gitError.read())
29702994
self.gitOutput.close()
29712995
self.gitError.close()

t/t9800-git-p4-basic.sh

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,18 @@ test_expect_success 'exit when p4 fails to produce marshaled output' '
143143
! test_i18ngrep Traceback errs
144144
'
145145

146-
test_expect_success 'clone bare' '
146+
# Hide a file from p4d, make sure we catch its complaint. This won't fail in
147+
# p4 changes, files, or describe; just in p4 print. If P4CLIENT is unset, the
148+
# message will include "Librarian checkout".
149+
test_expect_success 'exit gracefully for p4 server errors' '
150+
test_when_finished "mv \"$db\"/depot/file1,v,hidden \"$db\"/depot/file1,v" &&
151+
mv "$db"/depot/file1,v "$db"/depot/file1,v,hidden &&
152+
test_when_finished cleanup_git &&
153+
test_expect_code 1 git p4 clone --dest="$git" //depot@1 >out 2>err &&
154+
test_i18ngrep "Error from p4 print" err
155+
'
156+
157+
test_expect_success 'clone --bare should make a bare repository' '
147158
rm -rf "$git" &&
148159
git p4 clone --dest="$git" --bare //depot &&
149160
test_when_finished cleanup_git &&

0 commit comments

Comments
 (0)