From c625bf0ee80a2362ce59819ce011ee17f2a6b2ce Mon Sep 17 00:00:00 2001 From: Miguel Torroja Date: Thu, 13 Jul 2017 09:00:33 +0200 Subject: [PATCH 1/3] git-p4: git-p4 tests with p4 triggers Some p4 triggers in the server side generate some warnings when executed. Unfortunately those messages are mixed with the output of p4 commands. A few git-p4 commands don't expect extra messages or output lines and may fail with verbose triggers. New tests added are known to be broken. Signed-off-by: Miguel Torroja Signed-off-by: Junio C Hamano --- t/t9831-git-p4-triggers.sh | 103 +++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100755 t/t9831-git-p4-triggers.sh diff --git a/t/t9831-git-p4-triggers.sh b/t/t9831-git-p4-triggers.sh new file mode 100755 index 0000000000..28cafe4699 --- /dev/null +++ b/t/t9831-git-p4-triggers.sh @@ -0,0 +1,103 @@ +#!/bin/sh + +test_description='git p4 with server triggers' + +. ./lib-git-p4.sh + +test_expect_success 'start p4d' ' + start_p4d +' + +test_expect_success 'init depot' ' + ( + cd "$cli" && + echo file1 >file1 && + p4 add file1 && + p4 submit -d "change 1" + echo file2 >file2 && + p4 add file2 && + p4 submit -d "change 2" + ) +' + +test_expect_failure 'clone with extra info lines from verbose p4 trigger' ' + test_when_finished cleanup_git && + ( + p4 triggers -i <<-EOF + Triggers: p4triggertest-command command pre-user-change "echo verbose trigger" + EOF + ) && + ( + p4 change -o | grep -s "verbose trigger" + ) && + git p4 clone --dest="$git" //depot/@all && + ( + p4 triggers -i <<-EOF + Triggers: + EOF + ) +' + +test_expect_failure 'import with extra info lines from verbose p4 trigger' ' + test_when_finished cleanup_git && + ( + cd "$cli" && + echo file3 >file3 && + p4 add file3 && + p4 submit -d "change 3" + ) && + ( + p4 triggers -i <<-EOF + Triggers: p4triggertest-command command pre-user-describe "echo verbose trigger" + EOF + ) && + ( + p4 describe 1 | grep -s "verbose trigger" + ) && + git p4 clone --dest="$git" //depot/@all && + ( + cd "$git" && + git p4 sync + )&& + ( + p4 triggers -i <<-EOF + Triggers: + EOF + ) +' + +test_expect_failure 'submit description with extra info lines from verbose p4 change trigger' ' + test_when_finished cleanup_git && + ( + p4 triggers -i <<-EOF + Triggers: p4triggertest-command command pre-user-change "echo verbose trigger" + EOF + ) && + ( + p4 change -o | grep -s "verbose trigger" + ) && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + echo file4 >file4 && + git add file4 && + git commit -m file4 && + git p4 submit + ) && + ( + p4 triggers -i <<-EOF + Triggers: + EOF + ) && + ( + cd "$cli" && + test_path_is_file file4 + ) +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done From b596b3b920208acb775bb632288976377636ccd1 Mon Sep 17 00:00:00 2001 From: Miguel Torroja Date: Thu, 13 Jul 2017 09:00:34 +0200 Subject: [PATCH 2/3] git-p4: parse marshal output "p4 -G" in p4 changes The option -G of p4 (python marshal output) gives more context about the data being output. That's useful when using the command "change -o" as we can distinguish between warning/error line and real change description. This fixes the case where a p4 trigger for "p4 change" is set and the command git-p4 submit is run. Signed-off-by: Miguel Torroja Signed-off-by: Junio C Hamano --- git-p4.py | 85 +++++++++++++++++++++++++------------- t/t9831-git-p4-triggers.sh | 2 +- 2 files changed, 58 insertions(+), 29 deletions(-) diff --git a/git-p4.py b/git-p4.py index 8d151da91b..e3a2791e05 100755 --- a/git-p4.py +++ b/git-p4.py @@ -879,8 +879,12 @@ def p4ChangesForPaths(depotPaths, changeRange, requestedBlockSize): cmd += ["%s...@%s" % (p, revisionRange)] # Insert changes in chronological order - for line in reversed(p4_read_pipe_lines(cmd)): - changes.add(int(line.split(" ")[1])) + for entry in reversed(p4CmdList(cmd)): + if entry.has_key('p4ExitCode'): + die('Error retrieving changes descriptions ({})'.format(entry['p4ExitCode'])) + if not entry.has_key('change'): + continue + changes.add(int(entry['change'])) if not block_size: break @@ -1526,37 +1530,62 @@ class P4Submit(Command, P4UserMap): [upstream, settings] = findUpstreamBranchPoint() - template = "" + template = """\ +# A Perforce Change Specification. +# +# Change: The change number. 'new' on a new changelist. +# Date: The date this specification was last modified. +# Client: The client on which the changelist was created. Read-only. +# User: The user who created the changelist. +# Status: Either 'pending' or 'submitted'. Read-only. +# Type: Either 'public' or 'restricted'. Default is 'public'. +# Description: Comments about the changelist. Required. +# Jobs: What opened jobs are to be closed by this changelist. +# You may delete jobs from this list. (New changelists only.) +# Files: What opened files from the default changelist are to be added +# to this changelist. You may delete files from this list. +# (New changelists only.) +""" + files_list = [] inFilesSection = False + change_entry = None args = ['change', '-o'] if changelist: args.append(str(changelist)) - - for line in p4_read_pipe_lines(args): - if line.endswith("\r\n"): - line = line[:-2] + "\n" - if inFilesSection: - if line.startswith("\t"): - # path starts and ends with a tab - path = line[1:] - lastTab = path.rfind("\t") - if lastTab != -1: - path = path[:lastTab] - if settings.has_key('depot-paths'): - if not [p for p in settings['depot-paths'] - if p4PathStartsWith(path, p)]: - continue - else: - if not p4PathStartsWith(path, self.depotPath): - continue + for entry in p4CmdList(args): + if not entry.has_key('code'): + continue + if entry['code'] == 'stat': + change_entry = entry + break + if not change_entry: + die('Failed to decode output of p4 change -o') + for key, value in change_entry.iteritems(): + if key.startswith('File'): + if settings.has_key('depot-paths'): + if not [p for p in settings['depot-paths'] + if p4PathStartsWith(value, p)]: + continue else: - inFilesSection = False - else: - if line.startswith("Files:"): - inFilesSection = True - - template += line - + if not p4PathStartsWith(value, self.depotPath): + continue + files_list.append(value) + continue + # Output in the order expected by prepareLogMessage + for key in ['Change', 'Client', 'User', 'Status', 'Description', 'Jobs']: + if not change_entry.has_key(key): + continue + template += '\n' + template += key + ':' + if key == 'Description': + template += '\n' + for field_line in change_entry[key].splitlines(): + template += '\t'+field_line+'\n' + if len(files_list) > 0: + template += '\n' + template += 'Files:\n' + for path in files_list: + template += '\t'+path+'\n' return template def edit_template(self, template_file): diff --git a/t/t9831-git-p4-triggers.sh b/t/t9831-git-p4-triggers.sh index 28cafe4699..871544b1c9 100755 --- a/t/t9831-git-p4-triggers.sh +++ b/t/t9831-git-p4-triggers.sh @@ -66,7 +66,7 @@ test_expect_failure 'import with extra info lines from verbose p4 trigger' ' ) ' -test_expect_failure 'submit description with extra info lines from verbose p4 change trigger' ' +test_expect_success 'submit description with extra info lines from verbose p4 change trigger' ' test_when_finished cleanup_git && ( p4 triggers -i <<-EOF From 1997e91f4b36649e7e4f693ca9f35c7a6219de8c Mon Sep 17 00:00:00 2001 From: Miguel Torroja Date: Thu, 13 Jul 2017 09:00:35 +0200 Subject: [PATCH 3/3] git-p4: filter for {'code':'info'} in p4CmdList The function p4CmdList accepts a new argument: skip_info. When set to True it ignores any 'code':'info' entry (skip_info=False by default). That allows us to fix some of the tests in t9831-git-p4-triggers.sh known to be broken with verobse p4 triggers Signed-off-by: Miguel Torroja Signed-off-by: Junio C Hamano --- git-p4.py | 9 ++++++--- t/t9831-git-p4-triggers.sh | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/git-p4.py b/git-p4.py index e3a2791e05..2fa581789c 100755 --- a/git-p4.py +++ b/git-p4.py @@ -313,7 +313,7 @@ def p4_move(src, dest): p4_system(["move", "-k", wildcard_encode(src), wildcard_encode(dest)]) def p4_last_change(): - results = p4CmdList(["changes", "-m", "1"]) + results = p4CmdList(["changes", "-m", "1"], skip_info=True) return int(results[0]['change']) def p4_describe(change): @@ -321,7 +321,7 @@ def p4_describe(change): the presence of field "time". Return a dict of the results.""" - ds = p4CmdList(["describe", "-s", str(change)]) + ds = p4CmdList(["describe", "-s", str(change)], skip_info=True) if len(ds) != 1: die("p4 describe -s %d did not return 1 result: %s" % (change, str(ds))) @@ -509,7 +509,7 @@ def isModeExec(mode): def isModeExecChanged(src_mode, dst_mode): return isModeExec(src_mode) != isModeExec(dst_mode) -def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None): +def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False): if isinstance(cmd,basestring): cmd = "-G " + cmd @@ -545,6 +545,9 @@ def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None): try: while True: entry = marshal.load(p4.stdout) + if skip_info: + if 'code' in entry and entry['code'] == 'info': + continue if cb is not None: cb(entry) else: diff --git a/t/t9831-git-p4-triggers.sh b/t/t9831-git-p4-triggers.sh index 871544b1c9..bbcf14c664 100755 --- a/t/t9831-git-p4-triggers.sh +++ b/t/t9831-git-p4-triggers.sh @@ -20,7 +20,7 @@ test_expect_success 'init depot' ' ) ' -test_expect_failure 'clone with extra info lines from verbose p4 trigger' ' +test_expect_success 'clone with extra info lines from verbose p4 trigger' ' test_when_finished cleanup_git && ( p4 triggers -i <<-EOF @@ -38,7 +38,7 @@ test_expect_failure 'clone with extra info lines from verbose p4 trigger' ' ) ' -test_expect_failure 'import with extra info lines from verbose p4 trigger' ' +test_expect_success 'import with extra info lines from verbose p4 trigger' ' test_when_finished cleanup_git && ( cd "$cli" &&