Pārlūkot izejas kodu

Add a --max-depth option to git cl split

For some types of changes, git cl split generates too many small CLs.
--max-depth provides one way of generating larger CLs when the author
judges that the larger CLs do not adversely affect reviewability (e.g.
20x 1 line CLs packed into 1x 20 line CL is generally fine).

Fixed: 777781
Change-Id: I64426ff4723fbc412fbc47f3cc12767433aeb8ae
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/3933974
Reviewed-by: Josip Sokcevic <sokcevic@google.com>
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Daniel Cheng 2 gadi atpakaļ
vecāks
revīzija
403c44e293
2 mainītis faili ar 24 papildinājumiem un 8 dzēšanām
  1. 12 4
      git_cl.py
  2. 12 4
      split_cl.py

+ 12 - 4
git_cl.py

@@ -4509,6 +4509,14 @@ def CMDsplit(parser, args):
                     help='Sends your change to the CQ after an approval. Only '
                     help='Sends your change to the CQ after an approval. Only '
                          'works on repos that have the Auto-Submit label '
                          'works on repos that have the Auto-Submit label '
                          'enabled')
                          'enabled')
+  parser.add_option('--max-depth',
+                    type='int',
+                    default=0,
+                    help='The max depth to look for OWNERS files. Useful for '
+                    'controlling the granularity of the split CLs, e.g. '
+                    '--max-depth=1 will only split by top-level '
+                    'directory. Specifying a value less than 1 means no '
+                    'limit on max depth.')
   options, _ = parser.parse_args(args)
   options, _ = parser.parse_args(args)
 
 
   if not options.description_file:
   if not options.description_file:
@@ -4517,10 +4525,10 @@ def CMDsplit(parser, args):
   def WrappedCMDupload(args):
   def WrappedCMDupload(args):
     return CMDupload(OptionParser(), args)
     return CMDupload(OptionParser(), args)
 
 
-  return split_cl.SplitCl(
-      options.description_file, options.comment_file, Changelist,
-      WrappedCMDupload, options.dry_run, options.cq_dry_run,
-      options.enable_auto_submit, settings.GetRoot())
+  return split_cl.SplitCl(options.description_file, options.comment_file,
+                          Changelist, WrappedCMDupload, options.dry_run,
+                          options.cq_dry_run, options.enable_auto_submit,
+                          options.max_depth, settings.GetRoot())
 
 
 
 
 @subcommand.usage('DEPRECATED')
 @subcommand.usage('DEPRECATED')

+ 12 - 4
split_cl.py

@@ -140,7 +140,7 @@ def UploadCl(refactor_branch, refactor_branch_upstream, directory, files,
                             publish=True)
                             publish=True)
 
 
 
 
-def GetFilesSplitByOwners(files):
+def GetFilesSplitByOwners(files, max_depth):
   """Returns a map of files split by OWNERS file.
   """Returns a map of files split by OWNERS file.
 
 
   Returns:
   Returns:
@@ -149,7 +149,13 @@ def GetFilesSplitByOwners(files):
   """
   """
   files_split_by_owners = {}
   files_split_by_owners = {}
   for action, path in files:
   for action, path in files:
-    dir_with_owners = os.path.dirname(path)
+    # normpath() is important to normalize separators here, in prepration for
+    # str.split() before. It would be nicer to use something like pathlib here
+    # but alas...
+    dir_with_owners = os.path.normpath(os.path.dirname(path))
+    if max_depth >= 1:
+      dir_with_owners = os.path.join(
+          *dir_with_owners.split(os.path.sep)[:max_depth])
     # Find the closest parent directory with an OWNERS file.
     # Find the closest parent directory with an OWNERS file.
     while (dir_with_owners not in files_split_by_owners
     while (dir_with_owners not in files_split_by_owners
            and not os.path.isfile(os.path.join(dir_with_owners, 'OWNERS'))):
            and not os.path.isfile(os.path.join(dir_with_owners, 'OWNERS'))):
@@ -184,7 +190,7 @@ def PrintClInfo(cl_index, num_cls, directory, file_paths, description,
 
 
 
 
 def SplitCl(description_file, comment_file, changelist, cmd_upload, dry_run,
 def SplitCl(description_file, comment_file, changelist, cmd_upload, dry_run,
-            cq_dry_run, enable_auto_submit, repository_root):
+            cq_dry_run, enable_auto_submit, max_depth, repository_root):
   """"Splits a branch into smaller branches and uploads CLs.
   """"Splits a branch into smaller branches and uploads CLs.
 
 
   Args:
   Args:
@@ -195,6 +201,8 @@ def SplitCl(description_file, comment_file, changelist, cmd_upload, dry_run,
     dry_run: Whether this is a dry run (no branches or CLs created).
     dry_run: Whether this is a dry run (no branches or CLs created).
     cq_dry_run: If CL uploads should also do a cq dry run.
     cq_dry_run: If CL uploads should also do a cq dry run.
     enable_auto_submit: If CL uploads should also enable auto submit.
     enable_auto_submit: If CL uploads should also enable auto submit.
+    max_depth: The maximum directory depth to search for OWNERS files. A value
+               less than 1 means no limit.
 
 
   Returns:
   Returns:
     0 in case of success. 1 in case of error.
     0 in case of success. 1 in case of error.
@@ -224,7 +232,7 @@ def SplitCl(description_file, comment_file, changelist, cmd_upload, dry_run,
     assert refactor_branch_upstream, \
     assert refactor_branch_upstream, \
         "Branch %s must have an upstream." % refactor_branch
         "Branch %s must have an upstream." % refactor_branch
 
 
-    files_split_by_owners = GetFilesSplitByOwners(files)
+    files_split_by_owners = GetFilesSplitByOwners(files, max_depth)
 
 
     num_cls = len(files_split_by_owners)
     num_cls = len(files_split_by_owners)
     print('Will split current branch (' + refactor_branch + ') into ' +
     print('Will split current branch (' + refactor_branch + ') into ' +