################################################################################
#
# src_fetch.cygpart - cygport source downloading functions
#
# Copyright (C) 2006-2020 Cygport authors
# Provided by the Cygwin project <https://cygwin.com/>
#
# cygport is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# cygport is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with cygport.  If not, see <https://www.gnu.org/licenses/>.
#
################################################################################

#****** Chapter 5/Downloading
#****

#****v* Downloading/SRC_URI
#  DESCRIPTION
#  Download address(es) for the package source file(s), as a string.
#  The first file in SRC_URI will be considered the primary source file
#  and will determine the default SRC_DIR.
#
#  Individual source files maintained locally may also be used by adding
#  their basenames to SRC_URI.
#
#  The basename of each URI is treated as the source filename, except that
#  CGI query strings are dropped after downloading.  If this would not yield
#  a usable filename, then the file can be renamed by appending an artificial
#  URI fragment in the form of #/FILENAME to the URI.  Some examples where this
#  may be useful or even necessary:
#  * an unversioned source tarball
#  * a file, patch, or snapshot from a gitweb interface (where all specific
#    information is in the query string itself)
#  * a patch from a cgit interface (normally /patch?id=COMMIT)
#  * a file from a Bugzilla attachment (normally /attachment.cgi?id=NUMBER)
#
#  This variable is required, but many cygclasses automatically define
#  a default SRC_URI based on the values of PN and PV.
#  SEE ALSO
#  bzr.cygclass, cvs.cygclass, fossil.cygclass, git.cygclass, hg.cygclass,
#  mtn.cygclass, svn.cygclass, Mirrors.
#****

#****v* Downloading/PATCH_URI
#  DESCRIPTION
#  Download address(es) for source patches which are to be applied immediately
#  after unpacking sources, as a string.
#
#  Individual source patches maintained locally may also be used by adding
#  their basenames to PATCH_URI.  This provides an easy way to carry
#  Cygwin-specific patches forward between releases.
#
#  Compressed patches and patch archives will be uncompressed on-the-fly.
#  Supported compression formats are gzip, bzip2, xz and zstd.
#
#  NOTE
#
#  For historical reasons, patches with basenames of ${PF}.{cygwin,src}.patch
#  should not be listed in PATCH_URI, as they are treated specially and are
#  automatically applied, if present, and generated, if required.
#
#  NOTE
#
#  See SRC_URI for details about URI handling in cygport.
#****

# downloads file(s) from Internet
fetch() {
	local uri;
	local urifile;
	local prog;
	local rc;

	uri=${1%\#/*};
	urifile=${1##*\#/};
	urifile=${urifile%\?*};
	urifile=${urifile##*/};

	if [ -z "${urifile}" ]
	then
		error "Won't fetch URI '$1', as it doesn't have a basename. Please specify one by appending #/FILENAME. See SRC_URI in the reference manual for details."
	fi

	if defined __DL_ONLY_MISSING && defined DISTDIR && [ -f ${DISTDIR}/${urifile} ]
	then
		inform "Using ${urifile} from DISTDIR"
		return 0
	elif defined _CYGPORT_RESTRICT_fetch_
	then
		inform "Fetching from ${uri} inhibited by RESTRICT"
		return 1
	elif check_prog wget
	then
		prog=wget
		wget --no-check-certificate -O ${urifile}.tmp ${uri}
		rc=$?
	elif check_prog curl
	then
		prog=curl
		curl -R -k --url ${uri} -o ${urifile}.tmp
		rc=$?
	else
		error "Either wget or curl are required to fetch sources.";
	fi

	if [ 0 = ${rc} ]
	then
		mv -f ${urifile}.tmp ${urifile}
	else
		if defined __DL_MIRROR_LIST
		then
			return ${rc}
		else
			rm -f ${urifile}.tmp
			error "${prog} ${uri} failed"
		fi
	fi

	if defined DISTDIR && [ -f ${urifile} ]
	then
		[ -d ${DISTDIR} ] || mkdir -p ${DISTDIR}
		mv ${urifile} ${DISTDIR}/
	fi
}

__mirror_fetch() {
	local miruri;
	local mirname;
	local mirvar;
	local -a mirlist;
	local -i n;
	local dl_mirrors;

	miruri=${1#mirror://};
	mirname=${miruri%%/*};
	mirvar=mirror_${mirname};

	if ! defined ${mirvar}
	then
		error "unknown mirror ${mirname}";
	fi

	mirlist=(${!mirvar});

	if [ ${#mirlist[*]} -gt 1 ]	# iterate thru list > 1
	then
		dl_mirrors=${#mirlist[*]}
	fi

	n=0;
	while (( n < ${#mirlist[*]} ))
	do
		if __DL_MIRROR_LIST=${dl_mirrors} fetch ${mirlist[${n}]}/${miruri#*/}
		then
			return 0;
		fi
		n+=1;
	done

	error "Could not download ${1##*/} from ${mirname} mirror(s)";
}

# downloads all sources through method-specific functions
__src_fetch() {
	local rcs;
	local uri;

	# FIXME: Versions < 0.3.1 would allow only one in any case.
	# While theoretically possible to use more than one of the RCS_fetch cmds
	# it's not assured because the tarball names could be the same.
	# Unfortunately, changing the RCS tarball names would break existing
	# source packages.  So for now, follow the previous behavior.
	for rcs in cvs svn git bzr hg mtn fossil
	do
		if inherited ${rcs}
		then
			${rcs}_fetch;
			break;
		fi
	done

	# the RCS_fetch functions change PWD
	cd ${top};

	for uri in ${SRC_URI} ${PATCH_URI}
	do
		if defined __DL_ONLY_MISSING && [ -f ${uri##*/} ]
		then
				continue
		fi
		case ${uri%%//*} in
			mirror:)	__mirror_fetch ${uri} ;;
			http:|https:|ftp:)	fetch ${uri} || error "Download ${uri##*/} failed" ;;
			file:)		[ -f ${uri#file://} ] || error "${uri##*/}: does not exist" ;;
			*:)		error "Unsupported download protocol ${uri%%//*}" ;;
			*/*)		[ -f ${uri#file://} ] || error "${uri##*/}: does not exist" ;;
			${uri})		;; # file in working directory
			*)		error "Invalid download URI ${uri}" ;;
		esac
	done
}

#****v* Downloading/VCS_COMPRESSION_EXT
#  SYNOPSIS
#  VCS_COMPRESSION_EXT="bz2"
#  DESCRIPTION
#  The compression to be used for source tarballs created from a VCS.
#  Defaults to 'bz2'.
#  DEFINITION
VCS_COMPRESSION_EXT="${VCS_COMPRESSION_EXT:-bz2}"
#  SEE ALSO
#  bzr.cygclass, cvs.cygclass, fossil.cygclass, git.cygclass, hg.cygclass,
#  mtn.cygclass, svn.cygclass, Mirrors.
#****

readonly -f fetch __mirror_fetch __src_fetch
