Support git cl formatting for swift files

swift format is only available on mac hosts.
Swift formatting is disabled by default. It will be
enabled by default on mac host in another CL.

Change-Id: Id603be203edd44b6419d545027c249111abe1baf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/3550197
Reviewed-by: Josip Sokcevic <sokcevic@google.com>
Commit-Queue: Olivier Robin <olivierrobin@chromium.org>
diff --git a/git_cl.py b/git_cl.py
index 5751929..1e2f675 100755
--- a/git_cl.py
+++ b/git_cl.py
@@ -52,6 +52,7 @@
 import split_cl
 import subcommand
 import subprocess2
+import swift_format
 import watchlists
 
 from third_party import six
@@ -5143,6 +5144,33 @@
   return 0
 
 
+def _RunSwiftFormat(opts, swift_diff_files, top_dir, upstream_commit):
+  """Runs swift-format.  Just like _RunClangFormatDiff returns 2 to indicate
+  that presubmit checks have failed (and returns 0 otherwise)."""
+
+  if not swift_diff_files:
+    return 0
+
+  # Locate the swift-format binary.
+  try:
+    swift_format_tool = swift_format.FindSwiftFormatToolInChromiumTree()
+  except swift_format.NotFoundError as e:
+    DieWithError(e)
+
+  cmd = [swift_format_tool]
+  if opts.dry_run:
+    cmd.append('lint')
+  else:
+    cmd += ['format', '-i']
+  cmd += swift_diff_files
+  swift_format_exitcode = subprocess2.call(cmd)
+
+  if opts.presubmit and swift_format_exitcode != 0:
+    return 2
+
+  return 0
+
+
 def MatchingFileType(file_name, extensions):
   """Returns True if the file name ends with one of the given extensions."""
   return bool([ext for ext in extensions if file_name.lower().endswith(ext)])
@@ -5155,6 +5183,7 @@
   CLANG_EXTS = ['.cc', '.cpp', '.h', '.m', '.mm', '.proto', '.java']
   GN_EXTS = ['.gn', '.gni', '.typemap']
   RUST_EXTS = ['.rs']
+  SWIFT_EXTS = ['.swift']
   parser.add_option('--full', action='store_true',
                     help='Reformat the full content of all touched files')
   parser.add_option('--upstream', help='Branch to check against')
@@ -5200,6 +5229,19 @@
       action='store_false',
       help='Disables formatting of Rust file types using rustfmt.')
 
+  parser.add_option(
+      '--swift-format',
+      dest='use_swift_format',
+      action='store_true',
+      default=False,
+      help='Enables formatting of Swift file types using swift-format '
+      '(macOS host only).')
+  parser.add_option(
+      '--no-swift-format',
+      dest='use_swift_format',
+      action='store_false',
+      help='Disables formatting of Swift file types using swift-format.')
+
   opts, args = parser.parse_args(args)
 
   if opts.python is not None and opts.no_python:
@@ -5250,6 +5292,7 @@
     ]
   python_diff_files = [x for x in diff_files if MatchingFileType(x, ['.py'])]
   rust_diff_files = [x for x in diff_files if MatchingFileType(x, RUST_EXTS)]
+  swift_diff_files = [x for x in diff_files if MatchingFileType(x, SWIFT_EXTS)]
   gn_diff_files = [x for x in diff_files if MatchingFileType(x, GN_EXTS)]
 
   top_dir = settings.GetRoot()
@@ -5263,6 +5306,14 @@
     if rust_fmt_return_value == 2:
       return_value = 2
 
+  if opts.use_swift_format:
+    if sys.platform != 'darwin':
+      DieWithError('swift-format is only supported on macOS.')
+    swift_format_return_value = _RunSwiftFormat(opts, swift_diff_files, top_dir,
+                                                upstream_commit)
+    if swift_format_return_value == 2:
+      return_value = 2
+
   # Similar code to above, but using yapf on .py files rather than clang-format
   # on C/C++ files
   py_explicitly_disabled = opts.python is not None and not opts.python