feat: add leaf upgrade old new for upgrading
This commit is contained in:
168
leaf
168
leaf
@@ -75,12 +75,15 @@ main() {
|
||||
pkgdir="${srcdir}"/__pkgdir__
|
||||
if [[ x"$1" != x"dirct-install" ]]; then
|
||||
rm -rf "${srcdir}" && install -dm755 "${srcdir}" && cd "${srcdir}"
|
||||
mkdir -pv ${TMPDIR}
|
||||
mkdir -pv ${HOME}
|
||||
fi
|
||||
leaf_${1}_package
|
||||
done
|
||||
;;
|
||||
upgrade)
|
||||
leaf_check_permission
|
||||
[ $# -eq 3 ] || leaf_error "Usage: leaf upgrade <oldpkg> <newpkg>"
|
||||
leaf_upgrade_package "$2" "$3"
|
||||
;;
|
||||
search)
|
||||
leaf_search_package "${@:2}"
|
||||
;;
|
||||
@@ -246,22 +249,39 @@ leaf_merge_package() {
|
||||
_group=$(stat -c %g ."${_item}")
|
||||
install -d -m ${_mode} -o ${_owner} -g ${_group} "${_item}"
|
||||
done
|
||||
cat "${_trace_dir}"/FILES | while read -r _item; do
|
||||
|
||||
cat "${_trace_dir}"/FILES | while read -r _item; do
|
||||
_mode=$(stat -c %a ."${_item}")
|
||||
_owner=$(stat -c %u ."${_item}")
|
||||
_group=$(stat -c %g ."${_item}")
|
||||
if [[ "${_item}" == /etc/* && -e "${_item}" ]]; then
|
||||
_item_conflict="$(dirname "${_item}")/._$(basename "${_item}").conflict_${PKG_NAME}_${_time}"
|
||||
if (diff ."${_item}" "${_item}" > /dev/null); then
|
||||
install -D -m ${_mode} -o ${_owner} -g ${_group} ."${_item}" "${_item}"
|
||||
else
|
||||
install -D -m ${_mode} -o ${_owner} -g ${_group} ."${_item}" "${_item_conflict}"
|
||||
leaf_record_message "Config file confliction on ${_item}, the package provided version is installed as ${_item_conflict}."
|
||||
fi
|
||||
else
|
||||
|
||||
# Fast path: non-/etc, or /etc path that doesn't exist yet -> install/overwrite directly
|
||||
if [[ "${_item}" != /etc/* || ! -e "${_item}" ]]; then
|
||||
install -D -m ${_mode} -o ${_owner} -g ${_group} ."${_item}" "${_item}"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Now: /etc/* and already exists on the system.
|
||||
# Upgrade optimization: if OLD_TRACE_DIR is set and the current /etc file matches old baseline,
|
||||
# then user didn't modify it -> overwrite with new version directly.
|
||||
if [[ -n "${OLD_TRACE_DIR:-}" ]] \
|
||||
&& leaf_conffile_is_unmodified "${_item}" "${OLD_TRACE_DIR}"; then
|
||||
install -D -m ${_mode} -o ${_owner} -g ${_group} ."${_item}" "${_item}"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Otherwise, fall back to conflict logic:
|
||||
# - if content is identical -> overwrite (keeps permissions/ownership from pkg)
|
||||
# - else -> write conflict file and keep user's current file
|
||||
_item_conflict="$(dirname "${_item}")/._$(basename "${_item}").conflict_${PKG_NAME}_${_time}"
|
||||
if diff -q ."${_item}" "${_item}" >/dev/null 2>&1; then
|
||||
install -D -m ${_mode} -o ${_owner} -g ${_group} ."${_item}" "${_item}"
|
||||
else
|
||||
install -D -m ${_mode} -o ${_owner} -g ${_group} ."${_item}" "${_item_conflict}"
|
||||
leaf_record_message "Config file confliction on ${_item}, the package provided version is installed as ${_item_conflict}."
|
||||
fi
|
||||
done
|
||||
|
||||
cat "${_trace_dir}"/LINKS | while read -r _item; do
|
||||
cp -dp ."${_item}" "${_item}"
|
||||
done
|
||||
@@ -302,6 +322,7 @@ Option: prepare prepare packages but do not build
|
||||
forece-install install packages even if test failed
|
||||
dirct-install install packages directly from previous build
|
||||
remove remove packages
|
||||
upgrade upgrade oldpkg to newpkg (leaf upgrade old new)
|
||||
clean clean all source folders
|
||||
list list installed packages
|
||||
search search packages by keyword
|
||||
@@ -629,6 +650,9 @@ leaf_prepare_package() {
|
||||
}
|
||||
|
||||
leaf_build_package() {
|
||||
mkdir -pv ${TMPDIR}
|
||||
mkdir -pv ${HOME}
|
||||
|
||||
leaf_prepare_package
|
||||
leaf_phase_must "Building" src_build "Build failed."
|
||||
|
||||
@@ -713,6 +737,117 @@ leaf_force-install_package(){
|
||||
leaf_install_package
|
||||
}
|
||||
|
||||
leaf_upgrade_package() {
|
||||
local old_query="$1" new_query="$2"
|
||||
local old_prefix old_name new_prefix new_name
|
||||
local new_srcdir new_pkgdir
|
||||
local old_trace_dir new_trace_dir
|
||||
local skipfile
|
||||
|
||||
# -------- resolve OLD (installed) --------
|
||||
leaf_find_remove_pkgbuild "${old_query}"
|
||||
old_prefix="${PKG_PREFIX}"
|
||||
old_name="${PKG_NAME}"
|
||||
old_trace_dir="${TRACE_DIR}/${old_prefix}/${old_name}"
|
||||
OLD_TRACE_DIR="${old_trace_dir}"
|
||||
|
||||
# -------- resolve NEW (available) --------
|
||||
leaf_find_pkgbuild "${new_query}"
|
||||
new_prefix="${PKG_PREFIX}"
|
||||
new_name="${PKG_NAME}"
|
||||
|
||||
# sanity
|
||||
if [[ "${old_prefix}/${old_name}" == "${new_prefix}/${new_name}" ]]; then
|
||||
leaf_error "upgrade: old and new refer to the same package: ${old_prefix}/${old_name}"
|
||||
fi
|
||||
|
||||
# =========================================================
|
||||
# 1) BUILD NEW (no ROOT touch)
|
||||
# =========================================================
|
||||
PKG_PREFIX="${new_prefix}"
|
||||
PKG_NAME="${new_name}"
|
||||
|
||||
leaf_reset_state
|
||||
leaf_message_init
|
||||
source "${PKGBUILD_DIR}/${PKG_PREFIX}/${PKG_NAME}.PKGBUILD"
|
||||
leaf_parse_options
|
||||
|
||||
srcdir="${BUILD_DIR}/${PKG_PREFIX}/${PKG_NAME}"
|
||||
TMPDIR="${srcdir}/.leaf-tmp"
|
||||
HOME="${srcdir}/.leaf-home"
|
||||
export TMPDIR HOME
|
||||
pkgdir="${srcdir}/__pkgdir__"
|
||||
|
||||
rm -rf -- "${srcdir}" && install -dm755 -- "${srcdir}" && cd "${srcdir}"
|
||||
mkdir -pv -- "${TMPDIR}" "${HOME}"
|
||||
|
||||
leaf_build_package
|
||||
|
||||
new_srcdir="${srcdir}"
|
||||
new_pkgdir="${pkgdir}"
|
||||
|
||||
# =========================================================
|
||||
# 2) INSTALL NEW (touch ROOT)
|
||||
# Use dirct-install path so we don't rebuild.
|
||||
# =========================================================
|
||||
PKG_PREFIX="${new_prefix}"
|
||||
PKG_NAME="${new_name}"
|
||||
|
||||
leaf_reset_state
|
||||
leaf_message_init
|
||||
source "${PKGBUILD_DIR}/${PKG_PREFIX}/${PKG_NAME}.PKGBUILD"
|
||||
leaf_parse_options
|
||||
|
||||
srcdir="${new_srcdir}"
|
||||
pkgdir="${new_pkgdir}"
|
||||
TMPDIR="${srcdir}/.leaf-tmp"
|
||||
HOME="${srcdir}/.leaf-home"
|
||||
export TMPDIR HOME
|
||||
|
||||
[ -d "${pkgdir}" ] || leaf_error "upgrade: built pkgdir missing: ${pkgdir}"
|
||||
cd "${srcdir}" || leaf_error "upgrade: cannot enter build dir: ${srcdir}"
|
||||
|
||||
leaf_dirct-install_package
|
||||
|
||||
# new trace dir now exists (generated by leaf_dirct-install_package -> leaf_trace_package)
|
||||
new_trace_dir="${TRACE_DIR}/${new_prefix}/${new_name}"
|
||||
[ -d "${new_trace_dir}" ] || leaf_error "upgrade: new trace dir missing: ${new_trace_dir}"
|
||||
|
||||
# =========================================================
|
||||
# 3) REMOVE OLD, but SKIP paths owned by NEW
|
||||
# =========================================================
|
||||
skipfile="$(mktemp "${TEMP_DIR}/leaf-upgrade-skip.XXXXXX")" || leaf_error "mktemp failed"
|
||||
cat "${new_trace_dir}/FILES" "${new_trace_dir}/LINKS" "${new_trace_dir}/DIRS" > "${skipfile}" || {
|
||||
rm -f -- "${skipfile}"
|
||||
leaf_error "upgrade: cannot create skiplist"
|
||||
}
|
||||
|
||||
PKG_PREFIX="${old_prefix}"
|
||||
PKG_NAME="${old_name}"
|
||||
|
||||
leaf_reset_state
|
||||
leaf_message_init
|
||||
# old remove sources PKGBUILD from TRACE (best effort)
|
||||
source "${old_trace_dir}/PKGBUILD" 2>/dev/null || true
|
||||
|
||||
export LEAF_REMOVE_SKIPLIST="${skipfile}"
|
||||
leaf_remove_package
|
||||
unset LEAF_REMOVE_SKIPLIST
|
||||
|
||||
rm -f -- "${skipfile}"
|
||||
|
||||
echo -e "${GREEN_COLOR}* Upgraded ${old_prefix}/${old_name} -> ${new_prefix}/${new_name}${CLEAR_COLOR}\n"
|
||||
}
|
||||
|
||||
leaf_in_skiplist() {
|
||||
# usage: leaf_in_skiplist <abs_path>
|
||||
# return 0 if path in LEAF_REMOVE_SKIPLIST file
|
||||
local p="$1"
|
||||
[ -n "${LEAF_REMOVE_SKIPLIST:-}" ] || return 1
|
||||
[ -r "${LEAF_REMOVE_SKIPLIST}" ] || return 1
|
||||
grep -Fxq -- "$p" "${LEAF_REMOVE_SKIPLIST}" 2>/dev/null
|
||||
}
|
||||
|
||||
leaf_remove_package() {
|
||||
[ -n "$(grep "${PKG_PREFIX}/${PKG_NAME}" ${INSTALLED_PACKAGES})" ] || {
|
||||
leaf_error "Package ${PKG_PREFIX}/${PKG_NAME} is NOT installed"
|
||||
@@ -730,6 +865,9 @@ leaf_remove_package() {
|
||||
|
||||
# FILES
|
||||
while read -r _file; do
|
||||
if leaf_in_skiplist "${_file}"; then
|
||||
continue
|
||||
fi
|
||||
if [[ "${_file}" == /etc/* && -e "${_file}" ]]; then
|
||||
if [ "${_has_conffiles}" -eq 1 ]; then
|
||||
if leaf_conffile_is_unmodified "${_file}" "${_trace_dir}"; then
|
||||
@@ -760,6 +898,9 @@ leaf_remove_package() {
|
||||
|
||||
# LINKS
|
||||
while read -r _link; do
|
||||
if leaf_in_skiplist "${_link}"; then
|
||||
continue
|
||||
fi
|
||||
if [[ "${_link}" == /etc/* && -e "${_link}" ]]; then
|
||||
if [ "${_has_conffiles}" -eq 1 ]; then
|
||||
if leaf_conffile_is_unmodified "${_link}" "${_trace_dir}"; then
|
||||
@@ -776,6 +917,9 @@ leaf_remove_package() {
|
||||
|
||||
# DIRS
|
||||
while read -r _directory; do
|
||||
if leaf_in_skiplist "${_directory}"; then
|
||||
continue
|
||||
fi
|
||||
if [[ -d "${_directory}" ]]; then
|
||||
rmdir --ignore-fail-on-non-empty "${_directory}"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user