git-p4: better error reporting when p4 fails
Currently when p4 fails to run, git-p4 just crashes with an obscure error message. For example, if the P4 ticket has expired, you get: Error: Cannot locate perforce checkout of <path> in client view This change checks whether git-p4 can talk to the Perforce server when the first P4 operation is attempted, and tries to print a meaningful error message if it fails. Signed-off-by: Luke Diamand <luke@diamand.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Luke Diamand committed
Jun 8, 2018 at 21:32 UTC
0ef67acdd784852ee8e86dcdb653cc290c1a77a3
2 files changed
+133
git-p4.py
+55
@@ -50,6 +50,8 @@ defaultLabelRegexp = r'[a-zA-Z0-9_\-.]+$'
50
# Grab changes in blocks of this many revisions, unless otherwise requested
51
defaultBlockSize = 512
52
53
+p4_access_checked = False
54
+
55
def p4_build_cmd(cmd):
56
"""Build a suitable p4 command line.
57
@@ -91,6 +93,13 @@ def p4_build_cmd(cmd):
93
real_cmd = ' '.join(real_cmd) + ' ' + cmd
94
else:
95
real_cmd += cmd
96
+
97
+ # now check that we can actually talk to the server
98
+ global p4_access_checked
99
+ if not p4_access_checked:
100
+ p4_access_checked = True # suppress access checks in p4_check_access itself
101
+ p4_check_access()
102
+
103
return real_cmd
104
105
def git_dir(path):
@@ -264,6 +273,52 @@ def p4_system(cmd):
273
if retcode:
274
raise CalledProcessError(retcode, real_cmd)
275
276
+def die_bad_access(s):
277
+ die("failure accessing depot: {0}".format(s.rstrip()))
278
+
279
+def p4_check_access(min_expiration=1):
280
+ """ Check if we can access Perforce - account still logged in
281
+ """
282
+ results = p4CmdList(["login", "-s"])
283
+
284
+ if len(results) == 0:
285
+ # should never get here: always get either some results, or a p4ExitCode
286
+ assert("could not parse response from perforce")
287
+
288
+ result = results[0]
289
+
290
+ if 'p4ExitCode' in result:
291
+ # p4 returned non-zero status, e.g. P4PORT invalid, or p4 not in path
292
+ die_bad_access("could not run p4")
293
+
294
+ code = result.get("code")
295
+ if not code:
296
+ # we get here if we couldn't connect and there was nothing to unmarshal
297
+ die_bad_access("could not connect")
298
+
299
+ elif code == "stat":
300
+ expiry = result.get("TicketExpiration")
301
+ if expiry:
302
+ expiry = int(expiry)
303
+ if expiry > min_expiration:
304
+ # ok to carry on
305
+ return
306
+ else:
307
+ die_bad_access("perforce ticket expires in {0} seconds".format(expiry))
308
+
309
+ else:
310
+ # account without a timeout - all ok
311
+ return
312
+
313
+ elif code == "error":
314
+ data = result.get("data")
315
+ if data:
316
+ die_bad_access("p4 error: {0}".format(data))
317
+ else:
318
+ die_bad_access("unknown error")
319
+ else:
320
+ die_bad_access("unknown error code {0}".format(code))
321
+
322
_p4_version_string = None
323
def p4_version_string():
324
"""Read the version string, showing just the last line, which
t/t9833-errors.sh
new
+78
@@ -0,0 +1,78 @@
1
+#!/bin/sh
2
+
3
+test_description='git p4 errors'
4
+
5
+. ./lib-git-p4.sh
6
+
7
+test_expect_success 'start p4d' '
8
+ start_p4d
9
+'
10
+
11
+test_expect_success 'add p4 files' '
12
+ (
13
+ cd "$cli" &&
14
+ echo file1 >file1 &&
15
+ p4 add file1 &&
16
+ p4 submit -d "file1"
17
+ )
18
+'
19
+
20
+# after this test, the default user requires a password
21
+test_expect_success 'error handling' '
22
+ git p4 clone --dest="$git" //depot@all &&
23
+ (
24
+ cd "$git" &&
25
+ P4PORT=: test_must_fail git p4 submit 2>errmsg
26
+ ) &&
27
+ p4 passwd -P newpassword &&
28
+ (
29
+ P4PASSWD=badpassword test_must_fail git p4 clone //depot/foo 2>errmsg &&
30
+ grep -q "failure accessing depot.*P4PASSWD" errmsg
31
+ )
32
+'
33
+
34
+test_expect_success 'ticket logged out' '
35
+ P4TICKETS="$cli/tickets" &&
36
+ echo "newpassword" | p4 login &&
37
+ (
38
+ cd "$git" &&
39
+ test_commit "ticket-auth-check" &&
40
+ p4 logout &&
41
+ test_must_fail git p4 submit 2>errmsg &&
42
+ grep -q "failure accessing depot" errmsg
43
+ )
44
+'
45
+
46
+test_expect_success 'create group with short ticket expiry' '
47
+ P4TICKETS="$cli/tickets" &&
48
+ echo "newpassword" | p4 login &&
49
+ p4_add_user short_expiry_user &&
50
+ p4 -u short_expiry_user passwd -P password &&
51
+ p4 group -i <<-EOF &&
52
+ Group: testgroup
53
+ Timeout: 3
54
+ Users: short_expiry_user
55
+ EOF
56
+
57
+ p4 users | grep short_expiry_user
58
+'
59
+
60
+test_expect_success 'git operation with expired ticket' '
61
+ P4TICKETS="$cli/tickets" &&
62
+ P4USER=short_expiry_user &&
63
+ echo "password" | p4 login &&
64
+ (
65
+ cd "$git" &&
66
+ git p4 sync &&
67
+ sleep 5 &&
68
+ test_must_fail git p4 sync 2>errmsg &&
69
+ grep "failure accessing depot" errmsg
70
+ )
71
+'
72
+
73
+test_expect_success 'kill p4d' '
74
+ kill_p4d
75
+'
76
+
77
+
78
+test_done