git-p4: improve consistency of docstring formatting

This patch attempts to improve the consistency of the docstrings by
making the following changes:

  - Rewraps all docstrings to a 79-character column limit.
  - Adds a full stop at the end of every docstring.
  - Removes any spaces after the opening triple-quotes of all
    docstrings.
  - Sets the hanging indent of multi-line docstrings to 3-spaces.
  - Ensures that the closing triple-quotes of multi-line docstrings are
    always on a new line indented by a 3-space indent.

Signed-off-by: Joel Holdsworth <jholdsworth@nvidia.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Joel Holdsworth 2022-04-01 15:24:46 +01:00 committed by Junio C Hamano
parent 812ee74ea0
commit 59ef3fc104
1 changed files with 154 additions and 129 deletions

283
git-p4.py
View File

@ -61,9 +61,9 @@ re_k_keywords = re.compile(br'\$(Id|Header|Author|Date|DateTime|Change|File|Revi




def format_size_human_readable(num): def format_size_human_readable(num):
""" Returns a number of units (typically bytes) formatted as a human-readable """Returns a number of units (typically bytes) formatted as a
string. human-readable string.
""" """
if num < 1024: if num < 1024:
return '{:d} B'.format(num) return '{:d} B'.format(num)
for unit in ["Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]: for unit in ["Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]:
@ -76,10 +76,10 @@ def format_size_human_readable(num):
def p4_build_cmd(cmd): def p4_build_cmd(cmd):
"""Build a suitable p4 command line. """Build a suitable p4 command line.


This consolidates building and returning a p4 command line into one This consolidates building and returning a p4 command line into one
location. It means that hooking into the environment, or other configuration location. It means that hooking into the environment, or other
can be done more easily. configuration can be done more easily.
""" """
real_cmd = ["p4"] real_cmd = ["p4"]


user = gitConfig("git-p4.user") user = gitConfig("git-p4.user")
@ -122,9 +122,9 @@ def p4_build_cmd(cmd):




def git_dir(path): def git_dir(path):
""" Return TRUE if the given path is a git directory (/path/to/dir/.git). """Return TRUE if the given path is a git directory (/path/to/dir/.git).
This won't automatically add ".git" to a directory. This won't automatically add ".git" to a directory.
""" """
d = read_pipe(["git", "--git-dir", path, "rev-parse", "--git-dir"], True).strip() d = read_pipe(["git", "--git-dir", path, "rev-parse", "--git-dir"], True).strip()
if not d or len(d) == 0: if not d or len(d) == 0:
return None return None
@ -133,20 +133,18 @@ def git_dir(path):




def chdir(path, is_client_path=False): def chdir(path, is_client_path=False):
"""Do chdir to the given path, and set the PWD environment """Do chdir to the given path, and set the PWD environment variable for use
variable for use by P4. It does not look at getcwd() output. by P4. It does not look at getcwd() output. Since we're not using the
Since we're not using the shell, it is necessary to set the shell, it is necessary to set the PWD environment variable explicitly.
PWD environment variable explicitly.


Normally, expand the path to force it to be absolute. This Normally, expand the path to force it to be absolute. This addresses
addresses the use of relative path names inside P4 settings, the use of relative path names inside P4 settings, e.g.
e.g. P4CONFIG=.p4config. P4 does not simply open the filename P4CONFIG=.p4config. P4 does not simply open the filename as given; it
as given; it looks for .p4config using PWD. looks for .p4config using PWD.


If is_client_path, the path was handed to us directly by p4, If is_client_path, the path was handed to us directly by p4, and may be
and may be a symbolic link. Do not call os.getcwd() in this a symbolic link. Do not call os.getcwd() in this case, because it will
case, because it will cause p4 to think that PWD is not inside cause p4 to think that PWD is not inside the client path.
the client path.
""" """


os.chdir(path) os.chdir(path)
@ -167,9 +165,9 @@ def calcDiskFree():




def die(msg): def die(msg):
""" Terminate execution. Make sure that any running child processes have been wait()ed for before """Terminate execution. Make sure that any running child processes have
calling this. been wait()ed for before calling this.
""" """
if verbose: if verbose:
raise Exception(msg) raise Exception(msg)
else: else:
@ -178,11 +176,11 @@ def die(msg):




def prompt(prompt_text): def prompt(prompt_text):
""" Prompt the user to choose one of the choices """Prompt the user to choose one of the choices.


Choices are identified in the prompt_text by square brackets around Choices are identified in the prompt_text by square brackets around a
a single letter option. single letter option.
""" """
choices = set(m.group(1) for m in re.finditer(r"\[(.)\]", prompt_text)) choices = set(m.group(1) for m in re.finditer(r"\[(.)\]", prompt_text))
while True: while True:
sys.stderr.flush() sys.stderr.flush()
@ -215,8 +213,10 @@ else:




def decode_path(path): def decode_path(path):
"""Decode a given string (bytes or otherwise) using configured path encoding options """Decode a given string (bytes or otherwise) using configured path
""" encoding options.
"""

encoding = gitConfig('git-p4.pathEncoding') or 'utf_8' encoding = gitConfig('git-p4.pathEncoding') or 'utf_8'
if bytes is not str: if bytes is not str:
return path.decode(encoding, errors='replace') if isinstance(path, bytes) else path return path.decode(encoding, errors='replace') if isinstance(path, bytes) else path
@ -262,10 +262,9 @@ def p4_write_pipe(c, stdin, *k, **kw):




def read_pipe_full(c, *k, **kw): def read_pipe_full(c, *k, **kw):
""" Read output from command. Returns a tuple """Read output from command. Returns a tuple of the return status, stdout
of the return status, stdout text and stderr text and stderr text.
text. """
"""
if verbose: if verbose:
sys.stderr.write('Reading pipe: {}\n'.format(' '.join(c))) sys.stderr.write('Reading pipe: {}\n'.format(' '.join(c)))


@ -276,12 +275,12 @@ def read_pipe_full(c, *k, **kw):




def read_pipe(c, ignore_error=False, raw=False, *k, **kw): def read_pipe(c, ignore_error=False, raw=False, *k, **kw):
""" Read output from command. Returns the output text on """Read output from command. Returns the output text on success. On
success. On failure, terminates execution, unless failure, terminates execution, unless ignore_error is True, when it
ignore_error is True, when it returns an empty string. returns an empty string.


If raw is True, do not attempt to decode output text. If raw is True, do not attempt to decode output text.
""" """
(retcode, out, err) = read_pipe_full(c, *k, **kw) (retcode, out, err) = read_pipe_full(c, *k, **kw)
if retcode != 0: if retcode != 0:
if ignore_error: if ignore_error:
@ -294,9 +293,9 @@ def read_pipe(c, ignore_error=False, raw=False, *k, **kw):




def read_pipe_text(c, *k, **kw): def read_pipe_text(c, *k, **kw):
""" Read output from a command with trailing whitespace stripped. """Read output from a command with trailing whitespace stripped. On error,
On error, returns None. returns None.
""" """
(retcode, out, err) = read_pipe_full(c, *k, **kw) (retcode, out, err) = read_pipe_full(c, *k, **kw)
if retcode != 0: if retcode != 0:
return None return None
@ -324,14 +323,15 @@ def read_pipe_lines(c, raw=False, *k, **kw):




def p4_read_pipe_lines(c, *k, **kw): def p4_read_pipe_lines(c, *k, **kw):
"""Specifically invoke p4 on the command supplied. """ """Specifically invoke p4 on the command supplied."""
real_cmd = p4_build_cmd(c) real_cmd = p4_build_cmd(c)
return read_pipe_lines(real_cmd, *k, **kw) return read_pipe_lines(real_cmd, *k, **kw)




def p4_has_command(cmd): def p4_has_command(cmd):
"""Ask p4 for help on this command. If it returns an error, the """Ask p4 for help on this command. If it returns an error, the command
command does not exist in this version of p4.""" does not exist in this version of p4.
"""
real_cmd = p4_build_cmd(["help", cmd]) real_cmd = p4_build_cmd(["help", cmd])
p = subprocess.Popen(real_cmd, stdout=subprocess.PIPE, p = subprocess.Popen(real_cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE) stderr=subprocess.PIPE)
@ -340,10 +340,11 @@ def p4_has_command(cmd):




def p4_has_move_command(): def p4_has_move_command():
"""See if the move command exists, that it supports -k, and that """See if the move command exists, that it supports -k, and that it has not
it has not been administratively disabled. The arguments been administratively disabled. The arguments must be correct, but the
must be correct, but the filenames do not have to exist. Use filenames do not have to exist. Use ones with wildcards so even if they
ones with wildcards so even if they exist, it will fail.""" exist, it will fail.
"""


if not p4_has_command("move"): if not p4_has_command("move"):
return False return False
@ -372,7 +373,7 @@ def system(cmd, ignore_error=False, *k, **kw):




def p4_system(cmd, *k, **kw): def p4_system(cmd, *k, **kw):
"""Specifically invoke p4 as the system command. """ """Specifically invoke p4 as the system command."""
real_cmd = p4_build_cmd(cmd) real_cmd = p4_build_cmd(cmd)
retcode = subprocess.call(real_cmd, *k, **kw) retcode = subprocess.call(real_cmd, *k, **kw)
if retcode: if retcode:
@ -384,8 +385,8 @@ def die_bad_access(s):




def p4_check_access(min_expiration=1): def p4_check_access(min_expiration=1):
""" Check if we can access Perforce - account still logged in """Check if we can access Perforce - account still logged in."""
"""
results = p4CmdList(["login", "-s"]) results = p4CmdList(["login", "-s"])


if len(results) == 0: if len(results) == 0:
@ -433,14 +434,14 @@ _p4_version_string = None




def p4_version_string(): def p4_version_string():
"""Read the version string, showing just the last line, which """Read the version string, showing just the last line, which hopefully is
hopefully is the interesting version bit. the interesting version bit.


$ p4 -V $ p4 -V
Perforce - The Fast Software Configuration Management System. Perforce - The Fast Software Configuration Management System.
Copyright 1995-2011 Perforce Software. All rights reserved. Copyright 1995-2011 Perforce Software. All rights reserved.
Rev. P4/NTX86/2011.1/393975 (2011/12/16). Rev. P4/NTX86/2011.1/393975 (2011/12/16).
""" """
global _p4_version_string global _p4_version_string
if not _p4_version_string: if not _p4_version_string:
a = p4_read_pipe_lines(["-V"]) a = p4_read_pipe_lines(["-V"])
@ -495,9 +496,11 @@ def p4_last_change():




def p4_describe(change, shelved=False): def p4_describe(change, shelved=False):
"""Make sure it returns a valid result by checking for """Make sure it returns a valid result by checking for the presence of
the presence of field "time". Return a dict of the field "time".
results."""
Return a dict of the results.
"""


cmd = ["describe", "-s"] cmd = ["describe", "-s"]
if shelved: if shelved:
@ -651,21 +654,22 @@ _diff_tree_pattern = None
def parseDiffTreeEntry(entry): def parseDiffTreeEntry(entry):
"""Parses a single diff tree entry into its component elements. """Parses a single diff tree entry into its component elements.


See git-diff-tree(1) manpage for details about the format of the diff See git-diff-tree(1) manpage for details about the format of the diff
output. This method returns a dictionary with the following elements: output. This method returns a dictionary with the following elements:


src_mode - The mode of the source file src_mode - The mode of the source file
dst_mode - The mode of the destination file dst_mode - The mode of the destination file
src_sha1 - The sha1 for the source file src_sha1 - The sha1 for the source file
dst_sha1 - The sha1 fr the destination file dst_sha1 - The sha1 fr the destination file
status - The one letter status of the diff (i.e. 'A', 'M', 'D', etc) 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' status_score - The score for the status (applicable for 'C' and 'R'
statuses). This is None if there is no score. statuses). This is None if there is no score.
src - The path for the source file. src - The path for the source file.
dst - The path for the destination file. This is only present for dst - The path for the destination file. This is only present for
copy or renames. If it is not present, this is None. copy or renames. If it is not present, this is None.


