summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/mergemaster/mergemaster.864
-rwxr-xr-xusr.sbin/mergemaster/mergemaster.sh227
2 files changed, 194 insertions, 97 deletions
diff --git a/usr.sbin/mergemaster/mergemaster.8 b/usr.sbin/mergemaster/mergemaster.8
index e733c7c..65d22ae 100644
--- a/usr.sbin/mergemaster/mergemaster.8
+++ b/usr.sbin/mergemaster/mergemaster.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 10, 1999
+.Dd October 30, 2000
.Dt MERGEMASTER 8
.Os FreeBSD
.Sh NAME
@@ -32,12 +32,13 @@
.Nd Merge configuration files, et al during an upgrade
.Sh SYNOPSIS
.Nm
-.Op Fl scrvah
+.Op Fl scrvahi
.Op Fl m Ar /path/to/sources
.Op Fl t Ar /path/to/temp/root
.Op Fl d
.Op Fl u Ar N
.Op Fl w Ar N
+.Op Fl D Ar /path
.Sh DESCRIPTION
.Nm
is a Bourne shell script which is designed to aid you
@@ -58,7 +59,10 @@ files.
You can specify a different source directory
with the
.Op Fl m
-command line option.
+command line option, or specify the destination
+directory with the
+.Op Fl D
+option.
It then compares each file in that environment
to its installed counterpart.
When the script finds a
@@ -113,6 +117,26 @@ and file permissions as specified by the umask.
Unified diffs are used by default to display any
differences unless you choose context diffs.
.Pp
+.Nm
+will source scripts that you specify right before
+it starts the comparison, and after it's done running.
+The easiest way to handle this is to place the path
+to the script(s) in the appropriate variables in your
+.Pa .mergemasterrc
+file.
+The script sourced before comparison is named in
+.Ev MM_PRE_COMPARE_SCRIPT ,
+and the one sourced after the script is done is
+.Ev MM_EXIT_SCRIPT .
+This is the recommended way to specify local modifications,
+or files that you want to give special handling to.
+This includes files that you want to be deleted without
+being compared.
+Because the named scripts are sourced from within
+.Nm ,
+all of the script's variables are available for use in
+your custom script.
+.Pp
The options are as follows:
.Bl -tag -width Fl
.It Fl s
@@ -149,6 +173,9 @@ Setting -a makes
-w superfluous.
.It Fl h
Display usage and help information.
+.It Fl i
+Automatically install any files that do not exist in the
+destination directory.
.It Fl m Ar /path/to/sources
Specify the path to the directory where you want to do the
.Xr make 1 .
@@ -172,6 +199,8 @@ Supply an alternate screen width to the
.Xr sdiff 1
command in numbers of columns.
The default is 80.
+.It Fl D Ar /path
+Specify the destination directory for the installed files.
.El
.Sh ENVIRONMENT
The
@@ -190,6 +219,15 @@ limited
without specifying the full path,
.Nm
prompts you with options on how to proceed.
+The
+.Ev MM_PRE_COMPARE_SCRIPT
+and
+.Ev MM_EXIT_SCRIPT
+variables are used as described above.
+Other variables that are used by the script internally
+can be specified in
+.Pa .mergemasterrc
+as described in more detail below.
.Sh EXAMPLES
Typically all you will need to do is type
.Nm
@@ -240,19 +278,33 @@ with all values commented out:
# Verbose mode includes more details and additional checks
#VERBOSE=
#
+# Automatically install files that do not exist on the system already
+#AUTO_INSTALL=
+#
# Sourcedir is the directory to do the 'make' in (where the new files are)
-#SOURCEDIR=/usr/src/etc
+#SOURCEDIR='/usr/src/etc'
#
# The umask for mergemaster to compare the default file's modes to
#NEW_UMASK=022
#
+# Specify the destination directory for the installed files
+#DESTDIR=
+#
# The following options have no command line overrides
# For those who just cannot stand including the full path to PAGER
#DONT_CHECK_PAGER=
+#
# If you set 'yes' above, make sure to include the PATH to your pager
-#PATH=/bin:/usr/bin:/usr/sbin
+#PATH=/bin:/usr/bin:/usr/sbin:/sbin
+#
# Don't compare the old and new motd files
#IGNORE_MOTD=yes
+#
+# Specify the path to scripts to run before the comparison starts,
+# and/or after the script has finished its work
+#MM_PRE_COMPARE_SCRIPT=
+#MM_EXIT_SCRIPT=
+
.Ed
.Sh SEE ALSO
.Xr cvs 1 ,
@@ -291,7 +343,7 @@ make world tutorial which is referenced above.
.Pp
.Sh AUTHOR
This manual page and the script itself were written by
-.An Douglas Barton Aq Doug@gorean.org .
+.An Douglas Barton Aq DougB@FreeBSD.org .
.Sh BUGS
There are no known bugs.
Please report any problems,
diff --git a/usr.sbin/mergemaster/mergemaster.sh b/usr.sbin/mergemaster/mergemaster.sh
index 4900d12..8b38a55 100755
--- a/usr.sbin/mergemaster/mergemaster.sh
+++ b/usr.sbin/mergemaster/mergemaster.sh
@@ -15,7 +15,8 @@ PATH=/bin:/usr/bin:/usr/sbin:/sbin
display_usage () {
VERSION_NUMBER=`grep "[$]FreeBSD:" $0 | cut -d ' ' -f 4`
echo "mergemaster version ${VERSION_NUMBER}"
- echo "Usage: mergemaster [-scrvah] [-m /path] [-t /path] [-d] [-u N] [-w N]"
+ echo 'Usage: mergemaster [-scrvahi] [-m /path]'
+ echo ' [-t /path] [-d] [-u N] [-w N] [-D /path]'
echo "Options:"
echo " -s Strict comparison (diff every pair of files)"
echo " -c Use context diff instead of unified diff"
@@ -23,26 +24,24 @@ display_usage () {
echo " -v Be more verbose about the process, include additional checks"
echo " -a Leave all files that differ to merge by hand"
echo " -h Display more complete help"
+ echo ' -i Automatically install files that do not exist in destination directory'
echo " -m /path/directory Specify location of source to do the make in"
echo " -t /path/directory Specify temp root directory"
echo " -d Add date and time to directory name (e.g., /var/tmp/temproot.`date +%m%d.%H.%M`)"
echo " -u N Specify a numeric umask"
echo " -w N Specify a screen width in columns to sdiff"
+ echo ' -D /path/directory Specify the destination directory to install files to'
echo ''
}
display_help () {
- echo "* To create a temporary root environment, compare CVS revision \$Ids"
- echo " for files that have them, and compare diffs for files that do not,"
- echo " or have different ones, just type, mergemaster"
echo "* To specify a directory other than /var/tmp/temproot for the"
echo " temporary root environment, use -t /path/to/temp/root"
echo "* The -w option takes a number as an argument for the column width"
echo " of the screen. The default is 80."
- echo "* The -a option causes mergemaster to run without prompting"
+ echo '* The -a option causes mergemaster to run without prompting.'
}
-
# Loop allowing the user to use sdiff to merge files and display the merged
# file.
merge_loop () {
@@ -58,7 +57,7 @@ merge_loop () {
# Prime file.merged so we don't blat the owner/group id's
cp -p "${COMPFILE}" "${COMPFILE}.merged"
sdiff -o "${COMPFILE}.merged" --text --suppress-common-lines \
- --width=${SCREEN_WIDTH:-80} "${COMPFILE#.}" "${COMPFILE}"
+ --width=${SCREEN_WIDTH:-80} "${DESTDIR}${COMPFILE#.}" "${COMPFILE}"
INSTALL_MERGED=V
while [ "${INSTALL_MERGED}" = "v" -o "${INSTALL_MERGED}" = "V" ]; do
echo ''
@@ -107,18 +106,36 @@ diff_loop () {
HANDLE_COMPFILE=v
while [ "${HANDLE_COMPFILE}" = "v" -o "${HANDLE_COMPFILE}" = "V" -o "${HANDLE_COMPFILE}" = "NOT V" ]; do
- if [ -f "${COMPFILE#.}" -a -f "${COMPFILE}" ]; then
+ if [ -f "${DESTDIR}${COMPFILE#.}" -a -f "${COMPFILE}" ]; then
if [ "${HANDLE_COMPFILE}" = "v" -o "${HANDLE_COMPFILE}" = "V" ]; then
(
+ echo ''
echo " *** Displaying differences between ${COMPFILE} and installed version:"
echo ''
- diff "${DIFF_FLAG}" "${COMPFILE#.}" "${COMPFILE}"
+ diff "${DIFF_FLAG}" "${DESTDIR}${COMPFILE#.}" "${COMPFILE}"
) | ${PAGER}
echo ''
fi
else
+ echo ''
echo " *** There is no installed version of ${COMPFILE}"
- NO_INSTALLED=yes
+ case "${AUTO_INSTALL}" in
+ [Yy][Ee][Ss])
+ echo ''
+ if mm_install "${COMPFILE}"; then
+ echo " *** ${COMPFILE} installed successfully"
+ # Make the list print one file per line
+ AUTO_INSTALLED_FILES="${AUTO_INSTALLED_FILES} ${DESTDIR}${COMPFILE#.}
+"
+ else
+ echo " *** Problem installing ${COMPFILE}, it will remain to merge by hand"
+ fi
+ return
+ ;;
+ *)
+ NO_INSTALLED=yes
+ ;;
+ esac
fi
echo " Use 'd' to delete the temporary ${COMPFILE}"
@@ -179,7 +196,6 @@ diff_loop () {
;;
esac # End of "How to handle files that are different"
done
- echo ''
unset NO_INSTALLED
echo ''
case "${VERBOSE}" in
@@ -196,13 +212,13 @@ TEMPROOT='/var/tmp/temproot'
# Read .mergemasterrc before command line so CLI can override
#
-if [ -f "$HOME/.mergemasterrc" ]; then
+if [ -r "$HOME/.mergemasterrc" ]; then
. "$HOME/.mergemasterrc"
fi
# Check the command line options
#
-while getopts ":ascrvhm:t:du:w:" COMMAND_LINE_ARGUMENT ; do
+while getopts ":ascrvhim:t:du:w:D:" COMMAND_LINE_ARGUMENT ; do
case "${COMMAND_LINE_ARGUMENT}" in
s)
STRICT=yes
@@ -227,6 +243,9 @@ while getopts ":ascrvhm:t:du:w:" COMMAND_LINE_ARGUMENT ; do
display_help
exit 0
;;
+ i)
+ AUTO_INSTALL=yes
+ ;;
m)
SOURCEDIR=${OPTARG}
;;
@@ -242,6 +261,9 @@ while getopts ":ascrvhm:t:du:w:" COMMAND_LINE_ARGUMENT ; do
w)
SCREEN_WIDTH=${OPTARG}
;;
+ D)
+ DESTDIR=${OPTARG}
+ ;;
*)
display_usage
exit 1
@@ -406,6 +428,7 @@ case "${RERUN}" in
esac
{ cd ${SOURCEDIR} &&
+ make DESTDIR=${DESTDIR} distrib-dirs &&
make DESTDIR=${TEMPROOT} distrib-dirs &&
make DESTDIR=${TEMPROOT} -DNO_MAKEDEV distribution;} ||
{ echo '';
@@ -414,11 +437,33 @@ case "${RERUN}" in
echo '';
exit 1;}
+ # Doing the inventory and removing files that we don't want to compare only makes
+ # sense if we are not doing a rerun, since we have no way of knowing what happened
+ # to the files during previous incarnations.
+ case "${VERBOSE}" in
+ '') ;;
+ *)
+ echo ''
+ echo ' *** The following files exist only in the installed version of'
+ echo " ${DESTDIR}/etc. In the vast majority of cases these files"
+ echo ' are necessary parts of the system and should not be deleted.'
+ echo ' However because these files are not updated by this process you'
+ echo ' might want to verify their status before rebooting your system.'
+ echo ''
+ echo ' *** Press [Enter] or [Return] key to continue'
+ read ANY_KEY
+ unset ANY_KEY
+ diff -qr ${DESTDIR}/etc ${TEMPROOT}/etc | grep "^Only in /etc" | ${PAGER}
+ echo ''
+ echo ' *** Press [Enter] or [Return] key to continue'
+ read ANY_KEY
+ unset ANY_KEY
+ ;;
+ esac
+
# We really don't want to have to deal with these files, since
# master.passwd is the real file that should be compared, then
# the user should run pwd_mkdb if necessary.
- # Only do this if we are not rerun'ing, since if we are the
- # files will not be there.
#
rm ${TEMPROOT}/etc/spwd.db ${TEMPROOT}/etc/passwd ${TEMPROOT}/etc/pwd.db
@@ -439,27 +484,6 @@ esac
# Get ready to start comparing files
-case "${VERBOSE}" in
-'') ;;
-*)
- echo ''
- echo " *** The following files exist only in the installed version"
- echo " of /etc. In the far majority of cases these files are"
- echo " necessary parts of the system and should not be deleted,"
- echo " however because these files are not updated by this process"
- echo " you might want to verify their status before rebooting your system."
- echo ''
- echo " *** Press [Enter] or [Return] key to continue"
- read ANY_KEY
- unset ANY_KEY
- diff -qr /etc ${TEMPROOT}/etc | grep "^Only in /etc" | ${PAGER}
- echo ''
- echo " *** Press [Enter] or [Return] key to continue"
- read ANY_KEY
- unset ANY_KEY
- ;;
-esac
-
# Check umask if not specified on the command line,
# and we are not doing an autorun
#
@@ -490,15 +514,18 @@ fi
CONFIRMED_UMASK=${NEW_UMASK:-0022}
-# Warn users who have an /etc/sysconfig file
+# Warn users who still have ${DESTDIR}/etc/sysconfig
#
-if [ -f /etc/sysconfig ]; then
- echo " *** There is an /etc/sysconfig file on this system. Starting with"
- echo " FreeBSD version 2.2.2 those settings have moved from /etc/sysconfig"
- echo " to /etc/rc.conf. If you are upgrading an older system make sure"
- echo " that you transfer your settings by hand from sysconfig to rc.conf and"
- echo " install the rc.conf file. If you have already made this transition,"
- echo " you should consider renaming or deleting the /etc/sysconfig file."
+if [ -e "${DESTDIR}/etc/sysconfig" ]; then
+ echo ''
+ echo " *** There is a sysconfig file on this system in ${DESTDIR}/etc/."
+ echo ''
+ echo ' Starting with FreeBSD version 2.2.2 those settings moved from'
+ echo ' /etc/sysconfig to /etc/rc.conf. If you are upgrading an older'
+ echo ' system make sure that you transfer your settings by hand from'
+ echo ' sysconfig to rc.conf and install the rc.conf file. If you'
+ echo ' have already made this transition, you should consider'
+ echo ' renaming or deleting the sysconfig file.'
echo ''
case "${AUTO_RUN}" in
'')
@@ -519,12 +546,6 @@ if [ -f /etc/sysconfig ]; then
esac
fi
-echo ''
-echo "*** Beginning comparison"
-echo ''
-
-cd "${TEMPROOT}"
-
# Use the umask/mode information to install the files
# Create directories as needed
#
@@ -532,24 +553,22 @@ mm_install () {
local INSTALL_DIR
INSTALL_DIR=${1#.}
INSTALL_DIR=${INSTALL_DIR%/*}
+
case "${INSTALL_DIR}" in
'')
INSTALL_DIR=/
;;
esac
- if [ -n "${INSTALL_DIR}" -a ! -d "${INSTALL_DIR}" ]; then
+ if [ -n "${DESTDIR}${INSTALL_DIR}" -a ! -d "${DESTDIR}${INSTALL_DIR}" ]; then
DIR_MODE=`perl -e 'printf "%04o\n", (((stat("$ARGV[0]"))[2] & 07777) &~ oct("$ARGV[1]"))' "${TEMPROOT}/${INSTALL_DIR}" "${CONFIRMED_UMASK}"`
- install -d -o root -g wheel -m "${DIR_MODE}" "${INSTALL_DIR}"
+ install -d -o root -g wheel -m "${DIR_MODE}" "${DESTDIR}${INSTALL_DIR}"
fi
FILE_MODE=`perl -e 'printf "%04o\n", (((stat("$ARGV[0]"))[2] & 07777) &~ oct("$ARGV[1]"))' "${1}" "${CONFIRMED_UMASK}"`
if [ ! -x "${1}" ]; then
case "${1#.}" in
- /dev/MAKEDEV)
- NEED_MAKEDEV=yes
- ;;
/etc/mail/aliases)
NEED_NEWALIASES=yes
;;
@@ -557,7 +576,7 @@ mm_install () {
NEED_CAP_MKDB=yes
;;
/etc/master.passwd)
- install -m 600 "${1}" "${INSTALL_DIR}"
+ install -m 600 "${1}" "${DESTDIR}${INSTALL_DIR}"
NEED_PWD_MKDB=yes
DONT_INSTALL=yes
;;
@@ -575,7 +594,7 @@ mm_install () {
esac
echo " Use 'd' to delete the temporary ${COMPFILE}"
- echo " Use 'l' to delete the existing ${COMPFILE#.} and create the link"
+ echo " Use 'l' to delete the existing ${DESTDIR}${COMPFILE#.} and create the link"
echo ''
echo " Default is to leave the temporary file to deal with by hand"
echo ''
@@ -590,14 +609,12 @@ mm_install () {
;;
[lL]*)
echo ''
- if [ -e "${COMPFILE#.}" ]; then
- rm "${COMPFILE#.}"
- fi
- if ln "/root/${COMPFILE##*/}" "${COMPFILE#.}"; then
- echo " *** Link from ${COMPFILE#.} to /root/${COMPFILE##*/} installed successfully"
+ rm -f "${DESTDIR}${COMPFILE#.}"
+ if ln "${DESTDIR}/root/${COMPFILE##*/}" "${DESTDIR}${COMPFILE#.}"; then
+ echo " *** Link from ${DESTDIR}${COMPFILE#.} to ${DESTDIR}/root/${COMPFILE##*/} installed successfully"
rm "${COMPFILE}"
else
- echo " *** Error linking ${COMPFILE#.} to /root/${COMPFILE##*/}, ${COMPFILE} will remain to install by hand"
+ echo " *** Error linking ${DESTDIR}${COMPFILE#.} to ${DESTDIR}/root/${COMPFILE##*/}, ${COMPFILE} will remain to install by hand"
fi
;;
*)
@@ -610,56 +627,68 @@ mm_install () {
case "${DONT_INSTALL}" in
'')
- install -m "${FILE_MODE}" "${1}" "${INSTALL_DIR}"
+ install -m "${FILE_MODE}" "${1}" "${DESTDIR}${INSTALL_DIR}"
;;
*)
unset DONT_INSTALL
;;
esac
-
else
- install -m "${FILE_MODE}" "${1}" "${INSTALL_DIR}"
+ case "${1#.}" in
+ /dev/MAKEDEV)
+ NEED_MAKEDEV=yes
+ ;;
+ esac
+ install -m "${FILE_MODE}" "${1}" "${DESTDIR}${INSTALL_DIR}"
fi
return $?
}
-compare_ids () {
- case "${1}" in
- "${2}")
- echo " *** Temp ${COMPFILE} and installed have the same ${IDTAG}, deleting"
- rm "${COMPFILE}"
- ;;
- esac
-}
+echo ''
+echo "*** Beginning comparison"
+echo ''
+
+cd "${TEMPROOT}"
+
+if [ -r "${MM_PRE_COMPARE_SCRIPT}" ]; then
+ . "${MM_PRE_COMPARE_SCRIPT}"
+fi
# Using -size +0 avoids uselessly checking the empty log files created
# by ${SOURCEDIR}/Makefile and the device entries in ./dev, but does
-# check the scripts in ./dev, as we'd like.
+# check the scripts in ./dev, as we'd like (assuming no devfs of course).
#
for COMPFILE in `find . -type f -size +0`; do
+
+ # First, check to see if the file exists in DESTDIR. If not, the
+ # diff_loop function knows how to handle it.
+ #
+ if [ ! -e "${DESTDIR}${COMPFILE#.}" ]; then
+ diff_loop
+ continue
+ fi
+
case "${STRICT}" in
'' | [Nn][Oo])
# Compare CVS $Id's first so if the file hasn't been modified
# local changes will be ignored.
# If the files have the same $Id, delete the one in temproot so the
# user will have less to wade through if files are left to merge by hand.
- # Take the $Id -> $FreeBSD tag change into account
#
- FREEBSDID1=`grep "[$]FreeBSD:" ${COMPFILE#.} 2>/dev/null`
- FREEBSDID2=`grep "[$]FreeBSD:" ${COMPFILE} 2>/dev/null`
-
- if [ -n "${FREEBSDID1}" -a -n "${FREEBSDID2}" ]; then
- IDTAG='$FreeBSD'
- compare_ids "${FREEBSDID1}" "${FREEBSDID2}"
- else
- CVSID1=`grep "[$]Id:" ${COMPFILE#.} 2>/dev/null`
- CVSID2=`grep "[$]Id:" ${COMPFILE} 2>/dev/null`
+ # Reduce complexity and improve portability by using ident
+ #
+ CVSID1=`ident ${DESTDIR}${COMPFILE#.} 2>&1`
+ CVSID1="${CVSID1#${DESTDIR}}"
+ CVSID2=`ident ${COMPFILE} 2>&1`
- if [ -n "${CVSID1}" -a -n "${CVSID2}" ]; then
- IDTAG='$Id'
- compare_ids "${CVSID1}" "${CVSID2}"
- fi
- fi
+ case "${CVSID2}" in
+ *'no id keywords'*)
+ ;;
+ ."${CVSID1}")
+ echo " *** Temp ${COMPFILE} and installed have the same CVS Id, deleting"
+ rm "${COMPFILE}"
+ ;;
+ esac
;;
esac
@@ -671,7 +700,7 @@ for COMPFILE in `find . -type f -size +0`; do
# Do an absolute diff first to see if the files are actually different.
# If they're not different, delete the one in temproot.
#
- if diff -q "${COMPFILE#.}" "${COMPFILE}" > /dev/null 2>&1; then
+ if diff -q "${DESTDIR}${COMPFILE#.}" "${COMPFILE}" > /dev/null 2>&1; then
echo " *** Temp ${COMPFILE} and installed are the same, deleting"
rm "${COMPFILE}"
else
@@ -761,7 +790,23 @@ case "${NEED_PWD_MKDB}" in
;;
esac
+case "${AUTO_INSTALLED_FILES}" in
+'') ;;
+*)
+ (
+ echo ''
+ echo '*** You chose the automatic install option for files that did not exist'
+ echo ' on your system. The following files were installed for you:'
+ echo "${AUTO_INSTALLED_FILES}"
+ ) | ${PAGER}
+ ;;
+esac
+
echo ''
+if [ -r "${MM_EXIT_SCRIPT}" ]; then
+ . "${MM_EXIT_SCRIPT}"
+fi
+
exit 0
OpenPOWER on IntegriCloud