#!/bin/bash # libnetwork.lib -- @package@ library to get info from internet repositories # Copyright (C) 2008,2010,2012,2014 Davide Madrisan [ "$libnetwork_is_loaded" = 1 ] || { libnetwork_is_loaded=1 [ -z "$BASH" ] || [ ${BASH_VERSION:0:1} -lt 3 ] && { echo $"this script requires bash version 3 or better" >&2 && exit 1; } [ -r @libdir@/libmsgmng.lib ] || { echo "\ libnetwork.lib: "$"library not found"": @libdir@/libmsgmng.lib" 1>&2 exit 1; } . @libdir@/libmsgmng.lib [ -r @libdir@/libtranslate.lib ] || { echo "\ libnetwork.lib: "$"library not found"": @libdir@/libtranslate.lib" 1>&2 exit 1; } . @libdir@/libtranslate.lib notify.debug $"loading"": \`libnetwork.lib'..." # check if all the needed tools are available for tool in curl mktemp; do [ "$(type -p curl)" ] || notify.error $"utility not found"": \`curl'" done # function repository.get_srpm_pckname_from_site() # get the list of SRPM packages by looking at the curl dump of the # ftp or html site # args: # --ftp | --html # $1 : package name or regexpr to look for # $2 : a (temporary) file containing the curl dump # return value: # the list of srpm files function repository.get_srpm_pckname_from_site() { local ARGS ARGS=`LC_ALL=C getopt \ -o fh --long ftp,html \ -n "$FUNCNAME" -- "$@"` [ $? = 0 ] || notify.error $"(bug)"" -- $FUNCNAME: "$"\`getopt' error" local is_html="0" is_ftp="0" eval set -- "$ARGS" while :; do case "$1" in -f|--ftp) is_ftp="1" ;; -h|--html) is_html="1" ;; --) shift; break ;; *) notify.error $"\ (bug)"" -- $FUNCNAME: "$"\`getopt' error: bad command \`$1'" ;; esac shift done [ "$is_ftp" != "$is_html" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"usage error (--ftp/--html)" local pck_name="$1" local infile="$2" [ "$pck_name" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (#1)" [ "$infile" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (#2)" notify.debug "$FUNCNAME: pck_name = \"$pck_name\"" case "$pck_name" in */*) notify.error $"\ (bug)"" -- $FUNCNAME: "$"'\\' characters detected in \$pck_name" ;; esac notify.debug "$FUNCNAME: infile = \"$infile\"" local regexpr [[ "$pck_name" =~ ^[+a-zA-Z0-9_-]+$ ]] && \ regexpr="^$pck_name-[^-]\+-[^-]\+$" || regexpr="$pck_name" notify.debug "$FUNCNAME: regexpr = \"$regexpr\"" if [ "$is_html" = "1" ]; then notify.debug "$FUNCNAME: parsing HTML dump..." local pckname_from_HTML=($(sed -n "\ # remove HTML tags --> get a better input /<[aA]\+ [hH]\+[rR]\+[eE]\+[fF]\+=\".*\.src\.rpm\"/{ s|%2B|+|g; s|.*<[aA]\+ [hH]\+[rR]\+[eE]\+[fF]\+=\"\([^\"]*\)\".*|\1| {/$regexpr/Ip}}" $infile)) echo "${pckname_from_HTML[*]}" elif [ "$is_ftp" = "1" ]; then notify.debug "$FUNCNAME: parsing FTP dump..." local pckname_from_FTP=($(sed -n "s,.*\ ,,;{/$regexpr/p}" $infile)) echo "${pckname_from_FTP[*]}" fi } # function repository.resolveURL() # expand the given url according to the given arch # args: # $1 : url to expand # $2 : current architecture # return value: # the expanded url function repository.resolveURL() { local ftpurl="$1" curr_arch="$2" resurl [ "$ftpurl" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (#1)" [ "$curr_arch" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (#2)" case "$ftpurl" in *@arch@*) echo -n "$(echo $ftpurl | sed "s,@arch@,$curr_arch,g")" ;; *) #echo -n "$ftpurl/$curr_arch/" echo -n "$ftpurl/" ;; esac } # function repository.get_SRPMS_name() # get the full name of the first SRPMS package found using as # package name '$@' and looking in the given list of repositories. # The full names are saved in the vector 'got_SPEC_FILENAME[]'. # The URL where the files have been found is saved in the variables # 'got_SPEC_FILENAME_URL', and the index corresponding to this URL # is saved in 'got_SPEC_FILENAME_URL_LEVEL' (eventually set via the # '--urlnum' option) # args: # -r,--urllist : list of urls where to check for packages # -n,--urlnum : the url number where to look at # -p,--proxy : proxy server # -u,--proxy-user : proxy user # -l,--user : login user (for repositories that require authentication) # $@ : list of package names to find for # return value: # 0 on success, 1 otherwise function repository.get_SRPMS_name() { local ARGS ARGS=`LC_ALL=C getopt \ -o n:r:p:u: \ --long urlnum:,urllist:,proxy:,proxy-user:,user: \ -n "$FUNCNAME" -- "$@"` [ $? = 0 ] || notify.error $"(bug)"" -- $FUNCNAME: "$"\`getopt' error" local i urlnum urllist proxy proxy_user user eval set -- "$ARGS" while :; do case "$1" in -n|--urlnum) urlnum="$2"; shift notify.debug "$FUNCNAME: urlnum = \"$urlnum\"" ;; -r|--urllist) urllist=($2); shift for i in `seq 1 1 ${#urllist[*]}`; do notify.debug "$FUNCNAME: urllist[$(($i-1))] = ${urllist[$i-1]}" done ;; -p|--proxy) proxy="$2"; shift notify.debug "$FUNCNAME: proxy = \"$proxy\"" ;; -u|--proxy-user) proxy_user="$2"; shift notify.debug "$FUNCNAME: proxy_user = \"$proxy_user\"" ;; -l|--user) user="$2"; shift notify.debug "$FUNCNAME: user = \"$user\"" ;; --) shift; break ;; *) notify.error $"\ (bug)"" -- $FUNCNAME: "$"\`getopt' error: bad command \`$1'" ;; esac shift done if [ "$urlnum" ]; then [[ "$urlnum" =~ ^[0-9]+$ ]] || notify.error $"\ (bug)"" -- $FUNCNAME: urlnum: "$"not a number" fi # this can be the result of a buggy configuration file # [ "$urllist" ] || notify.error $"\ #(bug)"" -- $FUNCNAME: urllist: "$"unset" local pck_names="$@" notify.debug "$FUNCNAME: pck_names = \"${pck_names[@]}\"" [ "$pck_names" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (#1)" # FIXME: 'curl_opts_netlink' is an external variable local curlopts="\ -L --silent --list-only $curl_opts_netlink\ ${user:+ --user $user}\ ${proxy:+ --proxy $proxy}${proxy_user:+ --proxy-user $proxy_user}" local curlopts_debug="\ -L --silent --list-only $curl_opts_netlink\ ${user:+ --user ***}\ ${proxy:+ --proxy ***}${proxy_user:+ --proxy-user ***}" local flist currflist currurl local errors=0 let "i = 0" for currurl in ${urllist[*]}; do # get the list of files from the repository notify.note $"\ getting list of files from"" \`${NOTE}$currurl/${NORM}'..." case $currurl in ftp://*|http://*|https://*) ;; *) notify.warning $"unsupported query type for this protocol" let "errors += 1" continue ;; esac currflist="$(mktemp -q -t flist.XXXXXXXX)" || notify.error $"can't create temporary files" notify.debug "$FUNCNAME: currflist = $currflist" # NOTE: the trailing slash is necessary, do not remove it notify.debug "$FUNCNAME: curl $curlopts_debug --url $currurl/ -o $currflist" curl $curlopts --url $currurl/ -o $currflist let "retval = $?" notify.debug "$FUNCNAME: curl return code: $retval" case "$retval" in 0) sed -i 's/\x0D$//;s/%2B/+/g' $currflist flist[$i]="$currflist" ;; 6) notify.warning $"couldn't resolve host" let "errors += 1" ;; 7) notify.warning $"failed to connect to host" let "errors += 1" ;; 56) notify.warning $"failure in receiving network data" let "errors += 1" ;; *) notify.warning $"curl error (exit code: $retval)" let "errors += 1" ;; esac [ -s "$currflist" ] || notify.warning $"cannot get the list of files" let "i += 1" done [ "$errors" = "${#urllist[@]}" ] && return 1 local pck_name level for pck_name in ${pck_names[@]}; do let "level = ${urlnum:-0}" let "i = 0" for currurl in ${urllist[*]}; do notify.debug "$FUNCNAME: pck_name = $pck_name" if [ -s "${flist[$i]}" ]; then case $currurl in ftp://*) got_SPEC_FILENAME=($(\ repository.get_srpm_pckname_from_site --ftp "$pck_name" "${flist[$i]}")) ;; http://*|https://*) got_SPEC_FILENAME=($(\ repository.get_srpm_pckname_from_site --html "$pck_name" "${flist[$i]}")) ;; esac [ "$got_SPEC_FILENAME" ] && { notify.debug "\ $FUNCNAME: got_SPEC_FILENAME = ${got_SPEC_FILENAME[*]}" got_SPEC_FILENAME_URL_LEVEL="$level" got_SPEC_FILENAME_URL="$currurl" break 2; } fi let "level += 1" let "i += 1" done done for i in ${!flist[@]}; do notify.debug "$FUNCNAME: removing temporary file '${flist[$i]}'" rm -f ${flist[$i]} done return 0 } # function repository.get_RPMS_name() # get the full name of the RPMS package '$1' looking at the # repository '$1'. # The full names are saved in the vector 'got_RPM_FILENAME[]'. # args: # $1 : URL where to check # $2 .. $n : package names to look at # -a,--archlist : list of supported architectures in the specified url # -x,--exclude : exclude packages that match a given regexpr # -c,--target-cpu : set the build architecture # -p,--proxy : proxy server # -u,--proxy-user : proxy user # -l,--user : login user (for repositories that require authentication) # return value: # 0 on success, >0 otherwise # example of output: # got_RPM_FILENAME = ( # i586:mbrowse-0.3.1-1qilnx.i586.rpm # i586:mbrowse-contrib-0.3.1-1qilnx.noarch.rpm # ppc:mbrowse-contrib-0.3.1-1qilnx.noarch.rpm ) function repository.get_RPMS_name() { ARGS=`LC_ALL=C getopt \ -o a:x:c:p:u: \ --long archlist:,exclude:,target-cpu:,proxy:,proxy-user:,user: \ -n "$FUNCNAME" -- "$@"` [ $? = 0 ] || notify.error $"(bug)"" -- $FUNCNAME: "$"\`getopt' error" eval set -- "$ARGS" local archlist excludeopt proxy proxy_user user target_cpu while :; do case $1 in -a|--archlist) archlist="$2"; shift notify.debug "$FUNCNAME: archlist = \"$archlist\"" ;; -x|--exclude) excludeopt="$2"; shift notify.debug "$FUNCNAME: excludeopt = \"$excludeopt\"" ;; -c|--target-cpu) target_cpu="$2"; shift notify.debug "$FUNCNAME: target_cpu = \"$target_cpu\"" ;; -p|--proxy) proxy="$2"; shift notify.debug "$FUNCNAME: proxy = \"$proxy\"" ;; -u|--proxy-user) proxy_user="$2"; shift notify.debug "$FUNCNAME: proxy_user = \"$proxy_user\"" ;; -l|--user) user="$2"; shift notify.debug "$FUNCNAME: user = \"$user\"" ;; --) shift; break ;; *) notify.error $"\ (bug)"" -- $FUNCNAME: "$"\`getopt' error" ;; esac shift done local scanurl="$1" [ "$scanurl" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (#1)" shift local pck_names="$@" notify.debug "$FUNCNAME: pck_names = \"${pck_names[@]}\"" [ "$pck_names" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (#2)" [ "$archlist" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"no list of architectures set"" (\$archlist)" local flist=`mktemp -q -t flist.XXXXXXXX` || notify.error $"can't create temporary files" local curr_arch errors pck_name curr_match let "errors = 0" local curr_arch_list case "$target_cpu" in "") curr_arch_list=( $archlist ) ;; "noarch") #curr_arch_list=( ${arch_noarch_upload[*]} ) # FIXME : if the noarch directory cannot be found a warning # message is displayed curr_arch_list=( $archlist noarch ) ;; *) # if the architecture is set by the user do ignore packages # built for other architectures (aka: please do not remove # packages built for other architectures!) curr_arch_list="$target_cpu" ;; esac notify.debug "\ $FUNCNAME: curr_arch_list = ( ${curr_arch_list[*]} )" # FIXME: 'curl_opts_netlink' is an external variable local curlopts="\ -L --silent --list-only $curl_opts_netlink -o $flist\ ${user:+ --user $user}\ ${proxy:+ --proxy $proxy}${proxy_user:+ --proxy-user $proxy_user}" local curlopts_debug="\ -L --silent --list-only $curl_opts_netlink -o $flist\ ${user:+ --user ***}\ ${proxy:+ --proxy ***}${proxy_user:+ --proxy-user ***}" got_RPM_FILENAME= for curr_arch in ${curr_arch_list[*]}; do currurl="$(repository.resolveURL "$scanurl" "$curr_arch")" #[ "$currurl" ] || notify.error $"(bug)"" -- $FUNCNAME: currurl = \"\"" # get the list of files from the repository notify.note $"getting list of files from"" \`${NOTE}$currurl/${NORM}'..." > $flist # NOTE: the trailing slash is necessary, do not remote it notify.debug "$FUNCNAME: curl $curlopts_debug --url $currurl/" curl $curlopts --url $currurl/ let "retval = $?" notify.debug "$FUNCNAME: curl return code: $retval" case "$retval" in 0) ;; 6) notify.warning $"couldn't resolve host" ;; 7) notify.warning $"failed to connect to host" ;; 56) notify.warning $"failure in receiving network data" ;; *) notify.warning $"curl error (exit code: $retval)" ;; esac if [ -s "$flist" ]; then sed -i 's/\x0D$//;s/%2B/+/g' $flist case $currurl in ftp://*|http://*|https://*) for pck_name in ${pck_names[@]}; do got_RPM_FILENAME=( ${got_RPM_FILENAME[@]} $(\ if [ -n "$excludeopt" ]; then sed -n "\ / $destdir/$file_name" pushd $destdir >/dev/null local retval notify.debug "curl $curl_opts\ ${proxy:+ --proxy $proxy}${proxyuser:+ --proxy-user $proxy_user} $file_url" curl $curl_opts \ ${proxy:+ --proxy $proxy} ${proxyuser:+ --proxy-user $proxy_user} \ "$file_url" retval=$? notify.debug "$FUNCNAME: curl return code: $retval" case "$retval" in 0) ;; 6) notify.warning $"couldn't resolve host" ;; 7) notify.warning $"failed to connect to host" ;; 56) notify.warning $"failure in receiving network data" ;; *) notify.warning $"curl error (exit code: $retval)" ;; esac [ -e $destdir/$file_name ] || if [ "$exitonerror" = 1 ]; then notify.error $"cannot download"": \`$file_name'" else popd >/dev/null notify.warning $"cannot download"": \`$file_name'" return 1 fi popd >/dev/null } # function curl.upload # upload a file using curl # function curl.upload() { local ARGS ARGS=`LC_ALL=C getopt \ -o f:l:o:p:u:x \ --long upload-file:,user:,options:,proxy:,proxy-user:,\ repository-alias:,exit-on-err,debug-unsecure \ -n "$FUNCNAME" -- "$@"` [ $? = 0 ] || notify.error $"(bug)"" -- $FUNCNAME: "$"\`getopt' error" local upfile user options proxy proxy_user local exitonerror=0 local debug_unsecure=0 eval set -- "$ARGS" while :; do case "$1" in -f|--upload-file) upfile="$2"; shift ;; -l|--user) user="$2"; shift #notify.debug "$FUNCNAME: user = \"$user\"" ;; -o|--options) options="$2"; shift #notify.debug "$FUNCNAME: options = \"$options\"" ;; -p|--proxy) proxy="$2"; shift #notify.debug "$FUNCNAME: proxy = \"$proxy\"" ;; -u|--proxy-user) proxy_user="$2"; shift #notify.debug "$FUNCNAME: proxy_user = \"$proxy_user\"" ;; -x|--exit-on-err) exitonerror="1" #notify.debug "$FUNCNAME: exitonerror = \"$exitonerror\"" ;; --debug-unsecure) debug_unsecure="1" ;; --) shift; break;; *) notify.error $"\ (bug)"" -- $FUNCNAME: "$"\`getopt' error: bad command \`$1'" ;; esac shift done #notify.debug "$FUNCNAME: debug_unsecure = \"$debug_unsecure\"" local destfile="$1" [ "$destfile" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (#1)" [ -e "$upfile" ] || notify.error $"package not found"": \`$upfile'" # FIXED: add an extra newline to workaroung a bug in curl notify.note "\ * ${NOTE}$upfile${NORM} --> $destfile" # option: --write-out [%{url_effective}]\\n # the option '--progress-bar' is currently buggy in curl local curr_curl_cmd="$options --progress-bar --fail -o /dev/null \ ${proxy:+ --proxy $proxy}${proxyuser:+ --proxy-user $proxy_user} \ --upload-file $upfile $destfile" if [ "$debug_unsecure" = "1" ]; then notify.debug "curl --user $user $curr_curl_cmd" else notify.debug "curl --user ***:*** $curr_curl_cmd" fi curl --user $user $curr_curl_cmd [ $? -eq 0 ] || { [ "$exitonerror" = 1 ] && exit 1 || return 1; } } # function curl.ftp_command # execute an ftp command (creating a directory, renamig a file, # deleting) using curl # function curl.ftp_command() { local ARGS ARGS=`LC_ALL=C getopt \ -o l:o:p:u:a: \ --long user:,options:,proxy:,proxy-user:,debug-unsecure,\ action:,directory:,rename-from:,rename-to:,delete:,ftp-passive \ -n "$FUNCNAME" -- "$@"` [ $? = 0 ] || notify.error $"(bug)"" -- $FUNCNAME: "$"\`getopt' error" local user options proxy proxy_user ftp_passive local action directory fromfile tofile deletefile local exitonerror=0 eval set -- "$ARGS" while :; do case "$1" in -l|--user) user="$2"; shift #notify.debug "$FUNCNAME: user = \"$user\"" ;; -o|--options) options="$2"; shift #notify.debug "$FUNCNAME: options = \"$options\"" ;; -p|--proxy) proxy="$2"; shift #notify.debug "$FUNCNAME: proxy = \"$proxy\"" ;; -u|--proxy-user) proxy_user="$2"; shift #notify.debug "$FUNCNAME: proxy_user = \"$proxy_user\"" ;; --debug-unsecure) debug_unsecure="1" ;; -a|--action) action="$2"; shift ;; --directory) directory="$2"; shift ;; --rename-from) fromfile="$2"; shift ;; --rename-to) tofile="$2"; shift ;; --delete) deletefile="$2"; shift ;; --ftp-passive) ftp_passive="--ftp-pasv" ;; -x|--exit-on-err) exitonerror="1" ;; --) shift; break;; *) notify.error $"\ (bug)"" -- $FUNCNAME: "$"\`getopt' error: bad command \`$1'" ;; esac shift done local backup_ftp_server="$1" [ "$backup_ftp_server" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (#1)" [ "$ftp_passive" ] && options="$options $ftp_passive" [ "${1:0:4}" == "http" ] && http_mode=1 # NOTE: see RFC959 for the sintax of the 'quote' commands # curl --ftp-pasv --user user:password \ # -Q "MKD /devel/old/prova.dir" \ # -Q "RNFR /devel/old/prova.tmp" \ # -Q "RNTO /devel/old/prova.dir/prova.tmp" ftp.linuxdistro.org case "$action" in mkdir) [ "$directory" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (--directory)" if [ "$http_mode" == "1" ]; then notify.debug "\ curl $options --user \"***:***\" -X MKCOL $1${directory}/" curl $options --user "$user" -X MKCOL $1${directory}/ &>/dev/null else notify.debug "\ curl $options --user \"***:***\" --quote \"MKD $directory\" $1" curl $options --user "$user" --quote "MKD $directory" $1 &>/dev/null fi ;; rename-file) [ "$fromfile" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (--rename-from)" [ "$tofile" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (--rename-to)" if [ "$http_mode" == "1" ]; then notify.debug "curl $options --user \"***:***\" -X MOVE\ --header \"Destination:$1$tofile\" $1$fromfile" curl $options --user "$user" -X MOVE \ --header "Destination:$1$tofile" $1$fromfile &>/dev/null else notify.debug "curl $options --user \"***:***\"\ --quote \"RNFR $fromfile\" --quote \"RNTO $tofile\" $1" curl $options --user "$user" \ --quote "RNFR $fromfile" --quote "RNTO $tofile" $1 &>/dev/null fi ;; delete) [ "$deletefile" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (--delete)" # example: # curl -v --ftp-pasv --user "$user" \ # --quote "CWD SRPMS.base" \ # --quote "DELE filename-0.0.1-1distro.src.rpm" \ # ftp://ftpaccounts.openmamba.org # -or- # curl -v --ftp-pasv --user "$user" \ # --quote "DELE SRPMS.base/filename-0.0.1-1distro.src.rpm" \ # ftp://ftpaccounts.openmamba.org if [ "$http_mode" == "1" ]; then notify.debug "\ curl $options --user \"***:***\" -X DELETE $1$deletefile" curl $options --user "$user" -X DELETE $1$deletefile &>/dev/null else notify.debug "\ curl $options --user \"***:***\" --quote \"DELE $deletefile\" $1" curl $options --user "$user" --quote "DELE $deletefile" $1 &>/dev/null fi ;; *) notify.error $"\ (bug)"" -- $FUNCNAME: "$"unknown action"": ($action)" esac retval=$? case "$retval" in 0) ;; 6) notify.warning $"couldn't resolve host" ;; 7) notify.warning $"failed to connect to host" ;; *) notify.warning $"curl error (exit code: $retval)" ;; esac [[ "$retval" != "0" && "$exitonerror" = 1 ]] && exit 1 } # function git.download # helper for creating a tarball from a git repository # args: # -d, --destdir : target directory # -p, --proxy : proxy server # -u, --proxy-user : proxy user # --preserve-dot-git : do not remove .git files # $@ : git repository # # return value: # 0 function git.download() { local ARGS ARGS=`LC_ALL=C getopt \ -o d:v:p:u:k \ --long destdir:,pck-version:,proxy:,proxy-user:,preserve-dot-git: \ -n "$FUNCNAME" -- "$@"` [ $? = 0 ] || notify.error $"(bug)"" -- $FUNCNAME: "$"\`getopt' error" local destdir local proxy proxy_user local pck_version local preserve_dot_git=0 eval set -- "$ARGS" while :; do case "$1" in -d|--destdir) destdir="$2"; shift notify.debug "$FUNCNAME: destdir = \"$destdir\"" ;; -v|--pck-version) pck_version="$2"; shift notify.debug "$FUNCNAME: pck_version = \"$pck_version\"" ;; -p|--proxy) proxy="$2"; shift notify.debug "$FUNCNAME: proxy = \"$proxy\"" ;; -u|--proxy-user) proxy_user="$2"; shift notify.debug "$FUNCNAME: proxy_user = \"$proxy_user\"" ;; --preserve-dot-git) preserve_dot_git="$2"; shift notify.debug "$FUNCNAME: preserve_dot_git = \"$preserve_dot_git\"" ;; --) shift; break;; *) notify.error $"\ (bug)"" -- $FUNCNAME: "$"\`getopt' error: bad command \`$1'" ;; esac shift done local giturl_and_branch="$1" notify.debug "$FUNCNAME: giturl_and_branch = \"$giturl_and_branch\"" [ "$giturl_and_branch" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (#1)" [ "$destdir" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (--destdir)" local token_dirname="${giturl_and_branch%/*}" local token_basename="${giturl_and_branch##*/}" notify.debug "$FUNCNAME: token_dirname = \"$token_dirname\"" notify.debug "$FUNCNAME: token_basename = \"$token_basename\"" if [ -e $destdir/$token_basename ]; then if [ "$force_download" = "0" ]; then notify.note "[${filenum:-*}] $NOTE$token_basename$NORM ... "$"skipped" return 0 fi fi local git_branch="${token_dirname/*\/}" notify.debug "$FUNCNAME: git_branch = \"$git_branch\"" git.create_tarball \ --pck-version "$pck_version" \ --destdir "$destdir" \ --preserve-dot-git "${preserve_dot_git}" --git-branch "$git_branch" \ "${token_dirname/\/$git_branch*}" } # function git.urldecode # url decodes a given string function git.urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; } # function git.create_tarball # clone a git repository and convert is into a tarball file # # args: # -d,--destdir : target directory # -v,--pck-version : package version # --git-branch : git branch # --preserve-dot-git : do not remove .git files # $@ : git repository # # return value: # 0 # # set: spec_source, spec_source_comment, pck_tarball function git.create_tarball() { local ARGS ARGS=`LC_ALL=C getopt -o d:v:p:u: \ --long destdir:,pck-version:,git-branch:,preserve-dot-git:,proxy:,proxy-user:\ -n "$FUNCNAME" -- "$@"` [ $? = 0 ] || notify.error $"(bug)"" -- $FUNCNAME: "$"\`getopt' error" local destdir # FIXME: add support for proxy # HINT: git config --global http.proxy http://user:pwd@proxy.srv.com:port # see: http://bardofschool.blogspot.fr/2008/11/use-git-behind-proxy.html local proxy proxy_user local git_branch local git_commit local preserve_dot_git=0 local pck_version eval set -- "$ARGS" while :; do case "$1" in -d|--destdir) destdir="$2"; shift notify.debug "$FUNCNAME: destdir = \"$destdir\"" ;; -v|--pck-version) pck_version="$2"; shift notify.debug "$FUNCNAME: pck_version = \"$pck_version\"" ;; --git-branch) git_branch="`git.urldecode "$2"`"; shift if [ "${git_branch/@*}" != "${git_branch}" ]; then git_commit="${git_branch/*@}" git_branch="${git_branch/@*}" if [ ! "${git_commit}" ]; then notify.error "$FUNCNAME: cannot checkout empty commit" fi fi notify.debug "$FUNCNAME: git_branch = \"$git_branch\"" if [ "${git_commit}" ]; then notify.debug "$FUNCNAME: git_commit = \"$git_commit\"" fi ;; --preserve-dot-git) preserve_dot_git="$2"; shift notify.debug "$FUNCNAME: preserve_dot_git = \"$preserve_dot_git\"" ;; -p|--proxy) proxy="$2"; shift notify.debug "$FUNCNAME: proxy = \"$proxy\"" ;; -u|--proxy-user) proxy_user="$2"; shift notify.debug "$FUNCNAME: proxy_user = \"$proxy_user\"" ;; --) shift; break;; *) notify.error $"\ (bug)"" -- $FUNCNAME: "$"\`getopt' error: bad command \`$1'" ;; esac shift done local git_repository="$1" notify.debug "$FUNCNAME: git_repository = \"$git_repository\"" [ "$git_repository" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (#1)" [ "$destdir" ] || notify.error $"\ (bug)"" -- $FUNCNAME: "$"missing mandatory arg"" (--destdir)" type -p git &>/dev/null || notify.error $"utility not found"": \`git'" local tmpgitdir=$(mktemp -q -d -t tmpgit.XXXXXXXX) [ $? -eq 0 ] || notify.error $"can't create temporary files" notify.debug "$FUNCNAME: tmpgitdir = $tmpgitdir" pushd $tmpgitdir &>/dev/null # create a tarball by cloning the git repository notify.note \ "${NOTE}"$"cloning git repository""\ <$git_repository> ${git_branch:+($git_branch)}${NORM}""..." if [ "$preserve_dot_git" = "0" -a "${git_repository:0:4}" != "http" -a ! "${git_commit}" ]; then notify.debug "$FUNCNAME: git clone --recursive --depth=1 ${git_branch:+-b $git_branch} \"$git_repository\"" git clone --recursive --depth=1 ${git_branch:+-b $git_branch} "$git_repository" else notify.debug "$FUNCNAME: git clone --recursive ${git_branch:+-b $git_branch} \"$git_repository\"" git clone --recursive ${git_branch:+-b $git_branch} "$git_repository" fi [ $? -eq 0 ] || { popd &>/dev/null rm -fr $tmpgitdir notify.error $"cannot clone git repository"; } pck_tarball="$(find -mindepth 1 -maxdepth 1 -type d -printf "%f")" if [ "${git_commit}" ]; then cd ${pck_tarball} git checkout ${git_commit} || { popd &>/dev/null rm -fr $tmpgitdir notify.error $"cannot checkout the specified tag"; } cd .. fi if [ "$preserve_dot_git" = "0" ]; then # remove git files rm -fr $pck_tarball/.git rm -f $pck_tarball/.gitignore rm -f $pck_tarball/.gitmodules fi mv $pck_tarball ${pck_tarball}-${pck_version} pck_tarball="${pck_tarball}-${pck_version}" # create a compressed tarball # FIXME: why bzip2? The compression tool used here should be configurable notify.note "${NOTE}"$"creating the compressed source tarball""${NORM}..." tar -cvf ${pck_tarball}.tar $pck_tarball/ >/dev/null && bzip2 ${pck_tarball}.tar && mv ${pck_tarball}.tar.bz2 $destdir/ if [ $? -eq 0 ]; then notify.note "\ ...${NOTE}"$"done""${NORM}: \`${NOTE}${pck_tarball}.tar.bz2${NORM}'" else popd &>/dev/null rm -fr $tmpgitdir notify.error $"\ an error occurred while creating"": ${pck_tarball}.tar.bz2" fi spec_source="${pck_tarball}.tar.bz2" notify.debug "$FUNCNAME: spec_source = $spec_source" spec_source_comment="\ ## GITSOURCE $git_repository${git_branch:+ $git_branch}" notify.debug "$FUNCNAME: spec_source_comment = \"$spec_source_comment\"" pck_tarball="$destdir/${spec_source}" notify.debug "$FUNCNAME: pck_tarball = $pck_tarball" popd &>/dev/null rm -fr $tmpgitdir return 0 } } # endif $libnetwork_is_loaded