aboutsummaryrefslogtreecommitdiff
path: root/b4
diff options
context:
space:
mode:
authorKonstantin Ryabitsev <konstantin@linuxfoundation.org>2022-06-16 11:31:35 -0400
committerKonstantin Ryabitsev <konstantin@linuxfoundation.org>2022-06-16 11:31:35 -0400
commit0bff0fb4375a40755ec0ffcc3eb6c67e195baefc (patch)
treef05a6c8308122fc3304e0eb0167a12adf0b04ac6 /b4
parent6e1452d7e5008a1712aac0fb95bc4e377f95821b (diff)
downloadb4-0bff0fb4375a40755ec0ffcc3eb6c67e195baefc.tar.gz
Allow breaking threads using --no-parent
It is a common request to be able to get a partial thread in case someone submitted an auxiliary standalone patch in the middle of a larger patch series. Passing the msgid of the start of the thread along with --no-parent should tell b4 to break the thread at the start of the message-id specified and only consider that message and its children. Suggested-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/tools/YpTI9lhCfA7shi6j@sirena.org.uk/ Signed-off-by: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
Diffstat (limited to 'b4')
-rw-r--r--b4/__init__.py19
-rw-r--r--b4/command.py2
-rw-r--r--b4/mbox.py12
3 files changed, 24 insertions, 9 deletions
diff --git a/b4/__init__.py b/b4/__init__.py
index 1ac7eb1..bc4dd36 100644
--- a/b4/__init__.py
+++ b/b4/__init__.py
@@ -2148,8 +2148,9 @@ def get_msgid(cmdargs) -> Optional[str]:
return msgid
-def get_strict_thread(msgs, msgid):
+def get_strict_thread(msgs, msgid, noparent=False):
want = {msgid}
+ ignore = set()
got = set()
seen = set()
maybe = dict()
@@ -2157,6 +2158,8 @@ def get_strict_thread(msgs, msgid):
while True:
for msg in msgs:
c_msgid = LoreMessage.get_clean_msgid(msg)
+ if c_msgid in ignore:
+ continue
seen.add(c_msgid)
if c_msgid in got:
continue
@@ -2168,7 +2171,16 @@ def get_strict_thread(msgs, msgid):
msgrefs += email.utils.getaddresses([str(x) for x in msg.get_all('in-reply-to', [])])
if msg.get('References', None):
msgrefs += email.utils.getaddresses([str(x) for x in msg.get_all('references', [])])
+ # If noparent is set, we pretend the message we got passed has no references, and add all
+ # parent references of this message to ignore
+ if noparent and msgid == c_msgid:
+ logger.info('Breaking thread to remove parents of %s', msgid)
+ ignore = set([x[1] for x in msgrefs])
+ msgrefs = list()
+
for ref in set([x[1] for x in msgrefs]):
+ if ref in ignore:
+ continue
if ref in got or ref in want:
want.add(c_msgid)
elif len(ref):
@@ -2206,7 +2218,7 @@ def get_strict_thread(msgs, msgid):
return None
if len(msgs) > len(strict):
- logger.debug('Reduced mbox to strict matches only (%s->%s)', len(msgs), len(strict))
+ logger.debug('Reduced thread to requested matches only (%s->%s)', len(msgs), len(strict))
return strict
@@ -2266,7 +2278,8 @@ def get_pi_thread_by_url(t_mbx_url, nocache=False):
return list(deduped.values())
-def get_pi_thread_by_msgid(msgid, useproject=None, nocache=False, onlymsgids: Optional[set] = None):
+def get_pi_thread_by_msgid(msgid: str, useproject: Optional[str] = None, nocache: bool = False,
+ onlymsgids: Optional[set] = None) -> Optional[list]:
qmsgid = urllib.parse.quote_plus(msgid)
config = get_main_config()
loc = urllib.parse.urlparse(config['midmask'])
diff --git a/b4/command.py b/b4/command.py
index 6d3c899..aa307da 100644
--- a/b4/command.py
+++ b/b4/command.py
@@ -55,6 +55,8 @@ def cmd_am_common_opts(sp):
'"-P *globbing*" to match on commit subject)')
sp.add_argument('--cc-trailers', dest='copyccs', action='store_true', default=False,
help='Copy all Cc\'d addresses into Cc: trailers')
+ sp.add_argument('--no-parent', dest='noparent', action='store_true', default=False,
+ help='Break thread at the msgid specified and ignore any parent messages')
sp.add_argument('--allow-unicode-control-chars', dest='allowbadchars', action='store_true', default=False,
help='Allow unicode control characters (very rarely legitimate)')
diff --git a/b4/mbox.py b/b4/mbox.py
index c2e6319..4ac2c29 100644
--- a/b4/mbox.py
+++ b/b4/mbox.py
@@ -656,12 +656,9 @@ def get_msgs(cmdargs) -> Tuple[Optional[str], Optional[list]]:
sys.exit(1)
pickings = set()
- try:
- if cmdargs.cherrypick == '_':
- # Just that msgid, please
- pickings = {msgid}
- except AttributeError:
- pass
+ if 'cherrypick' in cmdargs and cmdargs.cherrypick == '_':
+ # Just that msgid, please
+ pickings = {msgid}
msgs = b4.get_pi_thread_by_msgid(msgid, useproject=cmdargs.useproject, nocache=cmdargs.nocache,
onlymsgids=pickings)
if not msgs:
@@ -693,6 +690,9 @@ def get_msgs(cmdargs) -> Tuple[Optional[str], Optional[list]]:
logger.critical('Mailbox %s does not exist', cmdargs.localmbox)
sys.exit(1)
+ if msgid and 'noparent' in cmdargs and cmdargs.noparent:
+ msgs = b4.get_strict_thread(msgs, msgid, noparent=True)
+
if not msgid and msgs:
for msg in msgs:
msgid = msg.get('Message-ID', None)