diff --git a/README.rst b/README.rst index 9679272..e53d27b 100644 --- a/README.rst +++ b/README.rst @@ -955,6 +955,13 @@ Example:: ./bugs-fixed-since.py -B -r ../neutron --start=8.0.0 +Use ``-e`` option to ignore patches that don't apply cleanly to one of stable +branches. + +Example:: + + ./bugs-fixed-since.py -e -r ../neutron --start=8.0.0 + lp-filter-bugs-by-importance.py ------------------------------- diff --git a/bugs-fixed-since.py b/bugs-fixed-since.py index 65e5b9c..d02b66f 100755 --- a/bugs-fixed-since.py +++ b/bugs-fixed-since.py @@ -19,6 +19,7 @@ This tool will list bugs that were fixed in project master. import argparse import re +from git import cmd from git import Repo @@ -42,6 +43,12 @@ def _parse_args(): action='store_true', help='whether to skip patches backported to all stable branches', ) + parser.add_argument( + '--easy-backport', '-e', + action='store_true', + default=False, + help='whether to include easy (no git conflicts) backports only', + ) return parser.parse_args() @@ -62,6 +69,28 @@ def _extract_changeid(commit): return id_ +def _is_easy_backport(repo, commit): + g_cmd = cmd.Git(working_dir=repo.working_tree_dir) + for ref in repo.refs: + # consider a patch easy to backport if only it cleanly applies to all + # stable branches; otherwise it will potentially require more work to + # resolve git conflicts + if ref.name.startswith('origin/stable/'): + # before applying any patches, make sure the tree is clean and + # fully reflects remote head + g_cmd.clean(force=True, d=True, x=True) + g_cmd.reset(hard=True) + g_cmd.checkout(ref.name) + try: + g_cmd.cherry_pick(commit.hexsha) + except cmd.GitCommandError: + # cherry-pick does not have a 'dry run' mode, so we need to + # actually clean up after a failure + g_cmd.cherry_pick(abort=True) + return False + return True + + def main(): args = _parse_args() @@ -87,6 +116,11 @@ def main(): _backported_to_all_stable_branches(repo, id_)): continue + # skip patches that result in git conflicts in any of stable branches + if (args.easy_backport and + not _is_easy_backport(repo, commit)): + continue + # collect every bug number mentioned in the message for match in re.finditer(BUG_PATTERN, commit.message): bugs.add(match.group('bugnum'))