#!@bashrun@
# -*- mode: sh; -*-

########################################################################
function usage {
########################################################################
    [[ -n "$1" ]] && echo "error: $1";
    
    cat <<EOT
usage: make-cpan-dist options

Utility to create a CPAN distribution. See 'man make-cpan-dist'

Options
-------
-a author           - author (ex: Anonymouse <anonymouse@example.org>)
-A any version      - do not include version numbers for required modules
-b buildspec        - use a buildspec file instead of options
-B file             - use file as the build dependency list
-c core modules     - include core modules (default is to omit)
-C create buildspec - create a buildspec file
-d description      - description to be included CPAN
-D file             - use file as the dependency list
-e path             - path for extra .pl files to package
-E exclude list     - list of files to exclude from distribution
-f file             - file containing a list of extra files to include
-F postamble        - file containing additional make instructions
-h                  - help
-H project home     - project home, defaults to '..'
-k                  - skip tests after building (or SKIP_TESTS=1)
-l path             - path to Perl modules
-L log level        - logging level 1=error, 5=trace
-m name             - module name
-M perl version     - minimum perl version
-n no require       - do not include 'require' modules
-o dir              - output directory (default: current directory)
-O overwrite        - overwrite the buildspec.yml file
-p                  - preserve Makefile.PL
-P file             - file that contains a list of modules to be packaged
-r pgm              - script or program to list dependencies
-R yes/no           - recurse directories for files to package (default: yes)
-s                  - use scandeps.pl to find dependncies
-S                  - path for script files
-T file             - use file as the test dependency list
-t path             - path to test files
-v                  - more verbose output
-V                  - version from module
-x                  - do not cleanup files
-y                  - name of a file containing PL_FILES entries
-Y                  - name of the recommends file
-z                  - dryrun
-Z                  - resources file

* NOCLEANUP=1, PRESERVE_MAKEFILE=1 can also be passed as environment
  variables.

* use -L for logging level or DEBUG=1 (debug), DEBUG=2 (trace)

This script is free software. It may be used, redistributed and/or
modified under the same terms as Perl itself.
EOT
    
    exit;
}

########################################################################
function build_module_index {
########################################################################
    local root="$1"
    local index_file="$2"

    find -L "$root" -not -path '*/.git/*' -type f -name '*.pm' | \
        perl -ne '
            chomp;
            my $f = $_;
            open my $fh, "<", $f or next;
            while (<$fh>) {
                if (/^package\s+([\w:]+)/) {
                    print "$1 $f\n";
                }
            }
            close $fh;
        ' > "$index_file"
}

########################################################################
function module2path_indexed {
########################################################################
    local module="$1"
    local index_file="$2"
    local root="$3"

    local hit
    hit=$(awk -v m="$module" '$1 == m { print $2; exit }' "$index_file")

    if [[ -n "$hit" ]]; then
        echo "${hit##$root}"
        return
    fi

    # fallback: direct path derivation
    echo "$module" | perl -npe 's/::/\//g; s/\n//' | sed 's/$/.pm/'
}

########################################################################
filter_file_list() {
########################################################################
  local file_list=$1
  local exclude_list=$2
  local tmpfile

  if [[ ! -f $file_list || ! -f $exclude_list ]]; then
    echo "Usage: filter_file_list <file_list> <exclude_list>" >&2
    return 1
  fi

  file_list_sorted=$(mktemp)
  exclude_list_sorted=$(mktemp)

  export LC_ALL=C

  sort -u $file_list > $file_list_sorted
  sort -u $exclude_list > $exclude_list_sorted

  comm -23 $file_list_sorted $exclude_list_sorted > "$file_list";

  rm $file_list_sorted $exclude_list_sorted
}

########################################################################
function FATAL_ERROR {
########################################################################
    ERROR "$1"
    
    exit "${2:-1}"
}

########################################################################
function ERROR {
########################################################################
    [ "$LOG_LEVEL" -ge 1 ] && 2>&1 echo "** ERROR: $1 **" && return
}

########################################################################
function INFO {
########################################################################
    [ "$LOG_LEVEL" -ge 2 ] && 2>&1 echo "INFO: $1" && return
}

########################################################################
function WARN {
########################################################################
    [ "$LOG_LEVEL" -ge 3 ] && 2>&1 echo "WARN: $1" && return
}