If the pattern is not matched, None is returned.""" If the pattern is not matched, None is returned.
"""


global _diff_tree_pattern global _diff_tree_pattern
if not _diff_tree_pattern: if not _diff_tree_pattern:
@ -693,14 +697,16 @@ def isModeExec(mode):




class P4Exception(Exception): class P4Exception(Exception):
""" Base class for exceptions from the p4 client """ """Base class for exceptions from the p4 client."""


def __init__(self, exit_code): def __init__(self, exit_code):
self.p4ExitCode = exit_code self.p4ExitCode = exit_code




class P4ServerException(P4Exception): class P4ServerException(P4Exception):
""" Base class for exceptions where we get some kind of marshalled up result from the server """ """Base class for exceptions where we get some kind of marshalled up result
from the server.
"""


def __init__(self, exit_code, p4_result): def __init__(self, exit_code, p4_result):
super(P4ServerException, self).__init__(exit_code) super(P4ServerException, self).__init__(exit_code)
@ -710,7 +716,7 @@ class P4ServerException(P4Exception):




class P4RequestSizeException(P4ServerException): class P4RequestSizeException(P4ServerException):
""" One of the maxresults or maxscanrows errors """ """One of the maxresults or maxscanrows errors."""


def __init__(self, exit_code, p4_result, limit): def __init__(self, exit_code, p4_result, limit):
super(P4RequestSizeException, self).__init__(exit_code, p4_result) super(P4RequestSizeException, self).__init__(exit_code, p4_result)
@ -718,7 +724,7 @@ class P4RequestSizeException(P4ServerException):




