diff --git a/sunrise-commit b/sunrise-commit index 5fe1af4..94ceaf0 100755 --- a/sunrise-commit +++ b/sunrise-commit @@ -59,6 +59,32 @@ find_repo() { sayv "Ok, we're in ${SC_VCS} working tree. Let's see what I can do around here..." } +# Check whether we're having a clean package removal. +is_package_removal() { + local fields list + [ -d profiles ] && fields=1-2 || fields=1 + + if [ ${SC_VCS%-svn} = git ]; then + list=$(git diff-index --relative --name-only --diff-filter=D HEAD \ + | cut -d / -f ${fields} | sort | uniq) + fi + + # 1) We have to have any removes. + [ -z "${list}" ] && return 1 + + # Few more checks. + local dir olist + for dir in ${list}; do + # 2) These removes have to remove whole directories. + [ -e ${dir} ] || olist=${olist+${olist} }${dir} + done + + [ -z "${olist}" ] && return 1 + + SC_CHANGE_LIST=${olist} + return 0 +} + # Look around for ebuilds. find_ebuilds() { # POSIX is fun -- look for ebuilds in the current directory. @@ -72,8 +98,40 @@ find_ebuilds() { SC_SCENARIO=ebuild-commit sayv "We have some ebuilds for ${SC_CP} here." + elif is_package_removal; then + local cplist category pkg rootprefix + # We can either have the category on the list or in PWD. + if [ -d profiles ]; then + category= + else + local stripped + stripped=${PWD%/*} + category=${PWD#${stripped}/}/ + fi + + SC_CP= + # Now we can have multiple packages around. + for pkg in ${SC_CHANGE_LIST}; do + if [ -z "${category}" ]; then + case ${pkg} in + eclass/*|licenses/*|local/*|profiles/*|scripts/*) + continue + ;; + esac + fi + SC_CP=${SC_CP:+${SC_CP}, }${category}${pkg} + done + + local root sdir + root=${category:+../} + + for sdir in eclass licenses profiles; do + check_for_changes ${root}${sdir} >/dev/null && SC_CHANGE_LIST="${SC_CHANGE_LIST} ${root}${sdir}" + done + SC_SCENARIO=package-removal + sayv "We're removing ${SC_CP}." else - die 'No familar situation found -- no ebuilds here.' + die 'No familiar scenario found.' fi } @@ -82,9 +140,10 @@ check_for_changes() { local output if [ ${SC_VCS%-svn} = git ]; then - output=$(git diff-index --name-only --relative HEAD) + output=$(git diff-index --name-only --relative HEAD "$@") fi + [ -z "${output}" ] && return 1 # We do not care about user mangling ChangeLog, we will reset it anyway. echo "${output}" | grep -v ChangeLog >/dev/null } @@ -98,7 +157,17 @@ vcs_reset() { vcs_status() { if [ ${SC_VCS%-svn} = git ]; then - git status -s . + git status -s ${1-.} "${@}" + fi +} + +vcs_commit() { + local msg + msg=${1} + shift + + if [ ${SC_VCS%-svn} = git ]; then + exec git commit -m "${msg}" ${1+-o} "${@}" fi } @@ -119,6 +188,26 @@ Options: _EOH_ } +confirm() { + while true; do + local answ + printf '%s' "${WHITE}Commit changes?${RESET} [${BGREEN}Yes${RESET}/${RED}No${RESET}] ${GREEN}" >&2 + read answ + printf '%s' "${RESET}" + + case "${answ}" in + [yY]|[yY][eE]|[yY][eE][sS]) + break + ;; + [nN]|[nN][oO]) + die 'Aborting.' + ;; + *) + say "Response '${answ}' not understood, try again." + esac + done +} + # Guess what! main() { local commitmsg force monochrome trivial @@ -237,29 +326,20 @@ main() { say "${GREEN}Please update portage to newer version in order to have repoman supporting" say "--ask option and thus delay the following question until after 'repoman full'.${RESET}" say - - while true; do - local answ - printf '%s' "${WHITE}Commit changes?${RESET} [${BGREEN}Yes${RESET}/${RED}No${RESET}] ${GREEN}" >&2 - read answ - printf '%s' "${RESET}" - - case "${answ}" in - [yY]|[yY][eE]|[yY][eE][sS]) - break - ;; - [nN]|[nN][oO]) - die 'Aborting.' - ;; - *) - say "Response '${answ}' not understood, try again." - esac - done + confirm fi sayv "Now, let's let repoman do its job..." exec repoman commit ${old_repoman--a} ${force+-f} -m "${SC_CP}: ${commitmsg}" ;; + package-removal) + vcs_status ${SC_CHANGE_LIST} + echo + say "Ready to commit ${WHITE}$(echo ${SC_CHANGE_LIST} | wc -w)${RESET} package removal(s), with message:" + say "${BGREEN}${SC_CP}: ${commitmsg}${RESET}" + confirm + vcs_commit "${SC_CP}: ${commitmsg}" ${SC_CHANGE_LIST} + ;; esac }