########################################################################
function DEBUG {
########################################################################
    [ $LOG_LEVEL -ge 4 ] && 2>&1 echo "DEBUG: $1" && return
}

########################################################################
function TRACE {
########################################################################
    [ "$LOG_LEVEL" -ge 5 ] && 2>&1 echo "TRACE: $1" && return
}

# look for project home directory from here back, sets PROJECT_HOME
########################################################################
function find_git_home {
########################################################################
    if [[ -d ".git" ]]; then
        project_home="$(pwd)"
    else
        project_home="..";
    fi

    git_home=""

    while true; do
        git_home=$(find "$project_home" -type d -path "*/.git" | head -1);

        PROJECT_HOME=$(cd $project_home; pwd)
        [[ -n "$git_home" ]] && break;

        project_home="../$project_home"

        if [[ "$PROJECT_HOME" = "/" ]]; then
            PROJECT_HOME=""
            break;
        fi
    done
}

# cleanup on exit
########################################################################
function cleanup {
########################################################################
    [[ -n "$NOCLEANUP" ]] && return;

    [[ -n "$testsfile"     ]] && rm -f "$testsfile"
    [[ -n "$package_files" ]] && rm -f "$package_files"
    [[ -n "$exe_files"     ]] && rm -f "$exe_files"
    [[ -n "$scripts"       ]] && rm -f "$scripts"
    [[ -n "$depfile"       ]] && rm -f "$depfile"
    [[ -n "$resources"     ]] && rm -f "$resources"
    [[ -n "$builddir"      ]] && rm -rf "$builddir"
    [[ -n "$tmp_gitdir"    ]] && rm -rf "$tmp_gitdir"
    
    if [[ -n "$workdir" ]]; then
        for a in *.tmp; do
            rm -f "${workdir}/$a"
        done
    fi
}

# default dependency finder
########################################################################
function perl_requires {
########################################################################

    if [[ -e "$REQUIRES" ]]; then
        cat $REQUIRES
    elif [[ -n "@PERL_REQUIRES@" ]]; then
        "@PERL_REQUIRES@" -r "$1" 
    else
        ERROR "no scandeps-static.pl found!"
        FATAL_ERROR "Install Module::ScanDeps::Static use the -r option to provide your own dependency checker"
    fi
}


# attempts to grab module versions
########################################################################
function get_module_versions {
########################################################################
    infile="$1"
    
    if ! [[ -e "$infile" ]]; then
        ERROR "file $infile not found!"
        return;
    fi

    modules=$(mktemp)
    
    sort -u "$infile" | perl -npe 's/^perl\(//; s/\)\s*$//;' >$modules;

    while read -r a; do 
	module="$(echo "$a" | awk '{print $1}')"
	version="$(echo "$a" | awk '{print $2}')"
	
	if test -n "$ANY_VERSION"; then
	    echo "$module 0"
	elif test -n "$a" && ! test -n "$version"; then
	    echo $module | @perlenv@ -I "$perl5libdir" \
            -ne 'chomp; $m=$_; eval "require $m"; $v = eval "\$${m}::VERSION"; print "$m ",$v||0,"\n";' || true;
	else
	    echo "$module $version";
	fi
        
    done <$modules

    rm $modules
}

########################################################################
function scan() {
########################################################################
    scan_target="$1";
    requires_file="$2";
    
    if [ "$PERL_REQUIRES" = "SCANDEPS" ]; then
        if [[ -z "@scandeps@" ]]; then
            FATAL_ERROR "no scandeps.pl found!"
        else
            set -o pipefail
            INFO "Scanning (@scandeps@) $scan_target..."
            if ! @scandeps@ -R $scan_target | perl -npe "s/^\'(.*?)\'.*\$/\$1/;" | awk '{print $1}' >> $requires_file; then
                FATAL_ERROR "could not resolve dependencies for $scan_target"
            else
                DEBUG $(echo "SCAN:" && cat $requires_file)
            fi
        fi
    else
        if [ "$CORE_MODULES" = "--no-core-modules" ]; then
            NOCORE="--no-core"
        fi

        @PERL_REQUIRES@ $NO_INCLUDE_REQUIRE $NOCORE -r $scan_target >> $requires_file
        DEBUG $(echo "SCAN:" && cat $requires_file)
    fi
}

