The woof-CE team has noticed how Jamesbond's repo database parser is faster than the puppy package manager at parsing this database. Aside from speed, another advantage that AWK has the advantage over a language like Perl and Python is that it is more stable and more frequently available in a system.
I'm exploring the idea of doing version comparison in AWK so that we can filter the database to includes results that are only within a given version range. Note that there is a difference between lib version as per the so-name of the primary lib within a package (e.g. libc6) which has a lib version of 6 vs the package version (e.g. glibc-2.24) (See post).
We could build tools to construct a database which equates the lib version with the package version either by downloading packages and using ldd or in some cases (e.g. Debian Repos) extracting the lib version from the package name.
Anyway, in my version comparison tool, that I'm working on we strip the lib version which searching for repo records.
Bash Code:
Code: Select all
stripped="$(echo $pkg_name | sed -e 's/[0-9]*$//g')"
Code: Select all
match(\$2,/^(.*[^[:digit:]])([[:digit:]]*$|$)/,pkg_split)
if ( pkg_split[1] == \"$stripped\" $CMP_Function ) {
print
Methodology
My mythology here is to build my AWK code in a Bash function called, "mk_AWK_prg()"
Version comparisons are based from the input to this function and used to create an array that will be used in the AWK function
Code: Select all
declare -a options="$(getopt -o f:l:m:np:su:v: --long full-version:,lib-version,min-version,--no-strip:,package:,stripped,version:,gt:,ge:,lt:,le: -- $@)"
eval set --"$options"
while [ $# -gt 0 ]; do
case "$1" in
...
-m|--min-version|--ge)
n_cmp=$((n_cmp+1))
awk_cmp_ary_op="$awk_cmp_ary_op$'\n'awk_cmp_ary_op[$n_cmp]=\"ge\""
awk_cmp_ary_val="$awk_cmp_ary_val$'\n'awk_cmp_ary_val[$n_cmp]=\"$2\""
shift 2 ;;
Code: Select all
AWK_Functions="\
function version_split(version1,version_array,split_chars i1,remainder1,matches){
match(num1,/[[:digit:]]*:(.*|$)/,num1_epoch_split)
if (length(num1_epoch_split) > 0 ){
version_array[1]=num1_epoch_split[1]
remainder1=num1_epoch_split[2]
} else {
version_array[1]=0
remainder1=version1
}
split_chars[1]=\":\"
i1=2
match(remainder1,/^([^+-~:])(([+.~])([^+.~-:]+))*(([-])([^+.~-:])+)?$/,matches)
version_array[i1]=matches[i2]
for (i2 = 4; i<length(matches); i2=i2+3){
i1=i1+1
version_array[i1]=matches[i2]
split_chars[i1-1]=matches[i2-1]
}
}
...
Note that the epoch is split first because we want to successively match up the other delimiters.
We test each element in the array of version comparisons against the repo record. If any test fails we return '0' Otherwise we return '1'.
AWK Code (part of the bash string "AWK_Functions")
Code: Select all
arry_cmp(version,ops_array,val_array){
for (i=1; i<=length(ops_array)){
#https://www.gnu.org/software/gawk/manual/gawk.html#Switch-Statement
switch(ops_array){
case \"<\":
case \"lt\":
if (v_lt(version,val_array[i]) == 0 ){
return 0
}
break
Code: Select all
CMP_Function="&& arry_cmp(\$3,awk_cmp_ary_op,awk_cmp_ary_val)"$'\n'
else
AWK_Functions=''
CMP_Function=''
fi
#https://www.gnu.org/software/gawk/manual/html_node/String-Functions.html
if [ $stripped_match -eq 1 ]
AWK_PRG=$AWK_Functions \
" BEGIN{FS=\"|\"
$awk_cmp_ary_op
$awk_cmp_ary_val
}
{
if( \$2 == \"$pkg_name\" $CMP_Function ) {
print
}
else
match(\$2,/^(.*[^[:digit:]])([[:digit:]]*$|$)/,pkg_split)
if ( pkg_split[1] == \"$stripped\" $CMP_Function ) {
print
}
}"
Further Work
1. Aside from the epoch, I'm not making much of a distinction based on the type of version separator. This will require further research. However, in most cases the version separator that we will be primary interested is the period (i.e. '.'), Therefore the code should be useful prior to me doing this investigation.
2. .... (more to follow)
Link to preliminary code: https://pastebin.com/wXQ6uLwY