summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Tarkovsky <alextarkovsky@gmail.org>2006-07-11 08:02:44 +0000
committerAlex Tarkovsky <alextarkovsky@gmail.org>2006-07-11 08:02:44 +0000
commit31d191b7ae8e34fccd2fa457806c2d68493c1cf6 (patch)
tree1b84d1fee69f27195ae4c824f0307a734f5980ac /scripts
parentnet-mail/gmail-notify: incorporated suggestions from Tristan Heaven (diff)
downloadsunrise-31d191b7ae8e34fccd2fa457806c2d68493c1cf6.tar.gz
sunrise-31d191b7ae8e34fccd2fa457806c2d68493c1cf6.tar.bz2
sunrise-31d191b7ae8e34fccd2fa457806c2d68493c1cf6.zip
scripts/sunrise-commit: Don't 'svn add' deleted items; new intelligent parsing and handling of 'svn status' output; more accurately determine working copy base dir; minor code cleanup.
svn path=/sunrise/; revision=587
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/sunrise-commit186
1 files changed, 151 insertions, 35 deletions
diff --git a/scripts/sunrise-commit b/scripts/sunrise-commit
index 06f17d98e..151abcb74 100755
--- a/scripts/sunrise-commit
+++ b/scripts/sunrise-commit
@@ -14,7 +14,19 @@ YELLOW=$WARN
commit_category="$(pwd | awk -F/ '{ print $(NF-1) }')"
commit_package="$(pwd | awk -F/ '{ print $NF }')"
+current_svn_status=( )
cwd_is_ebuild_dir=0
+items_added=( )
+items_conflicted=( )
+items_deleted=( )
+items_ignored=( )
+items_missing=( )
+items_modified=( )
+items_not_modified=( )
+items_not_version_controlled=( )
+items_obstructed=( )
+items_replaced=( )
+items_used_by_externals=( )
num_new_dirs=0
opt_changelog=0
opt_noformat=0
@@ -22,10 +34,12 @@ opt_norepoman=0
opt_noupdate=0
opt_quiet=0
opt_verbose=0
+working_copy_base_dir=""
changelog_append() {
- if [[ "$opt_changelog" == "1" ]] ; then
- if [[ "$(svn status)" =~ 'ChangeLog' ]] ; then
+ if [[ $opt_changelog == 1 ]] ; then
+ get_current_svn_status
+ if [[ "${current_svn_status[*]}" =~ 'ChangeLog' ]] ; then
echo "!!! Error: Only one ChangeLog entry should be made per commit, and you have"
echo "!!! already modified your ChangeLog locally since your last commit. To keep the"
echo "!!! pre-existing modifications please run sunrise-commit again without the -c"
@@ -39,8 +53,40 @@ changelog_append() {
fi
}
+check_working_copy_base_dir() {
+ local num_dirs=0
+
+ # Ascend to nearest working copy dir in parent dirs
+ while ! get_current_svn_status ; do
+ if [[ "$(pwd)" == "$(dirs -l +1 2>&1)" ]] ; then
+ echo "!!! Error: No working copy found in parents of current directory."
+ echo "!!! sunrise-commit must be run from within a working copy tree."
+ exit 1
+ fi
+ (( num_dirs++ ))
+ pushd .. >/dev/null
+ done
+
+ # Ascend from there to nearest non-working copy dir in parent dirs
+ while get_current_svn_status ; do
+ if [[ "$(pwd)" == "$(dirs -l +1 2>&1)" ]] ; then
+ break
+ fi
+ (( num_dirs++ ))
+ pushd .. >/dev/null
+ done
+
+ # Working copy base dir is previous dir on stack
+ popd >/dev/null && (( num_dirs-- ))
+ working_copy_base_dir="$(pwd)"
+
+ for (( i=num_dirs ; i > 0 ; i-- )) ; do
+ popd >/dev/null
+ done
+}
+
create_digests() {
- if [[ "$cwd_is_ebuild_dir" == "1" ]] ; then
+ if [[ $cwd_is_ebuild_dir == 1 ]] ; then
ebegin "Digesting ebuilds"
for i in *.ebuild ; do
ebuild $i digest
@@ -49,36 +95,106 @@ create_digests() {
fi
}
+# Sort current changed items into arrays based on symbols in `svn status`
+# output. For now we're only concerned with the symbols in the first column of
+# the output. See `svn help status` for symbol definitions.
+#
+# Returns with exit status 1 if the current dir isn't under version control.
+get_current_svn_status() {
+ local IFS_SAVED="$IFS"
+ local item column_1 #column_2 column_3 column_4 column_5 column_6
+ IFS=$'\n'
+ current_svn_status=( )
+ items_added=( )
+ items_conflicted=( )
+ items_deleted=( )
+ items_ignored=( )
+ items_missing=( )
+ items_modified=( )
+ items_not_modified=( )
+ items_not_version_controlled=( )
+ items_obstructed=( )
+ items_replaced=( )
+ items_used_by_externals=( )
+ for line in $(svn status 2>&1) ; do
+ [[ "$line" =~ 'is not a working copy' ]] && return 1
+ current_svn_status[${#current_svn_status[*]}]=$line
+ column_1=${line:0:1}
+ #column_2=${line:1:1}
+ #column_3=${line:2:1}
+ #column_4=${line:3:1}
+ #column_5=${line:4:1}
+ #column_6=${line:5:1}
+ item=${line:7}
+ case $column_1 in
+ ' ') items_not_modified[${#items_not_modified[*]}]=$item ;;
+ A) items_added[${#items_added[*]}]=$item ;;
+ C) items_conflicted[${#items_conflicted[*]}]=$item ;;
+ D) items_deleted[${#items_deleted[*]}]=$item ;;
+ I) items_ignored[${#items_ignored[*]}]=$item ;;
+ M) items_modified[${#items_modified[*]}]=$item ;;
+ R) items_replaced[${#items_replaced[*]}]=$item ;;
+ X) items_used_by_externals[${#items_used_by_externals[*]}]=$item ;;
+ !) items_missing[${#items_missing[*]}]=$item ;;
+ ?) items_not_version_controlled[${#items_not_version_controlled[*]}]=$item ;;
+ ~) items_obstructed[${#items_obstructed[*]}]=$item ;;
+ esac
+ done
+ IFS="$IFS_SAVED"
+}
+
repoman_check() {
- if [[ "$opt_norepoman" == "0" ]] ; then
- if [[ "$cwd_is_ebuild_dir" == "1" ]] ; then
+ if [[ $opt_norepoman == 0 ]] ; then
+ if [[ $cwd_is_ebuild_dir == 1 ]] ; then
ebegin "Running repoman"
- export PORTDIR_OVERLAY="$(dirname $(dirname $(pwd)))"
+ export PORTDIR_OVERLAY="$working_copy_base_dir"
repoman
eend $?
fi
- return $?
fi
}
svn_add() {
+ local num_unversioned_dirs=0
+
+ while ! get_current_svn_status ; do
+ (( num_unversioned_dirs++ ))
+ pushd .. >/dev/null
+ done
+
ebegin "Adding local changes to working copy"
- if [[ "$opt_verbose" == "1" ]] ; then
- svn add ../$(basename `pwd`) --force
- else
- svn add ../$(basename `pwd`) --force -q
+ if [[ ${#items_not_version_controlled[*]} > 0 ]] ; then
+ if [[ $opt_verbose == 1 ]] ; then
+ svn add "${items_not_version_controlled[@]}" || set $?
+ else
+ svn add -q "${items_not_version_controlled[@]}" || set $?
+ fi
fi
- eend $?
+ eend ${1:-0}
+
+ num_new_dirs=$num_unversioned_dirs
+
+ for (( i=num_unversioned_dirs ; i > 0 ; i-- )) ; do
+ popd >/dev/null
+ done
+
+ return ${1:-0}
}
svn_commit() {
local commit_message="$*"
- if [[ "$opt_noformat" == "0" ]] ; then
- if [[ "$cwd_is_ebuild_dir" == "1" ]] ; then
+ get_current_svn_status
+ if [[ ${#current_svn_status[*]} == 0 ]] ; then
+ echo "!!! Error: No working copy changes found in current directory. Aborting commit."
+ exit 1
+ fi
+
+ if [[ $opt_noformat == 0 ]] ; then
+ if [[ $cwd_is_ebuild_dir == 1 ]] ; then
commit_message="${commit_category}/${commit_package}: ${commit_message}"
else
- commit_message="${commit_package}/$(echo `svn status` | awk '{ print $2 }'): ${commit_message}"
+ commit_message="${commit_package}/${current_svn_status[0]:7}: ${commit_message}"
fi
fi
@@ -89,13 +205,18 @@ svn_commit() {
echo
echo "${DARKGREEN}The following local changes will be committed to the repository:${NORMAL}"
echo
- svn status
+
+ get_current_svn_status
+ for item in "${current_svn_status[@]}" ; do
+ echo "$item"
+ done
+
echo
echo "${DARKGREEN}The following commit message will be used:${NORMAL}"
echo
echo "$commit_message"
- if [[ "$opt_quiet" == "0" ]] ; then
+ if [[ $opt_quiet == 0 ]] ; then
echo
echo -n "${BOLD}Commit changes?${NORMAL} [${GREEN}Yes${NORMAL}/${RED}No${NORMAL}] "
read choice
@@ -118,14 +239,14 @@ svn_commit() {
}
svn_up() {
- if [[ "$opt_noupdate" == "0" ]] ; then
+ if [[ $opt_noupdate == 0 ]] ; then
for (( i=num_new_dirs ; i > 0 ; i-- )) ; do
pushd .. >/dev/null
done
ebegin "Updating working copy to latest version from repository"
- if [[ "$opt_verbose" == "1" ]] ; then
+ if [[ $opt_verbose == 1 ]] ; then
svn update || set $?
else
svn update -q || set $?
@@ -137,15 +258,15 @@ svn_up() {
popd >/dev/null
done
- local conflict_files=$(svn status | sed -rn 's/^C.+ ([^ ]+)$/\1/p')
- if [[ -n "$conflict_files" ]] ; then
- echo "!!! Error: Some local files have changes that conflict with the latest"
- echo "!!! revisions in the repository. Please contact the previous committer(s) to"
- echo "!!! resolve the conflicts manually before running sunrise-commit again:"
- for filename in $conflict_files ; do
+ get_current_svn_status
+ if [[ ${#items_conflicted[*]} > 0 ]] ; then
+ echo "!!! Error: Some local items have changes that conflict with the repository."
+ echo "!!! Please contact the most recent committer(s) of these items and resolve the"
+ echo "!!! conflicts manually before running sunrise-commit again:"
+ for item in "${items_conflicted[@]}" ; do
echo "!!!"
- echo "!!! file: ${filename}"
- echo "!!! committer: $(svn info ${filename} | sed -rn 's/Last Changed Author\: (.*)$/\1/p')"
+ echo "!!! item: ${item}"
+ echo "!!! committer: $(svn info ${item} | sed -rn 's/Last Changed Author\: (.*)$/\1/p')"
done
exit 1
fi
@@ -223,10 +344,11 @@ if [[ -z "$*" ]] ; then
exit 1
fi
+check_working_copy_base_dir
[[ "$(ls)" =~ '\.ebuild' ]] && cwd_is_ebuild_dir=1
pushd . >/dev/null
-while [[ "$(echo `svn status`)" =~ 'A.+? \.' ]] ; do
+while [[ "$(echo `svn status 2>&1`)" =~ 'A.+? \.' ]] ; do
(( num_new_dirs++ ))
cd ..
done
@@ -234,16 +356,10 @@ popd >/dev/null
svn_up || exit $?
-[[ "$cwd_is_ebuild_dir" == "1" && ! -e metadata.xml ]] && cp ../../skel.metadata.xml metadata.xml >/dev/null 2>&1
+[[ $cwd_is_ebuild_dir == 1 && ! -e metadata.xml ]] && cp ../../skel.metadata.xml metadata.xml >/dev/null 2>&1
changelog_append "$*" || exit $?
create_digests || exit $?
svn_add || exit $?
-
-if [[ -z "$(svn status)" ]] ; then
- echo "!!! Error: No changes found in current directory tree. Aborting commit."
- exit 1
-fi
-
repoman_check || exit $?
svn_commit "$*" || exit $?