########################################################################
function executables() {
########################################################################
    executables="$1";
    filelist="$2";

    if [[ -n "$filelist" ]] && [[ -n "$executables" ]]; then
        if [[ -d "${PROJECT_HOME}/$executables" ]]; then
            find -L ${PROJECT_HOME}/${executables} $maxdepth -not -path '*/.git/*' -type f -executable >> $filelist;
        else
            if [[ -f "$executables" ]]; then
                cat $executables >> $filelist;
            else
                FATAL_ERROR "no such file $executables"
            fi
        fi
    fi
}

# +--------------------+
# | SCRIPT STARTS HERE |
# +--------------------+

# optional
GIT=$(command -v git);
PERLTIDY=$(command -v perltidy);
TREE=$(command -v tree);

# required
PERL=$(command -v perl);
MAKE_CPAN_DIST=$(command -v make-cpan-dist.pl)

while getopts "?Aa:b:B:cC:d:D:E:e:f:F:g:hH:kl:L:m:M:no:OpP:r:R:sS:t:T:vV:xY:y:zZ:" arg "$@"; do

    case "${arg}" in

        a)
            author="$OPTARG";
            ;;

        A)
            ANY_VERSION="1";
            ;;

        b) BUILDSPEC="$OPTARG";
           ;;

        B)
            build_requires="$OPTARG";
            ;;
        
        c)
            CORE_MODULES="--core-modules";
            ;;

        C)
            CREATE_BUILDSPEC="--create-buildspec $OPTARG";
            ;;

        d)
            description="$OPTARG";
            ;;

        D)
            dependency_file="$OPTARG";
            ;;

        e)
            bindir="$OPTARG";
            ;;

        E)
            exclude_list="$OPTARG";
            ;;

        f)
            EXTRA="$OPTARG";
            ;;

        F)
            POSTAMBLE="$OPTARG";
            ;;
        g)
            git_project="$OPTARG";

            if [[ -z "$GIT" ]]; then
                FATAL_ERROR "you must have 'git' installed to use this option"
            fi
            ;;

        h)
	    usage;
	    ;;

        H)
            PROJECT_HOME="$OPTARG";
            ;;

        k)
            SKIP_TESTS=1;
            ;;
        l)
            perl5libdir="$OPTARG";
            ;;

        L)
            LOG_LEVEL="$OPTARG";
            ;;
        
        m)
            MODULE="$OPTARG";
            ;;

        M)  MIN_PERL_VERSION="$OPTARG";
            ;;

        n)
            NO_INCLUDE_REQUIRE="--no-include-require"
            ;;
        o)
            destdir="$OPTARG";
            ;;

        O)
            OVERWRITE="1";
            ;;

        p)
            PRESERVE_MAKEFILE="1";
            ;;

        P)
            provides="$OPTARG";
            if [[ -n "$provides" ]]; then
                recurse_directories="no"
            fi
            ;;

        r)
            PERL_REQUIRES="perl_requires";
            REQUIRES="$OPTARG"
            ;;
        R)
            recurse_directories="$OPTARG";
            ;;

        s)
            PERL_REQUIRES="SCANDEPS"
            ;;

        S)
            scriptsdir="$OPTARG";
            ;;

        t)
            testsdir="$OPTARG";
            ;;
        T)
            test_dependency_file="$OPTARG";
            ;;

        v)
            VERBOSE="1";
            ;;

        V)
            VERSION_FROM="$OPTARG";
            ;;

        x)
            NOCLEANUP="1";
            ;;

        y)
            PL_FILES="$OPTARG";
            ;;
        Y)
            recommends_file="$OPTARG";
            ;;

        z)
            DRYRUN="--dryrun";
            ;;
        Z)
            RESOURCES="$OPTARG";
            ;;
    esac
done


if [[ -n "$CREATE_BUILDSPEC" ]] && [[ -z "$OVERWRITE" ]]; then
    if [[ -e "$CREATE_BUILDSPEC" ]]; then
        FATAL_ERROR "$CREATE_BUILDSPEC already exists"
    fi
fi

if [[ -n "$DEBUG" ]]; then
    if [ "$DEBUG" = "1" ]; then
        LOG_LEVEL=4
    elif [ "$DEBUG" = "2" ]; then
        LOG_LEVEL=5
    fi
fi     