class P4CommandException(P4Exception): class P4CommandException(P4Exception):
""" Something went wrong calling p4 which means we have to give up """ """Something went wrong calling p4 which means we have to give up."""


def __init__(self, msg): def __init__(self, msg):
self.msg = msg self.msg = msg
@ -943,7 +949,8 @@ def gitConfig(key, typeSpecifier=None):
def gitConfigBool(key): def gitConfigBool(key):
"""Return a bool, using git config --bool. It is True only if the """Return a bool, using git config --bool. It is True only if the
variable is set to true, and False if set to false or not present variable is set to true, and False if set to false or not present
in the config.""" in the config.
"""


if key not in _gitConfig: if key not in _gitConfig:
_gitConfig[key] = gitConfig(key, '--bool') == "true" _gitConfig[key] = gitConfig(key, '--bool') == "true"
@ -976,7 +983,8 @@ def p4BranchesInGit(branchesAreInRemotes=True):
in remotes or heads as specified by the argument. Return in remotes or heads as specified by the argument. Return
a dictionary of { branch: revision } for each one found. a dictionary of { branch: revision } for each one found.
The branch names are the short names, without any The branch names are the short names, without any
"p4/" prefix.""" "p4/" prefix.
"""


branches = {} branches = {}


@ -1207,7 +1215,8 @@ def p4PathStartsWith(path, prefix):


