HiveBrain v1.2.0
Get Started
← Back to all entries
patternbashMinor

Bash script to run development tasks for configured projects

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
scriptprojectstasksdevelopmentforconfiguredbashrun

Problem

I wrote this script template at work to save typing repetitive commands and to improve my Bash-fu. I'd like to know of any moderate-to-severe quoting, robustness, security or usability issue. All code provided in answers should work in Bash 4.

.sedevrc:

```
#!/bin/bash
se_projects=()
se_cvs_dir="${USER}@172.0.0.1/export/home/cvsrootdir"
#============PROJECT CONFIG START================#
declare -A product
product[CVSROOT]="${se_cvs_dir}/product"
product[SOURCEDIR]="${HOME}/product"
product[WORKDIR]="${HOME}/test"
product[MAINPRG]="${product[SOURCEDIR]}/build/product"
se_projects+=("${!product@}")
#================================================#
# Other products in the same format as above
#=============PROJECT CONFIG END=================#

# se user commands
function secvs
{
se_loop_projects "_se_cvs" "$@"
}

function sectags
{
se_loop_projects "_se_ctags" "$@"
}

function semake
{
se_loop_projects "_se_make" "$@"
}

function sealias
{
se_loop_projects "_se_alias" "$@"
}

# se helper functions
function _se_cvs
{
echo_info "Updating ${project}..."
local cvsroot=${project}[CVSROOT]
CVSROOT=:pserver:${!cvsroot:?}
local sourcedir=${project}[SOURCEDIR]
cd ${!sourcedir:?}
cvs -q update -Pd && echo_noerror "Update ${project} complete" || echo_error "Update ${project} failed"
}

function _se_ctags
{
echo_info "Tagging ${project}..."
local sourcedir=${project}[SOURCEDIR]
cd ${!sourcedir:?}/src
{ file tags | grep 'Ctags tag' >/dev/null; } || rm -f tags
ctags -R --exclude=obj && echo_noerror "Tag ${project} complete" || echo_error "Tag ${project} failed"
}

function _se_make
{
echo_info "Building ${project}..."
local sourcedir=${project}[SOURCEDIR]
cd ${!sourcedir:?}
if [[ -d build ]] && (( $(bc 60 60 24 * 5 ))
then
make clean || echo_error "Clean ${project} failed"
fi
make && echo_noerror "Build ${project} complete" || echo_error "Build ${project} failed"
}

function _se_a

Solution

I see some things that may help you improve your code.

Use the correct form for associative arrays

The code contains this line:

local cvsroot=${project}[CVSROOT]


But I am pretty sure that what was meant was this:

local cvsroot=${project[CVSROOT]}


Quote to prevent word splitting

This line needs quotes to prevent word splitting:

cd ${!sourcedir:?}


If the contents of sourcedir contains a path with an embedded space, the cd will fail. Add quotes to prevent this problem:

cd "${!sourcedir:?}"


The same issue exists for the last clause of the complete function.

Use || exit if a command fails

If the cd command mentioned above actually fails, the script will proceed anyway and this is unlikely to be desired. Instead, you could use this:

cd "${!sourcedir:?}" || exit 1


Use if-else if you need that functionality

One of the lines in the current code is this:

ctags -R --exclude=obj && echo_noerror "Tag ${project} complete" || echo_error "Tag ${project} failed"


The intent appears to be to print one string or the other depending on the outcome of the ctags program. However, be aware that the second message might be printed even if ctags runs without error. This is because echo_noerror might fail and then the echo_error function would be invoked. To make the code more robust, don't use this trick. Instead, use the plain old if-else construct:

if ctags -R --exclude=obj; then echo_noerror "Tag ${project} complete"; else echo_error "Tag ${project} failed"; fi


Or as I'd probably prefer formatting it:

if ctags -R --exclude=obj 
then 
    echo_noerror "Tag ${project} complete" 
else 
    echo_error "Tag ${project} failed"
fi


Understand the use of numeric variables

In this context:

for (( i=0; i<${project_count}; i++ ))


The ${} is not needed because it's a numeric variable. Instead, just write this:

for (( i=0; i<project_count; i++ ))


Don't mix string and array

In this line

echo "${echo_noerror_color}$@${echo_reset_color}"


The colors expand to strings, but the $@ is an array. To make it a string, use this instead:

echo "${echo_noerror_color}$*${echo_reset_color}"


There's more, but it's all I have time for at the moment.

Code Snippets

local cvsroot=${project}[CVSROOT]
local cvsroot=${project[CVSROOT]}
cd ${!sourcedir:?}
cd "${!sourcedir:?}"
cd "${!sourcedir:?}" || exit 1

Context

StackExchange Code Review Q#150292, answer score: 2

Revisions (0)

No revisions yet.