Skip to content

Commit 4f0b213

Browse files
committed
Merge branch 'mt/p4-parse-G-output'
Use "p4 -G" to make "p4 changes" output more Python-friendly to parse. * mt/p4-parse-G-output: git-p4: filter for {'code':'info'} in p4CmdList git-p4: parse marshal output "p4 -G" in p4 changes git-p4: git-p4 tests with p4 triggers
2 parents 2842e06 + 1997e91 commit 4f0b213

File tree

2 files changed

+166
-31
lines changed

2 files changed

+166
-31
lines changed

git-p4.py

Lines changed: 63 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -313,15 +313,15 @@ def p4_move(src, dest):
313313
p4_system(["move", "-k", wildcard_encode(src), wildcard_encode(dest)])
314314

315315
def p4_last_change():
316-
results = p4CmdList(["changes", "-m", "1"])
316+
results = p4CmdList(["changes", "-m", "1"], skip_info=True)
317317
return int(results[0]['change'])
318318

319319
def p4_describe(change):
320320
"""Make sure it returns a valid result by checking for
321321
the presence of field "time". Return a dict of the
322322
results."""
323323

324-
ds = p4CmdList(["describe", "-s", str(change)])
324+
ds = p4CmdList(["describe", "-s", str(change)], skip_info=True)
325325
if len(ds) != 1:
326326
die("p4 describe -s %d did not return 1 result: %s" % (change, str(ds)))
327327

@@ -509,7 +509,7 @@ def isModeExec(mode):
509509
def isModeExecChanged(src_mode, dst_mode):
510510
return isModeExec(src_mode) != isModeExec(dst_mode)
511511

512-
def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None):
512+
def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False):
513513

514514
if isinstance(cmd,basestring):
515515
cmd = "-G " + cmd
@@ -545,6 +545,9 @@ def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None):
545545
try:
546546
while True:
547547
entry = marshal.load(p4.stdout)
548+
if skip_info:
549+
if 'code' in entry and entry['code'] == 'info':
550+
continue
548551
if cb is not None:
549552
cb(entry)
550553
else:
@@ -879,8 +882,12 @@ def p4ChangesForPaths(depotPaths, changeRange, requestedBlockSize):
879882
cmd += ["%s...@%s" % (p, revisionRange)]
880883

881884
# Insert changes in chronological order
882-
for line in reversed(p4_read_pipe_lines(cmd)):
883-
changes.add(int(line.split(" ")[1]))
885+
for entry in reversed(p4CmdList(cmd)):
886+
if entry.has_key('p4ExitCode'):
887+
die('Error retrieving changes descriptions ({})'.format(entry['p4ExitCode']))
888+
if not entry.has_key('change'):
889+
continue
890+
changes.add(int(entry['change']))
884891

885892
if not block_size:
886893
break
@@ -1526,37 +1533,62 @@ def prepareSubmitTemplate(self, changelist=None):
15261533

15271534
[upstream, settings] = findUpstreamBranchPoint()
15281535

1529-
template = ""
1536+
template = """\
1537+
# A Perforce Change Specification.
1538+
#
1539+
# Change: The change number. 'new' on a new changelist.
1540+
# Date: The date this specification was last modified.
1541+
# Client: The client on which the changelist was created. Read-only.
1542+
# User: The user who created the changelist.
1543+
# Status: Either 'pending' or 'submitted'. Read-only.
1544+
# Type: Either 'public' or 'restricted'. Default is 'public'.
1545+
# Description: Comments about the changelist. Required.
1546+
# Jobs: What opened jobs are to be closed by this changelist.
1547+
# You may delete jobs from this list. (New changelists only.)
1548+
# Files: What opened files from the default changelist are to be added
1549+
# to this changelist. You may delete files from this list.
1550+
# (New changelists only.)
1551+
"""
1552+
files_list = []
15301553
inFilesSection = False
1554+
change_entry = None
15311555
args = ['change', '-o']
15321556
if changelist:
15331557
args.append(str(changelist))
1534-
1535-
for line in p4_read_pipe_lines(args):
1536-
if line.endswith("\r\n"):
1537-
line = line[:-2] + "\n"
1538-
if inFilesSection:
1539-
if line.startswith("\t"):
1540-
# path starts and ends with a tab
1541-
path = line[1:]
1542-
lastTab = path.rfind("\t")
1543-
if lastTab != -1:
1544-
path = path[:lastTab]
1545-
if settings.has_key('depot-paths'):
1546-
if not [p for p in settings['depot-paths']
1547-
if p4PathStartsWith(path, p)]:
1548-
continue
1549-
else:
1550-
if not p4PathStartsWith(path, self.depotPath):
1551-
continue
1558+
for entry in p4CmdList(args):
1559+
if not entry.has_key('code'):
1560+
continue
1561+
if entry['code'] == 'stat':
1562+
change_entry = entry
1563+
break
1564+
if not change_entry:
1565+
die('Failed to decode output of p4 change -o')
1566+
for key, value in change_entry.iteritems():
1567+
if key.startswith('File'):
1568+
if settings.has_key('depot-paths'):
1569+
if not [p for p in settings['depot-paths']
1570+
if p4PathStartsWith(value, p)]:
1571+
continue
15521572
else:
1553-
inFilesSection = False
1554-
else:
1555-
if line.startswith("Files:"):
1556-
inFilesSection = True
1557-
1558-
template += line
1559-
1573+
if not p4PathStartsWith(value, self.depotPath):
1574+
continue
1575+
files_list.append(value)
1576+
continue
1577+
# Output in the order expected by prepareLogMessage
1578+
for key in ['Change', 'Client', 'User', 'Status', 'Description', 'Jobs']:
1579+
if not change_entry.has_key(key):
1580+
continue
1581+
template += '\n'
1582+
template += key + ':'
1583+
if key == 'Description':
1584+
template += '\n'
1585+
for field_line in change_entry[key].splitlines():
1586+
template += '\t'+field_line+'\n'
1587+
if len(files_list) > 0:
1588+
template += '\n'
1589+
template += 'Files:\n'
1590+
for path in files_list:
1591+
template += '\t'+path+'\n'
15601592
return template
15611593

15621594
def edit_template(self, template_file):

t/t9831-git-p4-triggers.sh

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#!/bin/sh
2+
3+
test_description='git p4 with server triggers'
4+
5+
. ./lib-git-p4.sh
6+
7+
test_expect_success 'start p4d' '
8+
start_p4d
9+
'
10+
11+
test_expect_success 'init depot' '
12+
(
13+
cd "$cli" &&
14+
echo file1 >file1 &&
15+
p4 add file1 &&
16+
p4 submit -d "change 1"
17+
echo file2 >file2 &&
18+
p4 add file2 &&
19+
p4 submit -d "change 2"
20+
)
21+
'
22+
23+
test_expect_success 'clone with extra info lines from verbose p4 trigger' '
24+
test_when_finished cleanup_git &&
25+
(
26+
p4 triggers -i <<-EOF
27+
Triggers: p4triggertest-command command pre-user-change "echo verbose trigger"
28+
EOF
29+
) &&
30+
(
31+
p4 change -o | grep -s "verbose trigger"
32+
) &&
33+
git p4 clone --dest="$git" //depot/@all &&
34+
(
35+
p4 triggers -i <<-EOF
36+
Triggers:
37+
EOF
38+
)
39+
'
40+
41+
test_expect_success 'import with extra info lines from verbose p4 trigger' '
42+
test_when_finished cleanup_git &&
43+
(
44+
cd "$cli" &&
45+
echo file3 >file3 &&
46+
p4 add file3 &&
47+
p4 submit -d "change 3"
48+
) &&
49+
(
50+
p4 triggers -i <<-EOF
51+
Triggers: p4triggertest-command command pre-user-describe "echo verbose trigger"
52+
EOF
53+
) &&
54+
(
55+
p4 describe 1 | grep -s "verbose trigger"
56+
) &&
57+
git p4 clone --dest="$git" //depot/@all &&
58+
(
59+
cd "$git" &&
60+
git p4 sync
61+
)&&
62+
(
63+
p4 triggers -i <<-EOF
64+
Triggers:
65+
EOF
66+
)
67+
'
68+
69+
test_expect_success 'submit description with extra info lines from verbose p4 change trigger' '
70+
test_when_finished cleanup_git &&
71+
(
72+
p4 triggers -i <<-EOF
73+
Triggers: p4triggertest-command command pre-user-change "echo verbose trigger"
74+
EOF
75+
) &&
76+
(
77+
p4 change -o | grep -s "verbose trigger"
78+
) &&
79+
git p4 clone --dest="$git" //depot &&
80+
(
81+
cd "$git" &&
82+
git config git-p4.skipSubmitEdit true &&
83+
echo file4 >file4 &&
84+
git add file4 &&
85+
git commit -m file4 &&
86+
git p4 submit
87+
) &&
88+
(
89+
p4 triggers -i <<-EOF
90+
Triggers:
91+
EOF
92+
) &&
93+
(
94+
cd "$cli" &&
95+
test_path_is_file file4
96+
)
97+
'
98+
99+
test_expect_success 'kill p4d' '
100+
kill_p4d
101+
'
102+
103+
test_done

0 commit comments

Comments
 (0)