def getClientSpec(): def getClientSpec():
"""Look at the p4 client spec, create a View() object that contains """Look at the p4 client spec, create a View() object that contains
all the mappings, and return it.""" all the mappings, and return it.
"""


specList = p4CmdList(["client", "-o"]) specList = p4CmdList(["client", "-o"])
if len(specList) != 1: if len(specList) != 1:
@ -1290,13 +1299,15 @@ class LargeFileSystem(object):
self.writeToGitStream = writeToGitStream self.writeToGitStream = writeToGitStream


def generatePointer(self, cloneDestination, contentFile): def generatePointer(self, cloneDestination, contentFile):
"""Return the content of a pointer file that is stored in Git instead of """Return the content of a pointer file that is stored in Git instead
the actual content.""" of the actual content.
"""
assert False, "Method 'generatePointer' required in " + self.__class__.__name__ assert False, "Method 'generatePointer' required in " + self.__class__.__name__


def pushFile(self, localLargeFile): def pushFile(self, localLargeFile):
"""Push the actual content which is not stored in the Git repository to """Push the actual content which is not stored in the Git repository to
a server.""" a server.
"""
assert False, "Method 'pushFile' required in " + self.__class__.__name__ assert False, "Method 'pushFile' required in " + self.__class__.__name__


def hasLargeFileExtension(self, relPath): def hasLargeFileExtension(self, relPath):
@ -1344,7 +1355,8 @@ class LargeFileSystem(object):
def processContent(self, git_mode, relPath, contents): def processContent(self, git_mode, relPath, contents):
"""Processes the content of git fast import. This method decides if a """Processes the content of git fast import. This method decides if a
file is stored in the large file system and handles all necessary file is stored in the large file system and handles all necessary
steps.""" steps.
"""
if self.exceedsLargeFileThreshold(relPath, contents) or self.hasLargeFileExtension(relPath): if self.exceedsLargeFileThreshold(relPath, contents) or self.hasLargeFileExtension(relPath):
contentTempFile = self.generateTempFile(contents) contentTempFile = self.generateTempFile(contents)
(pointer_git_mode, contents, localLargeFile) = self.generatePointer(contentTempFile) (pointer_git_mode, contents, localLargeFile) = self.generatePointer(contentTempFile)
@ -1369,7 +1381,8 @@ class MockLFS(LargeFileSystem):


