It seems I have found a couple bugs, I noticed that mergemaster was always saying that the "install failed, the file has to be merged manually" even thought the install was successful. It would seem that the recent commit is using "install && test && rm" but the install program will already have removed the files without the "-c" option. Patch attached (including another bug I found) I have also attached a diff file adding a form of md5 checking to mergemaster. Basically what I did is add use a file "/var/db/mmsums.md5" containing the checksum of any cleanly installed files. Here is what it does/doesn't do: 1) every time mm_install is called it removes the checksum for the file being installed from the database. 2) After the call to mm_install, if the install returned as successful, mergemaster will generate the checksum for the newly installed file and put it in the database. This is only done for clean files, not files that were merged. 3) When doing the comparison, if it is found that the installed file was unchanged, mergemaster says so and offers the options without showing the diff, you can still see the diff by pressing v. 4) When the "-I" (capital i) option is specified mergemaster will automatically install any file where the installed version was unchanged. 5) I take advantage of the code that detects the cvs tag by adding the md5 of the file in the temproot directory (after "fixing" the output to have the correct path), this will speed up getting the md5's of clean files into the database. Those who felt the need could fairly easily create the initial database, however after the first mergemaster run any file that has the same $FreeBSD$ or is cleanly installed will be added. That should cover just about all the files. it would not be hard to add options to choose a different md5 database, or to disable the entire thing. As it is now you can specify the database or to use the new feature by setting 'CHECKSUMFILE' to be the file holding the checksum database, or unset'ing 'USE_CHECKSUMS' to disable the whole thing in the ~/.mergemasterrc. The attached files are cumulative. the "mergemaster.sh.diff" is the two bugfixes I have noticed, and the "mergemastermd5.sh.diff" is my new version of mergemaster (patch against the bugfixed version) I just ran my new mergemaster with a hand generated database and it properly detected unchanged files, I also ran it with no database and just about every file was regenerated from the tree versions. Tell me what you think! sorry, but i have not updated the man pages... James.
--- mergemaster.sh Fri Jun 15 01:18:05 2001 +++ mergemastermd5.sh Sat Jun 16 02:10:16 2001 @@ -15,7 +15,7 @@ display_usage () { VERSION_NUMBER=`grep "[$]FreeBSD:" $0 | cut -d ' ' -f 4` echo "mergemaster version ${VERSION_NUMBER}" - echo 'Usage: mergemaster [-scrvahi] [-m /path]' + echo 'Usage: mergemaster [-scrvahiI] [-m /path]' echo ' [-t /path] [-d] [-u N] [-w N] [-D /path]' echo "Options:" echo " -s Strict comparison (diff every pair of files)" @@ -25,6 +25,7 @@ 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 ' -I Automatically install when the destination file has not been modified' 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`)" @@ -40,6 +41,8 @@ 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 -I option uses md5 checksums generated the last time a file' + echo ' was installed to detect changes.' } # Loop allowing the user to use sdiff to merge files and display the merged @@ -105,6 +108,32 @@ HANDLE_COMPFILE=v + # If we are using checksums, then check to see if the local version has been +modified + if [ -f "${DESTDIR}${COMPFILE#.}" -a -f "${COMPFILE}" ]; then + case "${USE_CHECKSUMS}" in + [Yy][Ee][Ss]) + if [ "`grep \(${DESTDIR}${COMPFILE#.}\) ${CHECKSUMFILE}`" = "`/sbin/md5 +${DESTDIR}${COMPFILE#.}`" ]; then + echo " *** The installed version of ${COMPFILE} has not been modified" + #Don't display diff the first time when file is not modified. + HANDLE_COMPFILE="NOT V" + case "${AUTO_INSTALL_UNCHANGED}" in + [Yy][Ee][Ss]) + if mm_install "${COMPFILE}"; then + echo " *** ${COMPFILE} installed successfully" + AUTO_INSTALLED_FILES_MD5="${AUTO_INSTALLED_FILES_MD5} +${DESTDIR}${COMPFILE#.} +" + /sbin/md5 ${DESTDIR}${COMPFILE#.} >> ${CHECKSUMFILE} 2>/dev/null + else + echo " *** Problem installing ${COMPFILE}, it will remain to merge by +hand" + fi + return + ;; + esac + fi + ;; + esac + fi + while [ "${HANDLE_COMPFILE}" = "v" -o "${HANDLE_COMPFILE}" = "V" -o \ "${HANDLE_COMPFILE}" = "NOT V" ]; do if [ -f "${DESTDIR}${COMPFILE#.}" -a -f "${COMPFILE}" ]; then @@ -129,6 +158,12 @@ # Make the list print one file per line AUTO_INSTALLED_FILES="${AUTO_INSTALLED_FILES} ${DESTDIR}${COMPFILE#.} " + case "${USE_CHECKSUMS}" in + [Yy][Ee][Ss]) + # Installed a clean file, update checkum data. + /sbin/md5 ${DESTDIR}${COMPFILE#.} >> ${CHECKSUMFILE} 2>/dev/null + ;; + esac else echo " *** Problem installing ${COMPFILE}, it will remain to merge by hand" fi @@ -164,6 +199,12 @@ echo '' if mm_install "${COMPFILE}"; then echo " *** ${COMPFILE} installed successfully" + case "${USE_CHECKSUMS}" in + [Yy][Ee][Ss]) + # Installed a clean file, update checkum data. + /sbin/md5 ${DESTDIR}${COMPFILE#.} >> ${CHECKSUMFILE} 2>/dev/null + ;; + esac else echo " *** Problem installing ${COMPFILE}, it will remain to merge by hand" fi @@ -212,6 +253,10 @@ # TEMPROOT='/var/tmp/temproot' +# Setup what we need to use md5 checksums. +CHECKSUMFILE=/var/db/mmsums.md5 +USE_CHECKSUMS=yes + # Read /etc/mergemaster.rc first so the one in $HOME can override # if [ -r /etc/mergemaster.rc ]; then @@ -226,7 +271,7 @@ # Check the command line options # -while getopts ":ascrvhim:t:du:w:D:" COMMAND_LINE_ARGUMENT ; do +while getopts ":ascrvhiIm:t:du:w:D:" COMMAND_LINE_ARGUMENT ; do case "${COMMAND_LINE_ARGUMENT}" in s) STRICT=yes @@ -254,6 +299,9 @@ i) AUTO_INSTALL=yes ;; + I) + AUTO_INSTALL_UNCHANGED=yes + ;; m) SOURCEDIR=${OPTARG} ;; @@ -281,6 +329,17 @@ echo '' +# Check if the checksums file exists and force it's mode to 600. +if [ ! -e ${CHECKSUMFILE} ]; then + touch ${CHECKSUMFILE} +fi + +if [ -f ${CHECKSUMFILE} ]; then + chmod 600 ${CHECKSUMFILE} +else + unset USE_CHECKSUMS +fi + # If the user has a pager defined, make sure we can run it # case "${DONT_CHECK_PAGER}" in @@ -574,6 +633,15 @@ ;; esac + case "${USE_CHECKSUMS}" in + [Yy][Ee][Ss]) + # Remove the md5 entry for this file, don't add new one since this may be a + # merged file. + grep -v \(${DESTDIR}${INSTALL_DIR}\) ${CHECKSUMFILE} > ${CHECKSUMFILE}.new + mv ${CHECKSUMFILE}.new ${CHECKSUMFILE} + ;; + esac + 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}"` @@ -666,7 +734,6 @@ esac install -c -m "${FILE_MODE}" "${1}" "${DESTDIR}${INSTALL_DIR}" && [ -f "${1}" ] && rm "${1}" -#echo "fourth install, return $?" fi return $? } @@ -723,6 +790,20 @@ case "${CVSID2}" in "${CVSID1}") echo " *** Temp ${COMPFILE} and installed have the same CVS Id, deleting" + # Since we know the temproot version is clean, lets generate a checksum + # from it, this will help the checksums file to be populated more quickly. + case "${USE_CHECKSUMS}" in + [Yy][Ee][Ss]) + # Remove the md5 entry for this file first, if it exists. + grep -v \(${DESTDIR}${COMPFILE#.}\) ${CHECKSUMFILE} > ${CHECKSUMFILE}.new + mv ${CHECKSUMFILE}.new ${CHECKSUMFILE} + # Installed a clean file, update checkum data. + { + echo -n "MD5 (${DESTDIR}${COMPFILE#.}) = " + /sbin/md5 -q ${COMPFILE} + } >> ${CHECKSUMFILE} 2>/dev/null + ;; + esac rm "${COMPFILE}" ;; esac @@ -809,6 +890,28 @@ echo '*** You chose the automatic install option for files that did not' echo ' exist on your system. The following were installed for you:' echo "${AUTO_INSTALLED_FILES}" + ;; + esac + ;; +esac + +case "${AUTO_INSTALLED_FILES_MD5}" in +'') ;; +*) + case "${AUTO_RUN}" in + '') + ( + echo '' + echo '*** You chose the automatic install option for files that were not' + echo ' changed on your system. The following were installed for you:' + echo "${AUTO_INSTALLED_FILES_MD5}" + ) | ${PAGER} + ;; + *) + echo '' + echo '*** You chose the automatic install option for files that were not' + echo ' chamged on your system. The following were installed for you:' + echo "${AUTO_INSTALLED_FILES_MD5}" ;; esac ;;
--- mergemaster.sh.orig Fri Jun 15 00:41:45 2001 +++ mergemaster.sh Fri Jun 15 01:18:05 2001 @@ -471,7 +471,7 @@ 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} + diff -qr ${DESTDIR}/etc ${TEMPROOT}/etc | grep "^Only in ${DESTDIR}/etc" | +${PAGER} echo '' echo ' *** Press [Enter] or [Return] key to continue' read ANY_KEY @@ -592,7 +592,7 @@ NEED_CAP_MKDB=yes ;; /etc/master.passwd) - install -m 600 "${1}" "${DESTDIR}${INSTALL_DIR}" && + install -c -m 600 "${1}" "${DESTDIR}${INSTALL_DIR}" && [ -f "${1}" ] && rm "${1}" NEED_PWD_MKDB=yes DONT_INSTALL=yes @@ -651,7 +651,7 @@ case "${DONT_INSTALL}" in '') - install -m "${FILE_MODE}" "${1}" "${DESTDIR}${INSTALL_DIR}" && + install -c -m "${FILE_MODE}" "${1}" "${DESTDIR}${INSTALL_DIR}" && [ -f "${1}" ] && rm "${1}" ;; *) @@ -664,8 +664,9 @@ NEED_MAKEDEV=yes ;; esac - install -m "${FILE_MODE}" "${1}" "${DESTDIR}${INSTALL_DIR}" && + install -c -m "${FILE_MODE}" "${1}" "${DESTDIR}${INSTALL_DIR}" && [ -f "${1}" ] && rm "${1}" +#echo "fourth install, return $?" fi return $? }