#!/bin/sh
# 
# 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
    				;;

    -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