LOG_LEVEL=${LOG_LEVEL:-1};
re='^[0-9]+$'

if ! [[ $LOG_LEVEL =~ $re ]] ; then
   FATAL_ERROR "$LOG_LEVEL must be a number between 1 and 5"
fi

if [[ "$LOG_LEVEL" -ge 4 ]]; then
    set -x
fi

shift $((OPTIND -1))

if [[ -n "$BUILDSPEC" ]]; then
    PROJECT_HOME="$PROJECT_HOME" $MAKE_CPAN_DIST -b $BUILDSPEC $DRYRUN
    exit $?;
fi

[[ -z "$MODULE" ]] && usage "no module specified";

[[ -z "$description" ]] && description="The $MODULE module!";

if [[ -z "$author" ]]; then
    if [[ -n "$GIT" ]]; then
        author=$($GIT config --global --get user.name 2>/dev/null)
        email=$($GIT config --global --get user.email 2>/dev/null)
        
        if [[ -n "$email" ]]; then
            author="$author <$email>"
        fi
    fi
    
    [[ -z "$author" ]] && usage "no author specified";
fi

recurse_directories=${recurse_directories:-yes}

# tarball destination directory
destdir=${destdir:-$(pwd)}

if [[ -n "$git_project" ]]; then
    tmp_gitdir=$(mktemp -d)
    PROJECT_HOME=$tmp_gitdir
    $GIT clone $git_project $PROJECT_HOME
    cd $PROJECT_HOME
    set -e -o pipeline

    if [[ -e configure.ac ]]; then
        autoreconf -i --force && ./configure --with-perlibdir=yes && make
    fi
elif [[ -z "$PROJECT_HOME" ]]; then
    if [[ -n "$GIT" ]]; then
      if $GIT status >/dev/null 2>/dev/null; then
          find_git_home
      else
          PROJECT_HOME="$(pwd)"
      fi
    fi
fi

