Index: trunk/tools/bin/backport-commit.cmd
===================================================================
--- trunk/tools/bin/backport-commit.cmd	(revision 83611)
+++ trunk/tools/bin/backport-commit.cmd	(revision 83611)
@@ -0,0 +1,42 @@
+@echo off
+rem $Id$
+rem rem @file
+rem Windows NT batch script for launching backport-commit.sh
+rem
+
+rem
+rem Copyright (C) 2009-2020 Oracle Corporation
+rem
+rem This file is part of VirtualBox Open Source Edition (OSE), as
+rem available from http://www.virtualbox.org. This file is free software;
+rem you can redistribute it and/or modify it under the terms of the GNU
+rem General Public License (GPL) as published by the Free Software
+rem Foundation, in version 2 as it comes in the "COPYING" file of the
+rem VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+rem hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+rem
+
+setlocal ENABLEEXTENSIONS
+setlocal
+
+rem
+rem svn-ps.sh should be in the same directory as this script.
+rem
+set MY_SCRIPT=%~dp0backport-commit.sh
+if exist "%MY_SCRIPT%" goto found
+echo backport-commit.sh: failed to find backport-commit.sh in "%~dp0".
+goto end
+
+rem
+rem Found it, convert slashes and tell kmk_ash to interpret it.
+rem
+:found
+set MY_SCRIPT=%MY_SCRIPT:\=/%
+set MY_ARGS=%*
+if ".%MY_ARGS%." NEQ ".." set MY_ARGS=%MY_ARGS:\=/%
+kmk_ash %MY_SCRIPT% %MY_ARGS%
+
+:end
+endlocal
+endlocal
+
Index: trunk/tools/bin/backport-commit.sh
===================================================================
--- trunk/tools/bin/backport-commit.sh	(revision 83611)
+++ trunk/tools/bin/backport-commit.sh	(revision 83611)
@@ -0,0 +1,120 @@
+# !kmk_ash
+# $Id$
+## @file
+# Script for committing a backport from trunk.
+#
+
+#
+# Copyright (C) 2020 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+
+#
+# Determin script dir so we can source the common bits.
+#
+MY_SED=kmk_sed
+MY_SCRIPT_DIR=`echo "$0" | "${MY_SED}" -e 's|\\\|/|g' -e 's|^\(.*\)/[^/][^/]*$|\1|'` # \ -> / is for windows.
+if test "${MY_SCRIPT_DIR}" = "$0"; then
+    MY_SCRIPT_DIR=`pwd -L`
+else
+    MY_SCRIPT_DIR=`cd "${MY_SCRIPT_DIR}"; pwd -L`       # pwd is built into kmk_ash.
+fi
+
+#
+# This does a lot.
+#
+MY_SCRIPT_NAME="backport-commit.sh"
+. "${MY_SCRIPT_DIR}/backport-common.sh"
+
+#
+# Generate the commit message into MY_MSG_FILE.
+#
+test -n "${MY_DEBUG}" && echo "MY_REVISIONS=${MY_REVISIONS}"
+MY_MSG_FILE=backport-commit.txt
+MY_TMP_FILE=backport-commit.tmp
+
+if test "${MY_REVISION_COUNT}" -eq 1; then
+    # Single revision, just prefix the commit message.
+    MY_REV=`echo ${MY_REVISIONS}`       # strip leading space
+    echo -n "${MY_BRANCH}: Backported r${MY_REV}: " > "${MY_MSG_FILE}"
+    if ! "${MY_SVN}" log "-r${MY_REV}" "${MY_TRUNK_DIR}" > "${MY_TMP_FILE}"; then
+        echo "error: failed to get log entry for revision ${MY_REV}"
+        exit 1;
+    fi
+    if ! "${MY_SED}" -e '1d;2d;3d;$d' --append "${MY_MSG_FILE}" "${MY_TMP_FILE}"; then
+        echo "error: failed to get log entry for revision ${MY_REV} (sed failed)"
+        exit 1;
+    fi
+else
+    # First line.
+    echo -n "${MY_BRANCH}: Backported" > "${MY_MSG_FILE}"
+    MY_COUNTER=0
+    for MY_REV in ${MY_REVISIONS};
+    do
+        if test ${MY_COUNTER} -eq 0; then
+            echo -n " r${MY_REV}" >> "${MY_MSG_FILE}"
+        else
+            echo -n " r${MY_REV}" >> "${MY_MSG_FILE}"
+        fi
+        MY_COUNTER=`"${MY_EXPR}" ${MY_COUNTER} + 1`
+    done
+    echo "." >> "${MY_MSG_FILE}"
+
+    # One bullet with the commit text.
+    for MY_REV in ${MY_REVISIONS};
+    do
+        echo -n "* r${MY_REV}: " >> "${MY_MSG_FILE}"
+        if ! "${MY_SVN}" log "-r${MY_REV}" "${MY_TRUNK}" > "${MY_TMP_FILE}"; then
+            echo "error: failed to get log entry for revision ${MY_REV}"
+            exit 1;
+        fi
+        if ! "${MY_SED}" -e '1d;2d;3d;$d' --append "${MY_MSG_FILE}" "${MY_TMP_FILE}"; then
+            echo "error: failed to get log entry for revision ${MY_REV} (sed failed)"
+            exit 1;
+        fi
+    done
+fi
+"${MY_RM}" -f -- "${MY_TMP_FILE}"
+
+#
+# Do the committing.
+#
+echo "***"
+echo "*** Commit message:"
+"${MY_CAT}" "${MY_MSG_FILE}"
+echo "***"
+IFS=`"${MY_PRINTF}" " \t\r\n"` # windows needs \r for proper 'read' operation.
+for MY_IGNORE in 1 2 3; do
+    read -p "*** Does the above commit message look okay (y/n)?" MY_ANSWER
+    case "${MY_ANSWER}" in
+        y|Y|[yY][eE][sS])
+            if "${MY_SVN}" commit -F "${MY_MSG_FILE}" "${MY_BRANCH_DIR}"; then
+                "${MY_RM}" -f -- "${MY_MSG_FILE}"
+
+                #
+                # Update the branch so we don't end up with mixed revisions.
+                #
+                echo "***"
+                echo "*** Updating branch dir..."
+                "${MY_SVN}" up "${MY_BRANCH_DIR}"
+                exit 0
+            fi
+            echo "error: commit failed" >2
+            exit 1
+            ;;
+        n|N|[nN][oO])
+            exit 1
+            ;;
+        *)
+            echo "Please answer 'y' or 'n'... (MY_ANSWER=${MY_ANSWER})"
+    esac
+done
+exit 1;
+
Index: trunk/tools/bin/backport-common.sh
===================================================================
--- trunk/tools/bin/backport-common.sh	(revision 83611)
+++ trunk/tools/bin/backport-common.sh	(revision 83611)
@@ -0,0 +1,160 @@
+# $Id$
+## @file
+# Common backport script bits.
+#
+
+#
+# Copyright (C) 2020 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+
+#
+# Globals.
+#
+   MY_CAT=kmk_cat
+  MY_EXPR=kmk_expr
+MY_PRINTF=kmk_printf
+    MY_RM=kmk_rm
+   MY_SVN=svn
+   MY_SED=kmk_sed
+
+MY_BRANCH_DEFAULT_DIR=`cd "${MY_SCRIPT_DIR}"; cd ../..; pwd -L`
+MY_BRANCH_DEFAULT=`echo "${MY_BRANCH_DEFAULT_DIR}" | "${MY_SED}" -e 's|^\(.*\)/\([^/][^/]*\)$|\2|' -e 's/VBox-//'`
+if test "${MY_BRANCH_DEFAULT}" = "trunk"; then
+    MY_TRUNK_DIR=${MY_BRANCH_DEFAULT_DIR}
+elif test -d "${MY_BRANCH_DEFAULT_DIR}/../../trunk"; then
+    MY_TRUNK_DIR=`cd "${MY_BRANCH_DEFAULT_DIR}"; cd ../../trunk; pwd -L`
+else
+    MY_TRUNK_DIR="^/trunk"
+fi
+
+#
+# Parse arguments.
+#
+MY_BRANCH_DIR=
+MY_BRANCH=
+MY_REVISIONS=
+MY_REVISION_COUNT=0
+MY_EXTRA_ARGS=
+MY_DEBUG=
+
+while test $# -ge 1;
+do
+    ARG=$1
+    shift
+    case "${ARG}" in
+        r[0-9][0-9]*)
+            MY_REV=`echo ${ARG} | "${MY_SED}" -e 's/^r//'`
+            MY_REVISIONS="${MY_REVISIONS} ${MY_REV}"
+            MY_REVISION_COUNT=`${MY_EXPR} ${MY_REVISION_COUNT} + 1`
+            ;;
+
+        [0-9][0-9]*)
+            MY_REVISIONS="${MY_REVISIONS} ${ARG}"
+            MY_REVISION_COUNT=`${MY_EXPR} ${MY_REVISION_COUNT} + 1`
+            ;;
+
+        --trunk-dir)
+            if test $# -eq 0; then
+                echo "error: missing --trunk-dir argument." 1>&2
+                exit 1;
+            fi
+            MY_TRUNK_DIR=`echo "$1" | "${SED}" -e 's|\\\|/|g'`
+            shift
+            ;;
+
+        --branch-dir)
+            if test $# -eq 0; then
+                echo "error: missing --branch-dir argument." 1>&2
+                exit 1;
+            fi
+            MY_BRANCH_DIR=`echo "$1" | "${SED}" -e 's|\\\|/|g'`
+            shift
+            ;;
+
+        --branch)
+            if test $# -eq 0; then
+                echo "error: missing --branch argument." 1>&2
+                exit 1;
+            fi
+            MY_BRANCH="$1"
+            shift
+            ;;
+
+        --extra)
+            if test $# -eq 0; then
+                echo "error: missing --extra argument." 1>&2
+                exit 1;
+            fi
+            MY_EXTRA_ARGS="${MY_EXTRA_ARGS} $1"
+            shift
+            ;;
+
+        --debug)
+            MY_DEBUG=1
+            ;;
+
+        # usage
+        --h*|-h*|-?|--?)
+            echo "usage: $0 [--trunk-dir <dir>] [--branch <ver>] [--branch-dir <dir>] [--extra <svn-arg>] rev1 [rev2..[revN]]]"
+            echo ""
+            echo "Options:"
+            echo "  --trunk-dir <dir>"
+            echo "  --branch <ver>"
+            echo "  --branch-dir <dir>"
+            echo "  --extra <svn-arg>"
+            echo ""
+            exit 2;
+            ;;
+
+        *)
+            echo "syntax error: ${ARG}"
+            exit 2;
+            ;;
+    esac
+done
+
+if test -n "${MY_DEBUG}"; then
+    echo "        MY_SCRIPT_DIR=${MY_SCRIPT_DIR}"
+    echo "MY_BRANCH_DEFAULT_DIR=${MY_BRANCH_DEFAULT_DIR}"
+    echo "    MY_BRANCH_DEFAULT=${MY_BRANCH_DEFAULT}"
+    echo "         MY_TRUNK_DIR=${MY_TRUNK_DIR}"
+    echo "         MY_REVISIONS=${MY_REVISIONS}"
+fi
+
+#
+# Resolve branch variables.
+#
+if test -z "${MY_BRANCH_DIR}" -a -z "${MY_BRANCH}"; then
+    MY_BRANCH_DIR=${MY_BRANCH_DEFAULT_DIR}
+    MY_BRANCH=${MY_BRANCH_DEFAULT}
+elif test -n "${MY_BRANCH}" -a -z "${MY_BRANCH_DIR}"; then
+    MY_BRANCH_DIR=${MY_BRANCH_DEFAULT_DIR}
+elif test -z "${MY_BRANCH}" -a -n "${MY_BRANCH_DIR}"; then
+    MY_BRANCH=`echo "${MY_BRANCH_DIR}" | "${SED}" -e 's/^-([1]*[5-9]\.[0-5])[/]*$/\1/'`
+    if test -z "${MY_BRANCH}" -o  "${MY_BRANCH}" = "${MY_BRANCH_DIR}"; then
+        echo "error: Failed to guess branch name for: ${MY_BRANCH_DIR}" >2
+        echo "       Use --branch to specify it." >2
+        exit 2;
+    fi
+fi
+if test "${MY_BRANCH}" = "trunk"; then
+    echo "error: script does not work with 'trunk' as the branch" >2
+    exit 2;
+fi
+
+#
+# Stop if no revisions specified.
+#
+if test -z "${MY_REVISIONS}"; then
+    echo "error: No revisions specified" >&2;
+    exit 2;
+fi
+
Index: trunk/tools/bin/backport-merge-and-commit.cmd
===================================================================
--- trunk/tools/bin/backport-merge-and-commit.cmd	(revision 83611)
+++ trunk/tools/bin/backport-merge-and-commit.cmd	(revision 83611)
@@ -0,0 +1,42 @@
+@echo off
+rem $Id$
+rem rem @file
+rem Windows NT batch script for launching backport-merge-and-commit.sh
+rem
+
+rem
+rem Copyright (C) 2009-2020 Oracle Corporation
+rem
+rem This file is part of VirtualBox Open Source Edition (OSE), as
+rem available from http://www.virtualbox.org. This file is free software;
+rem you can redistribute it and/or modify it under the terms of the GNU
+rem General Public License (GPL) as published by the Free Software
+rem Foundation, in version 2 as it comes in the "COPYING" file of the
+rem VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+rem hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+rem
+
+setlocal ENABLEEXTENSIONS
+setlocal
+
+rem
+rem svn-ps.sh should be in the same directory as this script.
+rem
+set MY_SCRIPT=%~dp0backport-merge-and-commit.sh
+if exist "%MY_SCRIPT%" goto found
+echo backport-merge-and-commit.sh: failed to find backport-merge-and-commit.sh in "%~dp0".
+goto end
+
+rem
+rem Found it, convert slashes and tell kmk_ash to interpret it.
+rem
+:found
+set MY_SCRIPT=%MY_SCRIPT:\=/%
+set MY_ARGS=%*
+if ".%MY_ARGS%." NEQ ".." set MY_ARGS=%MY_ARGS:\=/%
+kmk_ash %MY_SCRIPT% %MY_ARGS%
+
+:end
+endlocal
+endlocal
+
Index: trunk/tools/bin/backport-merge-and-commit.sh
===================================================================
--- trunk/tools/bin/backport-merge-and-commit.sh	(revision 83611)
+++ trunk/tools/bin/backport-merge-and-commit.sh	(revision 83611)
@@ -0,0 +1,37 @@
+# !kmk_ash
+# $Id$
+## @file
+# Script for merging and commit a backport from trunk.
+#
+
+#
+# Copyright (C) 2020 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+
+#
+# Determin script dir so we can invoke the two worker scripts.
+#
+MY_SED=kmk_sed
+MY_SCRIPT_DIR=`echo "$0" | "${MY_SED}" -e 's|\\\|/|g' -e 's|^\(.*\)/[^/][^/]*$|\1|'` # \ -> / is for windows.
+if test "${MY_SCRIPT_DIR}" = "$0"; then
+    MY_SCRIPT_DIR=`pwd -L`
+else
+    MY_SCRIPT_DIR=`cd "${MY_SCRIPT_DIR}"; pwd -L`       # pwd is built into kmk_ash.
+fi
+
+#
+# Merge & commit.
+#
+set -e
+"${MY_SCRIPT_DIR}/backport-merge.sh" $*
+echo
+"${MY_SCRIPT_DIR}/backport-commit.sh" $*
+
Index: trunk/tools/bin/backport-merge.cmd
===================================================================
--- trunk/tools/bin/backport-merge.cmd	(revision 83611)
+++ trunk/tools/bin/backport-merge.cmd	(revision 83611)
@@ -0,0 +1,42 @@
+@echo off
+rem $Id$
+rem rem @file
+rem Windows NT batch script for launching backport-merge.sh
+rem
+
+rem
+rem Copyright (C) 2009-2020 Oracle Corporation
+rem
+rem This file is part of VirtualBox Open Source Edition (OSE), as
+rem available from http://www.virtualbox.org. This file is free software;
+rem you can redistribute it and/or modify it under the terms of the GNU
+rem General Public License (GPL) as published by the Free Software
+rem Foundation, in version 2 as it comes in the "COPYING" file of the
+rem VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+rem hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+rem
+
+setlocal ENABLEEXTENSIONS
+setlocal
+
+rem
+rem svn-ps.sh should be in the same directory as this script.
+rem
+set MY_SCRIPT=%~dp0backport-merge.sh
+if exist "%MY_SCRIPT%" goto found
+echo backport-merge.sh: failed to find backport-merge.sh in "%~dp0".
+goto end
+
+rem
+rem Found it, convert slashes and tell kmk_ash to interpret it.
+rem
+:found
+set MY_SCRIPT=%MY_SCRIPT:\=/%
+set MY_ARGS=%*
+if ".%MY_ARGS%." NEQ ".." set MY_ARGS=%MY_ARGS:\=/%
+kmk_ash %MY_SCRIPT% %MY_ARGS%
+
+:end
+endlocal
+endlocal
+
Index: trunk/tools/bin/backport-merge.sh
===================================================================
--- trunk/tools/bin/backport-merge.sh	(revision 83611)
+++ trunk/tools/bin/backport-merge.sh	(revision 83611)
@@ -0,0 +1,77 @@
+# !kmk_ash
+# $Id$
+## @file
+# Script for merging a backport from trunk.
+#
+
+#
+# Copyright (C) 2020 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+
+#
+# Determin script dir so we can source the common bits.
+#
+MY_SED=kmk_sed
+MY_SCRIPT_DIR=`echo "$0" | "${MY_SED}" -e 's|\\\|/|g' -e 's|^\(.*\)/[^/][^/]*$|\1|'` # \ -> / is for windows.
+if test "${MY_SCRIPT_DIR}" = "$0"; then
+    MY_SCRIPT_DIR=`pwd -L`
+else
+    MY_SCRIPT_DIR=`cd "${MY_SCRIPT_DIR}"; pwd -L`       # pwd is built into kmk_ash.
+fi
+
+#
+# This does a lot.
+#
+MY_SCRIPT_NAME="backport-merge.sh"
+. "${MY_SCRIPT_DIR}/backport-common.sh"
+
+#
+# Do the merging.
+#
+MY_DONE_REVS=
+MY_FAILED_REV=
+MY_TODO_REVS=
+test -n "${MY_DEBUG}" && echo "MY_REVISIONS=${MY_REVISIONS}"
+for MY_REV in ${MY_REVISIONS};
+do
+    if test -z "${MY_FAILED}"; then
+        echo "***"
+        echo "*** Merging r${MY_REV} ..."
+        echo "***"
+        if "${MY_SVN}" merge ${MY_MERGE_ARGS} "${MY_TRUNK_DIR}" "${MY_BRANCH_DIR}" -c ${MY_REV}; then
+            # Check for conflict.
+            MY_CONFLICTS=`"${MY_SVN}" status "${MY_BRANCH_DIR}" | "${MY_SED}" -n -e '/^C/p'`
+            if test -z "${MY_CONFLICTS}"; then
+                MY_DONE_REVS="${MY_DONE_REVS} ${MY_REV}"
+            else
+                echo '!!!'" Have conflicts after merging ${MY_REV}."
+                MY_FAILED_REV=${MY_REV}
+            fi
+        else
+            echo '!!!'" Failed merging r${MY_REV}."
+            MY_FAILED_REV=${MY_REV}
+        fi
+    else
+        MY_TODO_REVS="${MY_TODO_REVS} ${MY_REV}"
+    fi
+done
+
+if test -z "${MY_FAILED_REV}"; then
+    echo "* Successfully merged all revision (${MY_DONE_REVS})."
+    exit 0;
+fi
+if test -n "${MY_DONE_REVS}"; then
+    echo "* Successfully merged: ${MY_DONE_REVS}"
+fi
+if test -n "${MY_TODO_REVS}"; then
+    echo "* Revisions left todo: ${MY_TODO_REVS}"
+fi
+exit 1;
