1 1.1 christos #! /bin/sh 2 1.1 christos 3 1.1 christos # commit version 0.9.2 4 1.1 christos 5 1.1 christos # Copyright (C) 1999, Free Software Foundation 6 1.1 christos 7 1.1 christos # This script is Free Software, and it can be copied, distributed and 8 1.1 christos # modified as defined in the GNU General Public License. A copy of 9 1.1 christos # its license can be downloaded from http://www.gnu.org/copyleft/gpl.html 10 1.1 christos 11 1.1 christos # Originally by Gary V. Vaughan <gvaughan (at] oranda.demon.co.uk> 12 1.1 christos # Heavily modified by Alexandre Oliva <oliva (at] dcc.unicamp.br> 13 1.1 christos 14 1.1 christos # This scripts eases checking in changes to CVS-maintained projects 15 1.1 christos # with ChangeLog files. It will check that there have been no 16 1.1 christos # conflicting commits in the CVS repository and print which files it 17 1.1 christos # is going to commit to stderr. A list of files to compare and to 18 1.1 christos # check in can be given in the command line. If it is not given, all 19 1.1 christos # files in the current directory (and below, unless `-l' is given) are 20 1.1 christos # considered for check in. 21 1.1 christos 22 1.1 christos # The commit message will be extracted from the differences between 23 1.1 christos # the local ChangeLog and the one in the repository (unless a message 24 1.1 christos # was specified with `-m' or `-F'). An empty message is not accepted 25 1.1 christos # (but a blank line is). If the message is acceptable, it will be 26 1.1 christos # presented for verification (and possible edition) using the $PAGER 27 1.1 christos # environment variable (or `more', if it is not set, or `cat', if the 28 1.1 christos # `-f' switch is given). If $PAGER exits successfully, the modified 29 1.1 christos # files (at that moment) are checked in, unless `-n' was specified, in 30 1.1 christos # which case nothing is checked in. 31 1.1 christos 32 1.1 christos # usage: commit [-v] [-h] [-f] [-l] [-n] [-q] [-z N] 33 1.1 christos # [-m msg|-F msg_file] [--] [file|dir ...] 34 1.1 christos 35 1.1 christos # -f --fast don't check (unless *followed* by -n), and just 36 1.1 christos # --force display commit message instead of running $PAGER 37 1.1 christos # -l --local don't descend into subdirectories 38 1.1 christos # -m msg --message=msg set commit message 39 1.1 christos # --msg=msg same as -m 40 1.1 christos # -F file --file=file read commit message from file 41 1.1 christos # -n --dry-run don't commit anything 42 1.1 christos # -q --quiet run cvs in quiet mode 43 1.1 christos # -zN --compress=N set compression level (0-9, 0=none, 9=max) 44 1.1 christos # -v --version print version information 45 1.1 christos # -h,-? --help print short or long help message 46 1.1 christos 47 1.1 christos name=commit 48 1.1 christos cvsopt= 49 1.1 christos updateopt= 50 1.1 christos commitopt= 51 1.1 christos dry_run=false 52 1.1 christos commit=: 53 1.1 christos update=: 54 1.1 christos log_file="${TMPDIR-/tmp}/commitlog.$$" 55 1.1 christos 56 1.1 christos rm -f "$log_file" 57 1.1 christos trap 'rm -f "$log_file"; exit 1' 1 2 15 58 1.1 christos 59 1.1 christos # this just eases exit handling 60 1.1 christos main_repeat=":" 61 1.1 christos while $main_repeat; do 62 1.1 christos 63 1.1 christos repeat="test $# -gt 0" 64 1.1 christos while $repeat; do 65 1.1 christos case "$1" in 66 1.1 christos -f|--force|--fast) 67 1.1 christos update=false 68 1.1 christos PAGER=cat 69 1.1 christos shift 70 1.1 christos ;; 71 1.1 christos -l|--local) 72 1.1 christos updateopt="$updateopt -l" 73 1.1 christos commitopt="$commitopt -l" 74 1.1 christos shift 75 1.1 christos ;; 76 1.1 christos -m|--message|--msg) 77 1.1 christos if test $# = 1; then 78 1.1 christos echo "$name: missing argument for $1" >&2 79 1.1 christos break 80 1.1 christos fi 81 1.1 christos if test -f "$log_file"; then 82 1.1 christos echo "$name: you can have at most one of -m and -F" >&2 83 1.1 christos break 84 1.1 christos fi 85 1.1 christos shift 86 1.1 christos echo "$1" > "$log_file" 87 1.1 christos shift 88 1.1 christos ;; 89 1.1 christos -F|--file) 90 1.1 christos if test -f "$log_file"; then 91 1.1 christos echo "$name: you can have at most one of -m and -F" >&2 92 1.1 christos break 93 1.1 christos fi 94 1.1 christos if test $# = 1; then 95 1.1 christos echo "$name: missing argument for $1" >&2 96 1.1 christos break 97 1.1 christos fi 98 1.1 christos shift 99 1.1 christos if cat < "$1" > "$log_file"; then :; else 100 1.1 christos break 101 1.1 christos fi 102 1.1 christos shift 103 1.1 christos ;; 104 1.1 christos -n|--dry-run) 105 1.1 christos commit=false 106 1.1 christos update=true 107 1.1 christos shift 108 1.1 christos ;; 109 1.1 christos -q|--quiet) 110 1.1 christos cvsopt="$cvsopt -q" 111 1.1 christos shift 112 1.1 christos ;; 113 1.1 christos -z|--compress) 114 1.1 christos if test $# = 1; then 115 1.1 christos echo "$name: missing argument for $1" >&2 116 1.1 christos break 117 1.1 christos fi 118 1.1 christos case "$2" in 119 1.1 christos [0-9]) :;; 120 1.1 christos *) echo "$name: invalid argument for $1" >&2 121 1.1 christos break 122 1.1 christos ;; 123 1.1 christos esac 124 1.1 christos cvsopt="$cvsopt -z$2" 125 1.1 christos shift 126 1.1 christos shift 127 1.1 christos ;; 128 1.1 christos 129 1.1 christos -m*|-F*|-z*) 130 1.1 christos opt=`echo "$1" | sed '1s/^\(..\).*$/\1/;q'` 131 1.1 christos arg=`echo "$1" | sed '1s/^-[a-zA-Z0-9]//'` 132 1.1 christos shift 133 1.1 christos set -- "$opt" "$arg" ${1+"$@"} 134 1.1 christos ;; 135 1.1 christos --message=*|--msg=*|--file=*|--compress=*) 136 1.1 christos opt=`echo "$1" | sed '1s/^\(--[^=]*\)=.*/\1/;q'` 137 1.1 christos arg=`echo "$1" | sed '1s/^--[^=]*=//'` 138 1.1 christos shift 139 1.1 christos set -- "$opt" "$arg" ${1+"$@"} 140 1.1 christos ;; 141 1.1 christos 142 1.1 christos -v|--version) 143 1.1 christos sed '/^# '$name' version /,/^# Heavily modified by/ { s/^# //; p; }; d' < $0 144 1.1 christos exit 0 145 1.1 christos ;; 146 1.1 christos -\?|-h) 147 1.1 christos sed '/^# usage:/,/# -h/ { s/^# //; p; }; d' < $0 && 148 1.1 christos echo 149 1.1 christos echo "run \`$name --help | more' for full usage" 150 1.1 christos exit 0 151 1.1 christos ;; 152 1.1 christos --help) 153 1.1 christos sed '/^# '$name' version /,/^[^#]/ { /^[^#]/ d; s/^# //; p; }; d' < $0 154 1.1 christos exit 0 155 1.1 christos ;; 156 1.1 christos --) 157 1.1 christos shift 158 1.1 christos repeat=false 159 1.1 christos ;; 160 1.1 christos -*) 161 1.1 christos echo "$name: invalid flag $1" >&2 162 1.1 christos break 163 1.1 christos ;; 164 1.1 christos *) 165 1.1 christos repeat=false 166 1.1 christos ;; 167 1.1 christos esac 168 1.1 christos done 169 1.1 christos # might have used break 2 within the previous loop, but so what 170 1.1 christos $repeat && break 171 1.1 christos 172 1.1 christos $update && \ 173 1.1 christos if echo "$name: checking for conflicts..." >&2 174 1.1 christos (cvs $cvsopt -q -n update $updateopt ${1+"$@"} 2>/dev/null \ 175 1.1 christos | while read line; do 176 1.1 christos echo "$line" 177 1.1 christos echo "$line" >&3 178 1.1 christos done | grep '^C') 3>&1 >/dev/null; then 179 1.1 christos echo "$name: some conflicts were found, aborting..." >&2 180 1.1 christos break 181 1.1 christos fi 182 1.1 christos 183 1.1 christos if test ! -f "$log_file"; then 184 1.1 christos echo "$name: checking commit message..." >&2 185 1.1 christos cvs $cvsopt diff -u ChangeLog \ 186 1.1 christos | while read line; do 187 1.1 christos case "$line" in 188 1.1 christos "--- ChangeLog"*) :;; 189 1.1 christos "-"*) 190 1.1 christos echo "$name: *** Warning: the following line in ChangeLog diff is suspicious:" >&2 191 1.1 christos echo "$line" | sed 's/^.//' >&2;; 192 1.1 christos "+ "*) 193 1.1 christos echo "$name: *** Warning: lines should start with tabs, not spaces; ignoring line:" >&2 194 1.1 christos echo "$line" | sed 's/^.//' >&2;; 195 1.1 christos "+") echo;; 196 1.1 christos "+ "*) echo "$line";; 197 1.1 christos esac 198 1.1 christos done \ 199 1.1 christos | sed -e 's,\+ ,,' -e '/./p' -e '/./d' -e '1d' -e '$d' > "$log_file" \ 200 1.1 christos || break 201 1.1 christos # The sed script above removes "+TAB" from the beginning of a line, then 202 1.1 christos # deletes the first and/or the last line, when they happen to be empty 203 1.1 christos fi 204 1.1 christos 205 1.1 christos if grep '[^ ]' < "$log_file" > /dev/null; then :; else 206 1.1 christos echo "$name: empty commit message, aborting" >&2 207 1.1 christos break 208 1.1 christos fi 209 1.1 christos 210 1.1 christos if grep '^$' < "$log_file" > /dev/null; then 211 1.1 christos echo "$name: *** Warning: blank lines should not appear within a commit messages." >&2 212 1.1 christos echo "$name: *** They should be used to separate distinct commits." >&2 213 1.1 christos fi 214 1.1 christos 215 1.1 christos ${PAGER-more} "$log_file" || break 216 1.1 christos 217 1.1 christos sleep 1 # give the user some time for a ^C 218 1.1 christos 219 1.1 christos # Do not check for empty $log_file again, even though the user might have 220 1.1 christos # zeroed it out. If s/he did, it was probably intentional. 221 1.1 christos 222 1.1 christos if $commit; then 223 1.1 christos cvs $cvsopt commit $commitopt -F $log_file ${1+"$@"} || break 224 1.1 christos fi 225 1.1 christos 226 1.1 christos main_repeat=false 227 1.1 christos done 228 1.1 christos 229 1.1 christos rm -f "$log_file" 230 1.1 christos 231 1.1 christos # if main_repeat was not set to `false', we failed 232 1.1 christos $main_repeat && exit 1 233 1.1 christos exit 0 234