git p4: add support for 'p4 move' in P4Submit

For -M option (detectRenames) in P4Submit, use 'p4 move' rather than 'p4 integrate'. Check Perforce server for exisitence of 'p4 move' and use it if present, otherwise revert to 'p4 integrate'. [pw: wildcard-encode src/dest, add/update tests, tweak code] Signed-off-by: Gary Gibbons <ggibbons@perforce.com> Signed-off-by: Pete Wyckoff <pw@padd.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Gary Gibbons committed Jul 12, 2012 at 19:29 UTC 8e9497c2e742f25dc25f85d0382833a0b79dfa8f
2 files changed +34 -16
git-p4.py
+26 -8
@@ -120,6 +120,15 @@ def p4_read_pipe_lines(c):
120 real_cmd = p4_build_cmd(c)
121 return read_pipe_lines(real_cmd)
122
123 +def p4_has_command(cmd):
124 + """Ask p4 for help on this command. If it returns an error, the
125 + command does not exist in this version of p4."""
126 + real_cmd = p4_build_cmd(["help", cmd])
127 + p = subprocess.Popen(real_cmd, stdout=subprocess.PIPE,
128 + stderr=subprocess.PIPE)
129 + p.communicate()
130 + return p.returncode == 0
131 +
132 def system(cmd):
133 expand = isinstance(cmd,basestring)
134 if verbose:
@@ -157,6 +166,9 @@ def p4_revert(f):
166 def p4_reopen(type, f):
167 p4_system(["reopen", "-t", type, wildcard_encode(f)])
168
169 +def p4_move(src, dest):
170 + p4_system(["move", "-k", wildcard_encode(src), wildcard_encode(dest)])
171 +
172 #
173 # Canonicalize the p4 type and return a tuple of the
174 # base type, plus any modifiers. See "p4 help filetypes"
@@ -850,6 +862,7 @@ class P4Submit(Command, P4UserMap):
862 self.preserveUser = gitConfig("git-p4.preserveUser").lower() == "true"
863 self.isWindows = (platform.system() == "Windows")
864 self.exportLabels = False
865 + self.p4HasMoveCommand = p4_has_command("move")
866
867 def check(self):
868 if len(p4CmdList("opened ...")) > 0:
@@ -1046,7 +1059,6 @@ class P4Submit(Command, P4UserMap):
1059
1060 (p4User, gitEmail) = self.p4UserForCommit(id)
1061
1049 -
1062 diff = read_pipe_lines("git diff-tree -r %s \"%s^\" \"%s\"" % (self.diffOpts, id, id))
1063 filesToAdd = set()
1064 filesToDelete = set()
@@ -1087,17 +1099,23 @@ class P4Submit(Command, P4UserMap):
1099 editedFiles.add(dest)
1100 elif modifier == "R":
1101 src, dest = diff['src'], diff['dst']
1090 - p4_integrate(src, dest)
1091 - if diff['src_sha1'] != diff['dst_sha1']:
1092 - p4_edit(dest)
1102 + if self.p4HasMoveCommand:
1103 + p4_edit(src) # src must be open before move
1104 + p4_move(src, dest) # opens for (move/delete, move/add)
1105 else:
1094 - pureRenameCopy.add(dest)
1106 + p4_integrate(src, dest)
1107 + if diff['src_sha1'] != diff['dst_sha1']:
1108 + p4_edit(dest)
1109 + else:
1110 + pureRenameCopy.add(dest)
1111 if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
1096 - p4_edit(dest)
1112 + if not self.p4HasMoveCommand:
1113 + p4_edit(dest) # with move: already open, writable
1114 filesToChangeExecBit[dest] = diff['dst_mode']
1098 - os.unlink(dest)
1115 + if not self.p4HasMoveCommand:
1116 + os.unlink(dest)
1117 + filesToDelete.add(src)
1118 editedFiles.add(dest)
1100 - filesToDelete.add(src)
1119 else:
1120 die("unknown modifier %s for %s" % (modifier, path))
1121
t/t9814-git-p4-rename.sh
+8 -8
@@ -77,16 +77,16 @@ test_expect_success 'detect renames' '
77 git commit -a -m "Rename file1 to file4" &&
78 git diff-tree -r -M HEAD &&
79 git p4 submit &&
80 - p4 filelog //depot/file4 &&
81 - p4 filelog //depot/file4 | test_must_fail grep -q "branch from" &&
80 + p4 filelog //depot/file4 >filelog &&
81 + ! grep " from //depot" filelog &&
82
83 git mv file4 file5 &&
84 git commit -a -m "Rename file4 to file5" &&
85 git diff-tree -r -M HEAD &&
86 git config git-p4.detectRenames true &&
87 git p4 submit &&
88 - p4 filelog //depot/file5 &&
89 - p4 filelog //depot/file5 | grep -q "branch from //depot/file4" &&
88 + p4 filelog //depot/file5 >filelog &&
89 + grep " from //depot/file4" filelog &&
90
91 git mv file5 file6 &&
92 echo update >>file6 &&
@@ -97,8 +97,8 @@ test_expect_success 'detect renames' '
97 test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 &&
98 git config git-p4.detectRenames $(($level + 2)) &&
99 git p4 submit &&
100 - p4 filelog //depot/file6 &&
101 - p4 filelog //depot/file6 | test_must_fail grep -q "branch from" &&
100 + p4 filelog //depot/file6 >filelog &&
101 + ! grep " from //depot" filelog &&
102
103 git mv file6 file7 &&
104 echo update >>file7 &&
@@ -109,8 +109,8 @@ test_expect_success 'detect renames' '
109 test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 &&
110 git config git-p4.detectRenames $(($level - 2)) &&
111 git p4 submit &&
112 - p4 filelog //depot/file7 &&
113 - p4 filelog //depot/file7 | grep -q "branch from //depot/file6"
112 + p4 filelog //depot/file7 >filelog &&
113 + grep " from //depot/file6" filelog
114 )
115 '
116