Merge branch 'pw/git-p4-move'

* pw/git-p4-move:
  git p4: add support for 'p4 move' in P4Submit
  git p4: refactor diffOpts calculation
maint
Junio C Hamano 2012-07-15 21:38:32 -07:00
commit 77f3591dbb
3 changed files with 72 additions and 40 deletions

View File

@ -255,7 +255,7 @@ These options can be used to modify 'git p4 submit' behavior.
p4. By default, this is the most recent p4 commit reachable p4. By default, this is the most recent p4 commit reachable
from 'HEAD'. from 'HEAD'.


-M[<n>]:: -M::
Detect renames. See linkgit:git-diff[1]. Renames will be Detect renames. See linkgit:git-diff[1]. Renames will be
represented in p4 using explicit 'move' operations. There represented in p4 using explicit 'move' operations. There
is no corresponding option to detect copies, but there are is no corresponding option to detect copies, but there are
@ -465,13 +465,15 @@ git-p4.useClientSpec::
Submit variables Submit variables
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
git-p4.detectRenames:: git-p4.detectRenames::
Detect renames. See linkgit:git-diff[1]. Detect renames. See linkgit:git-diff[1]. This can be true,
false, or a score as expected by 'git diff -M'.


git-p4.detectCopies:: git-p4.detectCopies::
Detect copies. See linkgit:git-diff[1]. Detect copies. See linkgit:git-diff[1]. This can be true,
false, or a score as expected by 'git diff -C'.


git-p4.detectCopiesHarder:: git-p4.detectCopiesHarder::
Detect copies harder. See linkgit:git-diff[1]. Detect copies harder. See linkgit:git-diff[1]. A boolean.


git-p4.preserveUser:: git-p4.preserveUser::
On submit, re-author changes to reflect the git author, On submit, re-author changes to reflect the git author,

View File

@ -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"
@ -849,6 +861,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:
@ -1079,27 +1092,7 @@ class P4Submit(Command, P4UserMap):


(p4User, gitEmail) = self.p4UserForCommit(id) (p4User, gitEmail) = self.p4UserForCommit(id)


if not self.detectRenames: diff = read_pipe_lines("git diff-tree -r %s \"%s^\" \"%s\"" % (self.diffOpts, id, id))
# If not explicitly set check the config variable
self.detectRenames = gitConfig("git-p4.detectRenames")

if self.detectRenames.lower() == "false" or self.detectRenames == "":
diffOpts = ""
elif self.detectRenames.lower() == "true":
diffOpts = "-M"
else:
diffOpts = "-M%s" % self.detectRenames

detectCopies = gitConfig("git-p4.detectCopies")
if detectCopies.lower() == "true":
diffOpts += " -C"
elif detectCopies != "" and detectCopies.lower() != "false":
diffOpts += " -C%s" % detectCopies

if gitConfig("git-p4.detectCopiesHarder", "--bool") == "true":
diffOpts += " --find-copies-harder"

diff = read_pipe_lines("git diff-tree -r %s \"%s^\" \"%s\"" % (diffOpts, id, id))
filesToAdd = set() filesToAdd = set()
filesToDelete = set() filesToDelete = set()
editedFiles = set() editedFiles = set()
@ -1139,17 +1132,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']
if self.p4HasMoveCommand:
p4_edit(src) # src must be open before move
p4_move(src, dest) # opens for (move/delete, move/add)
else:
p4_integrate(src, dest) p4_integrate(src, dest)
if diff['src_sha1'] != diff['dst_sha1']: if diff['src_sha1'] != diff['dst_sha1']:
p4_edit(dest) p4_edit(dest)
else: else:
pureRenameCopy.add(dest) 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']
if not self.p4HasMoveCommand:
os.unlink(dest) os.unlink(dest)
editedFiles.add(dest)
filesToDelete.add(src) filesToDelete.add(src)
editedFiles.add(dest)
else: else:
die("unknown modifier %s for %s" % (modifier, path)) die("unknown modifier %s for %s" % (modifier, path))


@ -1457,6 +1456,37 @@ class P4Submit(Command, P4UserMap):
if self.preserveUser: if self.preserveUser:
self.checkValidP4Users(commits) self.checkValidP4Users(commits)


#
# Build up a set of options to be passed to diff when
# submitting each commit to p4.
#
if self.detectRenames:
# command-line -M arg
self.diffOpts = "-M"
else:
# If not explicitly set check the config variable
detectRenames = gitConfig("git-p4.detectRenames")

if detectRenames.lower() == "false" or detectRenames == "":
self.diffOpts = ""
elif detectRenames.lower() == "true":
self.diffOpts = "-M"
else:
self.diffOpts = "-M%s" % detectRenames

# no command-line arg for -C or --find-copies-harder, just
# config variables
detectCopies = gitConfig("git-p4.detectCopies")
if detectCopies.lower() == "false" or detectCopies == "":
pass
elif detectCopies.lower() == "true":
self.diffOpts += " -C"
else:
self.diffOpts += " -C%s" % detectCopies

if gitConfig("git-p4.detectCopiesHarder", "--bool") == "true":
self.diffOpts += " --find-copies-harder"

while len(commits) > 0: while len(commits) > 0:
commit = commits[0] commit = commits[0]
commits = commits[1:] commits = commits[1:]

View File

@ -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
) )
' '