Merge tag 'u-boot-atmel-fixes-2021.01-b' of https://gitlab.denx.de/u-boot/custodians...
[platform/kernel/u-boot.git] / tools / patman / gitutil.py
index 5189840..31fb3b2 100644 (file)
@@ -49,19 +49,30 @@ def LogCmd(commit_range, git_dir=None, oneline=False, reverse=False,
     cmd.append('--')
     return cmd
 
-def CountCommitsToBranch():
+def CountCommitsToBranch(branch):
     """Returns number of commits between HEAD and the tracking branch.
 
     This looks back to the tracking branch and works out the number of commits
     since then.
 
+    Args:
+        branch: Branch to count from (None for current branch)
+
     Return:
         Number of patches that exist on top of the branch
     """
-    pipe = [LogCmd('@{upstream}..', oneline=True),
-            ['wc', '-l']]
-    stdout = command.RunPipe(pipe, capture=True, oneline=True).stdout
-    patch_count = int(stdout)
+    if branch:
+        us, msg = GetUpstream('.git', branch)
+        rev_range = '%s..%s' % (us, branch)
+    else:
+        rev_range = '@{upstream}..'
+    pipe = [LogCmd(rev_range, oneline=True)]
+    result = command.RunPipe(pipe, capture=True, capture_stderr=True,
+                             oneline=True, raise_on_error=False)
+    if result.return_code:
+        raise ValueError('Failed to determine upstream: %s' %
+                         result.stderr.strip())
+    patch_count = len(result.stdout.splitlines())
     return patch_count
 
 def NameRevision(commit_hash):
@@ -252,17 +263,62 @@ def Fetch(git_dir=None, work_tree=None):
     if result.return_code != 0:
         raise OSError('git fetch: %s' % result.stderr)
 
-def CreatePatches(start, count, ignore_binary, series):
+def CheckWorktreeIsAvailable(git_dir):
+    """Check if git-worktree functionality is available
+
+    Args:
+        git_dir: The repository to test in
+
+    Returns:
+        True if git-worktree commands will work, False otherwise.
+    """
+    pipe = ['git', '--git-dir', git_dir, 'worktree', 'list']
+    result = command.RunPipe([pipe], capture=True, capture_stderr=True,
+                             raise_on_error=False)
+    return result.return_code == 0
+
+def AddWorktree(git_dir, output_dir, commit_hash=None):
+    """Create and checkout a new git worktree for this build
+
+    Args:
+        git_dir: The repository to checkout the worktree from
+        output_dir: Path for the new worktree
+        commit_hash: Commit hash to checkout
+    """
+    # We need to pass --detach to avoid creating a new branch
+    pipe = ['git', '--git-dir', git_dir, 'worktree', 'add', '.', '--detach']
+    if commit_hash:
+        pipe.append(commit_hash)
+    result = command.RunPipe([pipe], capture=True, cwd=output_dir,
+                             capture_stderr=True)
+    if result.return_code != 0:
+        raise OSError('git worktree add: %s' % result.stderr)
+
+def PruneWorktrees(git_dir):
+    """Remove administrative files for deleted worktrees
+
+    Args:
+        git_dir: The repository whose deleted worktrees should be pruned
+    """
+    pipe = ['git', '--git-dir', git_dir, 'worktree', 'prune']
+    result = command.RunPipe([pipe], capture=True, capture_stderr=True)
+    if result.return_code != 0:
+        raise OSError('git worktree prune: %s' % result.stderr)
+
+def CreatePatches(branch, start, count, ignore_binary, series):
     """Create a series of patches from the top of the current branch.
 
     The patch files are written to the current directory using
     git format-patch.
 
     Args:
+        branch: Branch to create patches from (None for current branch)
         start: Commit to start from: 0=HEAD, 1=next one, etc.
         count: number of commits to include
+        ignore_binary: Don't generate patches for binary files
+        series: Series object for this series (set of patches)
     Return:
-        Filename of cover letter
+        Filename of cover letter (None if none)
         List of filenames of patch files
     """
     if series.get('version'):
@@ -275,7 +331,8 @@ def CreatePatches(start, count, ignore_binary, series):
     prefix = series.GetPatchPrefix()
     if prefix:
         cmd += ['--subject-prefix=%s' % prefix]
-    cmd += ['HEAD~%d..HEAD~%d' % (start + count, start)]
+    brname = branch or 'HEAD'
+    cmd += ['%s~%d..%s~%d' % (brname, start + count, brname, start)]
 
     stdout = command.RunList(cmd)
     files = stdout.splitlines()
@@ -333,6 +390,31 @@ def BuildEmailList(in_list, tag=None, alias=None, raise_on_error=True):
         return ['%s %s%s%s' % (tag, quote, email, quote) for email in result]
     return result
 
+def CheckSuppressCCConfig():
+    """Check if sendemail.suppresscc is configured correctly.
+
+    Returns:
+        True if the option is configured correctly, False otherwise.
+    """
+    suppresscc = command.OutputOneLine('git', 'config', 'sendemail.suppresscc',
+                                       raise_on_error=False)
+
+    # Other settings should be fine.
+    if suppresscc == 'all' or suppresscc == 'cccmd':
+        col = terminal.Color()
+
+        print((col.Color(col.RED, "error") +
+            ": git config sendemail.suppresscc set to %s\n"  % (suppresscc)) +
+            "  patman needs --cc-cmd to be run to set the cc list.\n" +
+            "  Please run:\n" +
+            "    git config --unset sendemail.suppresscc\n" +
+            "  Or read the man page:\n" +
+            "    git send-email --help\n" +
+            "  and set an option that runs --cc-cmd\n")
+        return False
+
+    return True
+
 def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname,
         self_only=False, alias=None, in_reply_to=None, thread=False,
         smtp_server=None):
@@ -373,21 +455,21 @@ def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname,
     >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, True, 'cc-fname', \
             False, alias)
     'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \
-"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" cover p1 p2'
+"m.poppins@cloud.net" --cc-cmd "./patman send --cc-cmd cc-fname" cover p1 p2'
     >>> EmailPatches(series, None, ['p1'], True, True, 'cc-fname', False, \
             alias)
     'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \
-"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" p1'
+"m.poppins@cloud.net" --cc-cmd "./patman send --cc-cmd cc-fname" p1'
     >>> series['cc'] = ['all']
     >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, True, 'cc-fname', \
             True, alias)
     'git send-email --annotate --to "this-is-me@me.com" --cc-cmd "./patman \
---cc-cmd cc-fname" cover p1 p2'
+send --cc-cmd cc-fname" cover p1 p2'
     >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, True, 'cc-fname', \
             False, alias)
     'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \
 "f.bloggs@napier.co.nz" --cc "j.bloggs@napier.co.nz" --cc \
-"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" cover p1 p2'
+"m.poppins@cloud.net" --cc-cmd "./patman send --cc-cmd cc-fname" cover p1 p2'
 
     # Restore argv[0] since we clobbered it.
     >>> sys.argv[0] = _old_argv0
@@ -418,7 +500,7 @@ def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname,
 
     cmd += to
     cmd += cc
-    cmd += ['--cc-cmd', '"%s --cc-cmd %s"' % (sys.argv[0], cc_fname)]
+    cmd += ['--cc-cmd', '"%s send --cc-cmd %s"' % (sys.argv[0], cc_fname)]
     if cover_fname:
         cmd.append(cover_fname)
     cmd += args