3e7de31fb0
If we're using old repoman version, call 'repoman full' before asking for confirmation to allow fixing minor problems before committing. That implies calling 'repoman manifest' too. Additionally, don't complain about outdated repoman before the patched version is released.
380 lines
8.3 KiB
Bash
Executable File
380 lines
8.3 KiB
Bash
Executable File
#!/bin/sh
|
|
# sunrise-commit -- a helper script for Sunrise commiters.
|
|
# (c) 2010 Michał Górny <gentoo@mgorny.alt.pl>
|
|
# Released under the terms of the 3-clause BSD license.
|
|
|
|
# Few output helpers.
|
|
say() {
|
|
echo "${@}" >&2
|
|
}
|
|
|
|
die() {
|
|
say "${RED}${@}${RESET}"
|
|
exit 1
|
|
}
|
|
|
|
sayv() {
|
|
[ -n "${SC_VERBOSE}" ] && say "${GREEN}${@}${RESET}"
|
|
}
|
|
|
|
req() {
|
|
"$@" || die "$@ failed."
|
|
}
|
|
|
|
# POSIX compat.
|
|
local_supported() {
|
|
local test 2>/dev/null
|
|
}
|
|
|
|
local_supported || eval 'local() {
|
|
unset ${@}
|
|
}'
|
|
|
|
# See if we're in a repo, and what VCS are we using.
|
|
find_repo() {
|
|
svn info >/dev/null 2>&1
|
|
|
|
if [ ${?} -eq 0 ]; then
|
|
SC_VCS=svn
|
|
else
|
|
local remotes
|
|
remotes=$(git branch -r 2>/dev/null)
|
|
|
|
if [ ${?} -ne 127 -a ${?} -ne 128 ]; then
|
|
echo "${remotes}" | grep git-svn >/dev/null 2>&1
|
|
if [ ${?} -eq 0 ]; then
|
|
SC_VCS=git-svn
|
|
else
|
|
SC_VCS=git
|
|
fi
|
|
else
|
|
die 'Unable to find any familiar repository type (are you inside the repo?).'
|
|
fi
|
|
fi
|
|
|
|
sayv "Ok, we're in ${SC_VCS} working tree. Let's see what I can do around here..."
|
|
}
|
|
|
|
is_whole_dir_removed() {
|
|
if [ ${SC_VCS} = svn ]; then
|
|
local flist
|
|
flist=$(find "${1}" \( -name '.svn' -prune -o ! -name "${1}" -print \))
|
|
[ -z "${flist}" ]
|
|
elif [ ${SC_VCS%-svn} = git ]; then
|
|
[ ! -e "${1}" ]
|
|
fi
|
|
}
|
|
|
|
# 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)
|
|
elif [ ${SC_VCS} = svn ]; then
|
|
list=$(svn status -q | sed -n -e 's/^D //p')
|
|
fi
|
|
list=$(echo "${list}" | cut -d / -f ${fields} | sort | uniq)
|
|
|
|
# 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.
|
|
is_whole_dir_removed ${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.
|
|
if [ -n "$(find \( -name '*.ebuild' -print -o ! -name '.' -prune \))" ]; then
|
|
local stripped
|
|
|
|
# Get CATEGORY and PN.
|
|
stripped=${PWD%/*}
|
|
stripped=${stripped%/*}
|
|
SC_CP=${PWD#${stripped}/}
|
|
|
|
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 familiar scenario found.'
|
|
fi
|
|
}
|
|
|
|
# VCS helpers.
|
|
check_for_changes() {
|
|
local output
|
|
|
|
if [ ${SC_VCS%-svn} = git ]; then
|
|
output=$(git diff-index --name-only --relative HEAD "$@")
|
|
elif [ ${SC_VCS} = svn ]; then
|
|
output=$(svn status "$@")
|
|
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
|
|
}
|
|
|
|
vcs_reset() {
|
|
if [ ${SC_VCS%-svn} = git ]; then
|
|
req git reset -q HEAD "${1}"
|
|
git checkout -f "${1}" 2>/dev/null || req rm -f ChangeLog
|
|
elif [ ${SC_VCS} = svn ]; then
|
|
req rm -f ChangeLog
|
|
svn up ChangeLog >/dev/null 2>&1
|
|
fi
|
|
}
|
|
|
|
vcs_status() {
|
|
if [ ${SC_VCS%-svn} = git ]; then
|
|
git status -s ${1-.} "${@}"
|
|
elif [ ${SC_VCS} = svn ]; then
|
|
svn status "${@}"
|
|
fi
|
|
}
|
|
|
|
vcs_add() {
|
|
${SC_VCS%-svn} add "$@"
|
|
}
|
|
|
|
vcs_commit() {
|
|
local msg
|
|
msg=${1}
|
|
shift
|
|
|
|
if [ ${SC_VCS%-svn} = git ]; then
|
|
exec git commit -m "${msg}" ${1+-o} "${@}"
|
|
elif [ ${SC_VCS} = svn ]; then
|
|
exec svn commit -m "${msg}" "${@}"
|
|
fi
|
|
}
|
|
|
|
print_help() {
|
|
cat <<_EOH_
|
|
Synopsis:
|
|
sunrise-commit [options] [--] <commit message>
|
|
|
|
Options:
|
|
-?, -h, --help print this message,
|
|
-V, --version print version string,
|
|
|
|
-c, --changelog backwards compat (ignored),
|
|
-C, --nocolor disable colorful output,
|
|
-f, --force force repoman to proceed with the commit,
|
|
-t, --trivial trivial changes (do not add a ChangeLog entry),
|
|
-v, --verbose enable verbose output.
|
|
_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
|
|
unset SC_VERBOSE
|
|
|
|
while [ ${#} -gt 0 ]; do
|
|
case "${1}" in
|
|
--help|-\?|-h)
|
|
print_help
|
|
exit 0
|
|
;;
|
|
--version|-V)
|
|
echo 'sunrise-commit 0.3'
|
|
exit 0
|
|
;;
|
|
|
|
-c|--changelog)
|
|
# Now changelog entries are implicit -- backwards compat.
|
|
;;
|
|
-C|--nocolor)
|
|
monochrome=1
|
|
;;
|
|
-f|--force)
|
|
force=1
|
|
;;
|
|
-t|--trivial)
|
|
trivial=1
|
|
;;
|
|
-v|--verbose)
|
|
SC_VERBOSE=1
|
|
;;
|
|
|
|
--)
|
|
shift
|
|
commitmsg=${commitmsg+${commitmsg} }${@}
|
|
break
|
|
;;
|
|
-*)
|
|
die "Unknown option: ${1}; see --help." >&2
|
|
;;
|
|
*)
|
|
commitmsg=${commitmsg+${commitmsg} }${1}
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [ -n "${monochrome}" ]; then
|
|
RESET=
|
|
RED=
|
|
GREEN=
|
|
BGREEN=
|
|
YELLOW=
|
|
WHITE=
|
|
else
|
|
local esc
|
|
esc=$(printf '\033[')
|
|
|
|
RESET=${esc}0m
|
|
RED="${esc}1;31m"
|
|
GREEN=${esc}32m
|
|
BGREEN="${esc}1;32m"
|
|
YELLOW="${esc}1;33m"
|
|
WHITE="${esc}1;37m"
|
|
fi
|
|
|
|
[ -n "${commitmsg}" ] || die 'No commit message provided.'
|
|
|
|
find_repo
|
|
find_ebuilds
|
|
|
|
case ${SC_SCENARIO} in
|
|
ebuild-commit)
|
|
check_for_changes || die 'No changes found to commit.'
|
|
|
|
# With native git repos, we do not do ChangeLogs by default...
|
|
# ...at least unless they're already there.
|
|
if [ ${SC_VCS} != git -o -f ChangeLog ]; then
|
|
sayv 'Cleaning up the ChangeLog...'
|
|
vcs_reset ChangeLog
|
|
|
|
local bns
|
|
# Let's take a lucky guess bugnumbers consist of 4+ digits.
|
|
bns=$(echo "${commitmsg}" | grep -o -E '[0-9]{4,}')
|
|
|
|
# Creating a new ChangeLog? Let's take a look at the commit message.
|
|
if [ ! -f ChangeLog ]; then
|
|
[ -n "${trivial}" ] && die "Trivial change for an initial commit? You're joking, right?"
|
|
[ -z "${bns}" ] && die 'Please supply the bug number in the initial commit message!'
|
|
if [ ! -f metadata.xml ]; then
|
|
req cp ../../skel.metadata.xml metadata.xml
|
|
# Output similar to echangelog.
|
|
diff -dup /dev/null metadata.xml
|
|
req vcs_add metadata.xml
|
|
fi
|
|
fi
|
|
|
|
if [ -z "${trivial}" ]; then
|
|
sayv '...and appending to it.'
|
|
echangelog "${commitmsg}" || die 'Please correct the problems pointed by echangelog.'
|
|
echo
|
|
fi
|
|
|
|
if [ -n "${bns}" ]; then
|
|
local bn cbn
|
|
for bn in ${bns}; do
|
|
cbn=#${WHITE}${bn}${NORMAL}
|
|
wget -q http://bugs.gentoo.org/show_bug.cgi?id=${bn} -O - | sed -n \
|
|
-e "s, *<title>Gentoo Bug \([0-9]*\) - \(.*\)</title>,Bug ${cbn}: ${BGREEN}\2${RESET},p" \
|
|
-e "s, *<title>Gentoo \(Invalid Bug ID\)</title>,Bug ${cbn}: ${YELLOW}!! \1${RESET},p"
|
|
done
|
|
echo
|
|
fi
|
|
fi
|
|
|
|
vcs_status
|
|
echo
|
|
|
|
# Do we have repoman new enough?
|
|
local old_repoman
|
|
repoman --version -a >/dev/null 2>&1
|
|
if [ $? -eq 2 ]; then
|
|
old_repoman=
|
|
|
|
#say "${GREEN}Please consider updating portage to newer version.${RESET}"
|
|
#say
|
|
req repoman manifest
|
|
if ! repoman full; then
|
|
[ -n "${force}" ] || die 'Please correct the problems pointed out by repoman.'
|
|
fi
|
|
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
|
|
}
|
|
|
|
main "${@}"
|