if [[ -n "$dependency_file" ]]; then
  if [[ "$dependency_file" != /* ]]; then
      dependency_file="$PROJECT_HOME/$dependency_file"
  fi
  if ! [[ -e "$dependency_file" ]]; then
     FATAL_ERROR "$dependency_file not found";
  fi
fi

if [[ -n "$test_dependency_file" ]]; then
  if [[ "$test_dependency_file" != /* ]]; then
      test_dependency_file="$PROJECT_HOME/$test_dependency_file"
  fi

  if ! [[ -e "$test_dependency_file" ]]; then
     FATAL_ERROR "$test_dependency_file not found";
  fi
fi

if [[ -n "$build_requires" ]]; then
  if [[ "$build_requires" != /* ]]; then
      build_requires="$PROJECT_HOME/$build_requires"
  fi

  BUILD_REQUIRES="--build-requires $build_requires"
  if ! [[ -e "$build_requires" ]]; then
     FATAL_ERROR "$build_requires not found";
  fi
fi

if [[ -n "$recommends_file" ]]; then
  if [[ "$recommends_file" != /* ]]; then
      recommends_file="$PROJECT_HOME/$recommends_file"
  fi

  RECOMMENDS="--recommends $recommends_file"
  if ! [[ -e "$recommends_file" ]]; then
     FATAL_ERROR "$recommends_file not found";
  fi
fi

if [[ -n "$dependency_file" ]]; then
    if [[ -z "$CORE_MODULES" ]]; then
        CORE_MODULES="--no-core-modules"
    fi
else
    # default: do not include core modules
    CORE_MODULES=${CORE_MODULES:---no-core-modules}
fi

if [[ -z "$PROJECT_HOME" ]]; then
    usage "PROJECT_HOME is not defined!"
elif ! [[ -d "$PROJECT_HOME" ]]; then
    FATAL_ERROR "no such directory $PROJECT_HOME";
fi

echo "        PROJECT HOME: $PROJECT_HOME"
echo "     DEPENDENCY FILE: $dependency_file"
echo "TEST DEPENDENCY FILE: $test_dependency_file"
echo "      BUILD REQUIRES: $build_requires"
echo "          RECOMMENDS: $recommends_file"

# typical directory within project tree containing Perl modules
perl5libdir=${perl5libdir:-src/main/perl/lib}
if ! [[ -d "${PROJECT_HOME}/$perl5libdir" ]]; then
      perl5libdir="."
fi

# program that will provide the dependency list
PERL_REQUIRES=${PERL_REQUIRES:-perl_requires}

builddir=$(mktemp -d)

trap cleanup EXIT

module_file="$(module2path $MODULE)"
if [[ -n "$module_file" ]]; then
    mkdir -p "${builddir}/lib/$(dirname $module_file)";
fi

if ! [[ -e "${PROJECT_HOME}/${perl5libdir}/$module_file" ]]; then
    FATAL_ERROR "no "${PROJECT_HOME}/${perl5libdir}/$module_file" found!"
fi

if [[ -s "$EXTRA" ]]; then
    EXTRA_PATH="$EXTRA";

    while IFS=' ' read -r a b
    do
        INFO "$a $b"
        
        if [[ -f "${PROJECT_HOME}/$a" ]]; then
            if [[ -n "$b" ]]; then
                dir=$(dirname $b)
                test -d $builddir/$dir || mkdir -p $builddir/$dir
            fi
            
            cp ${PROJECT_HOME}/$a $builddir/$dir
        else
            FATAL_ERROR "file [${PROJECT_HOME}/$a] not found?"
        fi
    done <"$EXTRA"
elif [[ -n "$EXTRA" ]]; then
    WARN "No EXTRA file ($EXTRA) found in $(pwd)!"
fi

workdir=$(pwd)
package_files=$(mktemp)

########################################################################
# gather executables - files must be executable if they are going to be packaged
########################################################################
exe_files=$(mktemp)

# default is yes
if [ ! "$recurse_directories" = "yes" ]; then
    maxdepth='-maxdepth 1'
fi

all_files=$(mktemp)
executables $bindir $all_files
EXEC_PATH=$bindir

executables $scriptsdir $all_files
SCRIPTS_PATH=$scriptsdir

if [[ -s "$all_files" ]]; then
    sort -u $all_files > $exe_files
fi

if [[ -n "$exclude_list" ]]; then
    filter_file_list $exe_files $exclude_list
fi

if [[ -z "$NOCLEANUP" ]]; then
    rm $all_files
fi

########################################################################
# resources
if [[  -e "resources" ]]; then
    RESOURCES="resources"
elif [[ -z "$RESOURCES" ]]; then
    if [[ -d "$PROJECT_HOME/.git" ]]; then
        URL="$(git config --get remote.origin.web)";
        resources=$(mktemp)

        URL=$URL perl -MJSON -e \
        'print JSON->new->pretty->encode({ repository => { web => "$ENV{URL}", type => "git" }, homepage => "", bugtracker => { web => ""}});' > $resources
        RESOURCES="$resources"
    fi
fi

# set 'recurse' to 'no' and 'provides' to some value to specify your
# own set of files to package

if [[ "$recurse_directories" = "yes" ]]; then
    find -L ${PROJECT_HOME}/${perl5libdir} -not -path '*/.git/*' -type f -name '*.pm' > $package_files;
    MODULE_PATH="--module-path ${perl5libdir}"
else
    if [[ -s "$provides" ]]; then
        echo "$MODULE" >>$provides
        # build index once
        _module_index=$(mktemp)
        root="${PROJECT_HOME}/${perl5libdir}/"
        build_module_index "$root" "$_module_index"
        
        for a in $(cat $provides); do
            if [[ -n "$a" ]]; then
                echo "${PROJECT_HOME}/${perl5libdir}/$(module2path_indexed $a $_module_index $root)" >> $package_files
            fi
        done

        rm "$_module_index"

#        for a in $(cat $provides); do
#            if [[ -n "$a" ]]; then
#                echo "${PROJECT_HOME}/${perl5libdir}/$(module2path $a)" >> $package_files
#            fi
#        done
    else
        # must package the module at least?
        echo "${PROJECT_HOME}/${perl5libdir}/$module_file" >$package_files
        PATH_SPEC=${perl5libdir}
    fi
fi

if [[ -e "$exclude_list" ]]; then
    filter_file_list $package_files $exclude_list
fi

for a in $(cat $package_files | sort -u); do
    DEBUG "provides: [$a]"

    if ! [[ -e "$a" ]]; then
        FATAL_ERROR "$a does not exist!"
        exit 1;
    fi

    required_module=${a##${PROJECT_HOME}/${perl5libdir}/}

    if test -n "$required_module"; then
        echo $required_module >> ${workdir}/provides.tmp
    
        mkdir -p $(dirname ${builddir}/lib/$required_module)
        cp $a ${builddir}/lib/$required_module
    fi
done

if [[ -s "$exe_files" ]]; then
    mkdir -p ${builddir}/bin
    
    for a in $(cat $exe_files); do
        cp $a ${builddir}/bin
    done
fi

if [[ -z "$dependency_file" ]]; then
    echo "NO dependency file scanning..."

    for a in $(cat $package_files | sort -u); do
        scan $a ${workdir}/requires.tmp;
    done
    
    # find dependencies for .pl files
    if [[ -s "$exe_files" ]]; then
        for a in $(cat $exe_files); do
            scan $a ${workdir}/requires.tmp;
        done
    fi
else
    if [ $(basename $dependency_file) = "cpanfile" ]; then
        if command -v >/dev/null 2>&1; then
            cpanfile-dump "$dependency_file" >${workdir}/requires.tmp
        else
            WARN "cpanfile-dump not found!"
        fi
    else
        cp $dependency_file ${workdir}/requires.tmp
    fi
fi

if ! [[ -s "${workdir}/requires.tmp" ]]; then
    WARN "no dependencies will be listed for this distribution!"
    touch ${workdir}/requires.tmp
fi

# takes perl module names and converts them to relative paths. Some of
# these modules may not be files to be packaged. If the list came from
# the .yml file, then there may be modules name that are embedded in other
# module files.
#
# The make-cpan-dist.pl script creates the 'provides' section of the
# Makefile.PL by reading each file in the provides list and determing
# the module version. It then creats an entry in the provides hash
# that looks like this:
#
# {
#   file => path-to-module
#   version => module-version
# }

if [[ -z "$provides" ]]; then
    cat ${workdir}/provides.tmp | perl -npe 's/\//::/g; s/\.pm$//;' | sort -u > ${workdir}/provides
else
    # make sure provides is sorted
    sorted_provides=$(mktemp)
    sort -u provides > $sorted_provides;
    mv $sorted_provides provides
fi

# should we resolve versions here or in Perl module?
# echo "$(get_module_versions ${workdir}/provides)" > ${workdir}/provides

if [[ -n "$MIN_PERL_VERSION" ]]; then
    has_perl_version="$MIN_PERL_VERSION"
else
    has_perl_version=$(cat ${workdir}/requires.tmp | grep '^perl' | awk '{print $2}')
fi

depfile=$(mktemp)
awk '{print $1}' ${workdir}/requires.tmp | sort -u | grep -v '^perl' > $depfile

# remove provided files from required list

comm -23 $depfile ${workdir}/provides > ${workdir}/requires.tmp

# get the module versions we are currently using
if [[ -z "$dependency_file" ]]; then
    get_module_versions ${workdir}/requires.tmp > ${workdir}/requires
    dependency_file="${workdir}/requires.tmp";
fi

if [[ -n "$testsdir" ]]; then

    if [[ -d "${PROJECT_HOME}/$testsdir" ]]; then
        TESTS_PATH="$testsdir"

        testsfile=$(mktemp);

        find -L "${PROJECT_HOME}/$testsdir" -not -path '*/.git/*' -type f -name '*.t' > $testsfile

        if ! [[ -e "$testsfile" ]]; then
            INFO "no tests found in [$testsdir]...proceeding anyway."
            rm -f "$testsfile"
            testsfile=""
            TESTS_PATH=""
        else
            [[ -d "${builddir}/t" ]] || mkdir -p "${builddir}/t"

            for a in $(cat $testsfile); do
                if ! [[ -e "$a" ]]; then
                    FATAL_ERROR "$a does not exist!"
                    exit 1;
                fi
                cp "$a" "${builddir}/t/"
            done
        fi
    else
        FATAL_ERROR "no test directory [${PROJECT_HOME}/$testsdir]"
    fi
fi

if [[ -z "$test_dependency_file" ]]; then
    if [[ -n "$testsfile" ]]; then
        for a in $(cat $testsfile); do
            if ! [[ -e "$a" ]]; then
                FATAL_ERROR "$a does not exist!"
                exit 1;
            fi
            scan "$a" "${workdir}/test-requires.tmp"
        done
                
        # remove provided files from required list
        sort -u ${workdir}/test-requires.tmp > ${workdir}/test-requires
        comm -23 ${workdir}/test-requires ${workdir}/provides > ${workdir}/test-requires.tmp
    
        # get module versions for test-requires
        get_module_versions ${workdir}/test-requires.tmp > ${workdir}/test-requires-versions.tmp
        test_dependency_file=${workdir}/test-requires-versions.tmp
    fi
fi

if [[ -n "$VERBOSE" ]]; then
    cat "$dependency_file"

    if [[ -e "$test_dependency_file" ]]; then
        cat "$test_dependency_file"
    fi
fi

if [[ -n "$testsfile" ]]; then
    TEST_REQUIRES="-t $test_dependency_file"
fi

if [[ -n "$has_perl_version" ]]; then
    min_perl_version="--min-perl-version $has_perl_version"
fi

[[ -n "$DEBUG" ]] && EXTRA_OPTIONS="--debug"

if [[ -z "$ANY_VERSION" ]]; then
    REQUIRE_VERSION="-R"
fi

# extra Makefile instructions
if [[ -e "$POSTAMBLE" ]]; then
    cp "$POSTAMBLE" "$builddir/postamble"
fi

# create the Makefile.PL
export PROJECT_HOME=$PROJECT_HOME

if [[ $recurse_directories = "yes" ]]; then
   RECURSE="--recurse";
fi

[[  -n "$EXEC_PATH"    ]] && EXEC_PATH="--exec-path=$EXEC_PATH"
[[  -n "$SCRIPTS_PATH" ]] && SCRIPTS_PATH="--scripts-path=$SCRIPTS_PATH"
[[  -n "$TESTS_PATH"   ]] && TESTS_PATH="--tests-path=$TESTS_PATH"
[[  -n "$EXTRA_PATH"   ]] && EXTRA_PATH="--extra-path=$EXTRA_PATH"
[[  -n "$VERSION_FROM" ]] && VERSION_FROM="--version-from $VERSION_FROM"
[[  -n "$OVERWRITE"    ]] && OVERWRITE="--overwrite"
[[  -n "$RESOURCES"    ]] && RESOURCES="--resources $RESOURCES"
[[  -n "$PL_FILES"     ]]  && PL_FILES="--pl-files $PL_FILES"

cmd=(
    "$MAKE_CPAN_DIST"
    $CORE_MODULES
    $BUILD_REQUIRES
    $RECOMMENDS
    -r "$dependency_file"
    -e $exe_files
    $TEST_REQUIRES
    $min_perl_version
    -w "$builddir"
    $EXTRA_OPTIONS
    $RECURSE
    -l "$LOG_LEVEL"
    $PL_FILES
    $REQUIRE_VERSION
    -m "$MODULE"
    $VERSION_FROM
    $OVERWRITE
    $CREATE_BUILDSPEC
    -A "$description"
    $RESOURCES
    -a "$author"
    $EXTRA_PATH
    $MODULE_PATH
    $EXEC_PATH
    $SCRIPTS_PATH
    $TESTS_PATH
)

if ! PROJECT_HOME="$PROJECT_HOME" "${cmd[@]}" > "$builddir/Makefile.PL"; then
    FATAL_ERROR "could not create Makefile.PL" 1
fi

# if that was successful, then try to build the distribution
if ! [[ -e "$builddir/Makefile.PL" ]]; then
    FATAL_ERROR "failed to build Makefile.PL" 1
else
    cd $builddir
    if [[ -n "$VERBOSE" ]] && [[ -n "$TREE" ]]; then
        $TREE
        cat Makefile.PL
    fi
    
    if [[ -n "$PERLTIDY" ]]; then
        if $PERLTIDY Makefile.PL; then
            mv Makefile.PL.tdy Makefile.PL;
        fi
    fi
    
    if $PERL Makefile.PL; then

        make manifest

        make dist

        cp *.tar.gz $destdir

        if [[ -z "$SKIP_TESTS" ]] || ! [[ "$SKIP_TESTS" = "1" ]]; then
            make test
        fi

        if [[ -n "$PRESERVE_MAKEFILE" ]]; then
            cp Makefile.PL $destdir
        fi
        
        echo "CPAN authors: cpan-upload-http $(ls -1rt *.tar.gz | tail -1)"
    fi
fi

exit 0;
