git-p4: convert descriptive class and function comments into docstrings
Previously, a small number of functions, methods and classes were documented using comments. This patch improves consistency by converting these into docstrings similar to those that already exist in the script. Signed-off-by: Joel Holdsworth <jholdsworth@nvidia.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
committed by
Junio C Hamano
parent
59ef3fc104
commit
522e914f65
164
git-p4.py
164
git-p4.py
@@ -458,7 +458,7 @@ def p4_sync(f, *options):
|
|||||||
|
|
||||||
|
|
||||||
def p4_add(f):
|
def p4_add(f):
|
||||||
# forcibly add file names with wildcards
|
"""Forcibly add file names with wildcards."""
|
||||||
if wildcard_present(f):
|
if wildcard_present(f):
|
||||||
p4_system(["add", "-f", f])
|
p4_system(["add", "-f", f])
|
||||||
else:
|
else:
|
||||||
@@ -526,12 +526,10 @@ def p4_describe(change, shelved=False):
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Canonicalize the p4 type and return a tuple of the
|
|
||||||
# base type, plus any modifiers. See "p4 help filetypes"
|
|
||||||
# for a list and explanation.
|
|
||||||
#
|
|
||||||
def split_p4_type(p4type):
|
def split_p4_type(p4type):
|
||||||
|
"""Canonicalize the p4 type and return a tuple of the base type, plus any
|
||||||
|
modifiers. See "p4 help filetypes" for a list and explanation.
|
||||||
|
"""
|
||||||
|
|
||||||
p4_filetypes_historical = {
|
p4_filetypes_historical = {
|
||||||
"ctempobj": "binary+Sw",
|
"ctempobj": "binary+Sw",
|
||||||
@@ -562,19 +560,18 @@ def split_p4_type(p4type):
|
|||||||
return (base, mods)
|
return (base, mods)
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# return the raw p4 type of a file (text, text+ko, etc)
|
|
||||||
#
|
|
||||||
def p4_type(f):
|
def p4_type(f):
|
||||||
|
"""Return the raw p4 type of a file (text, text+ko, etc)."""
|
||||||
|
|
||||||
results = p4CmdList(["fstat", "-T", "headType", wildcard_encode(f)])
|
results = p4CmdList(["fstat", "-T", "headType", wildcard_encode(f)])
|
||||||
return results[0]['headType']
|
return results[0]['headType']
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Given a type base and modifier, return a regexp matching
|
|
||||||
# the keywords that can be expanded in the file
|
|
||||||
#
|
|
||||||
def p4_keywords_regexp_for_type(base, type_mods):
|
def p4_keywords_regexp_for_type(base, type_mods):
|
||||||
|
"""Given a type base and modifier, return a regexp matching the keywords
|
||||||
|
that can be expanded in the file.
|
||||||
|
"""
|
||||||
|
|
||||||
if base in ("text", "unicode", "binary"):
|
if base in ("text", "unicode", "binary"):
|
||||||
if "ko" in type_mods:
|
if "ko" in type_mods:
|
||||||
return re_ko_keywords
|
return re_ko_keywords
|
||||||
@@ -586,12 +583,11 @@ def p4_keywords_regexp_for_type(base, type_mods):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Given a file, return a regexp matching the possible
|
|
||||||
# RCS keywords that will be expanded, or None for files
|
|
||||||
# with kw expansion turned off.
|
|
||||||
#
|
|
||||||
def p4_keywords_regexp_for_file(file):
|
def p4_keywords_regexp_for_file(file):
|
||||||
|
"""Given a file, return a regexp matching the possible RCS keywords that
|
||||||
|
will be expanded, or None for files with kw expansion turned off.
|
||||||
|
"""
|
||||||
|
|
||||||
if not os.path.exists(file):
|
if not os.path.exists(file):
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
@@ -600,8 +596,9 @@ def p4_keywords_regexp_for_file(file):
|
|||||||
|
|
||||||
|
|
||||||
def setP4ExecBit(file, mode):
|
def setP4ExecBit(file, mode):
|
||||||
# Reopens an already open file and changes the execute bit to match
|
"""Reopens an already open file and changes the execute bit to match the
|
||||||
# the execute bit setting in the passed in mode.
|
execute bit setting in the passed in mode.
|
||||||
|
"""
|
||||||
|
|
||||||
p4Type = "+x"
|
p4Type = "+x"
|
||||||
|
|
||||||
@@ -616,7 +613,7 @@ def setP4ExecBit(file, mode):
|
|||||||
|
|
||||||
|
|
||||||
def getP4OpenedType(file):
|
def getP4OpenedType(file):
|
||||||
# Returns the perforce file type for the given file.
|
"""Returns the perforce file type for the given file."""
|
||||||
|
|
||||||
result = p4_read_pipe(["opened", wildcard_encode(file)])
|
result = p4_read_pipe(["opened", wildcard_encode(file)])
|
||||||
match = re.match(".*\((.+)\)( \*exclusive\*)?\r?$", result)
|
match = re.match(".*\((.+)\)( \*exclusive\*)?\r?$", result)
|
||||||
@@ -626,8 +623,9 @@ def getP4OpenedType(file):
|
|||||||
die("Could not determine file type for %s (result: '%s')" % (file, result))
|
die("Could not determine file type for %s (result: '%s')" % (file, result))
|
||||||
|
|
||||||
|
|
||||||
# Return the set of all p4 labels
|
|
||||||
def getP4Labels(depotPaths):
|
def getP4Labels(depotPaths):
|
||||||
|
"""Return the set of all p4 labels."""
|
||||||
|
|
||||||
labels = set()
|
labels = set()
|
||||||
if not isinstance(depotPaths, list):
|
if not isinstance(depotPaths, list):
|
||||||
depotPaths = [depotPaths]
|
depotPaths = [depotPaths]
|
||||||
@@ -639,8 +637,9 @@ def getP4Labels(depotPaths):
|
|||||||
return labels
|
return labels
|
||||||
|
|
||||||
|
|
||||||
# Return the set of all git tags
|
|
||||||
def getGitTags():
|
def getGitTags():
|
||||||
|
"""Return the set of all git tags."""
|
||||||
|
|
||||||
gitTags = set()
|
gitTags = set()
|
||||||
for line in read_pipe_lines(["git", "tag"]):
|
for line in read_pipe_lines(["git", "tag"]):
|
||||||
tag = line.strip()
|
tag = line.strip()
|
||||||
@@ -691,8 +690,9 @@ def parseDiffTreeEntry(entry):
|
|||||||
|
|
||||||
|
|
||||||
def isModeExec(mode):
|
def isModeExec(mode):
|
||||||
# Returns True if the given git mode represents an executable file,
|
"""Returns True if the given git mode represents an executable file,
|
||||||
# otherwise False.
|
otherwise False.
|
||||||
|
"""
|
||||||
return mode[-3:] == "755"
|
return mode[-3:] == "755"
|
||||||
|
|
||||||
|
|
||||||
@@ -1201,13 +1201,14 @@ def p4ChangesForPaths(depotPaths, changeRange, requestedBlockSize):
|
|||||||
|
|
||||||
|
|
||||||
def p4PathStartsWith(path, prefix):
|
def p4PathStartsWith(path, prefix):
|
||||||
# This method tries to remedy a potential mixed-case issue:
|
"""This method tries to remedy a potential mixed-case issue:
|
||||||
#
|
|
||||||
# If UserA adds //depot/DirA/file1
|
If UserA adds //depot/DirA/file1
|
||||||
# and UserB adds //depot/dira/file2
|
and UserB adds //depot/dira/file2
|
||||||
#
|
|
||||||
# we may or may not have a problem. If you have core.ignorecase=true,
|
we may or may not have a problem. If you have core.ignorecase=true,
|
||||||
# we treat DirA and dira as the same directory
|
we treat DirA and dira as the same directory.
|
||||||
|
"""
|
||||||
if gitConfigBool("core.ignorecase"):
|
if gitConfigBool("core.ignorecase"):
|
||||||
return path.lower().startswith(prefix.lower())
|
return path.lower().startswith(prefix.lower())
|
||||||
return path.startswith(prefix)
|
return path.startswith(prefix)
|
||||||
@@ -1259,12 +1260,14 @@ def getClientRoot():
|
|||||||
return entry["Root"]
|
return entry["Root"]
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# P4 wildcards are not allowed in filenames. P4 complains
|
|
||||||
# if you simply add them, but you can force it with "-f", in
|
|
||||||
# which case it translates them into %xx encoding internally.
|
|
||||||
#
|
|
||||||
def wildcard_decode(path):
|
def wildcard_decode(path):
|
||||||
|
"""Decode P4 wildcards into %xx encoding
|
||||||
|
|
||||||
|
P4 wildcards are not allowed in filenames. P4 complains if you simply
|
||||||
|
add them, but you can force it with "-f", in which case it translates
|
||||||
|
them into %xx encoding internally.
|
||||||
|
"""
|
||||||
|
|
||||||
# Search for and fix just these four characters. Do % last so
|
# Search for and fix just these four characters. Do % last so
|
||||||
# that fixing it does not inadvertently create new %-escapes.
|
# that fixing it does not inadvertently create new %-escapes.
|
||||||
# Cannot have * in a filename in windows; untested as to
|
# Cannot have * in a filename in windows; untested as to
|
||||||
@@ -1278,6 +1281,8 @@ def wildcard_decode(path):
|
|||||||
|
|
||||||
|
|
||||||
def wildcard_encode(path):
|
def wildcard_encode(path):
|
||||||
|
"""Encode %xx coded wildcards into P4 coding."""
|
||||||
|
|
||||||
# do % first to avoid double-encoding the %s introduced here
|
# do % first to avoid double-encoding the %s introduced here
|
||||||
path = path.replace("%", "%25") \
|
path = path.replace("%", "%25") \
|
||||||
.replace("*", "%2A") \
|
.replace("*", "%2A") \
|
||||||
@@ -1524,7 +1529,7 @@ class P4UserMap:
|
|||||||
die("Could not find your p4 user id")
|
die("Could not find your p4 user id")
|
||||||
|
|
||||||
def p4UserIsMe(self, p4User):
|
def p4UserIsMe(self, p4User):
|
||||||
# return True if the given p4 user is actually me
|
"""Return True if the given p4 user is actually me."""
|
||||||
me = self.p4UserId()
|
me = self.p4UserId()
|
||||||
if not p4User or p4User != me:
|
if not p4User or p4User != me:
|
||||||
return False
|
return False
|
||||||
@@ -1727,7 +1732,9 @@ class P4Submit(Command, P4UserMap):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def patchRCSKeywords(self, file, regexp):
|
def patchRCSKeywords(self, file, regexp):
|
||||||
# Attempt to zap the RCS keywords in a p4 controlled file matching the given regex
|
"""Attempt to zap the RCS keywords in a p4 controlled file matching the
|
||||||
|
given regex.
|
||||||
|
"""
|
||||||
(handle, outFileName) = tempfile.mkstemp(dir='.')
|
(handle, outFileName) = tempfile.mkstemp(dir='.')
|
||||||
try:
|
try:
|
||||||
with os.fdopen(handle, "wb") as outFile, open(file, "rb") as inFile:
|
with os.fdopen(handle, "wb") as outFile, open(file, "rb") as inFile:
|
||||||
@@ -1745,7 +1752,9 @@ class P4Submit(Command, P4UserMap):
|
|||||||
print("Patched up RCS keywords in %s" % file)
|
print("Patched up RCS keywords in %s" % file)
|
||||||
|
|
||||||
def p4UserForCommit(self,id):
|
def p4UserForCommit(self,id):
|
||||||
# Return the tuple (perforce user,git email) for a given git commit id
|
"""Return the tuple (perforce user,git email) for a given git commit
|
||||||
|
id.
|
||||||
|
"""
|
||||||
self.getUserMapFromPerforceServer()
|
self.getUserMapFromPerforceServer()
|
||||||
gitEmail = read_pipe(["git", "log", "--max-count=1",
|
gitEmail = read_pipe(["git", "log", "--max-count=1",
|
||||||
"--format=%ae", id])
|
"--format=%ae", id])
|
||||||
@@ -1756,7 +1765,7 @@ class P4Submit(Command, P4UserMap):
|
|||||||
return (self.emails[gitEmail],gitEmail)
|
return (self.emails[gitEmail],gitEmail)
|
||||||
|
|
||||||
def checkValidP4Users(self,commits):
|
def checkValidP4Users(self,commits):
|
||||||
# check if any git authors cannot be mapped to p4 users
|
"""Check if any git authors cannot be mapped to p4 users."""
|
||||||
for id in commits:
|
for id in commits:
|
||||||
(user,email) = self.p4UserForCommit(id)
|
(user,email) = self.p4UserForCommit(id)
|
||||||
if not user:
|
if not user:
|
||||||
@@ -1767,10 +1776,12 @@ class P4Submit(Command, P4UserMap):
|
|||||||
die("Error: %s\nSet git-p4.allowMissingP4Users to true to allow this." % msg)
|
die("Error: %s\nSet git-p4.allowMissingP4Users to true to allow this." % msg)
|
||||||
|
|
||||||
def lastP4Changelist(self):
|
def lastP4Changelist(self):
|
||||||
# Get back the last changelist number submitted in this client spec. This
|
"""Get back the last changelist number submitted in this client spec.
|
||||||
# then gets used to patch up the username in the change. If the same
|
|
||||||
# client spec is being used by multiple processes then this might go
|
This then gets used to patch up the username in the change. If the
|
||||||
# wrong.
|
same client spec is being used by multiple processes then this might
|
||||||
|
go wrong.
|
||||||
|
"""
|
||||||
results = p4CmdList(["client", "-o"]) # find the current client
|
results = p4CmdList(["client", "-o"]) # find the current client
|
||||||
client = None
|
client = None
|
||||||
for r in results:
|
for r in results:
|
||||||
@@ -1786,7 +1797,7 @@ class P4Submit(Command, P4UserMap):
|
|||||||
die("Could not get changelist number for last submit - cannot patch up user details")
|
die("Could not get changelist number for last submit - cannot patch up user details")
|
||||||
|
|
||||||
def modifyChangelistUser(self, changelist, newUser):
|
def modifyChangelistUser(self, changelist, newUser):
|
||||||
# fixup the user field of a changelist after it has been submitted.
|
"""Fixup the user field of a changelist after it has been submitted."""
|
||||||
changes = p4CmdList(["change", "-o", changelist])
|
changes = p4CmdList(["change", "-o", changelist])
|
||||||
if len(changes) != 1:
|
if len(changes) != 1:
|
||||||
die("Bad output from p4 change modifying %s to user %s" %
|
die("Bad output from p4 change modifying %s to user %s" %
|
||||||
@@ -1809,8 +1820,9 @@ class P4Submit(Command, P4UserMap):
|
|||||||
die("Could not modify user field of changelist %s to %s" % (changelist, newUser))
|
die("Could not modify user field of changelist %s to %s" % (changelist, newUser))
|
||||||
|
|
||||||
def canChangeChangelists(self):
|
def canChangeChangelists(self):
|
||||||
# check to see if we have p4 admin or super-user permissions, either of
|
"""Check to see if we have p4 admin or super-user permissions, either
|
||||||
# which are required to modify changelists.
|
of which are required to modify changelists.
|
||||||
|
"""
|
||||||
results = p4CmdList(["protects", self.depotPath])
|
results = p4CmdList(["protects", self.depotPath])
|
||||||
for r in results:
|
for r in results:
|
||||||
if 'perm' in r:
|
if 'perm' in r:
|
||||||
@@ -2262,9 +2274,11 @@ class P4Submit(Command, P4UserMap):
|
|||||||
os.remove(fileName)
|
os.remove(fileName)
|
||||||
return submitted
|
return submitted
|
||||||
|
|
||||||
# Export git tags as p4 labels. Create a p4 label and then tag
|
|
||||||
# with that.
|
|
||||||
def exportGitTags(self, gitTags):
|
def exportGitTags(self, gitTags):
|
||||||
|
"""Export git tags as p4 labels. Create a p4 label and then tag with
|
||||||
|
that.
|
||||||
|
"""
|
||||||
|
|
||||||
validLabelRegexp = gitConfig("git-p4.labelExportRegexp")
|
validLabelRegexp = gitConfig("git-p4.labelExportRegexp")
|
||||||
if len(validLabelRegexp) == 0:
|
if len(validLabelRegexp) == 0:
|
||||||
validLabelRegexp = defaultLabelRegexp
|
validLabelRegexp = defaultLabelRegexp
|
||||||
@@ -2787,8 +2801,8 @@ class P4Sync(Command, P4UserMap):
|
|||||||
self.tz = "%+03d%02d" % (- time.timezone / 3600, ((- time.timezone % 3600) / 60))
|
self.tz = "%+03d%02d" % (- time.timezone / 3600, ((- time.timezone % 3600) / 60))
|
||||||
self.labels = {}
|
self.labels = {}
|
||||||
|
|
||||||
# Force a checkpoint in fast-import and wait for it to finish
|
|
||||||
def checkpoint(self):
|
def checkpoint(self):
|
||||||
|
"""Force a checkpoint in fast-import and wait for it to finish."""
|
||||||
self.gitStream.write("checkpoint\n\n")
|
self.gitStream.write("checkpoint\n\n")
|
||||||
self.gitStream.write("progress checkpoint\n\n")
|
self.gitStream.write("progress checkpoint\n\n")
|
||||||
self.gitStream.flush()
|
self.gitStream.flush()
|
||||||
@@ -2934,10 +2948,12 @@ class P4Sync(Command, P4UserMap):
|
|||||||
print('Path with non-ASCII characters detected. Used %s to encode: %s ' % (encoding, path))
|
print('Path with non-ASCII characters detected. Used %s to encode: %s ' % (encoding, path))
|
||||||
return path
|
return path
|
||||||
|
|
||||||
# output one file from the P4 stream
|
|
||||||
# - helper for streamP4Files
|
|
||||||
|
|
||||||
def streamOneP4File(self, file, contents):
|
def streamOneP4File(self, file, contents):
|
||||||
|
"""Output one file from the P4 stream.
|
||||||
|
|
||||||
|
This is a helper for streamP4Files().
|
||||||
|
"""
|
||||||
|
|
||||||
file_path = file['depotFile']
|
file_path = file['depotFile']
|
||||||
relPath = self.stripRepoPath(decode_path(file_path), self.branchPrefixes)
|
relPath = self.stripRepoPath(decode_path(file_path), self.branchPrefixes)
|
||||||
|
|
||||||
@@ -3029,8 +3045,8 @@ class P4Sync(Command, P4UserMap):
|
|||||||
if self.largeFileSystem and self.largeFileSystem.isLargeFile(relPath):
|
if self.largeFileSystem and self.largeFileSystem.isLargeFile(relPath):
|
||||||
self.largeFileSystem.removeLargeFile(relPath)
|
self.largeFileSystem.removeLargeFile(relPath)
|
||||||
|
|
||||||
# handle another chunk of streaming data
|
|
||||||
def streamP4FilesCb(self, marshalled):
|
def streamP4FilesCb(self, marshalled):
|
||||||
|
"""Handle another chunk of streaming data."""
|
||||||
|
|
||||||
# catch p4 errors and complain
|
# catch p4 errors and complain
|
||||||
err = None
|
err = None
|
||||||
@@ -3094,8 +3110,9 @@ class P4Sync(Command, P4UserMap):
|
|||||||
|
|
||||||
self.stream_have_file_info = True
|
self.stream_have_file_info = True
|
||||||
|
|
||||||
# Stream directly from "p4 files" into "git fast-import"
|
|
||||||
def streamP4Files(self, files):
|
def streamP4Files(self, files):
|
||||||
|
"""Stream directly from "p4 files" into "git fast-import."""
|
||||||
|
|
||||||
filesForCommit = []
|
filesForCommit = []
|
||||||
filesToRead = []
|
filesToRead = []
|
||||||
filesToDelete = []
|
filesToDelete = []
|
||||||
@@ -3199,15 +3216,18 @@ class P4Sync(Command, P4UserMap):
|
|||||||
return hasPrefix
|
return hasPrefix
|
||||||
|
|
||||||
def findShadowedFiles(self, files, change):
|
def findShadowedFiles(self, files, change):
|
||||||
# Perforce allows you commit files and directories with the same name,
|
"""Perforce allows you commit files and directories with the same name,
|
||||||
# so you could have files //depot/foo and //depot/foo/bar both checked
|
so you could have files //depot/foo and //depot/foo/bar both checked
|
||||||
# in. A p4 sync of a repository in this state fails. Deleting one of
|
in. A p4 sync of a repository in this state fails. Deleting one of
|
||||||
# the files recovers the repository.
|
the files recovers the repository.
|
||||||
#
|
|
||||||
# Git will not allow the broken state to exist and only the most recent
|
Git will not allow the broken state to exist and only the most
|
||||||
# of the conflicting names is left in the repository. When one of the
|
recent of the conflicting names is left in the repository. When one
|
||||||
# conflicting files is deleted we need to re-add the other one to make
|
of the conflicting files is deleted we need to re-add the other one
|
||||||
# sure the git repository recovers in the same way as perforce.
|
to make sure the git repository recovers in the same way as
|
||||||
|
perforce.
|
||||||
|
"""
|
||||||
|
|
||||||
deleted = [f for f in files if f['action'] in self.delete_actions]
|
deleted = [f for f in files if f['action'] in self.delete_actions]
|
||||||
to_check = set()
|
to_check = set()
|
||||||
for f in deleted:
|
for f in deleted:
|
||||||
@@ -3324,8 +3344,11 @@ class P4Sync(Command, P4UserMap):
|
|||||||
print("Tag %s does not match with change %s: file count is different."
|
print("Tag %s does not match with change %s: file count is different."
|
||||||
% (labelDetails["label"], change))
|
% (labelDetails["label"], change))
|
||||||
|
|
||||||
# Build a dictionary of changelists and labels, for "detect-labels" option.
|
|
||||||
def getLabels(self):
|
def getLabels(self):
|
||||||
|
"""Build a dictionary of changelists and labels, for "detect-labels"
|
||||||
|
option.
|
||||||
|
"""
|
||||||
|
|
||||||
self.labels = {}
|
self.labels = {}
|
||||||
|
|
||||||
l = p4CmdList(["labels"] + ["%s..." % p for p in self.depotPaths])
|
l = p4CmdList(["labels"] + ["%s..." % p for p in self.depotPaths])
|
||||||
@@ -3351,11 +3374,12 @@ class P4Sync(Command, P4UserMap):
|
|||||||
if self.verbose:
|
if self.verbose:
|
||||||
print("Label changes: %s" % self.labels.keys())
|
print("Label changes: %s" % self.labels.keys())
|
||||||
|
|
||||||
# Import p4 labels as git tags. A direct mapping does not
|
|
||||||
# exist, so assume that if all the files are at the same revision
|
|
||||||
# then we can use that, or it's something more complicated we should
|
|
||||||
# just ignore.
|
|
||||||
def importP4Labels(self, stream, p4Labels):
|
def importP4Labels(self, stream, p4Labels):
|
||||||
|
"""Import p4 labels as git tags. A direct mapping does not exist, so
|
||||||
|
assume that if all the files are at the same revision then we can
|
||||||
|
use that, or it's something more complicated we should just ignore.
|
||||||
|
"""
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
print("import p4 labels: " + ' '.join(p4Labels))
|
print("import p4 labels: " + ' '.join(p4Labels))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user