Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package b4 for openSUSE:Factory checked in 
at 2025-10-02 19:20:06
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/b4 (Old)
 and      /work/SRC/openSUSE:Factory/.b4.new.11973 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "b4"

Thu Oct  2 19:20:06 2025 rev:44 rq:1308445 version:0.14.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/b4/b4.changes    2024-09-25 21:54:33.323436538 
+0200
+++ /work/SRC/openSUSE:Factory/.b4.new.11973/b4.changes 2025-10-02 
19:20:57.800374287 +0200
@@ -1,0 +2,17 @@
+Wed Oct  1 16:09:50 UTC 2025 - Jiri Slaby <[email protected]>
+
+- update to 0.14.3:
+  * Don't strip trailing blank lines in patches when not needed
+  * fix show-info in another branch
+  * stop generating full object IDs for non-binary diffs
+  * better handle invalid timezone values
+  * Create patches with --default-prefix (when git version supports it)
+  * Add --find-renames to git-show to counteract local configs
+  * Fix misleading error message on cherry-picked patches
+  * be more careful when applying trailers to non-prep branches
+  * Don't quote trailers containing brackets
+  * Support smtpauth=none in sendemail configs
+  * when querying by change-id, don't add author and subject
+  * clean up after git-filter-repo runs in recent git-filter-repo versions
+
+-------------------------------------------------------------------

Old:
----
  b4-0.14.2.tar.gz

New:
----
  _scmsync.obsinfo
  b4-0.14.3.tar.gz
  build.specials.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ b4.spec ++++++
--- /var/tmp/diff_new_pack.WvXJ6v/_old  2025-10-02 19:20:59.368439883 +0200
+++ /var/tmp/diff_new_pack.WvXJ6v/_new  2025-10-02 19:20:59.368439883 +0200
@@ -24,7 +24,7 @@
 %global pprefix python311
 %endif
 Name:           b4
-Version:        0.14.2
+Version:        0.14.3
 Release:        0
 Summary:        Helper scripts for kernel.org patches
 License:        GPL-2.0-or-later

++++++ _scmsync.obsinfo ++++++
mtime: 1759335021
commit: 4ea1653c0a82e128a0a85343b9cfef77f76f7081aa84d3e88b90acfb51c818f7
url: https://src.opensuse.org/jirislaby/d-t-b4.git

++++++ b4-0.14.2.tar.gz -> b4-0.14.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/b4-0.14.2/pyproject.toml new/b4-0.14.3/pyproject.toml
--- old/b4-0.14.2/pyproject.toml        2024-09-17 15:24:20.000000000 +0200
+++ new/b4-0.14.3/pyproject.toml        2025-10-01 16:05:34.000000000 +0200
@@ -4,7 +4,7 @@
 
 [project]
 name = "b4"
-version = "0.14.2"
+version = "0.14.3"
 description = "A tool to work with public-inbox and patch archives"
 readme = "README.rst"
 keywords = ["git", "public-inbox", "lore.kernel.org", "patch", "email", 
"workflow"]
@@ -44,10 +44,10 @@
 
 [tool.pytest.ini_options]
 filterwarnings = "ignore:.*(pyopenssl|invalid escape 
sequence).*:DeprecationWarning"
-norecursedirs = "tests/helpers"
+norecursedirs = ["tests/helpers", "patatt"]
 
 [tool.bumpversion]
