# 
# valid-package-name.sh - test a package name for validity
################################################################
# Copyright (C) 2001, 2002 Tom Lord
# 
# See the file "COPYING" for further information about
# the copyright and warranty status of this work.
# 

set -e 

################################################################
# special options
# 
# Some options are special:
# 
#       --version | -V
#       --help | -h
# 
if test $# -ne 0 ; then

  for opt in "$@" ; do
    case $opt in

      --version|-V) exec larch --version
                    ;;


      --help|-h)
                printf "test a package name for validity\\n"
                printf "usage: valid-package-name [options] [--] [archive/]package\\n"
                printf "\\n"
                printf " -V --version                  print version info\\n"
                printf " -h --help                     display help\\n"
                printf "\\n"
                printf " -e --errname prog             specify program name for errors\\n"
                printf "\\n"
                printf " --archive                     require an explicit archive.\\n"
                printf " --no-archive                  prohibit an explicit archive.\\n"
                printf " -b --basename                 require basename\\n"
                printf " -v --vsn                      require version number\\n"
                printf " -l --patch-level\\n"
                printf "    --lvl                      require patch-level\\n"
                printf "\\n"
                printf " -t --tolerant                 tolerate more specific names\\n"
                printf "\\n"
                printf "Exit with status 0 if PACKAGE is a valid package name,\\n"
                printf "status 1 otherwise.\\n"
                printf "\\n"
                printf "By default, require a basename or basename plus branch label.\\n"
                printf "\\n"
                printf "Options -v and -l cancel -b and vice versa.\\n"
                printf "\\n"
                printf "Option -l implies -v.\\n"
                printf "\\n"
                printf "If an error name is specified (-e or --errname), then invalid\\n"
                printf "names cause an error message on stdout.  Otherwise, the exit\\n"
                printf "status is the only output.\\n"
                printf "\\n"
                printf "By default, validation is strict.  For example, -b checks\\n"
                printf "for a valid basename and does not permit a branch label\\n"
                printf "or version number.\\n"
                printf "\\n"
                printf "With -t, more specific names are permitted.  For example, -b\\n"
                printf "will permit a branch name, version number, and patch level.\\n"
                printf "\\n"
                exit 0
                ;;

      *)
                ;;
    esac
  done
fi

################################################################
# Ordinary Options
# 
# 

req_archive=
no_archive=
type=package
tolerant=0

while test $# -ne 0 ; do

  case "$1" in 
    --)                         shift
                                break
                                ;;


    --silent)                   shift   # ignored
                                ;;
    --quiet)                    shift   # ignored
                                ;;
    --report)                   shift   # ignored
                                ;;
    --verbose)                  shift   # ignored
                                ;;

    -e|--errname)               shift
                                if test $# -eq 0 ; then
                                  printf "valid-package-name: -e and --errname require an argument\\n" 1>&2
                                  printf "try --help\\n" 1>&2
                                  exit 1
                                fi
                                errname="$1"
                                shift
                                ;;

    --archive)                  req_archive=--archive
                                no_archive=
                                shift
                                ;;

    --no-archive)               no_archive=--no-archive
                                req_archive=
                                shift
                                ;;

    -b|--basename)              type=basename
                                shift
                                ;;

    -v|--vsn)                   type=version
                                shift
                                ;;

    -l|--patch-level|--lvl)     type=patch-level
                                shift
                                ;;

    -t|--tolerant)              tolerant=1
                                shift
                                ;;

    --)                         shift;
                                break
                                ;;

    -*)                         printf "valid-package-name: unrecognized option (%s)\\n" "$1" 1>&2
                                printf "try --help\\n" 1>&2
                                exit 1
                                ;;

    *)                          break
                                ;;
  esac

done



################################################################
# Ordinary Arguments
# 

if test $# -ne 1 ; then
  printf "usage: valid-package-name [options] [archive/]package\\n" 1>&2
  printf "try --help\\n" 1>&2
  exit 1
fi

package="$1"

archive=${package%%/*}
package=${package#*/}

if test "$archive" = "$package" ; then
  archive=
fi

################################################################
# Check Package Name
# 

if test -z "$package" ; then
  if test ! -z "$errname" ; then
    printf "%s: empty %s names are not valid\\n" "$errname" "$type" 1>&2
  fi
  exit 1
fi

if test ! -z "$req_archive" -a -z "$archive" ; then
  if test ! -z "$errname" ; then
    printf "%s: an explicit archive name is required\\n" "$errname" 1>&2
    printf "  argument: %s\\n" "$package" 1>&2
  fi
  exit 1
fi

if test ! -z "$no_archive" -a ! -z "$archive" ; then
  if test ! -z "$errname" ; then
    printf "%s: an explicit archive name is prohibitted\\n" "$errname" 1>&2
    printf "  argument: %s\\n" "$package" 1>&2
  fi
  exit 1
fi

if test ! -z "$archive" ; then
  larch valid-archive-name -e "$errname" -- "$archive"
fi


basere="([[:alpha:]]([[:alnum:]]*(-[[:alnum:]]+)?)*)"
vsnre="([[:digit:]]+\\.[[:digit:]]+)"
patchre="(base-0|patch-[0-9]+|version-0|versionfix-[0-9]+)"

case "$type" in 
  basename)     if test $tolerant -eq 0 ; then
                  re="^($basere)$"
                else
                  re="^($basere)(--$basere)?((--$vsnre)(--$patchre)?)?$"
                fi
                ;;

  package)      if test $tolerant -eq 0 ; then
                  re="^($basere)(--$basere)?$"
                else
                  re="^($basere)(--$basere)?((--$vsnre)(--$patchre)?)?$"
                fi
                ;;

  version)      if test $tolerant -eq 0 ; then
                  re="^($basere)(--$basere)?(--$vsnre)$"
                else
                  re="^($basere)(--$basere)?(--$vsnre)(--$patchre)?$"
                fi
                ;;

  patch-level)  re="^($basere)(--$basere)?(--$vsnre)(--$patchre)$"
                ;;
esac

set +e
filtered=`printf "%s\\n" "$package" | grep -E -e "$re"`
set -e

if test "x$filtered" = "x$package" ; then
  exit 0
else
  if test "x$errname" != x ; then
    printf "%s: invalid %s id (%s)\\n" "$errname" "$type" "$package" 1>&2
  fi
  exit 1
fi
