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 72fc95d..31fb3b2 100644 (file)
@@ -7,9 +7,7 @@ import os
 import subprocess
 import sys
 
 import subprocess
 import sys
 
-from patman import checkpatch
 from patman import command
 from patman import command
-from patman import series
 from patman import settings
 from patman import terminal
 from patman import tools
 from patman import settings
 from patman import terminal
 from patman import tools
@@ -51,19 +49,30 @@ def LogCmd(commit_range, git_dir=None, oneline=False, reverse=False,
     cmd.append('--')
     return cmd
 
     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.
 
     """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
     """
     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):
     return patch_count
 
 def NameRevision(commit_hash):
@@ -254,17 +263,62 @@ def Fetch(git_dir=None, work_tree=None):
     if result.return_code != 0:
         raise OSError('git fetch: %s' % result.stderr)
 
     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:
     """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
         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:
     Return:
-        Filename of cover letter
+        Filename of cover letter (None if none)
         List of filenames of patch files
     """
     if series.get('version'):
         List of filenames of patch files
     """
     if series.get('version'):
@@ -277,7 +331,8 @@ def CreatePatches(start, count, ignore_binary, series):
     prefix = series.GetPatchPrefix()
     if prefix:
         cmd += ['--subject-prefix=%s' % prefix]
     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()
 
     stdout = command.RunList(cmd)
     files = stdout.splitlines()
@@ -335,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
 
         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):
 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):
@@ -369,27 +449,27 @@ def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname,
     >>> alias['boys'] = ['fred', ' john']
     >>> alias['all'] = ['fred ', 'john', '   mary   ']
     >>> alias[os.getenv('USER')] = ['this-is-me@me.com']
     >>> alias['boys'] = ['fred', ' john']
     >>> alias['all'] = ['fred ', 'john', '   mary   ']
     >>> alias[os.getenv('USER')] = ['this-is-me@me.com']
-    >>> series = series.Series()
-    >>> series.to = ['fred']
-    >>> series.cc = ['mary']
+    >>> series = {}
+    >>> series['to'] = ['fred']
+    >>> series['cc'] = ['mary']
     >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, True, 'cc-fname', \
             False, alias)
     'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \
     >>> 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 \
     >>> 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'
-    >>> series.cc = ['all']
+"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 \
     >>> 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 \
     >>> 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
 
     # Restore argv[0] since we clobbered it.
     >>> sys.argv[0] = _old_argv0
@@ -420,7 +500,7 @@ def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname,
 
     cmd += to
     cmd += cc
 
     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
     if cover_fname:
         cmd.append(cover_fname)
     cmd += args