-current_version = "0.14.2"
+current_version = "0.14.3"
 files = [
     {filename = "src/b4/__init__.py"},
     {filename = "src/b4/man/b4.5.rst"},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/b4-0.14.2/src/b4/__init__.py 
new/b4-0.14.3/src/b4/__init__.py
--- old/b4-0.14.2/src/b4/__init__.py    2024-09-17 15:24:20.000000000 +0200
+++ new/b4-0.14.3/src/b4/__init__.py    2025-10-01 16:05:34.000000000 +0200
@@ -64,7 +64,7 @@
 # global setting allowing us to turn off networking
 can_network = True
 
-__VERSION__ = '0.14.2'
+__VERSION__ = '0.14.3'
 PW_REST_API_VERSION = '1.2'
 
 
@@ -142,7 +142,7 @@
     'thanks-pr-template': None,
     # See thanks-am-template.example
     'thanks-am-template': None,
-    # If this is not set, we'll use what we find in 
+    # If this is not set, we'll use what we find in
     # git-config for gpg.program, and if that's not set,
     # we'll use "gpg" and hope for the better
     'gpgbin': None,
@@ -1057,12 +1057,16 @@
                 self.type = 'utility'
             elif re.search(r'\S+@\S+\.\S+', value):
                 self.type = 'person'
-                self.addr = email.utils.parseaddr(value)
+                if '<mailto:' in value:
+                    # This was inserted by a mail client that back-converted 
from html mail
+                    # Remove the <mailto:...> part
+                    self.value = re.sub(r'<mailto:[^>]+>', '', value)
+                self.addr = email.utils.parseaddr(self.value)
                 # Normalize the value with parsed data
-                if self.addr[0]:
-                    self.value = f'{self.addr[0]} <{self.addr[1]}>'
+                if self.addr[0] or self.addr[1]:
+                    self.value = format_addrs([self.addr], header_safe=False)
                 else:
-                    self.value = self.addr[1]
+                    self.type = 'unknown'
             else:
                 self.type = 'unknown'
         self.lname = self.name.lower()
@@ -1245,7 +1249,12 @@
 
         msgdate = self.msg.get('Date')
         if msgdate:
-            self.date = email.utils.parsedate_to_datetime(str(msgdate))
+            dtuple = email.utils.parsedate_tz(str(msgdate))
+            # Invalid timezone (e.g. -9900)
+            if abs(dtuple[-1]) > 86400:
+                self.date = datetime.datetime(*dtuple[:6])
+            else:
+                self.date = email.utils.parsedate_to_datetime(str(msgdate))
         else:
             # An email without a Date: field?
             self.date = datetime.datetime.now()
@@ -2102,7 +2111,7 @@
             else:
                 # We don't need to add a ---
                 body += '\n'
-            body += basement.strip('\r\n') + '\n'
+            body += basement.lstrip('\r\n') + '\n'
 
         if len(signature):
             body += '-- \n'
@@ -2126,22 +2135,22 @@
         sparts = body.rsplit('\n-- \n', 1)
         if len(sparts) > 1:
             signature = sparts[1]
-            body = sparts[0].rstrip('\n')
+            body = sparts[0]
 
         parts = re.split('^---\n', body, maxsplit=1, flags=re.M)
         if len(parts) == 2:
-            basement = parts[1].rstrip('\n')
+            basement = parts[1]
         elif body.find('\ndiff ') >= 0:
             parts = body.split('\ndiff ', 1)
             if len(parts) == 2:
                 parts[1] = 'diff ' + parts[1]
-            basement = parts[1].rstrip('\n')
+            basement = parts[1]
         elif body.find('\n--- a/') >= 0:
             # patches generated by some really peculiar tools
             parts = body.split('\n--- a/', 1)
             if len(parts) == 2:
                 parts[1] = '--- a/' + parts[1]
-            basement = parts[1].rstrip('\n')
+            basement = parts[1]
 
         mbody = parts[0].strip('\n')
 
@@ -2720,6 +2729,12 @@
     return ecode, out
 
 
+def git_check_minimal_version(min_version: str) -> bool:
+    ecode, out = git_run_command(None, ["version"])
+    current_version = re.sub(r"git version (\d+\.\d+)\..*", r"\1", out)
+    return tuple(map(int, current_version.split(".")[:2])) >= tuple(map(int, 
min_version.split(".")[:2]))
+
+
 def git_credential_fill(gitdir: Optional[str], protocol: str, host: str, 
username: str) -> Optional[str]:
     stdin = f'protocol={protocol}\nhost={host}\nusername={username}\n'.encode()
     ecode, out = git_run_command(gitdir, args=['credential', 'fill'], 
stdin=stdin)
@@ -3104,6 +3119,13 @@
             logger.debug('Overriding midmask with passed url parameters')
             config['midmask'] = 
f'{wantloc.scheme}://{wantloc.netloc}/{chunks[0]}/%s'
         msgid = urllib.parse.unquote(chunks[1])
+    elif msgid.startswith('http'):
+        # Finally, try finding something that looks like msgid in that URL
+        matches = re.search(r'^https?://[^@]+/([^/]+@[^/]+)', msgid, 
re.IGNORECASE)
+        if matches:
+            chunks = matches.groups()
+            msgid = urllib.parse.unquote(chunks[0])
+
     # Handle special case when msgid is prepended by id: or rfc822msgid:
     if msgid.find('id:') >= 0:
         msgid = re.sub(r'^\w*id:', '', msgid)
@@ -3454,19 +3476,23 @@
         if commit in ignore_commits:
             logger.debug('Ignoring commit %s', commit)
             continue
+
+        showargs = [
+            '--format=email',
+            '--binary',
+            '--patch-with-stat',
+            '--encoding=utf-8',
+            '--find-renames',
+        ]
+
+        if git_check_minimal_version("2.40"):
+            showargs.append("--default-prefix")
+
         ecode, out = git_run_command(
-            gitdir,
-            [
-                'show',
-                '--format=email',
-                '--full-index',
-                '--binary',
-                '--patch-with-stat',
-                '--encoding=utf-8',
-                commit,
-            ],
+            gitdir, ['show'] + showargs + [commit],
             decode=False,
         )
+
         if ecode > 0:
             raise RuntimeError(f'Could not get a patch out of {commit}')
         msg = email.message_from_bytes(out, policy=emlpolicy)
@@ -3579,15 +3605,19 @@
     return topdir
 
 
-def format_addrs(pairs: List[Tuple[str, str]], clean: bool = True) -> str:
+def format_addrs(pairs: List[Tuple[str, str]], clean: bool = True,
+                 header_safe: bool = True) -> str:
     addrs = list()
     for pair in pairs:
-        if pair[0] == pair[1]:
+        if not pair[0] or pair[0] == pair[1]:
             addrs.append(pair[1])
             continue
         if clean:
             # Remove any quoted-printable header junk from the name
             pair = (LoreMessage.clean_header(pair[0]), pair[1])
+        if not header_safe:
+            addrs.append(f'{pair[0]} <{pair[1]}>')
+            continue
         # Work around https://github.com/python/cpython/issues/100900
         if not pair[0].startswith('=?') and not pair[0].startswith('"') and 
qspecials.search(pair[0]):
             quoted = email.utils.quote(pair[0])
@@ -3630,7 +3660,7 @@
                 yield i
             else:
                 logger.critical('Unknown range value specified: %s', n)
-                continue
+            continue
         except ValueError:
             pass
 
@@ -3867,6 +3897,10 @@
             raise smtplib.SMTPException('Unclear what to do with 
smtpencryption=%s' % encryption)
 
         # If we got to this point, we should do authentication.
+        # unless smtpauth is set to a special "none" value
+        smtpauth = str(sconfig.get('smtpauth', ''))
+        if smtpauth.lower() == 'none':
+            return smtp, fromaddr
         auser = sconfig.get('smtpuser')
         apass = sconfig.get('smtppass')
         if auser and not apass:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/b4-0.14.2/src/b4/ez.py new/b4-0.14.3/src/b4/ez.py
--- old/b4-0.14.2/src/b4/ez.py  2024-09-17 15:24:20.000000000 +0200
+++ new/b4-0.14.3/src/b4/ez.py  2025-10-01 16:05:34.000000000 +0200
@@ -108,6 +108,31 @@
 PFHASH_CACHE = dict()
 
 
+def run_frf(frf: fr.RepoFilter) -> None:
+    """
+    Run git-filter-repo with the provided RepoFilter configuration
+    and then clean up any trace files that are created during the process.
+
+    Recent versions of git-filter-repo create a .git/filter-repo/already_ran
+    file after each run that may be useful for other uses of git-filter-repo,
+    but is completely unnecessary for b4's purposes. Delete this file after
+    each invocation, so it doesn't interfere with subsequent runs.
+    """
+    if not can_gfr:
+        logger.critical('CRITICAL: git-filter-repo is not available')
+        sys.exit(1)
+    logger.debug('Running git-filter-repo...')
+    frf.run()
+    logger.debug('git-filter-repo complete')
+    gtl = b4.git_get_toplevel()
+    if isinstance(gtl, str):
+        # Remove .git/filter-repo/already_ran
+        already_ran = os.path.join(gtl, '.git', 'filter-repo', 'already_ran')
+        if os.path.exists(already_ran):
+            logger.debug('Removing %s', already_ran)
+            os.remove(already_ran)
+
+
 def get_auth_configs() -> Tuple[str, str, str, str, str, str]:
     config = b4.get_main_config()
     endpoint = config.get('send-endpoint-web', '')
@@ -656,7 +681,7 @@
             args.refs = [f'{commit}~1..HEAD']
             frf = fr.RepoFilter(args, commit_callback=fred.callback)
             logger.info('Invoking git-filter-repo to update the cover letter.')
-            frf.run()
+            run_frf(frf)
 
     if strategy == 'branch-description':
         mybranch = b4.git_get_current_branch(None)
@@ -1016,10 +1041,11 @@
     changeid = None
     cover = None
     msgid = None
-    end = 'HEAD'
-    limit_committer = usercfg['email']
+    end = b4.git_revparse_obj('HEAD')
+    limit_committer: Optional[str] = str(usercfg['email'])
     # If we are in an b4-prep branch, we start from the beginning of the series
-    if is_prep_branch():
+    in_prep_branch = is_prep_branch()
+    if in_prep_branch:
         # Don't limit by committer in a prep branch
         limit_committer = None
         start = get_series_start()
@@ -1045,17 +1071,47 @@
             sys.exit(1)
 
     else:
-        # There doesn't appear to be a great way to find the first commit
-        # where we're NOT the committer, so we get all commits since range 
specified where
-        # we're the committer and pick the earliest commit
-        gitargs = ['log', '-F', '--no-merges', 
f'--committer={limit_committer}', '--format=%H', '--reverse',
-                   '--since', cmdargs.since]
+        # Find the most recent commit where we're not the committer
+        gitargs = ['log', '--perl-regexp', 
f'--committer=^(?!.*<{limit_committer}>)', '--max-count=1',
+                   '--format=%H', '--since', cmdargs.since]
+
         lines = b4.git_get_command_lines(None, gitargs)
         if not lines:
-            logger.critical('CRITICAL: could not find any commits where 
committer=%s', limit_committer)
+            logger.critical('CRITICAL: could not find any commits, try 
changing --since')
+            sys.exit(1)
+        # Iterate through the commits we will consider and do some sanity 
checking
+        first_considered = lines[0]
+        logger.debug('First commit to consider: %s', first_considered)
+        # Make sure this commit isn't HEAD
+        if first_considered == end:
+            logger.critical('CRITICAL: the tip commit was not committed by 
you, refusing to continue')
             sys.exit(1)
-        first_commit = lines[0]
-        start = f'{first_commit}~1'
+        start = first_considered
+
+    # Do some sanity checking to makes sure that all commits between the start 
and the HEAD are:
+    # 1. Single-parent commits
+    # 2. Committed by the limit_committer
+    gitargs = ['log', '--format=%H %ce %p', f'{start}..']
+    lines = b4.git_get_command_lines(None, gitargs)
+    if not lines:
+        # Should never happen?
+        logger.critical('CRITICAL: could not find any commits between %s and 
HEAD.', start)
+        sys.exit(1)
+    first_to_update = end
+    for line in lines:
+        logger.debug('Considering commit line: %s', line)
+        cparts = line.split()
+        # If we have more than 3 parts, that means we found a commit with 
multiple parents
+        commit, committer_email, parents = cparts[0], cparts[1], cparts[2:]
+        if len(parents) != 1:
+            logger.debug('Commit %s has non-single parent, stopping: %s', 
commit, parents)
+            break
+        if committer_email != limit_committer and not in_prep_branch:
+            logger.debug('Commit %s is not by %s, stopping', commit, 
committer_email)
+            break
+        first_to_update = commit
+    logger.debug('Will use %s as the start of the range', first_to_update)
+    start = b4.git_revparse_obj(f'{first_to_update}~1')
 
     if cmdargs.msgid or cmdargs.trailers_from:
         if cmdargs.trailers_from:
@@ -1063,6 +1119,9 @@
             cmdargs.msgid = cmdargs.trailers_from
         msgid = b4.get_msgid(cmdargs)
 
+    logger.debug('Start of the range: %s', start)
+    logger.debug('End of the range: %s', end)
+
     try:
         patches = b4.git_range_to_patches(None, start, end, 
ignore_commits=ignore_commits,
                                           limit_committer=limit_committer)
@@ -1082,6 +1141,7 @@
     for commit, msg in patches:
         if commit:
             msg['Message-Id'] = f'<{commit}>'
+            logger.debug('  %s', msg.get('Subject', '(no subject)'))
         bbox.add_message(msg)
 
     commit_map = dict()
@@ -1157,6 +1217,7 @@
         if not lmsg.followup_trailers:
             logger.debug('No new follow-up trailers in: %s', lmsg.subject)
             continue
+        logger.info('%s', lmsg.subject)
 
         commit = lmsg.msgid
         parts = b4.LoreMessage.get_body_parts(lmsg.body)
@@ -1171,7 +1232,9 @@
                 seen_froms.add(rendered)
                 source = config['midmask'] % 
urllib.parse.quote_plus(fltr.lmsg.msgid, safe='@')
                 logger.info('  + %s', rendered)
-                logger.info('    %s', source)
+                logger.info('    via: %s', source)
+            else:
+                logger.debug('  . %s', fltr.as_string(omit_extinfo=True))
 
         # Check if we've applied mismatched trailers already
         if not cmdargs.sloppytrailers and mismatches:
@@ -1192,13 +1255,21 @@
         logger.info('No trailer updates found.')
         return
 
-    try:
-        logger.critical('---')
-        if not cmdargs.no_interactive:
-            input('Press Enter to apply these trailers or Ctrl-C to abort')
-    except KeyboardInterrupt:
-        logger.info('')
-        sys.exit(130)
+    # Shrink the update range to start with the first commit we're actually 
modifying
+    commits = [x[0] for x in patches]
+    for commit in list(commits):
+        if commit in updates:
+            start = b4.git_revparse_obj(f'{commit}~1')
+            logger.debug('Will update trailers starting from %s', start)
+            break
+        commits.pop(0)
+
+    logger.critical('---')
+    if not cmdargs.no_interactive:
+        resp = input('Rewrite %d commit(s) to add these trailers? [y/N] ' % 
len(commits))
+        if resp.lower() not in {'y', 'yes'}:
+            logger.info('Exiting without changes.')
+            sys.exit(130)
 
     # Create the map of new messages
     fred = FRCommitMessageEditor()
@@ -1214,7 +1285,7 @@
     args.refs = [f'{start}..']
     frf = fr.RepoFilter(args, commit_callback=fred.callback)
     logger.info('Invoking git-filter-repo to update trailers.')
-    frf.run()
+    run_frf(frf)
     logger.info('Trailers updated.')
 
 
@@ -1445,7 +1516,7 @@
     if prefixes is None:
         prefixes = list()
     prefixes += tracking['series'].get('prefixes', list())
-    start_commit = get_series_start()
+    base_commit, start_commit, end_commit = 
get_series_range(usebranch=usebranch)
     change_id = tracking['series'].get('change-id')
     revision = tracking['series'].get('revision')
     msgid_tpt = make_msgid_tpt(change_id, revision)
@@ -1458,7 +1529,7 @@
     strategy = get_cover_strategy()
     ignore_commits = None
     if strategy in {'commit', 'tip-commit'}:
-        cover_commit = find_cover_commit()
+        cover_commit = find_cover_commit(usebranch=usebranch)
         if cover_commit:
             ignore_commits = {cover_commit}
 
@@ -1466,7 +1537,7 @@
     for cprefix in csubject.get_extra_prefixes(exclude=prefixes):
         prefixes.append(cprefix)
 
-    patches = b4.git_range_to_patches(None, start_commit, 'HEAD',
+    patches = b4.git_range_to_patches(None, start_commit, end_commit,
                                       revision=revision,
                                       prefixes=prefixes,
                                       msgid_tpt=msgid_tpt,
@@ -1474,7 +1545,8 @@
                                       mailfrom=mailfrom,
                                       ignore_commits=ignore_commits)
 
-    base_commit, stc, endc, oneline, shortlog, diffstat = 
get_series_details(start_commit=start_commit)
+    base_commit, stc, endc, oneline, shortlog, diffstat = 
get_series_details(start_commit=start_commit,
+                                                                             
usebranch=usebranch)
 
     config = b4.get_main_config()
     cover_template = DEFAULT_COVER_TEMPLATE
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/b4-0.14.2/src/b4/man/b4.5 
new/b4-0.14.3/src/b4/man/b4.5
--- old/b4-0.14.2/src/b4/man/b4.5       2024-09-17 15:24:20.000000000 +0200
+++ new/b4-0.14.3/src/b4/man/b4.5       2025-10-01 16:05:34.000000000 +0200
@@ -27,7 +27,7 @@
 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
 .in \\n[rst2man-indent\\n[rst2man-indent-level]]u
 ..
-.TH "B4" 5 "2024-06-14" "0.14.2"
+.TH "B4" "5" "2025-10-01" "0.14.3"
 .SH NAME
 B4 \- Work with code submissions in a public-inbox archive
 .SH SYNOPSIS
@@ -43,7 +43,7 @@
 The name \(dqb4\(dq was chosen for ease of typing and because B\-4 was the
 precursor to Lore and Data in the Star Trek universe.
 .sp
-Full documentation is available on \fI\%https://b4.docs.kernel.org/\fP\&;.
+Full documentation is available on  <https://b4.docs.kernel.org/> \&.
 .SH SUBCOMMANDS
 .sp
 Maintainer\-oriented:
@@ -285,7 +285,7 @@
 on the mailing list. Full documentation is available online at the
 following address:
 .sp
-\fI\%https://b4.docs.kernel.org/en/latest/contributor/overview.html\fP
+ <https://b4.docs.kernel.org/en/latest/contributor/overview.html> 
 .sp
 For options, see the output of \fBb4 prep \-\-help\fP, \fBb4 trailers
 \-\-help\fP and \fBb4 send \-\-help\fP\&.
@@ -330,16 +330,16 @@
 \&.git/config file if your workflow changes per project.
 .sp
 To see configuration options available, see online documentation at
-\fI\%https://b4.docs.kernel.org/en/latest/config.html\fP
+ <https://b4.docs.kernel.org/en/latest/config.html> 
 .SH PROXYING REQUESTS
 .sp
 Commands making remote HTTP requests may be configured to use a proxy by
 setting the \fBHTTPS_PROXY\fP environment variable, as described in
-\fI\%https://docs.python\-requests.org/en/latest/user/advanced/#proxies\fP\&;.
+ <https://docs.python\-requests.org/en/latest/user/advanced/#proxies> \&.
 .SH SUPPORT
 .sp
-Please email \fI\%[email protected]\fP with support requests, or browse the list
-archive at \fI\%https://lore.kernel.org/tools\fP\&;.
+Please email  <[email protected]>  with support requests, or browse the list
+archive at  <https://lore.kernel.org/tools> \&.
 .SH AUTHOR
 [email protected]
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/b4-0.14.2/src/b4/man/b4.5.rst 
new/b4-0.14.3/src/b4/man/b4.5.rst
--- old/b4-0.14.2/src/b4/man/b4.5.rst   2024-09-17 15:24:20.000000000 +0200
+++ new/b4-0.14.3/src/b4/man/b4.5.rst   2025-10-01 16:05:34.000000000 +0200
@@ -5,10 +5,10 @@
 ----------------------------------------------------
 
 :Author:    [email protected]
-:Date:      2024-06-14
+:Date:      2025-10-01
 :Copyright: The Linux Foundation and contributors
 :License:   GPLv2+
-:Version:   0.14.2
+:Version:   0.14.3
 :Manual section: 5
 
 SYNOPSIS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/b4-0.14.2/src/b4/mbox.py new/b4-0.14.3/src/b4/mbox.py
--- old/b4-0.14.2/src/b4/mbox.py        2024-09-17 15:24:20.000000000 +0200
+++ new/b4-0.14.3/src/b4/mbox.py        2025-10-01 16:05:34.000000000 +0200
@@ -564,6 +564,7 @@
     seen_msgids = set()
     seen_covers = set()
     queries = set()
+    by_changeid = False
     for msg in msgs:
         msgid = b4.LoreMessage.get_clean_msgid(msg)
         seen_msgids.add(msgid)
@@ -573,17 +574,22 @@
         if lsub.counter > 1:
             continue
 
-        if not lsub.reply:
-            payload, charset = b4.LoreMessage.get_payload(msg)
-            if payload:
-                matches = re.search(r'^change-id:\s+(\S+)', payload, 
flags=re.I | re.M)
-                if matches:
-                    logger.debug('Found change-id %s', matches.groups()[0])
-                    q = 'nq:"change-id: %s"' % matches.groups()[0]
-                    queries.add(q)
-
         if base_msg is not None:
             logger.debug('Current base_msg: %s', base_msg['Subject'])
+
+        if lsub.reply:
+            logger.debug('Ignoring reply: %s', lsub.full_subject)
+            continue
+
+        payload, _ = b4.LoreMessage.get_payload(msg)
+        if payload:
+            matches = re.search(r'^change-id:\s+(\S+)', payload, flags=re.I | 
re.M)
+            if matches:
+                logger.debug('Found change-id %s', matches.groups()[0])
+                by_changeid = True
+                q = 'nq:"change-id: %s"' % matches.groups()[0]
+                queries.add(q)
+
         logger.debug('Checking the subject on %s', lsub.full_subject)
         if latest_revision is None or lsub.revision >= latest_revision:
             latest_revision = lsub.revision
@@ -609,10 +615,17 @@
     if direction < 0 and wantvers is None:
         wantvers = [latest_revision - 1]
 
-    fromeml = email.utils.getaddresses(base_msg.get_all('from', []))[0][1]
     msgdate = email.utils.parsedate_tz(str(base_msg['Date']))
-    q = '(s:"%s" AND f:"%s")' % (lsub.subject.replace('"', ''), fromeml)
-    queries.add(q)
+    if msgdate is None:
+        logger.debug('Unable to parse the date, not checking for revisions')
+        return msgs
+
+    if not by_changeid:
+        logger.debug('Using subject+from combo for query')
+        fromeml = email.utils.getaddresses(base_msg.get_all('from', []))[0][1]
+        q = '(s:"%s" AND f:"%s")' % (lsub.subject.replace('"', ''), fromeml)
+        queries.add(q)
+
     startdate = time.strftime('%Y%m%d', msgdate[:9])
     if direction > 0:
         logger.critical('Checking for newer revisions')
@@ -622,6 +635,7 @@
         datelim = 'd:..%s' % startdate
 
     q = '(%s) AND %s' % (' OR '.join(queries), datelim)
+    logger.debug('Query: %s', q)
     q_msgs = b4.get_pi_search_results(q, nocache=nocache)
     if not q_msgs:
         return msgs
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/b4-0.14.2/src/tests/samples/trailers-followup-htmljunk-ref-defaults.txt 
new/b4-0.14.3/src/tests/samples/trailers-followup-htmljunk-ref-defaults.txt
--- old/b4-0.14.2/src/tests/samples/trailers-followup-htmljunk-ref-defaults.txt 
1970-01-01 01:00:00.000000000 +0100
+++ new/b4-0.14.3/src/tests/samples/trailers-followup-htmljunk-ref-defaults.txt 
2025-10-01 16:05:34.000000000 +0200
@@ -0,0 +1,31 @@
+From git@z Thu Jan  1 00:00:00 1970
+Subject: [PATCH] Simple test
+From: Test Test <[email protected]>
+Date: Tue, 30 Aug 2022 11:19:07 -0400
+Message-Id: <[email protected]>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 7bit
+
+Follow-up trailer collating test.
+
+Fixes: abcdef01234567890
+Reviewed-by: Original Reviewer <[email protected]>
+Link: https://msgid.link/[email protected]
+Signed-off-by: Original Submitter <[email protected]>
+Reviewed-by: HTML Junker <[email protected]>
+
+diff --git a/b4/junk.py b/b4/junk.py
+index 12345678..23456789 100644
+--- a/b4/junk.py
++++ b/b4/junk.py
+@@@ -1,1 +1,1 @@ def junk():
+ 
+ 
+-junk1
++junk2
+ 
+ 
+-- 
+2.wong.fu
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/b4-0.14.2/src/tests/samples/trailers-followup-htmljunk.mbox 
new/b4-0.14.3/src/tests/samples/trailers-followup-htmljunk.mbox
--- old/b4-0.14.2/src/tests/samples/trailers-followup-htmljunk.mbox     
1970-01-01 01:00:00.000000000 +0100
+++ new/b4-0.14.3/src/tests/samples/trailers-followup-htmljunk.mbox     
2025-10-01 16:05:34.000000000 +0200
@@ -0,0 +1,46 @@
+From foo@z Thu Jan  1 00:00:00 1970
+From: Test Test <[email protected]>
+Subject: [PATCH] Simple test
+To: Some List <[email protected]>
+Cc: Dev Eloper1 <[email protected]>,
+ Dev Eloper2 <[email protected]>
+Date: Tue, 30 Aug 2022 11:19:07 -0400
+Message-Id: <[email protected]>
+
+Follow-up trailer collating test.
+
+Fixes: abcdef01234567890
+Reviewed-by: Original Reviewer <[email protected]>
+Link: https://msgid.link/[email protected]
+Signed-off-by: Original Submitter <[email protected]>
+---
+
+diff --git a/b4/junk.py b/b4/junk.py
+index 12345678..23456789 100644
+--- a/b4/junk.py
++++ b/b4/junk.py
+@@@ -1,1 +1,1 @@ def junk():
+ 
+ 
+-junk1
++junk2
+ 
+ 
+-- 
+2.wong.fu
+
+From foo@z Thu Jan  1 00:00:00 1970
+From: HTML Junker <[email protected]>
+Subject: Re: [PATCH] Simple test
+Date: Tue, 30 Aug 2022 11:19:07 -0400
+Message-Id: <[email protected]>
+In-Reply-To: <[email protected]>
+References: <[email protected]>
+
+> This is a simple trailer parsing test.
+
+Reviewed-by: HTML Junker 
<[email protected]<mailto:[email protected]>>
+
+--
+My sig
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/b4-0.14.2/src/tests/samples/trailers-followup-name-parens-ref-defaults.txt 
new/b4-0.14.3/src/tests/samples/trailers-followup-name-parens-ref-defaults.txt
--- 
old/b4-0.14.2/src/tests/samples/trailers-followup-name-parens-ref-defaults.txt  
    2024-09-17 15:24:20.000000000 +0200
+++ 
new/b4-0.14.3/src/tests/samples/trailers-followup-name-parens-ref-defaults.txt  
    2025-10-01 16:05:34.000000000 +0200
@@ -15,6 +15,8 @@
 Signed-off-by: Original Submitter <[email protected]>
 Reviewed-by: Followup Reviewer1 (corporate) <[email protected]>
 Tested-by: Followup Reviewer2 <[email protected]>
+Tested-by: Followup Tester1 [corporate] <[email protected]>
+Tested-by: Tester2, Followup <[email protected]>
 
 diff --git a/b4/junk.py b/b4/junk.py
 index 12345678..23456789 100644
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/b4-0.14.2/src/tests/samples/trailers-followup-name-parens.mbox 
new/b4-0.14.3/src/tests/samples/trailers-followup-name-parens.mbox
--- old/b4-0.14.2/src/tests/samples/trailers-followup-name-parens.mbox  
2024-09-17 15:24:20.000000000 +0200
+++ new/b4-0.14.3/src/tests/samples/trailers-followup-name-parens.mbox  
2025-10-01 16:05:34.000000000 +0200
@@ -76,3 +76,32 @@
 --
 My sig
 
+From foo@z Thu Jan  1 00:00:00 1970
+From: Followup Tester1 <[email protected]>
+Subject: Re: [PATCH] Simple test
+Date: Tue, 30 Aug 2022 11:19:07 -0400
+Message-Id: <[email protected]>
+In-Reply-To: <[email protected]>
+References: <[email protected]>
+
+> This is a simple trailer parsing test.
+
+Tested-by: Followup Tester1 [corporate] <[email protected]>
+
+--
+My sig
+
+From foo@z Thu Jan  1 00:00:00 1970
+From: Followup Tester2 <[email protected]>
+Subject: Re: [PATCH] Simple test
+Date: Tue, 30 Aug 2022 11:19:07 -0400
+Message-Id: <[email protected]>
+In-Reply-To: <[email protected]>
+References: <[email protected]>
+
+> This is a simple trailer parsing test.
+
+Tested-by: Tester2, Followup <[email protected]>
+
+--
+My sig
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/b4-0.14.2/src/tests/samples/trailers-followup-stripped-lines-ref-defaults.txt
 
new/b4-0.14.3/src/tests/samples/trailers-followup-stripped-lines-ref-defaults.txt
--- 
old/b4-0.14.2/src/tests/samples/trailers-followup-stripped-lines-ref-defaults.txt
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/b4-0.14.3/src/tests/samples/trailers-followup-stripped-lines-ref-defaults.txt
   2025-10-01 16:05:34.000000000 +0200
@@ -0,0 +1,29 @@
+From git@z Thu Jan  1 00:00:00 1970
+Subject: [PATCH] Simple test
+From: Test Test <[email protected]>
+Date: Tue, 30 Aug 2022 11:19:07 -0400
+Message-Id: <[email protected]>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 7bit
+
+Follow-up trailer collating test.
+
+Fixes: abcdef01234567890
+Reviewed-by: Original Reviewer <[email protected]>
+Link: https://msgid.link/[email protected]
+Signed-off-by: Original Submitter <[email protected]>
+Reviewed-by: Followup Reviewer1 <[email protected]>
+
+--- a/b4/junk.py
++++ b/b4/junk.py
+@@@ -1,1 +1,1 @@ def junk():
+
+
+-junk1
++junk2
+
+
+-- 
+2.wong.fu
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/b4-0.14.2/src/tests/samples/trailers-followup-stripped-lines.mbox 
new/b4-0.14.3/src/tests/samples/trailers-followup-stripped-lines.mbox
--- old/b4-0.14.2/src/tests/samples/trailers-followup-stripped-lines.mbox       
1970-01-01 01:00:00.000000000 +0100
+++ new/b4-0.14.3/src/tests/samples/trailers-followup-stripped-lines.mbox       
2025-10-01 16:05:34.000000000 +0200
@@ -0,0 +1,42 @@
+From foo@z Thu Jan  1 00:00:00 1970
+From: Test Test <[email protected]>
+Subject: [PATCH] Simple test
+To: Some List <[email protected]>
+Cc: Dev Eloper1 <[email protected]>,
+ Dev Eloper2 <[email protected]>
+Date: Tue, 30 Aug 2022 11:19:07 -0400
+Message-Id: <[email protected]>
+
+Follow-up trailer collating test.
+
+Fixes: abcdef01234567890
+Reviewed-by: Original Reviewer <[email protected]>
+Link: https://msgid.link/[email protected]
+Signed-off-by: Original Submitter <[email protected]>
+
+--- a/b4/junk.py
++++ b/b4/junk.py
+@@@ -1,1 +1,1 @@ def junk():
+
+
+-junk1
++junk2
+
+
+-- 
+2.wong.fu
+
+From foo@z Thu Jan  1 00:00:00 1970
+From: Followup Reviewer1 <[email protected]>
+Subject: Re: [PATCH] Simple test
+Date: Tue, 30 Aug 2022 11:19:07 -0400
+Message-Id: <[email protected]>
+In-Reply-To: <[email protected]>
+References: <[email protected]>
+
+> This is a simple trailer parsing test.
+
+Reviewed-by: Followup Reviewer1 <[email protected]>
+
+--
+My sig
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/b4-0.14.2/src/tests/test___init__.py 
new/b4-0.14.3/src/tests/test___init__.py
--- old/b4-0.14.2/src/tests/test___init__.py    2024-09-17 15:24:20.000000000 
+0200
+++ new/b4-0.14.3/src/tests/test___init__.py    2025-10-01 16:05:34.000000000 
+0200
@@ -105,8 +105,10 @@
     ('with-diffstat', {}, {}, 'defaults', {}),
     ('name-parens', {}, {}, 'defaults', {}),
     ('bare-address', {}, {}, 'defaults', {}),
+    ('stripped-lines', {}, {}, 'defaults', {}),
+    ('htmljunk', {}, {}, 'defaults', {}),
 ])
-def test_followup_trailers(sampledir, source, serargs, amargs, reference, 
b4cfg):
+def test_followup_trailers(sampledir, source, serargs, amargs, reference, 
b4cfg) -> None:
     b4.MAIN_CONFIG.update(b4cfg)
     lmbx = b4.LoreMailbox()
     for msg in mailbox.mbox(f'{sampledir}/trailers-followup-{source}.mbox'):

++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore      1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore      2025-10-01 18:10:31.000000000 +0200
@@ -0,0 +1 @@
+.osc

Reply via email to