Skip to content

Instantly share code, notes, and snippets.

@hypersoft
Last active December 19, 2015 13:19
Show Gist options
  • Save hypersoft/5961125 to your computer and use it in GitHub Desktop.
Save hypersoft/5961125 to your computer and use it in GitHub Desktop.
Build No. Automated build number tracking utility
#!/bin/bash
declare -i MAJOR="0"
declare -i MINOR="0"
declare -i MINORMAX="99"
declare -i REVISION="0"
declare -i REVISIONMAX="9999"
buildnum ()
{
: "A self replicating build number database script";
: "Written by Triston J. Taylor (C) 2013 All Rights Reserved";
function noBiDiRequest () {
((generate)) || {
echo "$0: error: bi-directional request: set for information in progress; prognostic: terminate";
exit 1;
} 1>&2
};
function acceptFinalOption ()
{
noBiDiRequest;
(($# > 1)) && {
echo "$0: invocation error: option $1 must be the final argument";
exit 1
} 1>&2
};
function acceptFinalArgument ()
{
(($# > 2)) && {
echo "$0: invocation error: option $1 argument '$2' must be the final argument";
exit 1
} 1>&2
};
function catdb ()
{
printf "%s\n\n%s\n\n%s\n\n%s;\n\n" '#!/bin/bash' "`declare -p MAJOR MINOR MINORMAX REVISION REVISIONMAX`" "`declare -f buildnum`" 'buildnum "$@"'
};
local -i update=1 generate=1 report=1;
local target="$0";
while [[ "${1:0:1}" = - ]]; do
[[ $1 == '-g' ]] && {
acceptFinalOption "$@";
printf "%i.%i.%i\\n" $MAJOR $MINOR $REVISION;
return 0
};
: "Pass option -G to get the verbose current build info";
[[ $1 == '-G' ]] && {
acceptFinalOption "$@";
printf "Build No. %i.%i.%i\\n" $MAJOR $MINOR $REVISION;
return 0
};
: "Pass option -m to manually increment minor";
[[ $1 == '-m' ]] && {
let REVISION=$((REVISIONMAX + 1));
shift;
continue
};
: "Pass option -M to manually increment major";
[[ $1 == '-M' ]] && {
let MINOR=$((MINORMAX + 1));
shift;
continue
};
: "Pass option -p to preview the next build number";
[[ $1 == '-p' ]] && {
let update=0 generate=1;
shift;
continue
};
: "Pass option -P to preview the verbose next build number";
[[ $1 == '-P' ]] && {
printf "Build No. ";
let update=0 generate=1;
shift;
continue
};
: "Pass option -q to mute generate -> report";
: "This option adversely affects -p and -P";
[[ $1 == '-q' ]] && {
let report=0;
shift;
continue
};
: "Pass option -smm INTEGER to set the MINORMAX";
[[ $1 == '-smm' ]] && {
let MINORMAX=$2 generate=0;
shift 2;
continue
};
: "Pass option -gmm to get the MINORMAX";
[[ $1 == '-gmm' ]] && {
acceptFinalOption "$@";
echo MINORMAX=$MINORMAX;
return 0
};
: "Pass option -srm INTEGER to set the REVISIONMAX";
[[ $1 == '-srm' ]] && {
let REVISIONMAX=$2 generate=0;
shift 2;
continue
};
: "Pass option -grm to get the REVISIONMAX";
[[ $1 == '-grm' ]] && {
acceptFinalOption "$@";
echo REVISIONMAX=$REVISIONMAX;
return 0
};
: "Pass option -c to clear the build number database";
: "Pass option -c FILE to create a new build number database";
[[ $1 == '-c' ]] && {
acceptFinalArgument "$@";
declare -i MAJOR="0" MINOR="0" REVISION="0";
target="${2:-$target}";
catdb > "$target";
chmod +x "$target";
return 0
};
printf "$0: invocation error: unrecognized option: %s\n" "$1" 1>&2;
exit 1;
done;
((generate)) && {
let REVISION++;
(( REVISION > REVISIONMAX )) && {
let MINOR++ REVISION=0
};
(( MINOR > MINORMAX )) && {
let MAJOR++ MINOR=0 REVISION=0
};
((report)) && printf "%i.%i.%i\\n" $MAJOR $MINOR $REVISION
};
((update)) && catdb > "$target"
}
buildnum "$@";
@hypersoft
Copy link
Author

Revision 7 Adds facilities to create new buildnum database scripts, clear internal database, generate basic verbose reports, and set build number component maximums

@livibetter
Copy link

Any reason you prefer using ifs over case? (wondering if you are also coding in Python)

Also, those semicolon kind of annoying for me to see.

By the way, you are the first one I have ever seen using : builtin for comments.

@hypersoft
Copy link
Author

if is a universal statement. case is just an implementation of ifs. At the risk of sounding cliche, "There is nothing like the real thing baby"... As a matter of coding taste, I simply prefer to defer from abstract methodology wherever possible. The code is complicated enough... I see no immediate need to over complicate things in the interest of being lazy.

I'm a C coder. Semicolons are a part of everyday life for me. I get annoyed when they are missing.

Since the code is self replicating, comments are destroyed when the database is regenerated. true is just one of many commands that afford us some commentary.

@hypersoft
Copy link
Author

R8 introduces several new features by adding an internal generate flag. For example now we can do something like this:

./buildnum -c foo;
./foo
./foo -srm 0 -P

Which does not actually set REVISIONMAX on the database, because the -P option turns the update flag off and activates the generate flag (which the -s*m options) explicitly deactivate. The result is a preview of the next build number given the specified REVISIONMAX.

-srm and -smm can be used to set the REVISIONMAX, and MINORMAX respectively on the current database and new ones as well, created with -c option:

./buildnum -smm 99 -srm 999 -c foo

The -c option is a weird one (aren't they all...) When supplied, it must always be the last argument, because the input from other arguments affect its operation, as well as the fact that it terminates script execution.

External utilities can access the REVISIONMAX and MINORMAX components by supplying -grm and -gmm respectively.

@hypersoft
Copy link
Author

R9 adds error checking for options and arguments which must be supplied as the last invocation parameters.

@hypersoft
Copy link
Author

R10 adds bi-directional request exception handling and the ability to mute a generated report.

@hypersoft
Copy link
Author

R11 permits bi-di create exception

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment