You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2018/10/06 05:53:03 UTC

svn commit: r1843003 - in /subversion/branches/better-pristines: ./ subversion/include/ subversion/svn/ subversion/tests/cmdline/getopt_tests_data/ subversion/tests/cmdline/svntest/ tools/dist/

Author: brane
Date: Sat Oct  6 05:53:03 2018
New Revision: 1843003

URL: http://svn.apache.org/viewvc?rev=1843003&view=rev
Log:
On the better-pristines branch: Sync with trunk up to r1843002.

Modified:
    subversion/branches/better-pristines/   (props changed)
    subversion/branches/better-pristines/CHANGES
    subversion/branches/better-pristines/subversion/include/svn_client.h
    subversion/branches/better-pristines/subversion/include/svn_fs.h
    subversion/branches/better-pristines/subversion/svn/svn.c
    subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
    subversion/branches/better-pristines/subversion/tests/cmdline/svntest/main.py
    subversion/branches/better-pristines/tools/dist/create-minor-release-branch.py
    subversion/branches/better-pristines/tools/dist/release.py

Propchange: subversion/branches/better-pristines/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sat Oct  6 05:53:03 2018
@@ -101,4 +101,4 @@
 /subversion/branches/verify-at-commit:1462039-1462408
 /subversion/branches/verify-keep-going:1439280-1546110
 /subversion/branches/wc-collate-path:1402685-1480384
-/subversion/trunk:1807118-1842402
+/subversion/trunk:1807118-1843002

