Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package b4 for openSUSE:Factory checked in 
at 2024-09-25 21:54:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/b4 (Old)
 and      /work/SRC/openSUSE:Factory/.b4.new.29891 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "b4"

Wed Sep 25 21:54:03 2024 rev:43 rq:1203258 version:0.14.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/b4/b4.changes    2024-07-25 16:21:26.805255600 
+0200
+++ /work/SRC/openSUSE:Factory/.b4.new.29891/b4.changes 2024-09-25 
21:54:33.323436538 +0200
@@ -1,0 +2,9 @@
+Wed Sep 18 05:13:21 UTC 2024 - Jiri Slaby <jsl...@suse.cz>
+
+- update to 0.14.2:
+  * fixes "b4 am/shazam" sometimes pulling in bogus trailers
+  * fixes "b4 send" treating message-ids as email addresses to cc
+  * fixes "prep-perpatch-check-cmd" for custom checkpatch configurations
+  * fixes "b4 send" expanding prerequisites in incorrect order
+
+-------------------------------------------------------------------

Old:
----
  b4-0.14.1.tar.gz

New:
----
  b4-0.14.2.tar.gz

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

Other differences:
------------------
++++++ b4.spec ++++++
--- /var/tmp/diff_new_pack.DjsVoZ/_old  2024-09-25 21:54:33.767455006 +0200
+++ /var/tmp/diff_new_pack.DjsVoZ/_new  2024-09-25 21:54:33.771455172 +0200
@@ -24,7 +24,7 @@
 %global pprefix python311
 %endif
 Name:           b4
-Version:        0.14.1
+Version:        0.14.2
 Release:        0
 Summary:        Helper scripts for kernel.org patches
 License:        GPL-2.0-or-later

++++++ b4-0.14.1.tar.gz -> b4-0.14.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/b4-0.14.1/pyproject.toml new/b4-0.14.2/pyproject.toml
--- old/b4-0.14.1/pyproject.toml        2024-07-23 16:42:58.000000000 +0200
+++ new/b4-0.14.2/pyproject.toml        2024-09-17 15:24:20.000000000 +0200
@@ -4,7 +4,7 @@
 
 [project]
 name = "b4"
-version = "0.14.1"
+version = "0.14.2"
 description = "A tool to work with public-inbox and patch archives"
 readme = "README.rst"
 keywords = ["git", "public-inbox", "lore.kernel.org", "patch", "email", 
"workflow"]
@@ -47,7 +47,7 @@
 norecursedirs = "tests/helpers"
 
 [tool.bumpversion]
-current_version = "0.14.1"
+current_version = "0.14.2"
 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.1/src/b4/__init__.py 
new/b4-0.14.2/src/b4/__init__.py
--- old/b4-0.14.1/src/b4/__init__.py    2024-07-23 16:42:58.000000000 +0200
+++ new/b4-0.14.2/src/b4/__init__.py    2024-09-17 15:24:20.000000000 +0200
@@ -64,7 +64,7 @@
 # global setting allowing us to turn off networking
 can_network = True
 
-__VERSION__ = '0.14.1'
+__VERSION__ = '0.14.2'
 PW_REST_API_VERSION = '1.2'
 
 
@@ -394,17 +394,27 @@
                 break
 
         # Carry over trailers from previous series if patch/metadata did not 
change
+        logger.debug('Analyzing trailer_map (%s entries)', 
len(self.trailer_map))
         for lmsg in lser.patches:
             if lmsg is None or lmsg.git_patch_id is None:
                 continue
+            logger.debug('  matching patch_id %s from: %s', lmsg.git_patch_id, 
lmsg.full_subject)
             if lmsg.git_patch_id in self.trailer_map:
                 for fmsg in self.trailer_map[lmsg.git_patch_id]:
+                    logger.debug('  matched: %s', fmsg.msgid)
                     fltrs, fmis = fmsg.get_trailers(sloppy=sloppytrailers)
                     for fltr in fltrs:
