@ -7082,17 +7082,67 @@ def _RunLUCICfgFormat(opts, paths, top_dir, upstream_commit):
FormatterFunction = Callable [ [ Any , list [ str ] , str , str ] , int ]
def _SplitDiffsByFile ( diff_string : str ) - > Dict [ str , str ] :
""" Split a given diff string into per-file patches.
This function expects that the diff_string was generated with a prefix .
In other words , if it was generated by git - diff , don ' t add `--no-prefix`.
` diff ` always generates one with prefixes .
Deleted files will be skipped .
Args :
diff_string : Unified diff
Returns :
a dict of file_path - > patch
"""
if not diff_string :
return { }
file_diffs = re . split ( r ' ^(?=diff --git) ' , diff_string , flags = re . MULTILINE )
file_diffs = [ d for d in file_diffs if d . strip ( ) ]
ret = { }
for file_diff in file_diffs :
# Look for the line with `+++ ${prefix}/path/file.cc`
# For file deletion, the line would be omitted or with `+++ /dev/null`,
# which wouldn't match the regex.
match = re . search ( r ' ^ \ + \ + \ + [^ \ s/]+/(.+) ' ,
file_diff ,
flags = re . MULTILINE )
if match :
ret [ match . group ( 1 ) ] = file_diff
return ret
def _FindFilesToFormat (
opts : optparse . Values , files : list [ str ] | None ,
upstream_commit : str | None ) - > Tuple [ List [ str ] , Dict [ str , str ] | None ] :
""" Returns a list of files to format and the diffs.
If opts . full , returns None for the diffs .
Deleted files are always excluded in the return .
"""
if opts . input_diff_file :
with open ( opts . input_diff_file ) as f :
diffs = _SplitDiffsByFile ( f . read ( ) )
return diffs . keys ( ) , diffs
if opts . full :
files = RunGitDiffCmd ( [ ' --name-only ' , ' --diff-filter=d ' ] ,
upstream_commit , files ) . splitlines ( )
return files . keys ( ) , None
diffs = _SplitDiffsByFile (
RunGitDiffCmd ( [ ' -U0 ' ] , upstream_commit , files , allow_prefix = True ) )
return diffs . keys ( ) , diffs
@subcommand.usage ( ' [files or directories to diff] ' )
@metrics.collector.collect_metrics ( ' git cl format ' )
def CMDformat ( parser : optparse . OptionParser , args : list [ str ] ) :
""" Runs auto-formatting tools (clang-format etc.) on the diff. """
if gclient_utils . IsEnvCog ( ) :
print (
' format command is not supported in non-git environment. Please '
' use the " Format Modified Lines in All Files (git cl format) " '
' functionality in the command palette in the editor instead. ' ,
file = sys . stderr )
return 1
clang_exts = [ ' .cc ' , ' .cpp ' , ' .h ' , ' .m ' , ' .mm ' , ' .proto ' ]
GN_EXTS = [ ' .gn ' , ' .gni ' , ' .typemap ' ]
parser . add_option ( ' --full ' ,
@ -7154,26 +7204,46 @@ def CMDformat(parser: optparse.OptionParser, args: list[str]):
dest = ' use_swift_format ' ,
action = ' store_false ' ,
help = ' Disables formatting of Swift file types using swift-format. ' )
parser . add_option ( ' --input_diff_file ' ,
help = ' File to read input change diff from. '
' If given, the added blocks of the files in the diff '
' will be formatted. ' )
parser . add_option ( ' --mojom ' ,
action = ' store_true ' ,
help = ' Enables formatting of .mojom files. ' )
parser . add_option ( ' --no-java ' ,
action = ' store_true ' ,
help = ' Disable auto-formatting of .java ' )
parser . add_option ( ' --lucicfg ' ,
action = ' store_true ' ,
help = ' Enables formatting of .star files. ' )
opts , files = parser . parse_args ( args )
opts . full = opts . full or settings . GetFormatFullByDefault ( )
# Normalize files against the current path, so paths relative to the
# current directory are still resolved as expected.
files = [ os . path . join ( os . getcwd ( ) , file ) for file in files ]
upstream_commit : str | None = None
upstream_branch : str | None = opts . upstream
top_dir : str | None = None
if opts . input_diff_file :
if opts . full :
print ( ' --full and --input_diff_file cannot be used together. ' ,
file = sys . stderr )
return 1
if files :
print (
' No file paths to format are allowed '
' if --input_diff_file is given. ' ,
file = sys . stderr )
return 1
elif gclient_utils . IsEnvCog ( ) :
print (
' Use --input_diff_file to run the format command in non-git '
' environments. In CiderG, please use the '
' " Format Modified Lines in All Files (git cl format) " '
' functionality in the command palette instead. ' ,
file = sys . stderr )
return 1
else :
opts . full = opts . full or settings . GetFormatFullByDefault ( )
# git diff generates paths against the root of the repository. Change
# to that directory so clang-format can find files even within subdirs.
rel_base_path = settings . GetRelativeRoot ( )
@ -7184,23 +7254,20 @@ def CMDformat(parser: optparse.OptionParser, args: list[str]):
# branch when it was created or the last time it was rebased. This is
# to cover the case where the user may have called "git fetch origin",
# moving the origin branch to a newer commit, but hasn't rebased yet.
upstream_commit : str | None = None
upstream_branch : str | None = opts . upstream
if not upstream_branch :
cl = Changelist ( )
upstream_branch = cl . GetUpstreamBranch ( )
if upstream_branch :
upstream_commit = RunGit ( [ ' merge-base ' , ' HEAD ' ,
upstream_branch ] ) . strip ( )
if not upstream_commit :
DieWithError ( ' Could not find base commit for this branch. '
' Are you in detached state? ' )
# Filter out deleted files
diff_output = RunGitDiffCmd ( [ ' --name-only ' , ' --diff-filter=d ' ] ,
upstream_commit , files )
diff_files = diff_output . splitlines ( )
# Normalize files against the current path, so paths relative to the
# current directory are still resolved as expected.
files = [ os . path . join ( os . getcwd ( ) , file ) for file in files ]
diff_files , _ = _FindFilesToFormat ( opts , files , upstream_commit )
if opts . js :
clang_exts . extend ( [ ' .js ' , ' .ts ' ] )
@ -7224,7 +7291,7 @@ def CMDformat(parser: optparse.OptionParser, args: list[str]):
if opts . lucicfg :
formatters . append ( ( [ ' .star ' ] , _RunLUCICfgFormat ) )
top_dir = settings. GetRoot ( )
top_dir = os. getcwd ( ) if opts . presubmit else settings. GetRoot ( )
return_value = 0
for file_types , format_func in formatters :
paths = [ p for p in diff_files if p . lower ( ) . endswith ( tuple ( file_types ) ) ]