dotfiles

Cem's Dotfiles
git clone git://git.ckyln.com/dotfiles.git
Log | Files | Refs | Submodules | README | LICENSE

bug (6740B)


      1 #!/usr/bin/env bash
      2 # (encoding: UTF-8)
      3 #
      4 # bug 1.1 - Simple Bug / ToDo tracker for the command line.
      5 #  (Instructions below the license)
      6 # LICENSE
      7 # Copyright (C) 2006 LluĂ­s Batlle i Rossell
      8 # 
      9 # This program is free software; you can redistribute it and/or
     10 # modify it under the terms of the GNU General Public License
     11 # as published by the Free Software Foundation; either version 2
     12 # of the License, or (at your option) any later version.
     13 # 
     14 # This program is distributed in the hope that it will be useful,
     15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 # GNU General Public License for more details.
     18 # 
     19 # You should have received a copy of the GNU General Public License
     20 # along with this program; if not, write to the Free Software
     21 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
     22 #
     23 # Instructions:
     24 #  1. Your $BUG_PROJECT should point to a file. It will be the database you'll
     25 #     be using. Use an absolute path. It may be, for instance, "~/todo.bug"
     26 #
     27 #  Having the $BUG_PROJECT set:
     28 #  1. Create the database:
     29 #      bug create
     30 #  2. Add an issue
     31 #      bug add
     32 #     Use integers for the priorities. Higher -> more priority.
     33 #     Use any words you prefer for the state
     34 #     Don't break the number of lines until "-- Description --". Write
     35 #     multilines only below that label.
     36 #  3. List the issues (all but description, priority sorted)
     37 #      bug list [ | grep as_you_wish ]
     38 #  4. View an issue
     39 #      bug view <ID>
     40 #  5. Edit an issue
     41 #      bug edit <ID>
     42 #     Change the state, the priority, add data as long as you fix it, ...
     43 #     When I consider an issue is fulfilled, I negate its priority.
     44 #  6. Delete an issue
     45 #      bug delete <ID>
     46 #     Do that whenever you will not need the issue anymore.
     47 #
     48 #
     49 # Contributions:
     50 # --------------
     51 #
     52 # pancake <pancake@youterm.com>
     53 #   - drop bashisms
     54 #   - implement -h flag
     55 #   - error messages to stderr
     56 #   - more checks and help on BUG_PROJECT environ
     57 #
     58 # TODO:
     59 #   Support for an array of bug report files ?? readonly
     60 #   Check BUG_PROJECT file format before processing
     61 #
     62 
     63 PNAME=`basename "$0"`
     64 CMD="$1"
     65 
     66 if [ -z "$EDITOR" ]; then
     67 	EDITOR=vim
     68 fi
     69 
     70 function usage
     71 {
     72 	echo "Usage: $PNAME [add | list | view | edit | delete | create | project | version]"
     73 }
     74 
     75 function create
     76 {
     77 	if [ ! -f "$BUG_PROJECT" ]; then
     78 		echo 0 > "$BUG_PROJECT"
     79 		return 0
     80 	else
     81 		echo "The project exists. Please remove the file before create." 2>&1
     82 		return 1
     83 	fi
     84 }
     85 
     86 function getnext
     87 {
     88 	head -n 1 "$BUG_PROJECT"
     89 }
     90 
     91 function updatenext
     92 {
     93 	NEXT=$1
     94 	ed $BUG_PROJECT >&/dev/null << END
     95 1
     96 c
     97 $NEXT
     98 .
     99 w
    100 q
    101 END
    102 
    103 }
    104 
    105 function trim
    106 {
    107 	sed 's/^ *//g; s/ *$//g'
    108 }
    109 function trimlastdbNL
    110 {
    111 	sed 's/\\n$//g'
    112 }
    113 
    114 function noNL
    115 {
    116 	tr -d "\\n"
    117 }
    118 
    119 function string2db
    120 {
    121 	noNL | trim | sed 's/\t/\\t/g'
    122 }
    123 
    124 function text2db
    125 {
    126 	sed 's/\t/\\t/g ; s/$/\\/g' | tr "\\n" n
    127 }
    128 
    129 function db2text
    130 {
    131 	sed 's/\\t/\t/g ; s/\\n/\n/g'
    132 }
    133 
    134 function addfile
    135 {	
    136 	ID=`grep "^Id:" $1 | head -n 1 | cut -d : -f 2- | string2db`
    137 	SUBJECT=`grep "^Subject:" $1 | head -n 1 | cut -d : -f 2- | string2db`
    138 	STATE=`grep "^State:" $1 | head -n 1 | cut -d : -f 2- | string2db`
    139 	PRIORITY=`grep "^Priority:" $1 | head -n 1 | cut -d : -f 2- | string2db`
    140 
    141 	if [ -z "$PRIORITY" ]; then
    142 		echo "Error in ticket: subject or priority." > /dev/stderr
    143 		return 1
    144 	fi
    145 
    146 	if [ -z "$SUBJECT" ]; then
    147 		echo "Error in ticket: subject or priority." > /dev/stderr
    148 		return 1
    149 	fi
    150 
    151 	LINES=`cat $1 | wc -l`
    152 
    153 	# Substract Id, Subject, State and Priority
    154 	#TOTAIL=$(( LINES - 5 ))
    155 	let TOTAIL=LINES-5
    156 	DESCRIPTION=`tail -n $TOTAIL $1 | text2db | trimlastdbNL`
    157 
    158 	echo "$ID	$PRIORITY	$STATE	$SUBJECT	$DESCRIPTION" >> $BUG_PROJECT
    159 
    160 	# Update the next ID number
    161 	NEXT=`getnext`
    162 	if [ $NEXT -gt $ID ]; then
    163 		updatenext $((NEXT + 1))
    164 	else
    165 		updatenext $((ID + 1))
    166 	fi
    167 		
    168 	return 0
    169 }
    170 
    171 function list
    172 {
    173 	echo "Id	Prior.	State	Subject"
    174 	catlist | cut -f 1,2,3,4 | sort -n -r -k 2
    175 }
    176 
    177 function view
    178 {
    179 	ID=$1
    180 
    181 	LINE=`catlist | grep "^$ID	"`
    182 
    183 	if [ -n "$LINE" ]; then
    184 		PRIORITY=`echo "$LINE" | cut -f 2`
    185 		STATE=`echo "$LINE" | cut -f 3`
    186 		SUBJECT=`echo "$LINE" | cut -f 4`
    187 		DESCRIPTION=`echo "$LINE" | cut -f 5`
    188 
    189 		echo "Id: $ID" | db2text
    190 		echo "Priority: $PRIORITY" | db2text
    191 		echo "State: $STATE" | db2text
    192 		echo "Subject: $SUBJECT" | db2text
    193 		echo "-- Description below --"
    194 		echo "$DESCRIPTION" | db2text
    195 		return 0
    196 	else
    197 		echo "Id not found." 2>&1
    198 		return 1
    199 	fi
    200 }
    201 
    202 function catlist
    203 {
    204 	LINES=`cat $BUG_PROJECT | wc -l`
    205 	let TOTAIL=LINES-1
    206 	#TOTAIL=$(( LINES - 1 ))
    207 	tail -n $TOTAIL $BUG_PROJECT | grep -v "^#"
    208 }
    209 
    210 function version
    211 {
    212 	echo "bug 1.1 - Simple Bug / ToDo tracker for the command line."
    213 	echo "Copyright (C) 2006 Lluis Batlle i Rossell"
    214 }
    215 
    216 function searchline
    217 {	
    218 	ID=$1
    219 
    220 	LINE=`cat $BUG_PROJECT | grep -n "^$ID	" | cut -d : -f 1`
    221 	if [ -n "$LINE" ]; then
    222 		echo $LINE
    223 		return 0
    224 	else
    225 		return 1
    226 	fi
    227 }
    228 
    229 function delete
    230 {
    231 	ID=$1
    232 	LINE=`searchline $ID`
    233 	if [ $? -eq 0 ]; then
    234 		ed $BUG_PROJECT >&/dev/null << END
    235 $LINE
    236 d
    237 w
    238 q
    239 END
    240 	else
    241 		echo "Id not found." 2>&1
    242 	fi
    243 }
    244 
    245 function edit
    246 {
    247 	ID=$1
    248 
    249 	# Get a random file
    250 	FILE="/tmp/$RANDOM.txt"
    251 	while [ -f "$FILE" ]; do
    252 		FILE="/tmp/$RANDOM.txt"
    253 	done
    254 
    255 	view $ID > $FILE
    256 
    257 	if [ $? -eq 0 ]; then
    258 		MD5=`md5sum "$FILE"`
    259 
    260 		"$EDITOR" "$FILE"
    261 
    262 		MD5_bis=`md5sum "$FILE"`
    263 
    264 		if [ "$MD5" != "$MD5_bis" ]; then
    265 			delete $ID
    266 			addfile "$FILE" && rm "$FILE"
    267 		else
    268 			echo "File not changed. Not changing the ticket."
    269 			rm "$FILE"
    270 		fi
    271 	else
    272 		echo "Id not found."
    273 		rm "$FILE"
    274 	fi
    275 }
    276 
    277 function add
    278 {	
    279 	# Get a random file
    280 	FILE="/tmp/$RANDOM.txt"
    281 	while [ -f "$FILE" ]; do
    282 		FILE="/tmp/$RANDOM.txt"
    283 	done
    284 	
    285 	ID=`getnext`
    286 
    287 	cat > "$FILE" << TEMPLATE
    288 Id: $ID
    289 Priority:
    290 State:
    291 Subject: 
    292 -- Description below --
    293 TEMPLATE
    294 	MD5=`md5sum "$FILE"`
    295 
    296 	"$EDITOR" "$FILE"
    297 
    298 	MD5_bis=`md5sum "$FILE"`
    299 	
    300 	if [ "$MD5" != "$MD5_bis" ]; then
    301 		addfile "$FILE" && rm "$FILE"
    302 	else
    303 		echo "File not changed. Not adding a ticket."
    304 		rm "$FILE"
    305 	fi
    306 
    307 }
    308 
    309 if [ -z "$BUG_PROJECT" ]; then
    310 	echo "\$BUG_PROJECT is not set."
    311 	exit 1
    312 fi
    313 
    314 if [ ! "`echo $BUG_PROJECT | cut -c 1`" = "/" ]; then
    315 	echo "Do not use relative paths in BUG_PROJECT environ."
    316 	exit 1
    317 fi
    318 
    319 if [ ! "$CMD" = "create" ]; then
    320 if [ ! -f "$BUG_PROJECT" ]; then
    321 	echo "BUG_PROJECT file does not exist. Type 'bug create'"
    322 	exit 0
    323 fi
    324 fi
    325 
    326 if [ -z "$CMD" ]; then
    327 	usage
    328 	exit 1
    329 fi
    330 
    331 case "$CMD" in
    332 	-h)
    333 		echo "Usage: bug [[alvpe] [del] [create]] [args]"
    334 		exit 1
    335 		;;
    336 	a*)
    337 		add || exit 1
    338 		;;
    339 	l*)
    340 		list || exit 1
    341 		;;
    342 	ver*)
    343 		version || exit 1
    344 		;;
    345 	v*)
    346 		view $2 || exit 1
    347 		;;
    348 	p*)
    349 		echo Project: $BUG_PROJECT
    350 		;;
    351 	del*)
    352 		delete $2 || exit 1
    353 		;;
    354 	create)
    355 		create || exit 1
    356 		;;
    357 	e*)
    358 		edit $2 || exit 1
    359 		;;
    360 	*)
    361 		usage
    362 		exit 1
    363 		;;
    364 esac
    365 exit 0
    366 
    367 # vim:ts=8:sw=8:noet