forked from tools/pkgutils
317 lines
6.0 KiB
Bash
317 lines
6.0 KiB
Bash
#!/bin/bash
|
|
#
|
|
# rejmerge (pkgutils)
|
|
#
|
|
# Copyright (c) 2000-2005 Per Liden
|
|
# Copyright (c) 2006-2021 by CRUX team (http://crux.nu)
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
# USA.
|
|
#
|
|
|
|
info_n() {
|
|
echo -n "=======> $1"
|
|
}
|
|
|
|
info() {
|
|
info_n "$1"
|
|
echo
|
|
}
|
|
|
|
interrupted() {
|
|
echo ""
|
|
info "Aborted."
|
|
exit 1
|
|
}
|
|
|
|
atexit() {
|
|
if [ -e "$TMPFILE" ]; then
|
|
rm -f "$TMPFILE"
|
|
fi
|
|
}
|
|
|
|
rejmerge_diff() {
|
|
diff -u "$1" "$2" > "$3"
|
|
}
|
|
|
|
rejmerge_merge() {
|
|
diff --old-group-format="%<" \
|
|
--new-group-format="%>" \
|
|
--changed-group-format="<<<<< MERGE CONFLICT $1 >>>>>
|
|
%<<<<<< MERGE CONFLICT $2 >>>>>
|
|
%><<<<< END MERGE CONFLICT >>>>>
|
|
" \
|
|
"$1" "$2" > "$3"
|
|
|
|
REJMERGE_MERGE_INFO="$(grep -c '^<<<<< END MERGE CONFLICT >>>>>$' "$3") merge conflict(s)."
|
|
}
|
|
|
|
permissions_menu() {
|
|
while true; do
|
|
info "Access permissions $1"
|
|
stat -c '%A %U %G %n' "$1"
|
|
stat -c '%A %U %G %n' "$2"
|
|
while true; do
|
|
info_n "[K]eep [U]pgrade [D]iff [S]kip? "
|
|
read -n1 CMD
|
|
echo
|
|
|
|
case "$CMD" in
|
|
k|K) chown --reference="$1" "$2"
|
|
chmod --reference="$1" "$2"
|
|
break 2
|
|
;;
|
|
u|U) chown --reference="$2" "$1"
|
|
chmod --reference="$2" "$1"
|
|
break 2
|
|
;;
|
|
d|D) break 1
|
|
;;
|
|
s|S) break 2
|
|
;;
|
|
esac
|
|
done
|
|
done
|
|
}
|
|
|
|
merge_menu() {
|
|
rejmerge_merge "$1" "$2" "$TMPFILE"
|
|
|
|
while true; do
|
|
info "Merged $1"
|
|
cat "$TMPFILE" | more
|
|
|
|
if [ "$REJMERGE_MERGE_INFO" ]; then
|
|
info "$REJMERGE_MERGE_INFO"
|
|
unset REJMERGE_MERGE_INFO
|
|
fi
|
|
|
|
while true; do
|
|
info_n "[I]nstall [E]dit [V]iew [S]kip? "
|
|
read -n1 CMD
|
|
echo
|
|
|
|
case "$CMD" in
|
|
i|I) chmod --reference="$1" "$TMPFILE"
|
|
mv -f "$TMPFILE" "$1"
|
|
rm -f "$2"
|
|
break 2
|
|
;;
|
|
e|E) $EDITOR "$TMPFILE"
|
|
break 1
|
|
;;
|
|
v|V) break 1
|
|
;;
|
|
s|S) break 2
|
|
;;
|
|
esac
|
|
done
|
|
done
|
|
|
|
: > "$TMPFILE"
|
|
}
|
|
|
|
diff_menu() {
|
|
rejmerge_diff "$1" "$2" "$TMPFILE"
|
|
|
|
while true; do
|
|
info "$1"
|
|
cat "$TMPFILE" | more
|
|
while true; do
|
|
info_n "[K]eep [U]pgrade [M]erge [D]iff [S]kip? "
|
|
read -n1 CMD
|
|
echo
|
|
|
|
case "$CMD" in
|
|
k|K) rm -f "$2"
|
|
break 2
|
|
;;
|
|
u|U) mv -f "$2" "$1"
|
|
break 2
|
|
;;
|
|
m|M) merge_menu "$1" "$2"
|
|
break 2
|
|
;;
|
|
d|D) break 1
|
|
;;
|
|
s|S) break 2
|
|
;;
|
|
esac
|
|
done
|
|
done
|
|
|
|
: > "$TMPFILE"
|
|
}
|
|
|
|
file_menu() {
|
|
while true; do
|
|
info "$1"
|
|
file "$1" "$2"
|
|
while true; do
|
|
info_n "[K]eep [U]pgrade [D]iff [S]kip? "
|
|
read -n1 CMD
|
|
echo
|
|
|
|
case "$CMD" in
|
|
k|K) rm -f "$2"
|
|
break 2
|
|
;;
|
|
u|U) mv -f "$2" "$1"
|
|
break 2
|
|
;;
|
|
d|D) break 1
|
|
;;
|
|
s|S) break 2
|
|
;;
|
|
esac
|
|
done
|
|
done
|
|
}
|
|
|
|
print_help() {
|
|
echo "usage: $REJMERGE_COMMAND [options]"
|
|
echo "options:"
|
|
echo " -r, --root <path> specify alternative root"
|
|
echo " -v, --version print version and exit "
|
|
echo " -h, --help print help and exit"
|
|
}
|
|
|
|
parse_options() {
|
|
while [ "$1" ]; do
|
|
case $1 in
|
|
-r|--root)
|
|
if [ ! "$2" ]; then
|
|
echo "$REJMERGE_COMMAND: option $1 requires an argument"
|
|
exit 1
|
|
fi
|
|
REJMERGE_ROOT="$2"
|
|
REJMERGE_CONF="$2$REJMERGE_CONF"
|
|
REJECTED_DIR="$2$REJECTED_DIR"
|
|
shift ;;
|
|
-v|--version)
|
|
echo "$REJMERGE_COMMAND (pkgutils) $REJMERGE_VERSION"
|
|
exit 0 ;;
|
|
-h|--help)
|
|
print_help
|
|
exit 0 ;;
|
|
*)
|
|
echo "$REJMERGE_COMMAND: invalid option $1"
|
|
exit 1 ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [ ! -d "$REJECTED_DIR" ]; then
|
|
echo "$REJMERGE_COMMAND: $REJECTED_DIR not found"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
files_regular() {
|
|
local STAT_FILE1=$(stat -c '%F' "$1")
|
|
local STAT_FILE2=$(stat -c '%F' "$2")
|
|
|
|
if [ "$STAT_FILE1" != "regular file" ]; then
|
|
return 1
|
|
fi
|
|
|
|
if [ "$STAT_FILE2" != "regular file" ]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
main() {
|
|
parse_options "$@"
|
|
|
|
if [ "$UID" != "0" ]; then
|
|
echo "$REJMERGE_COMMAND: only root can merge rejected files"
|
|
exit 1
|
|
fi
|
|
|
|
# Read configuration
|
|
if [ -f "$REJMERGE_CONF" ]; then
|
|
. "$REJMERGE_CONF"
|
|
fi
|
|
|
|
REJECTED_FILES_FOUND="no"
|
|
|
|
# Check files
|
|
for REJECTED_FILE in $(find $REJECTED_DIR ! -type d); do
|
|
INSTALLED_FILE="$REJMERGE_ROOT${REJECTED_FILE##$REJECTED_DIR}"
|
|
|
|
# Remove rejected file if there is no installed version
|
|
if [ ! -e "$INSTALLED_FILE" ]; then
|
|
rm -f "$REJECTED_FILE"
|
|
continue
|
|
fi
|
|
|
|
# Check permissions
|
|
local STAT_FILE1=$(stat -c '%A %U %G' "$INSTALLED_FILE")
|
|
local STAT_FILE2=$(stat -c '%A %U %G' "$REJECTED_FILE")
|
|
|
|
if [ "$STAT_FILE1" != "$STAT_FILE2" ]; then
|
|
REJECTED_FILES_FOUND="yes"
|
|
permissions_menu "$INSTALLED_FILE" "$REJECTED_FILE"
|
|
fi
|
|
|
|
# Check file types
|
|
if files_regular "$INSTALLED_FILE" "$REJECTED_FILE"; then
|
|
# Both files are regular
|
|
if cmp -s "$INSTALLED_FILE" "$REJECTED_FILE"; then
|
|
rm -f "$REJECTED_FILE"
|
|
else
|
|
REJECTED_FILES_FOUND="yes"
|
|
diff_menu "$INSTALLED_FILE" "$REJECTED_FILE"
|
|
fi
|
|
else
|
|
# At least one file is non-regular
|
|
REJECTED_FILES_FOUND="yes"
|
|
file_menu "$INSTALLED_FILE" "$REJECTED_FILE"
|
|
fi
|
|
done
|
|
|
|
# Remove empty directories
|
|
for DIR in $(find $REJECTED_DIR -depth -type d); do
|
|
if [ "$DIR" != "$REJECTED_DIR" ]; then
|
|
rmdir "$DIR" &> /dev/null
|
|
fi
|
|
done
|
|
|
|
if [ "$REJECTED_FILES_FOUND" = "no" ]; then
|
|
echo "Nothing to merge"
|
|
fi
|
|
|
|
exit 0
|
|
}
|
|
|
|
trap "interrupted" SIGHUP SIGINT SIGQUIT SIGTERM
|
|
trap "atexit" EXIT
|
|
|
|
export LC_ALL=POSIX
|
|
|
|
readonly REJMERGE_VERSION="#VERSION#"
|
|
readonly REJMERGE_COMMAND="${0##*/}"
|
|
REJMERGE_ROOT=""
|
|
REJMERGE_CONF="/etc/rejmerge.conf"
|
|
REJECTED_DIR="/var/lib/pkg/rejected"
|
|
EDITOR=${EDITOR:-vi}
|
|
TMPFILE=$(mktemp) || exit 1
|
|
|
|
main "$@"
|
|
|
|
# End of file
|