Modified: subversion/branches/better-pristines/CHANGES
URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/CHANGES?rev=1843003&r1=1843002&r2=1843003&view=diff
==============================================================================
--- subversion/branches/better-pristines/CHANGES (original)
+++ subversion/branches/better-pristines/CHANGES Sat Oct  6 05:53:03 2018
@@ -57,6 +57,37 @@ http://svn.apache.org/repos/asf/subversi
     * Fix a potential crash in JavaHL (issue #4764)
 
 
+Version 1.10.3
+(?? Oct 2018, from /branches/1.10.x)
+http://svn.apache.org/repos/asf/subversion/tags/1.10.3
+
+ User-visible changes:
+  - Minor new features and improvements:
+    * Store the HTTPS client cert password (r1842578)
+
+  - Client-side bugfixes:
+    * Fix shelving when custom diff command is configured (issue #4758)
+    * Fix conflict resolver crashes (issue #4744, r1842581, r1842582, r1842583)
+    * Fix conflict resolver endless scan in some cases (r1842586)
+    * Fix "Accept incoming deletion" on locally deleted file (issue #4739)
+    * Fix "resolver adds unrelated moves to move target list" (issue #4766)
+
+  - Server-side bugfixes:
+    * Reject bad PUT before CHECKOUT in v1 HTTP protocol (r1841281)
+    * Let 'svnadmin recover' prune the rep-cache even if disabled (r1842585)
+
+  - Client-side and server-side bugfixes:
+    * Allow commands like 'svn ci --file X' to work when X is a FIFO (r1841282)
+
+  - Other tool improvements and bugfixes:
+    * 'svnadmin verify --keep-going --quiet' shows an error summary (r1842584)
+    * Fix error in german translation for 'svn help merge' (r1837038)
+
+ Developer-visible changes:
+  - General:
+    * Python tests use the current python executable (r1842626)
+
+
 Version 1.10.2
 (20 Jul 2018, from /branches/1.10.x)
 http://svn.apache.org/repos/asf/subversion/tags/1.10.2

Modified: subversion/branches/better-pristines/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/include/svn_client.h?rev=1843003&r1=1843002&r2=1843003&view=diff
==============================================================================
--- subversion/branches/better-pristines/subversion/include/svn_client.h (original)
+++ subversion/branches/better-pristines/subversion/include/svn_client.h Sat Oct  6 05:53:03 2018
@@ -6815,7 +6815,7 @@ svn_client_list2(const char *path_or_url
 
 /**
  * Similar to svn_client_list2(), but with @a recurse instead of @a depth.
- * If @a recurse is TRUE, pass #svn_depth_files for @a depth; else
+ * If @a recurse is FALSE, pass #svn_depth_immediates for @a depth; else
  * pass #svn_depth_infinity.
  *
  * @since New in 1.4.

Modified: subversion/branches/better-pristines/subversion/include/svn_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/include/svn_fs.h?rev=1843003&r1=1843002&r2=1843003&view=diff
==============================================================================
--- subversion/branches/better-pristines/subversion/include/svn_fs.h (original)
+++ subversion/branches/better-pristines/subversion/include/svn_fs.h Sat Oct  6 05:53:03 2018
@@ -1828,9 +1828,9 @@ svn_fs_node_history(svn_fs_history_t **h
  * the same as the original.  This will happen if the original
  * location was an interesting one (where the node was modified, or
  * took place in a copy event).  This behavior allows looping callers
- * to avoid the calling svn_fs_history_location() on the object
- * returned by svn_fs_node_history(), and instead go ahead and begin
- * calling svn_fs_history_prev().
+ * to avoid calling svn_fs_history_location() on the object returned
+ * by svn_fs_node_history(), and instead go ahead and begin calling
+ * svn_fs_history_prev().
  *
  * @note This function uses node-id ancestry alone to determine
  * modifiedness, and therefore does NOT claim that in any of the

Modified: subversion/branches/better-pristines/subversion/svn/svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/svn/svn.c?rev=1843003&r1=1843002&r2=1843003&view=diff
==============================================================================
--- subversion/branches/better-pristines/subversion/svn/svn.c (original)
+++ subversion/branches/better-pristines/subversion/svn/svn.c Sat Oct  6 05:53:03 2018
@@ -166,7 +166,7 @@ const apr_getopt_option_t svn_cl__option
   {"message",       'm', 1, N_("specify log message ARG")},
   {"quiet",         'q', 0, N_("print nothing, or only summary information")},
   {"recursive",     'R', 0, N_("descend recursively, same as --depth=infinity")},
-  {"non-recursive", 'N', 0, N_("obsolete; try --depth=files or --depth=immediates")},
+  {"non-recursive", 'N', 0, N_("obsolete")},
   {"change",        'c', 1,
                     N_("the change made by revision ARG (like -r ARG-1:ARG)\n"
                        "                             "
@@ -539,18 +539,39 @@ const int svn_cl__global_options[] =
 const svn_opt_subcommand_desc3_t svn_cl__cmd_table[] =
 {
   { "add", svn_cl__add, {0}, {N_(
-     "Put files and directories under version control, scheduling\n"
-     "them for addition to repository.  They will be added in next commit.\n"
+     "Put new files and directories under version control.\n"
      "usage: add PATH...\n"
+     "\n"), N_(
+     "  Schedule unversioned PATHs for addition, so they will become versioned and\n"
+     "  be added to the repository in the next commit. Recurse into directories by\n"
+     "  default (see the --depth option).\n"
+     "\n"), N_(
+     "  The 'svn add' command is only necessary for files and directories that are\n"
+     "  not yet under version control. Unversioned files and directories can be\n"
+     "  identified with 'svn status' (see 'svn help status').\n"
+     "\n"), N_(
+     "  The effects of 'svn add' can be undone with 'svn revert' before the addition\n"
+     "  has been committed. Once committed, a path can be removed from version\n"
+     "  control with 'svn delete', and in some circumstances by running a reverse-\n"
+     "  merge (see 'svn help merge' for details).\n"
+     "\n"), N_(
+     "  With --force, add all the unversioned paths found in PATHs and ignore the\n"
+     "  rest; otherwise, error out if any specified paths are already versioned.\n"
+     "\n"), N_(
+     "  The selection of items to add may be influenced by the 'ignores' feature.\n"
+     "  Properties may be attached to the items as configured by the 'auto-props'\n"
+     "  feature.\n"
     )},
     {opt_targets, 'N', opt_depth, 'q', opt_force, opt_no_ignore, opt_autoprops,
      opt_no_autoprops, opt_parents },
-     {{opt_parents, N_("add intermediate parents")}} },
+    {{opt_parents, N_("add intermediate parents")},
+     {'N', N_("obsolete; same as --depth=empty")},
+     {opt_force, N_("ignore already versioned paths")}} },
 
   { "auth", svn_cl__auth, {0}, {N_(
      "Manage cached authentication credentials.\n"
      "usage: 1. svn auth [PATTERN ...]\n"
-     "usage: 2. svn auth --remove PATTERN [PATTERN ...]\n"
+     "       2. svn auth --remove PATTERN [PATTERN ...]\n"
      "\n"), N_(
      "  With no arguments, list all cached authentication credentials.\n"
      "  Authentication credentials include usernames, passwords,\n"
@@ -642,7 +663,8 @@ const svn_opt_subcommand_desc3_t svn_cl_
      "  reporting the action taken.\n"
     )},
     {'r', 'q', 'N', opt_depth, opt_force, opt_ignore_externals,
-     opt_compatible_version} },
+     opt_compatible_version},
+    {{'N', N_("obsolete; same as --depth=files")}} },
 
   { "cleanup", svn_cl__cleanup, {0}, {N_(
      "Either recover from an interrupted operation that left the working copy locked,\n"
@@ -691,7 +713,8 @@ const svn_opt_subcommand_desc3_t svn_cl_
      "  fixed revision.\n"
     )},
     {'q', 'N', opt_depth, opt_targets, opt_no_unlock, SVN_CL__LOG_MSG_OPTIONS,
-     opt_changelist, opt_keep_changelists, opt_include_externals} },
+     opt_changelist, opt_keep_changelists, opt_include_externals},
+    {{'N', N_("obsolete; same as --depth=empty")}} },
 
   { "copy", svn_cl__copy, {"cp"}, {N_(
      "Copy files and directories in a working copy or repository.\n"
@@ -773,7 +796,9 @@ const svn_opt_subcommand_desc3_t svn_cl_
      opt_internal_diff, 'x', opt_no_diff_added, opt_no_diff_deleted,
      opt_ignore_properties, opt_properties_only,
      opt_show_copies_as_adds, opt_notice_ancestry, opt_summarize, opt_changelist,
-     opt_force, opt_xml, opt_use_git_diff_format, opt_patch_compatible} },
+     opt_force, opt_xml, opt_use_git_diff_format, opt_patch_compatible},
+    {{'N', N_("obsolete; same as --depth=files")}} },
+
   { "export", svn_cl__export, {0}, {N_(
      "Create an unversioned copy of a tree.\n"
      "usage: 1. export [-r REV] URL[@PEGREV] [PATH]\n"
@@ -795,7 +820,8 @@ const svn_opt_subcommand_desc3_t svn_cl_
      "  looked up.\n"
     )},
     {'r', 'q', 'N', opt_depth, opt_force, opt_native_eol, opt_ignore_externals,
-     opt_ignore_keywords} },
+     opt_ignore_keywords},
+    {{'N', N_("obsolete; same as --depth=files")}} },
 
   { "help", svn_cl__help, {"?", "h"}, {N_(
      "Describe the usage of this program or its subcommands.\n"
@@ -817,7 +843,8 @@ const svn_opt_subcommand_desc3_t svn_cl_
      "  if --force is specified.\n"
     )},
     {'q', 'N', opt_depth, opt_autoprops, opt_force, opt_no_autoprops,
-     SVN_CL__LOG_MSG_OPTIONS, opt_no_ignore} },
+     SVN_CL__LOG_MSG_OPTIONS, opt_no_ignore},
+    {{'N', N_("obsolete; same as --depth=files")}} },
 
   { "info", svn_cl__info, {0}, {N_(
      "Display information about a local or remote item.\n"
@@ -1348,7 +1375,8 @@ const svn_opt_subcommand_desc3_t svn_cl_
     {'r', 'c', 'N', opt_depth, 'q', opt_force, opt_dry_run, opt_merge_cmd,
      opt_record_only, 'x', opt_ignore_ancestry, opt_accept, opt_reintegrate,
      opt_allow_mixed_revisions, 'v'},
-    { { opt_force, N_("force deletions even if deleted contents don't match") } }
+    { { opt_force, N_("force deletions even if deleted contents don't match") },
+      {'N', N_("obsolete; same as --depth=files")} }
   },
 
   { "mergeinfo", svn_cl__mergeinfo, {0}, {N_(
@@ -1839,7 +1867,8 @@ const svn_opt_subcommand_desc3_t svn_cl_
     )},
     { 'u', 'v', 'N', opt_depth, 'r', 'q', opt_no_ignore, opt_incremental,
       opt_xml, opt_ignore_externals, opt_changelist},
-    {{'q', N_("don't print unversioned items")}} },
+    {{'q', N_("don't print unversioned items")},
+     {'N', N_("obsolete; same as --depth=immediates")}} },
 
   { "switch", svn_cl__switch, {"sw"}, {N_(
      "Update the working copy to a different URL within the same repository.\n"
@@ -1889,7 +1918,8 @@ const svn_opt_subcommand_desc3_t svn_cl_
      N_("allow switching to a node with no common ancestor")},
      {opt_force,
       N_("handle unversioned obstructions as changes")},
-     {opt_relocate,N_("deprecated; use 'svn relocate'")}}
+     {opt_relocate, N_("deprecated; use 'svn relocate'")},
+     {'N', N_("obsolete; same as --depth=files")}}
   },
 
   { "unlock", svn_cl__unlock, {0}, {N_(
@@ -1952,7 +1982,8 @@ const svn_opt_subcommand_desc3_t svn_cl_
      opt_ignore_externals, opt_changelist, opt_editor_cmd, opt_accept,
      opt_parents, opt_adds_as_modification},
     { {opt_force,
-       N_("handle unversioned obstructions as changes")} } },
+       N_("handle unversioned obstructions as changes")},
+      {'N', N_("obsolete; same as --depth=files")} } },
 
   { "upgrade", svn_cl__upgrade, {0}, {N_(
      "Upgrade the metadata storage format for a working copy.\n"

Modified: subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout?rev=1843003&r1=1843002&r2=1843003&view=diff
==============================================================================
--- subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout (original)
+++ subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout Sat Oct  6 05:53:03 2018
@@ -209,7 +209,7 @@ Valid options:
                                 'BASE'       base rev of item's working copy
                                 'COMMITTED'  last commit at or before BASE
                                 'PREV'       revision just before COMMITTED
-  -N [--non-recursive]     : obsolete; try --depth=files or --depth=immediates
+  -N [--non-recursive]     : obsolete; same as --depth=files
   --depth ARG              : limit operation by depth ARG ('empty', 'files',
                              'immediates', or 'infinity')
   --set-depth ARG          : set new working copy depth to ARG ('exclude',

Modified: subversion/branches/better-pristines/subversion/tests/cmdline/svntest/main.py
URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/cmdline/svntest/main.py?rev=1843003&r1=1843002&r2=1843003&view=diff
==============================================================================
--- subversion/branches/better-pristines/subversion/tests/cmdline/svntest/main.py (original)
+++ subversion/branches/better-pristines/subversion/tests/cmdline/svntest/main.py Sat Oct  6 05:53:03 2018
@@ -2108,7 +2108,7 @@ def _create_parser(usage=None):
                     help='Run the given number of tests in parallel')
   parser.add_option('-c', action='store_true', dest='is_child_process',
                     help='Flag if we are running this python test as a ' +
-                         'child process')
+                    'child process; used by build/run_tests.py:334')
   parser.add_option('--mode-filter', action='store', dest='mode_filter',
                     default='ALL',
                     help='Limit tests to those with type specified (e.g. XFAIL)')

Modified: subversion/branches/better-pristines/tools/dist/create-minor-release-branch.py
URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/tools/dist/create-minor-release-branch.py?rev=1843003&r1=1843002&r2=1843003&view=diff
==============================================================================
--- subversion/branches/better-pristines/tools/dist/create-minor-release-branch.py (original)
+++ subversion/branches/better-pristines/tools/dist/create-minor-release-branch.py Sat Oct  6 05:53:03 2018
@@ -39,6 +39,9 @@ repos = 'https://svn.apache.org/repos/as
 secure_repos = 'https://svn.apache.org/repos/asf/subversion'
 buildbot_repos = 'https://svn.apache.org/repos/infra/infrastructure/buildbot/aegis/buildmaster'
 
+# Parameters
+dry_run = False
+
 # Local working copies
 base_dir = None  # set by main()
 
@@ -72,15 +75,21 @@ def run(cmd, dry_run=False):
     if not dry_run:
         stdout = subprocess.check_output(cmd)
         print(stdout)
+    else:
+        print('  ## dry-run; not executed')
 
 def run_svn(cmd, dry_run=False):
     run(['svn'] + cmd, dry_run)
 
 def svn_commit(cmd):
-    run_svn(['commit'] + cmd, dry_run=True)
+    run_svn(['commit'] + cmd, dry_run=dry_run)
+
+def svn_copy_branch(src, dst, message):
+    args = ['copy', src, dst, '-m', message]
+    run_svn(args, dry_run=dry_run)
 
-def svn_checkout(*args):
-    args = ['checkout'] + list(args) + ['--revision={2017-12-01}']
+def svn_checkout(url, wc, *args):
+    args = ['checkout', url, wc] + list(args)
     run_svn(args)
 
 #----------------------------------------------------------------------
@@ -100,18 +109,19 @@ def prepend_file(path, text):
     open(path, 'w').write(text + original)
 
 #----------------------------------------------------------------------
-def make_release_branch(ver):
-    run_svn(['copy', get_trunk_url(), get_branch_url(ver),
-             '-m', 'Create the ' + ver.branch + '.x release branch.'],
-             dry_run=True)
+def make_release_branch(ver, revnum):
+    svn_copy_branch(get_trunk_url() + '@' + (str(revnum) if revnum else ''),
+                    get_branch_url(ver),
+                    'Create the ' + ver.branch + '.x release branch.')
 
 #----------------------------------------------------------------------
-def update_minor_ver_in_trunk(ver):
+def update_minor_ver_in_trunk(ver, revnum):
     """Change the minor version in trunk to the next (future) minor version.
     """
     trunk_wc = get_trunk_wc_path()
     trunk_url = get_trunk_url()
-    svn_checkout(trunk_url, trunk_wc)
+    svn_checkout(trunk_url + '@' + (str(revnum) if revnum else ''),
+                 trunk_wc)
 
     prev_ver = Version('1.%d.0' % (ver.minor - 1,))
     next_ver = Version('1.%d.0' % (ver.minor + 1,))
@@ -242,14 +252,12 @@ Subversion: start monitoring the %s bran
     svn_commit(commit_paths + ['-m', log_msg])
 
 #----------------------------------------------------------------------
-def steps(args):
-    ver = Version('1.10.0')
-
-    make_release_branch(ver)
-    update_minor_ver_in_trunk(ver)
-    create_status_file_on_branch(ver)
-    update_backport_bot(ver)
-    update_buildbot_config(ver)
+def create_release_branch(args):
+    make_release_branch(args.version, args.revnum)
+    update_minor_ver_in_trunk(args.version, args.revnum)
+    create_status_file_on_branch(args.version)
+    update_backport_bot(args.version)
+    update_buildbot_config(args.version)
 
 
 #----------------------------------------------------------------------
@@ -261,24 +269,37 @@ def main():
     # Setup our main parser
     parser = argparse.ArgumentParser(
                             description='Create an Apache Subversion release branch.')
-    parser.add_argument('--verbose', action='store_true', default=False,
+    subparsers = parser.add_subparsers(title='subcommands')
+
+    # Setup the parser for the create-release-branch subcommand
+    subparser = subparsers.add_parser('create-release-branch',
+                    help='''Create a minor release branch: branch from trunk,
+                            update version numbers on trunk, create status
+                            file on branch, update backport bot,
+                            update buildbot config.''')
+    subparser.set_defaults(func=create_release_branch)
+    subparser.add_argument('version', type=Version,
+                    help='''A version number to indicate the branch, such as
+                            '1.7.0' (the '.0' is required).''')
+    subparser.add_argument('revnum', type=lambda arg: int(arg.lstrip('r')),
+                           nargs='?', default=None,
+                    help='''The trunk revision number to base the branch on.
+                            Default is HEAD.''')
+    subparser.add_argument('--dry-run', action='store_true', default=False,
+                   help='Avoid committing any changes to repositories.')
+    subparser.add_argument('--verbose', action='store_true', default=False,
                    help='Increase output verbosity')
-    parser.add_argument('--base-dir', default=os.getcwd(),
+    subparser.add_argument('--base-dir', default=os.getcwd(),
                    help='''The directory in which to create needed files and
                            folders.  The default is the current working
                            directory.''')
-    subparsers = parser.add_subparsers(title='subcommands')
-
-    # Setup the parser for the build-env subcommand
-    subparser = subparsers.add_parser('steps',
-                    help='''Run the release-branch-creation steps.''')
-    subparser.set_defaults(func=steps)
 
     # Parse the arguments
     args = parser.parse_args()
 
-    global base_dir
+    global base_dir, dry_run
     base_dir = args.base_dir
+    dry_run = args.dry_run
 
     # Set up logging
     logger = logging.getLogger()

Modified: subversion/branches/better-pristines/tools/dist/release.py
URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/tools/dist/release.py?rev=1843003&r1=1843002&r2=1843003&view=diff
==============================================================================
--- subversion/branches/better-pristines/tools/dist/release.py (original)
+++ subversion/branches/better-pristines/tools/dist/release.py Sat Oct  6 05:53:03 2018
@@ -53,6 +53,8 @@ import subprocess
 import argparse       # standard in Python 2.7
 import io
 
+import backport.status
+
 # Find ezt, using Subversion's copy, if there isn't one on the system.
 try:
     import ezt
@@ -1306,15 +1308,29 @@ def write_changelog(args):
     branch = secure_repos + '/' + args.branch
     previous = secure_repos + '/' + args.previous
     include_unlabeled = args.include_unlabeled
+    separator_line = ('-' * 72) + '\n'
     
     mergeinfo = subprocess.check_output(['svn', 'mergeinfo', '--show-revs',
-                    'eligible', '--log', branch, previous]).splitlines()
+                    'eligible', '--log', branch, previous])
+    log_messages_dict = {
+        # This is a dictionary mapping revision numbers to their respective
+        # log messages.  The expression in the "key:" part of the dict
+        # comprehension extracts the revision number, as integer, from the
+        # 'svn log' output.
+        int(log_message.splitlines()[0].split()[0][1:]): log_message
+        # The [1:-1] ignores the empty first and last element of the split().
+        for log_message in mergeinfo.split(separator_line)[1:-1]
+    }
+    mergeinfo = mergeinfo.splitlines()
     
     separator_pattern = re.compile('^-{72}$')
     revline_pattern = re.compile('^r(\d+) \| [^\|]+ \| [^\|]+ \| \d+ lines?$')
     changes_prefix_pattern = re.compile('^\[(U|D)?:?([^\]]+)?\](.+)$')
     changes_suffix_pattern = re.compile('^(.+)\[(U|D)?:?([^\]]+)?\]$')
-    
+    # TODO: push this into backport.status as a library function
+    auto_merge_pattern = \
+        re.compile(r'^Merge (r\d+,? |the r\d+ group |the \S+ branch:)')
+
     changes_dict = dict()  # audience -> (section -> (change -> set(revision)))
     revision = -1
     got_firstline = False
@@ -1330,8 +1346,27 @@ def write_changelog(args):
             # If there's an unlabeled summary from a previous section, and
             # include_unlabeled is True, put it into uncategorized_changes.
             if include_unlabeled and unlabeled_summary and not changes_ignore:
-                add_to_changes_dict(changes_dict, None, None,
-                                    unlabeled_summary, revision)
+                if auto_merge_pattern.match(unlabeled_summary):
+                    # 1. Parse revision numbers from the first line
+                    merged_revisions = [
+                        int(x) for x in
+                        re.compile(r'(?<=\br)\d+\b').findall(unlabeled_summary)
+                    ]
+                    # TODO pass each revnum in MERGED_REVISIONS through this
+                    #      logic, in order to extract CHANGES_PREFIX_PATTERN
+                    #      and CHANGES_SUFFIX_PATTERN lines from the trunk log
+                    #      message.
+                    
+                    # 2. Parse the STATUS entry
+                    this_log_message = log_messages_dict[revision]
+                    status_paragraph = this_log_message.split('\n\n')[2]
+                    logsummary = \
+                        backport.status.StatusEntry(status_paragraph).logsummary
+                    add_to_changes_dict(changes_dict, None, None,
+                                        ' '.join(logsummary), revision)
+                else:
+                    add_to_changes_dict(changes_dict, None, None,
+                                        unlabeled_summary, revision)
             revision = -1
             got_firstline = False
             unlabeled_summary = None