Merge branch 'cp/p4'
* cp/p4: git-p4: Detect changes to executable bit and include them in p4 submit. git-p4: Add a helper function to parse the full git diff-tree output.
This commit is contained in:
commit
7481ebe991
@ -71,6 +71,79 @@ def isP4Exec(kind):
|
|||||||
a plus sign, it is also executable"""
|
a plus sign, it is also executable"""
|
||||||
return (re.search(r"(^[cku]?x)|\+.*x", kind) != None)
|
return (re.search(r"(^[cku]?x)|\+.*x", kind) != None)
|
||||||
|
|
||||||
|
def setP4ExecBit(file, mode):
|
||||||
|
# Reopens an already open file and changes the execute bit to match
|
||||||
|
# the execute bit setting in the passed in mode.
|
||||||
|
|
||||||
|
p4Type = "+x"
|
||||||
|
|
||||||
|
if not isModeExec(mode):
|
||||||
|
p4Type = getP4OpenedType(file)
|
||||||
|
p4Type = re.sub('^([cku]?)x(.*)', '\\1\\2', p4Type)
|
||||||
|
p4Type = re.sub('(.*?\+.*?)x(.*?)', '\\1\\2', p4Type)
|
||||||
|
if p4Type[-1] == "+":
|
||||||
|
p4Type = p4Type[0:-1]
|
||||||
|
|
||||||
|
system("p4 reopen -t %s %s" % (p4Type, file))
|
||||||
|
|
||||||
|
def getP4OpenedType(file):
|
||||||
|
# Returns the perforce file type for the given file.
|
||||||
|
|
||||||
|
result = read_pipe("p4 opened %s" % file)
|
||||||
|
match = re.match(".*\((.+)\)$", result)
|
||||||
|
if match:
|
||||||
|
return match.group(1)
|
||||||
|
else:
|
||||||
|
die("Could not determine file type for %s" % file)
|
||||||
|
|
||||||
|
def diffTreePattern():
|
||||||
|
# This is a simple generator for the diff tree regex pattern. This could be
|
||||||
|
# a class variable if this and parseDiffTreeEntry were a part of a class.
|
||||||
|
pattern = re.compile(':(\d+) (\d+) (\w+) (\w+) ([A-Z])(\d+)?\t(.*?)((\t(.*))|$)')
|
||||||
|
while True:
|
||||||
|
yield pattern
|
||||||
|
|
||||||
|
def parseDiffTreeEntry(entry):
|
||||||
|
"""Parses a single diff tree entry into its component elements.
|
||||||
|
|
||||||
|
See git-diff-tree(1) manpage for details about the format of the diff
|
||||||
|
output. This method returns a dictionary with the following elements:
|
||||||
|
|
||||||
|
src_mode - The mode of the source file
|
||||||
|
dst_mode - The mode of the destination file
|
||||||
|
src_sha1 - The sha1 for the source file
|
||||||
|
dst_sha1 - The sha1 fr the destination file
|
||||||
|
status - The one letter status of the diff (i.e. 'A', 'M', 'D', etc)
|
||||||
|
status_score - The score for the status (applicable for 'C' and 'R'
|
||||||
|
statuses). This is None if there is no score.
|
||||||
|
src - The path for the source file.
|
||||||
|
dst - The path for the destination file. This is only present for
|
||||||
|
copy or renames. If it is not present, this is None.
|
||||||
|
|
||||||
|
If the pattern is not matched, None is returned."""
|
||||||
|
|
||||||
|
match = diffTreePattern().next().match(entry)
|
||||||
|
if match:
|
||||||
|
return {
|
||||||
|
'src_mode': match.group(1),
|
||||||
|
'dst_mode': match.group(2),
|
||||||
|
'src_sha1': match.group(3),
|
||||||
|
'dst_sha1': match.group(4),
|
||||||
|
'status': match.group(5),
|
||||||
|
'status_score': match.group(6),
|
||||||
|
'src': match.group(7),
|
||||||
|
'dst': match.group(10)
|
||||||
|
}
|
||||||
|
return None
|
||||||
|
|
||||||
|
def isModeExec(mode):
|
||||||
|
# Returns True if the given git mode represents an executable file,
|
||||||
|
# otherwise False.
|
||||||
|
return mode[-3:] == "755"
|
||||||
|
|
||||||
|
def isModeExecChanged(src_mode, dst_mode):
|
||||||
|
return isModeExec(src_mode) != isModeExec(dst_mode)
|
||||||
|
|
||||||
def p4CmdList(cmd, stdin=None, stdin_mode='w+b'):
|
def p4CmdList(cmd, stdin=None, stdin_mode='w+b'):
|
||||||
cmd = "p4 -G %s" % cmd
|
cmd = "p4 -G %s" % cmd
|
||||||
if verbose:
|
if verbose:
|
||||||
@ -494,18 +567,23 @@ class P4Submit(Command):
|
|||||||
else:
|
else:
|
||||||
print "Applying %s" % (read_pipe("git log --max-count=1 --pretty=oneline %s" % id))
|
print "Applying %s" % (read_pipe("git log --max-count=1 --pretty=oneline %s" % id))
|
||||||
diffOpts = ("", "-M")[self.detectRename]
|
diffOpts = ("", "-M")[self.detectRename]
|
||||||
diff = read_pipe_lines("git diff-tree -r --name-status %s \"%s^\" \"%s\"" % (diffOpts, id, id))
|
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()
|
||||||
|
filesToChangeExecBit = {}
|
||||||
for line in diff:
|
for line in diff:
|
||||||
modifier = line[0]
|
diff = parseDiffTreeEntry(line)
|
||||||
path = line[1:].strip()
|
modifier = diff['status']
|
||||||
|
path = diff['src']
|
||||||
if modifier == "M":
|
if modifier == "M":
|
||||||
system("p4 edit \"%s\"" % path)
|
system("p4 edit \"%s\"" % path)
|
||||||
|
if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
|
||||||
|
filesToChangeExecBit[path] = diff['dst_mode']
|
||||||
editedFiles.add(path)
|
editedFiles.add(path)
|
||||||
elif modifier == "A":
|
elif modifier == "A":
|
||||||
filesToAdd.add(path)
|
filesToAdd.add(path)
|
||||||
|
filesToChangeExecBit[path] = diff['dst_mode']
|
||||||
if path in filesToDelete:
|
if path in filesToDelete:
|
||||||
filesToDelete.remove(path)
|
filesToDelete.remove(path)
|
||||||
elif modifier == "D":
|
elif modifier == "D":
|
||||||
@ -513,9 +591,11 @@ class P4Submit(Command):
|
|||||||
if path in filesToAdd:
|
if path in filesToAdd:
|
||||||
filesToAdd.remove(path)
|
filesToAdd.remove(path)
|
||||||
elif modifier == "R":
|
elif modifier == "R":
|
||||||
src, dest = line.strip().split("\t")[1:3]
|
src, dest = diff['src'], diff['dst']
|
||||||
system("p4 integrate -Dt \"%s\" \"%s\"" % (src, dest))
|
system("p4 integrate -Dt \"%s\" \"%s\"" % (src, dest))
|
||||||
system("p4 edit \"%s\"" % (dest))
|
system("p4 edit \"%s\"" % (dest))
|
||||||
|
if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
|
||||||
|
filesToChangeExecBit[dest] = diff['dst_mode']
|
||||||
os.unlink(dest)
|
os.unlink(dest)
|
||||||
editedFiles.add(dest)
|
editedFiles.add(dest)
|
||||||
filesToDelete.add(src)
|
filesToDelete.add(src)
|
||||||
@ -568,6 +648,11 @@ class P4Submit(Command):
|
|||||||
system("p4 revert \"%s\"" % f)
|
system("p4 revert \"%s\"" % f)
|
||||||
system("p4 delete \"%s\"" % f)
|
system("p4 delete \"%s\"" % f)
|
||||||
|
|
||||||
|
# Set/clear executable bits
|
||||||
|
for f in filesToChangeExecBit.keys():
|
||||||
|
mode = filesToChangeExecBit[f]
|
||||||
|
setP4ExecBit(f, mode)
|
||||||
|
|
||||||
logMessage = ""
|
logMessage = ""
|
||||||
if not self.directSubmit:
|
if not self.directSubmit:
|
||||||
logMessage = extractLogMessageFromGitCommit(id)
|
logMessage = extractLogMessageFromGitCommit(id)
|
||||||
|
Loading…
Reference in New Issue
Block a user