def generatePointer(self, contentFile): def generatePointer(self, contentFile):
"""The pointer content is the original content prefixed with "pointer-". """The pointer content is the original content prefixed with "pointer-".
The local filename of the large file storage is derived from the file content. The local filename of the large file storage is derived from the
file content.
""" """
with open(contentFile, 'r') as f: with open(contentFile, 'r') as f:
content = next(f) content = next(f)
@ -1379,8 +1392,8 @@ class MockLFS(LargeFileSystem):
return (gitMode, pointerContents, localLargeFile) return (gitMode, pointerContents, localLargeFile)


def pushFile(self, localLargeFile): def pushFile(self, localLargeFile):
"""The remote filename of the large file storage is the same as the local """The remote filename of the large file storage is the same as the
one but in a different directory. local one but in a different directory.
""" """
remotePath = os.path.join(os.path.dirname(localLargeFile), '..', 'remote') remotePath = os.path.join(os.path.dirname(localLargeFile), '..', 'remote')
if not os.path.exists(remotePath): if not os.path.exists(remotePath):
@ -1390,7 +1403,8 @@ class MockLFS(LargeFileSystem):


class GitLFS(LargeFileSystem): class GitLFS(LargeFileSystem):
"""Git LFS as backend for the git-p4 large file system. """Git LFS as backend for the git-p4 large file system.
See https://git-lfs.github.com/ for details.""" See https://git-lfs.github.com/ for details.
"""


def __init__(self, *args): def __init__(self, *args):
LargeFileSystem.__init__(self, *args) LargeFileSystem.__init__(self, *args)
@ -1656,20 +1670,20 @@ class P4Submit(Command, P4UserMap):
die("You have files opened with perforce! Close them before starting the sync.") die("You have files opened with perforce! Close them before starting the sync.")


def separate_jobs_from_description(self, message): def separate_jobs_from_description(self, message):
"""Extract and return a possible Jobs field in the commit """Extract and return a possible Jobs field in the commit message. It
message. It goes into a separate section in the p4 change goes into a separate section in the p4 change specification.
specification.


A jobs line starts with "Jobs:" and looks like a new field A jobs line starts with "Jobs:" and looks like a new field in a
in a form. Values are white-space separated on the same form. Values are white-space separated on the same line or on
line or on following lines that start with a tab. following lines that start with a tab.


This does not parse and extract the full git commit message This does not parse and extract the full git commit message like a
like a p4 form. It just sees the Jobs: line as a marker p4 form. It just sees the Jobs: line as a marker to pass everything
to pass everything from then on directly into the p4 form, from then on directly into the p4 form, but outside the description
but outside the description section. section.


Return a tuple (stripped log message, jobs string).""" Return a tuple (stripped log message, jobs string).
"""


m = re.search(r'^Jobs:', message, re.MULTILINE) m = re.search(r'^Jobs:', message, re.MULTILINE)
if m is None: if m is None:
@ -1680,9 +1694,10 @@ class P4Submit(Command, P4UserMap):
return (stripped_message, jobtext) return (stripped_message, jobtext)


def prepareLogMessage(self, template, message, jobs): def prepareLogMessage(self, template, message, jobs):
"""Edits the template returned from "p4 change -o" to insert """Edits the template returned from "p4 change -o" to insert the
the message in the Description field, and the jobs text in message in the Description field, and the jobs text in the Jobs
the Jobs field.""" field.
"""
result = "" result = ""


inDescriptionSection = False inDescriptionSection = False
@ -1807,11 +1822,13 @@ class P4Submit(Command, P4UserMap):


def prepareSubmitTemplate(self, changelist=None): def prepareSubmitTemplate(self, changelist=None):
"""Run "p4 change -o" to grab a change specification template. """Run "p4 change -o" to grab a change specification template.

This does not use "p4 -G", as it is nice to keep the submission This does not use "p4 -G", as it is nice to keep the submission
template in original order, since a human might edit it. template in original order, since a human might edit it.


Remove lines in the Files section that show changes to files Remove lines in the Files section that show changes to files
outside the depot path we're committing into.""" outside the depot path we're committing into.
"""


[upstream, settings] = findUpstreamBranchPoint() [upstream, settings] = findUpstreamBranchPoint()


@ -1874,8 +1891,10 @@ class P4Submit(Command, P4UserMap):
return template return template


def edit_template(self, template_file): def edit_template(self, template_file):
"""Invoke the editor to let the user change the submission """Invoke the editor to let the user change the submission message.
message. Return true if okay to continue with the submit."""
Return true if okay to continue with the submit.
"""


# if configured to skip the editing part, just submit # if configured to skip the editing part, just submit
if gitConfigBool("git-p4.skipSubmitEdit"): if gitConfigBool("git-p4.skipSubmitEdit"):
@ -2571,8 +2590,9 @@ class P4Submit(Command, P4UserMap):




class View(object): class View(object):
"""Represent a p4 view ("p4 help views"), and map files in a """Represent a p4 view ("p4 help views"), and map files in a repo according
repo according to the view.""" to the view.
"""


def __init__(self, client_name): def __init__(self, client_name):
self.mappings = [] self.mappings = []
@ -2581,9 +2601,10 @@ class View(object):
self.client_spec_path_cache = {} self.client_spec_path_cache = {}


def append(self, view_line): def append(self, view_line):
"""Parse a view line, splitting it into depot and client """Parse a view line, splitting it into depot and client sides. Append
sides. Append to self.mappings, preserving order. This to self.mappings, preserving order. This is only needed for tag
is only needed for tag creation.""" creation.
"""


# Split the view line into exactly two words. P4 enforces # Split the view line into exactly two words. P4 enforces
# structure on these lines that simplifies this quite a bit. # structure on these lines that simplifies this quite a bit.
@ -2632,7 +2653,7 @@ class View(object):
return clientFile[len(self.client_prefix):] return clientFile[len(self.client_prefix):]


def update_client_spec_path_cache(self, files): def update_client_spec_path_cache(self, files):
""" Caching file paths by "p4 where" batch query """ """Caching file paths by "p4 where" batch query."""


# List depot file paths exclude that already cached # List depot file paths exclude that already cached
fileArgs = [f['path'] for f in files if decode_path(f['path']) not in self.client_spec_path_cache] fileArgs = [f['path'] for f in files if decode_path(f['path']) not in self.client_spec_path_cache]
@ -2664,9 +2685,11 @@ class View(object):
self.client_spec_path_cache[depotFile] = b'' self.client_spec_path_cache[depotFile] = b''


def map_in_client(self, depot_path): def map_in_client(self, depot_path):
"""Return the relative location in the client where this """Return the relative location in the client where this depot file
depot file should live. Returns "" if the file should should live.
not be mapped in the client."""
Returns "" if the file should not be mapped in the client.
"""


if gitConfigBool("core.ignorecase"): if gitConfigBool("core.ignorecase"):
depot_path = depot_path.lower() depot_path = depot_path.lower()
@ -2817,10 +2840,10 @@ class P4Sync(Command, P4UserMap):
return jobs return jobs


def stripRepoPath(self, path, prefixes): def stripRepoPath(self, path, prefixes):
"""When streaming files, this is called to map a p4 depot path """When streaming files, this is called to map a p4 depot path to where
to where it should go in git. The prefixes are either it should go in git. The prefixes are either self.depotPaths, or
self.depotPaths, or self.branchPrefixes in the case of self.branchPrefixes in the case of branch detection.
branch detection.""" """


if self.useClientSpec: if self.useClientSpec:
# branch detection moves files up a level (the branch name) # branch detection moves files up a level (the branch name)
@ -2849,8 +2872,9 @@ class P4Sync(Command, P4UserMap):
return path return path


def splitFilesIntoBranches(self, commit): def splitFilesIntoBranches(self, commit):
"""Look at each depotFile in the commit to figure out to what """Look at each depotFile in the commit to figure out to what branch it
branch it belongs.""" belongs.
"""


if self.clientSpecDirs: if self.clientSpecDirs:
files = self.extractFilesFromCommit(commit) files = self.extractFilesFromCommit(commit)
@ -3122,9 +3146,10 @@ class P4Sync(Command, P4UserMap):
return "%s <a@b>" % userid return "%s <a@b>" % userid


def streamTag(self, gitStream, labelName, labelDetails, commit, epoch): def streamTag(self, gitStream, labelName, labelDetails, commit, epoch):
""" Stream a p4 tag. """Stream a p4 tag.
commit is either a git commit, or a fast-import mark, ":<p4commit>"
""" Commit is either a git commit, or a fast-import mark, ":<p4commit>".
"""


if verbose: if verbose:
print("writing tag %s for commit %s" % (labelName, commit)) print("writing tag %s for commit %s" % (labelName, commit))
@ -4175,8 +4200,7 @@ class P4Unshelve(Command):
self.destbranch = "refs/remotes/p4-unshelved" self.destbranch = "refs/remotes/p4-unshelved"


def renameBranch(self, branch_name): def renameBranch(self, branch_name):
""" Rename the existing branch to branch_name.N """Rename the existing branch to branch_name.N ."""
"""


found = True found = True
for i in range(0,1000): for i in range(0,1000):
@ -4192,9 +4216,9 @@ class P4Unshelve(Command):
sys.exit("gave up trying to rename existing branch {0}".format(sync.branch)) sys.exit("gave up trying to rename existing branch {0}".format(sync.branch))


def findLastP4Revision(self, starting_point): def findLastP4Revision(self, starting_point):
""" Look back from starting_point for the first commit created by git-p4 """Look back from starting_point for the first commit created by git-p4
to find the P4 commit we are based on, and the depot-paths. to find the P4 commit we are based on, and the depot-paths.
""" """


for parent in (range(65535)): for parent in (range(65535)):
log = extractLogMessageFromGitCommit("{0}~{1}".format(starting_point, parent)) log = extractLogMessageFromGitCommit("{0}~{1}".format(starting_point, parent))
@ -4205,8 +4229,9 @@ class P4Unshelve(Command):
sys.exit("could not find git-p4 commits in {0}".format(self.origin)) sys.exit("could not find git-p4 commits in {0}".format(self.origin))


def createShelveParent(self, change, branch_name, sync, origin): def createShelveParent(self, change, branch_name, sync, origin):
""" Create a commit matching the parent of the shelved changelist 'change' """Create a commit matching the parent of the shelved changelist
""" 'change'.
"""
parent_description = p4_describe(change, shelved=True) parent_description = p4_describe(change, shelved=True)
parent_description['desc'] = 'parent for shelved changelist {}\n'.format(change) parent_description['desc'] = 'parent for shelved changelist {}\n'.format(change)
files = sync.extractFilesFromCommit(parent_description, shelved=False, shelved_cl=change) files = sync.extractFilesFromCommit(parent_description, shelved=False, shelved_cl=change)