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>
This commit is contained in:
Gary Gibbons 2012-07-12 19:29:00 -04:00 коммит произвёл Junio C Hamano
Родитель 84cb00036f
Коммит 8e9497c2e7
2 изменённых файлов: 34 добавлений и 16 удалений

Просмотреть файл

@ -120,6 +120,15 @@ def p4_read_pipe_lines(c):
real_cmd = p4_build_cmd(c) real_cmd = p4_build_cmd(c)
return read_pipe_lines(real_cmd) return read_pipe_lines(real_cmd)
def p4_has_command(cmd):
"""Ask p4 for help on this command. If it returns an error, the
command does not exist in this version of p4."""
real_cmd = p4_build_cmd(["help", cmd])
p = subprocess.Popen(real_cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
p.communicate()
return p.returncode == 0
def system(cmd): def system(cmd):
expand = isinstance(cmd,basestring) expand = isinstance(cmd,basestring)
if verbose: if verbose:
@ -157,6 +166,9 @@ def p4_revert(f):
def p4_reopen(type, f): def p4_reopen(type, f):
p4_system(["reopen", "-t", type, wildcard_encode(f)]) p4_system(["reopen", "-t", type, wildcard_encode(f)])
def p4_move(src, dest):
p4_system(["move", "-k", wildcard_encode(src), wildcard_encode(dest)])
# #
# Canonicalize the p4 type and return a tuple of the # Canonicalize the p4 type and return a tuple of the
# base type, plus any modifiers. See "p4 help filetypes" # base type, plus any modifiers. See "p4 help filetypes"
@ -850,6 +862,7 @@ class P4Submit(Command, P4UserMap):
self.preserveUser = gitConfig("git-p4.preserveUser").lower() == "true" self.preserveUser = gitConfig("git-p4.preserveUser").lower() == "true"
self.isWindows = (platform.system() == "Windows") self.isWindows = (platform.system() == "Windows")
self.exportLabels = False self.exportLabels = False
self.p4HasMoveCommand = p4_has_command("move")
def check(self): def check(self):
if len(p4CmdList("opened ...")) > 0: if len(p4CmdList("opened ...")) > 0:
@ -1046,7 +1059,6 @@ class P4Submit(Command, P4UserMap):
(p4User, gitEmail) = self.p4UserForCommit(id) (p4User, gitEmail) = self.p4UserForCommit(id)
diff = read_pipe_lines("git diff-tree -r %s \"%s^\" \"%s\"" % (self.diffOpts, id, id)) diff = read_pipe_lines("git diff-tree -r %s \"%s^\" \"%s\"" % (self.diffOpts, id, id))
filesToAdd = set() filesToAdd = set()
filesToDelete = set() filesToDelete = set()
@ -1087,17 +1099,23 @@ class P4Submit(Command, P4UserMap):
editedFiles.add(dest) editedFiles.add(dest)
elif modifier == "R": elif modifier == "R":
src, dest = diff['src'], diff['dst'] src, dest = diff['src'], diff['dst']
p4_integrate(src, dest) if self.p4HasMoveCommand:
if diff['src_sha1'] != diff['dst_sha1']: p4_edit(src) # src must be open before move
p4_edit(dest) p4_move(src, dest) # opens for (move/delete, move/add)
else: else:
pureRenameCopy.add(dest) p4_integrate(src, dest)
if diff['src_sha1'] != diff['dst_sha1']:
p4_edit(dest)
else:
pureRenameCopy.add(dest)
if isModeExecChanged(diff['src_mode'], diff['dst_mode']): if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
p4_edit(dest) if not self.p4HasMoveCommand:
p4_edit(dest) # with move: already open, writable
filesToChangeExecBit[dest] = diff['dst_mode'] filesToChangeExecBit[dest] = diff['dst_mode']
os.unlink(dest) if not self.p4HasMoveCommand:
os.unlink(dest)
filesToDelete.add(src)
editedFiles.add(dest) editedFiles.add(dest)
filesToDelete.add(src)
else: else:
die("unknown modifier %s for %s" % (modifier, path)) die("unknown modifier %s for %s" % (modifier, path))

Просмотреть файл

@ -77,16 +77,16 @@ test_expect_success 'detect renames' '
git commit -a -m "Rename file1 to file4" && git commit -a -m "Rename file1 to file4" &&
git diff-tree -r -M HEAD && git diff-tree -r -M HEAD &&
git p4 submit && git p4 submit &&
p4 filelog //depot/file4 && p4 filelog //depot/file4 >filelog &&
p4 filelog //depot/file4 | test_must_fail grep -q "branch from" && ! grep " from //depot" filelog &&
git mv file4 file5 && git mv file4 file5 &&
git commit -a -m "Rename file4 to file5" && git commit -a -m "Rename file4 to file5" &&
git diff-tree -r -M HEAD && git diff-tree -r -M HEAD &&
git config git-p4.detectRenames true && git config git-p4.detectRenames true &&
git p4 submit && git p4 submit &&
p4 filelog //depot/file5 && p4 filelog //depot/file5 >filelog &&
p4 filelog //depot/file5 | grep -q "branch from //depot/file4" && grep " from //depot/file4" filelog &&
git mv file5 file6 && git mv file5 file6 &&
echo update >>file6 && echo update >>file6 &&
@ -97,8 +97,8 @@ test_expect_success 'detect renames' '
test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 && test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 &&
git config git-p4.detectRenames $(($level + 2)) && git config git-p4.detectRenames $(($level + 2)) &&
git p4 submit && git p4 submit &&
p4 filelog //depot/file6 && p4 filelog //depot/file6 >filelog &&
p4 filelog //depot/file6 | test_must_fail grep -q "branch from" && ! grep " from //depot" filelog &&
git mv file6 file7 && git mv file6 file7 &&
echo update >>file7 && echo update >>file7 &&
@ -109,8 +109,8 @@ test_expect_success 'detect renames' '
test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 && test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 &&
git config git-p4.detectRenames $(($level - 2)) && git config git-p4.detectRenames $(($level - 2)) &&
git p4 submit && git p4 submit &&
p4 filelog //depot/file7 && p4 filelog //depot/file7 >filelog &&
p4 filelog //depot/file7 | grep -q "branch from //depot/file6" grep " from //depot/file6" filelog
) )
' '