-                        if fltr not in lmsg.trailers and fltr not in 
lmsg.followup_trailers:
-                            logger.debug('    adding "%s" from trailer_map to: 
%s',
-                                         fltr.as_string(), lmsg.full_subject)
-                            lmsg.followup_trailers.append(fltr)
+                        if fltr in lmsg.trailers:
+                            logger.debug('  trailer already exists')
+                            continue
+                        if fltr in lmsg.followup_trailers:
+                            logger.debug('  identical trailer received for 
this series')
+                            continue
+                        logger.debug('  carrying over the trailer to this 
series (may be duplicate)')
+                        logger.debug('  %s', lmsg.full_subject)
+                        logger.debug('    + %s', fltr.as_string())
+                        logger.debug('      via: %s', fltr.lmsg.msgid)
+                        lmsg.followup_trailers.append(fltr)
                     for fltr in fmis:
                         lser.trailer_mismatches.add((fltr.name, fltr.value, 
fmsg.fromname, fmsg.fromemail))
 
@@ -1142,7 +1152,7 @@
 
     # header-based info
     in_reply_to: Optional[str]
-    references: Set[str]
+    references: List[str]
     fromname: str
     fromemail: str
     date: datetime.datetime
@@ -1213,14 +1223,15 @@
             self.expected = self.counter
 
         self.in_reply_to = LoreMessage.get_clean_msgid(self.msg, 
header='In-Reply-To')
-        self.references = set()
         if self.in_reply_to:
-            self.references.add(self.in_reply_to)
+            self.references = [self.in_reply_to]
+        else:
+            self.references = list()
 
         if self.msg.get('References'):
             for pair in email.utils.getaddresses([str(x) for x in 
self.msg.get_all('references', [])]):
-                if pair:
-                    self.references.add(pair[1])
+                if pair and pair[1].strip() and pair[1] not in self.references:
+                    self.references.append(pair[1])
 
         try:
             fromdata = 
email.utils.getaddresses([LoreMessage.clean_header(str(x))
@@ -1275,13 +1286,14 @@
         mismatches = set()
 
         for ltr in self.trailers:
+            logger.debug('Examining: %s', ltr.as_string())
             ltr.lmsg = self
             if sloppy or ltr.type != 'person':
                 trailers.append(ltr)
                 continue
 
             if ltr.email_eq(self.fromemail):
-                logger.debug('  trailer email match')
+                logger.debug('  trailer email match with %s', self.fromemail)
                 trailers.append(ltr)
                 continue
 
@@ -1291,7 +1303,7 @@
             hlname = self.fromname.lower()
 
             if tlname == hlname:
-                logger.debug('  trailer exact name match')
+                logger.debug('  trailer exact name match with %s', 
self.fromname)
                 nmatch = True
             # Finally, see if the header From has a comma in it and try to 
find all
             # parts in the trailer name
@@ -1301,12 +1313,14 @@
                     if hlname.find(nchunk.strip()) < 0:
                         nmatch = False
                         break
+                if nmatch:
+                    logger.debug('  trailer fuzzy name match with %s', 
self.fromname)
+
             if nmatch:
-                logger.debug('  trailer fuzzy name match')
                 trailers.append(ltr)
                 continue
 
-            logger.debug('trailer did not match: %s: %s', ltr.name, ltr.value)
+            logger.debug('  trailer did not match: %s: %s', ltr.name, 
ltr.value)
             mismatches.add(ltr)
 
         return trailers, mismatches
@@ -1520,18 +1534,29 @@
         topdir = git_get_toplevel()
         mycmd = os.path.basename(cmdargs[0])
         ecode, out, err = _run_command(cmdargs, stdin=bdata, rundir=topdir)
+        report = list()
+
         out = out.strip()
         out_lines = out.decode(errors='replace').split('\n') if out else list()
-        report = list()
-        if out_lines:
-            for line in out_lines:
-                flag = 'fail' if 'ERROR:' in line else 'warning'
-                # Remove '-:' from the start of the line, because it's never 
useful
-                if line.startswith('-:'):
-                    line = line[2:]
-                report.append((flag, f'{mycmd}: {line}'))
-        else:
-            report.append(('success', f'{mycmd}: passed all checks'))
+        for line in out_lines:
+            flag = 'fail' if 'ERROR:' in line else 'warning'
+            # Remove '-:' from the start of the line, because it's never useful
+            if line.startswith('-:'):
+                line = line[2:]
+            report.append((flag, f'{mycmd}: {line}'))
+
+        err = err.strip()
+        err_lines = err.decode(errors='replace').split('\n') if err else list()
+        for line in err_lines:
+            if line.startswith('-:'):
+                line = line[2:]
+            report.append(('fail', f'{mycmd}: {line}'))
+
+        if (not out_lines) and (not err_lines):
+            if ecode:
+                report.append(('fail', f'{mycmd}: Exited with error code 
{ecode}'))
+            else:
+                report.append(('success', f'{mycmd}: passed all checks'))
 
         save_cache(report, cacheid, suffix='checks', is_json=True)
         return report
@@ -1976,7 +2001,7 @@
 
     @staticmethod
     def find_trailers(body: str, followup: bool = False) -> 
Tuple[List[LoreTrailer], List[str]]:
-        ignores = {'phone', 'email'}
+        ignores = {'phone', 'email', 'prerequisite-message-id'}
         headers = {'subject', 'date', 'from'}
         links = {'link', 'buglink', 'closes'}
         nonperson = links | {'fixes', 'subject', 'date', 'obsoleted-by', 
'change-id', 'base-commit'}
@@ -2843,6 +2868,14 @@
     return gitconfig
 
 
+def _val_to_path(topdir, val):
+    if val.startswith('./'):
+        # replace it with full topdir path
+        return os.path.abspath(os.path.join(topdir, val))
+    else:
+        return val
+
+
 def _setup_main_config(cmdargs: Optional[argparse.Namespace] = None) -> None:
     global MAIN_CONFIG
 
@@ -2851,23 +2884,24 @@
     # so load them up and use as defaults
     topdir = git_get_toplevel()
     wtglobs = ['prep-*-check-cmd', 'send-*', '*mask', '*template*', 
'trailer*', 'pw-*']
+    multivals = ['keyringsrc', 'am-perpatch-check-cmd', 
'prep-perpatch-check-cmd']
     if topdir:
         wtcfg = os.path.join(topdir, '.b4-config')
         if os.access(wtcfg, os.R_OK):
             logger.debug('Loading worktree configs from %s', wtcfg)
-            wtconfig = get_config_from_git(r'b4\..*', source=wtcfg)
+            wtconfig = get_config_from_git(r'b4\..*', multivals=multivals, 
source=wtcfg)
             logger.debug('wtcfg=%s', wtconfig)
             for key, val in wtconfig.items():
-                if val.startswith('./'):
-                    # replace it with full topdir path
-                    val = os.path.abspath(os.path.join(topdir, val))
+                if key in multivals:
+                    val = [_val_to_path(topdir, x) for x in val]
+                else:
+                    val = _val_to_path(topdir, val)
                 for wtglob in wtglobs:
                     if fnmatch.fnmatch(key, wtglob):
                         logger.debug('wtcfg: %s=%s', key, val)
                         defcfg[key] = val
                         break
-    config = get_config_from_git(r'b4\..*', defaults=defcfg,
-                                 multivals=['keyringsrc', 
'am-perpatch-check-cmd', 'prep-perpatch-check-cmd'])
+    config = get_config_from_git(r'b4\..*', defaults=defcfg, 
multivals=multivals)
     config['listid-preference'] = config['listid-preference'].split(',')
     config['listid-preference'].remove('*')
     config['listid-preference'].append('*')
@@ -3277,6 +3311,16 @@
     return msgs
 
 
+def get_series_by_msgid(msgid: str, nocache: bool = False) -> 
Optional['LoreMailbox']:
+    lmbx = LoreMailbox()
+    t_msgs = get_pi_thread_by_msgid(msgid, nocache=nocache)
+    if t_msgs:
+        for t_msg in t_msgs:
+            lmbx.add_message(t_msg)
+
+    return lmbx
+
+
 def get_series_by_change_id(change_id: str, nocache: bool = False) -> 
Optional['LoreMailbox']:
     q = f'nq:"change-id:{change_id}"'
     q_msgs = get_pi_search_results(q, nocache=nocache, full_threads=False)
@@ -3410,8 +3454,19 @@
         if commit in ignore_commits:
             logger.debug('Ignoring commit %s', commit)
             continue
-        ecode, out = git_run_command(gitdir, ['show', '--format=email', 
'--patch-with-stat', '--encoding=utf-8',
-                                              commit], decode=False)
+        ecode, out = git_run_command(
+            gitdir,
+            [
+                'show',
+                '--format=email',
+                '--full-index',
+                '--binary',
+                '--patch-with-stat',
+                '--encoding=utf-8',
+                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)
@@ -4294,36 +4349,29 @@
         # Find the patch-id to which this belongs
         pfound = False
         for refmid in qlmsg.references:
+            logger.debug('  looking at parent ref: %s', refmid)
             if refmid in qmid_map:
+                logger.debug('  found in qmid_map: %s', refmid)
                 # Is it a patch?
                 _qmsg = qmid_map[refmid]
-                if _qmsg.has_diff:
+                logger.debug('  subj: %s', _qmsg.full_subject)
+                # Is it the cover letter?
+                if (_qmsg.counter == 0 and (not _qmsg.counters_inferred or 
_qmsg.has_diffstat)
+                        and _qmsg.msgid in ref_map):
+                    logger.debug('  stopping: found the cover letter for %s', 
qlmsg.full_subject)
+                    break
+                elif _qmsg.has_diff:
                     pqpid = _qmsg.git_patch_id
                     if pqpid:
+                        logger.debug('  pqpid: %s', pqpid)
                         # Found our parent patch
                         if pqpid not in patchid_map:
                             patchid_map[pqpid] = list()
                         if qlmsg not in patchid_map[pqpid]:
                             patchid_map[pqpid].append(qlmsg)
+                            logger.debug('  matched patch-id %s to %s', pqpid, 
qlmsg.full_subject)
                         pfound = True
-                        logger.debug('  found matching patch-id for %s', 
qlmsg.subject)
                         break
-                # Is it a cover letter?
-                elif (_qmsg.counter == 0 and (not _qmsg.counters_inferred or 
_qmsg.has_diffstat)
-                      and _qmsg.msgid in ref_map):
-                    logger.debug('  found a cover letter for %s', 
qlmsg.subject)
-                    # Now we find all descendant patches of the same series
-                    for _child_msgid in ref_map[_qmsg.msgid]:
-                        if _child_msgid == refmid:
-                            continue
-                        if qmid_map[_child_msgid].has_diff:
-                            cqpid = qmid_map[_child_msgid].git_patch_id
-                            if cqpid:
-                                # Found our parent patch
-                                if cqpid not in patchid_map:
-                                    patchid_map[cqpid] = list()
-                                if qlmsg not in patchid_map[cqpid]:
-                                    patchid_map[cqpid].append(qlmsg)
                 else:
                     logger.debug('  skipping parent without a diff or 
diffstat')
         if not pfound:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/b4-0.14.1/src/b4/ez.py new/b4-0.14.2/src/b4/ez.py
--- old/b4-0.14.1/src/b4/ez.py  2024-07-23 16:42:58.000000000 +0200
+++ new/b4-0.14.2/src/b4/ez.py  2024-09-17 15:24:20.000000000 +0200
@@ -1509,11 +1509,16 @@
             prerequisites += f'prerequisite-{prereq}\n'
             if expandprereqs:
                 msgid = chunks[1].strip('<>')
-                spatches = b4.get_pi_thread_by_msgid(msgid)
-                if not spatches:
+                lmbx = b4.get_series_by_msgid(msgid)
+                if not lmbx:
                     logger.info('Nothing known about message-id: %s', msgid)
                     logger.info('Consider running --check-deps')
                     continue
+                wantver = max(lmbx.series.keys())
+                for lmsg in lmbx.series[wantver].patches:
+                    if not lmsg:
+                        continue
+                    spatches.append(lmsg.get_am_message(add_trailers=False))
 
         if prereq.startswith('change-id:'):
             prerequisites += f'prerequisite-{prereq}\n'
@@ -1595,6 +1600,9 @@
     if addtracking:
         patches[0][1].add_header('X-B4-Tracking', thdata)
 
+    # Add X-Change-ID header
+    patches[0][1].add_header('X-Change-ID', change_id)
+
     samethread = config.get('send-same-thread', '').lower() in {'yes', 'true', 
'y'}
     if samethread and revision > 1:
         oldrev = revision - 1
@@ -2163,45 +2171,55 @@
 
     tagname, revision = get_sent_tagname(change_id, tagprefix, revision)
     logger.debug('checking if we already have %s', tagname)
+    topdir = b4.git_get_toplevel()
     if not b4.git_revparse_tag(None, tagname):
+        strategy = get_cover_strategy()
+        tagcommit = 'HEAD'
         try:
-            strategy = get_cover_strategy()
             if strategy == 'commit':
-                # Find out the head commit, which is the end of our range
-                gitargs = ['rev-parse', 'HEAD']
-                ecode, out = b4.git_run_command(None, gitargs)
-                end_commit = out.strip()
-                # Detach the head at our parent commit and apply the 
cover-less series
-                cover_commit = find_cover_commit()
-                gitargs = ['checkout', f'{cover_commit}~1']
-                ecode, out = b4.git_run_command(None, gitargs)
-                if ecode > 0:
-                    raise RuntimeError('Could not switch to a detached head')
-                # cherry-pick from cover letter to the last commit
-                gitargs = ['cherry-pick', f'{cover_commit}..{end_commit}']
-                ecode, out = b4.git_run_command(None, gitargs)
-                if ecode > 0:
-                    raise RuntimeError('Could not cherry-pick the cover-less 
range')
-                # Find out the head commit
-                gitargs = ['rev-parse', 'HEAD']
-                ecode, out = b4.git_run_command(None, gitargs)
-                if ecode > 0:
-                    raise RuntimeError('Could not find the HEAD commit of the 
detached head')
-                tagcommit = out.strip()
-                # Switch back to our branch
-                gitargs = ['checkout', mybranch]
-                ecode, out = b4.git_run_command(None, gitargs)
-                if ecode > 0:
-                    raise RuntimeError('Could not switch back to %s' % 
mybranch)
+                base_commit, start_commit, end_commit = 
get_series_range(usebranch=mybranch)
+                with b4.git_temp_worktree(topdir, base_commit) as gwt:
+                    logger.debug('Preparing a sparse worktree')
+                    ecode, out = b4.git_run_command(gwt, ['sparse-checkout', 
'init'], logstderr=True)
+                    if ecode > 0:
+                        logger.critical('Error running sparse-checkout init')
+                        logger.critical(out)
+                        raise RuntimeError
+                    ecode, out = b4.git_run_command(gwt, ['checkout'], 
logstderr=True)
+                    if ecode > 0:
+                        logger.critical('Error running checkout into sparse 
workdir')
+                        logger.critical(out)
+                        raise RuntimeError
+                    gitargs = ['cherry-pick', f'{start_commit}..{end_commit}']
+                    ecode, out = b4.git_run_command(gwt, gitargs, 
logstderr=True)
+                    if ecode > 0:
+                        # In theory, this shouldn't happen
+                        logger.critical('Unable to cleanly apply series, see 
failure log below')
+                        logger.critical('---')
+                        logger.critical(out.strip())
+                        logger.critical('---')
+                        logger.critical('Not fetching into FETCH_HEAD')
+                        raise RuntimeError
+                    gitargs = ['rev-parse', 'HEAD']
+                    ecode, out = b4.git_run_command(gwt, gitargs, 
logstderr=True)
+                    if ecode > 0:
+                        logger.critical('Unable to resolve FETCH_HEAD')
+                        logger.critical(out.strip())
+                        raise RuntimeError
+                    tagcommit = out.strip()
+                    gitargs = ['fetch', gwt]
+                    ecode, out = b4.git_run_command(topdir, gitargs, 
logstderr=True)
+                    if ecode > 0:
+                        logger.critical('Unable to fetch from the worktree')
+                        logger.critical(out.strip())
+                        raise RuntimeError
             elif strategy == 'tip-commit':
                 cover_commit = find_cover_commit()
                 tagcommit = f'{cover_commit}~1'
-            else:
-                tagcommit = 'HEAD'
 
             logger.info('Tagging %s', tagname)
             gitargs = ['tag', '-a', '-F', '-', tagname, tagcommit]
-            ecode, out = b4.git_run_command(None, gitargs, 
stdin=tag_msg.encode())
+            ecode, out = b4.git_run_command(topdir, gitargs, 
stdin=tag_msg.encode())
             if ecode > 0:
                 # Not a fatal error, complain about it and move on
                 logger.info('Could not tag %s as %s:', tagcommit, tagname)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/b4-0.14.1/src/b4/man/b4.5 
new/b4-0.14.2/src/b4/man/b4.5
--- old/b4-0.14.1/src/b4/man/b4.5       2024-07-23 16:42:58.000000000 +0200
+++ new/b4-0.14.2/src/b4/man/b4.5       2024-09-17 15:24:20.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.1"
+.TH "B4" 5 "2024-06-14" "0.14.2"
 .SH NAME
 B4 \- Work with code submissions in a public-inbox archive
 .SH SYNOPSIS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/b4-0.14.1/src/b4/man/b4.5.rst 
new/b4-0.14.2/src/b4/man/b4.5.rst
--- old/b4-0.14.1/src/b4/man/b4.5.rst   2024-07-23 16:42:58.000000000 +0200
+++ new/b4-0.14.2/src/b4/man/b4.5.rst   2024-09-17 15:24:20.000000000 +0200
@@ -8,7 +8,7 @@
 :Date:      2024-06-14
 :Copyright: The Linux Foundation and contributors
 :License:   GPLv2+
-:Version:   0.14.1
+:Version:   0.14.2
 :Manual section: 5
 
 SYNOPSIS

Reply via email to