<HTML><BODY><div>Sergey, thanks a lot for the review, I’ve added the checker as you suggested.<br><br> <blockquote style="border-left:1px solid #0857A6; margin:10px; padding:0 0 0 10px;">Четверг, 9 апреля 2020, 17:55 +03:00 от Sergey Bronnikov <sergeyb@tarantool.org>:<br> <div id=""><div class="js-helper js-readmsg-msg"><style type="text/css"></style><div><div id="style_15864441020306470418_BODY">Sasha, thanks for the patch!<br><br>it would be useful to use 'set -uf -o pipefail' at the<br>beginning of script in addition to 'set -e'.<br><br>LGTM<br><br>On 08:33 Thu 09 Apr , Alexander V. Tikhonov wrote:<div class="mail-quote-collapse">> Added ability to remove given in options package from S3. TO remove the<br>> needed package need to set '-r=<package name with version>' option,<br>> like:<br>> ./tools/update_repo.sh -o=<OS> -d=<DIST> -b=<S3 repo> \<br>> -r=tarantool-2.2.2.0<br>> it will remove all found appropriate source and binaries packages from<br>> the given S3 repository, also the meta files will be corrected there.<br>><br>> Close #4839<br>> ---<br>><br>> Github: <a href="https://github.com/tarantool/tarantool/tree/avtikhon/gh-4839-s3-script-full-ci" target="_blank">https://github.com/tarantool/tarantool/tree/avtikhon/gh-4839-s3-script-full-ci</a><br>> Issue: <a href="https://github.com/tarantool/tarantool/issues/4839" target="_blank">https://github.com/tarantool/tarantool/issues/4839</a><br>><br>> tools/update_repo.sh | 389 ++++++++++++++++++++++++++++++++++---------<br>> 1 file changed, 309 insertions(+), 80 deletions(-)<br>><br>> diff --git a/tools/update_repo.sh b/tools/update_repo.sh<br>> index df94cd1ee..9459c2997 100755<br>> --- a/tools/update_repo.sh<br>> +++ b/tools/update_repo.sh<br>> @@ -8,6 +8,7 @@ ws_prefix=/tmp/tarantool_repo_s3<br>><br>> alloss='ubuntu debian el fedora'<br>> product=tarantool<br>> +remove=<br>> force=<br>> skip_errors=<br>> # the path with binaries either repository<br>> @@ -62,6 +63,9 @@ Usage for store package binaries from the given path:<br>> Usage for mirroring Debian|Ubuntu OS repositories:<br>> $0 -o=<OS name> -d=<OS distribuition> -b=<S3 bucket> [-p=<product>] <path to packages binaries><br>><br>> +Usage for removing specific package from S3 repository:<br>> + $0 -o=<OS name> -d=<OS distribuition> -b=<S3 bucket> [-p=<product>] -r <package version> <path to packages binaries><br>> +<br>> Arguments:<br>> <path><br>> Path points to the directory with deb/prm packages to be used.<br>> @@ -101,6 +105,24 @@ EOF<br>> - for RPM packages:<br>> # prepare local path with needed "tarantool-queue-*" packages only<br>> ./$0 -b=s3://<target repository> -o=fedora -d=30 <local path><br>> + -r|--remove<br>> + Remove package specified by version from S3 repository. It will remove<br>> + all found appropriate source and binaries packages from the given S3<br>> + repository, also the meta files will be corrected there.<br>> + Example of usage on 'tarantool-2.2.2.0' version:<br>> + ./tools/update_repo.sh -o=<OS> -d=<DIST> -b=<S3 repo> \\<br>> + -r=tarantool-2.2.2.0<br>> + It will search and try to remove packages:<br>> + - for DEB repositories:<br>> + tarantool-2.2.2.0-1_all.deb<br>> + tarantool-2.2.2.0-1_amd64.deb<br>> + tarantool-2.2.2.0-1.dsc<br>> + tarantool-2.2.2.0-1.debian.tar.xz<br>> + tarantool-2.2.2.0.orig.tar.xz<br>> + - for RPM repositories:<br>> + x86_64/tarantool-2.2.2.0-1.*.x86_64.rpm<br>> + x86_64/tarantool-2.2.2.0-1.*.noarch.rpm<br>> + SRPMS/tarantool-2.2.2.0--1.*.src.rpm<br>> -f|--force<br>> Force updating the remote package with the local one despite the checksum difference<br>> -s|--skip_errors<br>> @@ -134,6 +156,10 @@ case $i in<br>> product="${i#*=}"<br>> shift # past argument=value<br>> ;;<br>> + -r=*|--remove=*)<br>> + remove="${i#*=}"<br>> + shift # past argument=value<br>> + ;;<br>> -f|--force)<br>> force=1<br>> ;;<br>> @@ -146,12 +172,15 @@ case $i in<br>> ;;<br>> *)<br>> repo="${i#*=}"<br>> - pushd $repo >/dev/null ; repo=$PWD ; popd >/dev/null<br>> shift # past argument=value<br>> ;;<br>> esac<br>> done<br>><br>> +if [ "$remove" == "" ]; then<br>> + pushd $repo >/dev/null ; repo=$PWD ; popd >/dev/null<br>> +fi<br>> +<br>> # check that all needed options were set and correct<br>> if [ "$bucket" == "" ]; then<br>> echo "ERROR: need to set -b|--bucket bucket option, check usage"<br>> @@ -195,7 +224,7 @@ function update_deb_packfile {<br>><br>> # WORKAROUND: unknown why, but reprepro doesn`t save the Sources file,<br>> # let`s recreate it manualy from it's zipped version<br>> - [ ! -f $psources ] || gunzip -c $psources.gz >$psources<br>> + gunzip -c $psources.gz >$psources<br>><br>> # WORKAROUND: unknown why, but reprepro creates paths w/o distribution in<br>> # it and no solution using configuration setup neither options<br>> @@ -226,6 +255,8 @@ function update_deb_metadata {<br>> touch $packpath.saved<br>> fi<br>><br>> + [ "$remove" == "" ] || cp $packpath.saved $packpath<br>> +<br>> if [ "$packtype" == "dsc" ]; then<br>> # check if the DSC hash already exists in old Sources file from S3<br>> # find the hash from the new Sources file<br>> @@ -328,6 +359,135 @@ function update_deb_metadata {<br>> cat $packpath >>$packpath.saved<br>> }<br>><br>> +function update_deb_dists {<br>> + # 2(binaries). update Packages file archives<br>> + for packpath in dists/$loop_dist/$component/binary-* ; do<br>> + pushd $packpath<br>> + if [ -f Packages ]; then<br>> + sed -i '/./,$!d' Packages<br>> + bzip2 -c Packages >Packages.bz2<br>> + gzip -c Packages >Packages.gz<br>> + fi<br>> + popd<br>> + done<br>> +<br>> + # 2(sources). update Sources file archives<br>> + pushd dists/$loop_dist/$component/source<br>> + if [ -f Sources ]; then<br>> + sed -i '/./,$!d' Sources<br>> + bzip2 -c Sources >Sources.bz2<br>> + gzip -c Sources >Sources.gz<br>> + fi<br>> + popd<br>> +<br>> + # 3. update checksums entries of the Packages* files in *Release files<br>> + # NOTE: it is stable structure of the *Release files when the checksum<br>> + # entries in it in the following way:<br>> + # MD5Sum:<br>> + # <checksum> <size> <file orig><br>> + # <checksum> <size> <file debian><br>> + # SHA1:<br>> + # <checksum> <size> <file orig><br>> + # <checksum> <size> <file debian><br>> + # SHA256:<br>> + # <checksum> <size> <file orig><br>> + # <checksum> <size> <file debian><br>> + # The script bellow puts 'md5' value at the 1st found file entry,<br>> + # 'sha1' - at the 2nd and 'sha256' at the 3rd<br>> + pushd dists/$loop_dist<br>> + for file in $(grep " $component/" Release | awk '{print $3}' | sort -u) ; do<br>> + [ -f $file ] || continue<br>> + sz=$(stat -c "%s" $file)<br>> + md5=$(md5sum $file | awk '{print $1}')<br>> + sha1=$(sha1sum $file | awk '{print $1}')<br>> + sha256=$(sha256sum $file | awk '{print $1}')<br>> + awk 'BEGIN{c = 0} ; {<br>> + if ($3 == p) {<br>> + c = c + 1<br>> + if (c == 1) {print " " md " " s " " p}<br>> + if (c == 2) {print " " sh1 " " s " " p}<br>> + if (c == 3) {print " " sh2 " " s " " p}<br>> + } else {print $0}<br>> + }' p="$file" s="$sz" md="$md5" sh1="$sha1" sh2="$sha256" \<br>> + Release >Release.new<br>> + mv Release.new Release<br>> + done<br>> + # resign the selfsigned InRelease file<br>> + $rm_file InRelease<br>> + gpg --clearsign -o InRelease Release<br>> + # resign the Release file<br>> + $rm_file Release.gpg<br>> + gpg -u $GPG_SIGN_KEY -abs -o Release.gpg Release<br>> + popd<br>> +<br>> + # 4. sync the latest distribution path changes to S3<br>> + $aws_sync_public dists/$loop_dist "$bucket_path/dists/$loop_dist"<br>> +}<br>> +<br>> +function remove_deb {<br>> + pushd $ws<br>> +<br>> + # get Release file<br>> + relpath=dists/$option_dist<br>> + $mk_dir $relpath<br>> + $aws cp $bucket_path/$relpath/Release $relpath/<br>> +<br>> + # get Packages files<br>> + for bindirs in $($aws ls $bucket_path/dists/$option_dist/$component/ \<br>> + | awk '{print $2}' | grep -v 'source/' | sed 's#/##g') ; do<br>> + packpath=$relpath/$component/$bindirs<br>> + $mk_dir $packpath<br>> + pushd $packpath<br>> + $aws cp $bucket_path/$packpath/Packages .<br>> +<br>> + hashes_old=$(grep -e "^Filename: " -e "^SHA256: " Packages | \<br>> + grep -A1 "$remove" | grep "^SHA256: " | awk '{print $2}')<br>> + # NOTE: for the single file name may exists more than one<br>> + # entry in damaged file, to fix it all found entries<br>> + # of this file need to be removed<br>> + # find and remove all package blocks for the bad hashes<br>> + for hash_rm in $hashes_old ; do<br>> + echo "Removing from Packages file old hash: $hash_rm"<br>> + sed -i '1s/^/\n/' Packages<br>> + pcregrep -Mi -v "(?s)Package: (\N+\n)+(?=SHA256: ${hash_rm}).*?^__BODY_HTML_PLACEHOLDER__quot; \<br>> + Packages >Packages.new<br>> + mv Packages.new Packages<br>> + done<br>> + popd<br>> + done<br>> +<br>> + # get Sources file<br>> + packpath=$relpath/$component/source<br>> + $mk_dir $packpath<br>> + pushd $packpath<br>> + $aws cp $bucket_path/$packpath/Sources .<br>> +<br>> + hashes_old=$(grep '^Checksums-Sha256:' -A3 Sources | \<br>> + grep " .* .* $remove" | awk '{print $1}')<br>> + # NOTE: for the single file name may exists more than one<br>> + # entry in damaged file, to fix it all found entries<br>> + # of this file need to be removed<br>> + # find and remove all package blocks for the bad hashes<br>> + for hash_rm in $hashes_old ; do<br>> + echo "Removing from Sources file old hash: $hash_rm"<br>> + sed -i '1s/^/\n/' Sources<br>> + pcregrep -Mi -v "(?s)Package: (\N+\n)+(?=^ ${hash_rm}).*?^__BODY_HTML_PLACEHOLDER__quot; \<br>> + Sources >Sources.new<br>> + mv Sources.new Sources<br>> + done<br>> + popd<br>> +<br>> + # call DEB dists path updater<br>> + loop_dist=$option_dist<br>> + update_deb_dists<br>> +<br>> + # remove all found file by the given pattern in options<br>> + for suffix in '-1_all.deb' '-1_amd64.deb' '-1.dsc' '-1.debian.tar.xz' '.orig.tar.xz' ; do<br>> + $aws ls "$bucket_path/$poolpath/${remove}$suffix" || continue<br>> + $aws rm "$bucket_path/$poolpath/${remove}$suffix"<br>> + done<br>> +}<br>> +<br>> # The 'pack_deb' function especialy created for DEB packages. It works<br>> # with DEB packing OS like Ubuntu, Debian. It is based on globally known<br>> # tool 'reprepro' from:<br>> @@ -339,18 +499,7 @@ function update_deb_metadata {<br>> # <a href="https://www.tarantool.io/en/download/os-installation/debian/" target="_blank">https://www.tarantool.io/en/download/os-installation/debian/</a><br>> # <a href="https://www.tarantool.io/en/download/os-installation/ubuntu/" target="_blank">https://www.tarantool.io/en/download/os-installation/ubuntu/</a><br>> function pack_deb {<br>> - # we need to push packages into 'main' repository only<br>> - component=main<br>> -<br>> - # debian has special directory 'pool' for packages<br>> - debdir=pool<br>> -<br>> - # set the subpath with binaries based on literal character of the product name<br>> - proddir=$(echo $product | head -c 1)<br>> -<br>> # copy single distribution with binaries packages<br>> - repopath=$ws/pool/${option_dist}/$component/$proddir/$product<br>> - $mk_dir ${repopath}<br>> file_found=0<br>> for file in $repo/*.deb $repo/*.dsc $repo/*.tar.*z ; do<br>> [ -f $file ] || continue<br>> @@ -450,68 +599,8 @@ EOF<br>> mv $sources.saved $sources<br>> fi<br>><br>> - # 2(binaries). update Packages file archives<br>> - for packpath in dists/$loop_dist/$component/binary-* ; do<br>> - pushd $packpath<br>> - if [ -f Packages ]; then<br>> - sed -i '/./,$!d' Packages<br>> - bzip2 -c Packages >Packages.bz2<br>> - gzip -c Packages >Packages.gz<br>> - fi<br>> - popd<br>> - done<br>> -<br>> - # 2(sources). update Sources file archives<br>> - pushd dists/$loop_dist/$component/source<br>> - if [ -f Sources ]; then<br>> - sed -i '/./,$!d' Sources<br>> - bzip2 -c Sources >Sources.bz2<br>> - gzip -c Sources >Sources.gz<br>> - fi<br>> - popd<br>> -<br>> - # 3. update checksums entries of the Packages* files in *Release files<br>> - # NOTE: it is stable structure of the *Release files when the checksum<br>> - # entries in it in the following way:<br>> - # MD5Sum:<br>> - # <checksum> <size> <file orig><br>> - # <checksum> <size> <file debian><br>> - # SHA1:<br>> - # <checksum> <size> <file orig><br>> - # <checksum> <size> <file debian><br>> - # SHA256:<br>> - # <checksum> <size> <file orig><br>> - # <checksum> <size> <file debian><br>> - # The script bellow puts 'md5' value at the 1st found file entry,<br>> - # 'sha1' - at the 2nd and 'sha256' at the 3rd<br>> - pushd dists/$loop_dist<br>> - for file in $(grep " $component/" Release | awk '{print $3}' | sort -u) ; do<br>> - [ -f $file ] || continue<br>> - sz=$(stat -c "%s" $file)<br>> - md5=$(md5sum $file | awk '{print $1}')<br>> - sha1=$(sha1sum $file | awk '{print $1}')<br>> - sha256=$(sha256sum $file | awk '{print $1}')<br>> - awk 'BEGIN{c = 0} ; {<br>> - if ($3 == p) {<br>> - c = c + 1<br>> - if (c == 1) {print " " md " " s " " p}<br>> - if (c == 2) {print " " sh1 " " s " " p}<br>> - if (c == 3) {print " " sh2 " " s " " p}<br>> - } else {print $0}<br>> - }' p="$file" s="$sz" md="$md5" sh1="$sha1" sh2="$sha256" \<br>> - Release >Release.new<br>> - mv Release.new Release<br>> - done<br>> - # resign the selfsigned InRelease file<br>> - $rm_file InRelease<br>> - gpg --clearsign -o InRelease Release<br>> - # resign the Release file<br>> - $rm_file Release.gpg<br>> - gpg -u $GPG_SIGN_KEY -abs -o Release.gpg Release<br>> - popd<br>> -<br>> - # 4. sync the latest distribution path changes to S3<br>> - $aws_sync_public dists/$loop_dist "$bucket_path/dists/$loop_dist"<br>> + # call DEB dists path updater<br>> + update_deb_dists<br>> done<br>> }<br>><br>> @@ -525,6 +614,7 @@ EOF<br>> # at the Tarantool web site:<br>> # <a href="https://www.tarantool.io/en/download/os-installation/rhel-centos/" target="_blank">https://www.tarantool.io/en/download/os-installation/rhel-centos/</a><br>> # <a href="https://www.tarantool.io/en/download/os-installation/fedora/" target="_blank">https://www.tarantool.io/en/download/os-installation/fedora/</a><br>> +<br>> function pack_rpm {<br>> pack_subdir=$1<br>> pack_patterns=$2<br>> @@ -631,12 +721,12 @@ function pack_rpm {<br>> packs_rm=$(($packs_rm+1))<br>> done<br>> # reduce number of packages in metafile counter<br>> - gunzip ${metafile}.xml.gz<br>> + gunzip -f ${metafile}.xml.gz<br>> packs=$(($(grep " packages=" ${metafile}.xml | \<br>> sed 's#.* packages="\([0-9]*\)".*#\1#g')-${packs_rm}))<br>> sed "s# packages=\"[0-9]*\"# packages=\"${packs}\"#g" \<br>> -i ${metafile}.xml<br>> - gzip ${metafile}.xml<br>> + gzip -f ${metafile}.xml<br>> done<br>> fi<br>> done<br>> @@ -711,10 +801,141 @@ EOF<br>> $aws_sync_public repodata "$bucket_path/$repopath/repodata"<br>> }<br>><br>> +function remove_rpm {<br>> + pack_subdir=$1<br>> + pack_patterns=$2<br>> +<br>> + pushd $ws<br>> +<br>> + # set the paths<br>> + repopath=$option_dist/$pack_subdir<br>> + rpmpath=Packages<br>> + packpath=$repopath/$rpmpath<br>> +<br>> + # prepare local repository with packages<br>> + $mk_dir $packpath<br>> + cd $repopath<br>> +<br>> + # copy the current metadata files from S3<br>> + mkdir repodata<br>> + pushd repodata<br>> + for file in $($aws ls $bucket_path/$repopath/repodata/ | awk '{print $NF}') ; do<br>> + $aws ls $bucket_path/$repopath/repodata/$file || continue<br>> + $aws cp $bucket_path/$repopath/repodata/$file $file<br>> + [[ ! $file =~ .*.gz ]] || gunzip $file<br>> + done<br>> +<br>> + updated_rpms=0<br>> + # loop by the new hashes from the new meta file<br>> + for hash in $(grep "<package pkgid=" other.xml | awk -F'"' '{print $2}') ; do<br>> + updated_rpm=0<br>> + file_exists=''<br>> + name=$(grep "<package pkgid=\"$hash\"" other.xml | awk -F'"' '{print $4}')<br>> + file=$(grep -e "<checksum type=" -e "<location href=" primary.xml | \<br>> + grep "$hash" -A1 | grep "<location href=" | \<br>> + awk -F'"' '{print $2}')<br>> + for pack_pattern in $pack_patterns ; do<br>> + [[ $file =~ Packages/$remove$pack_pattern ]] || continue<br>> +<br>> + # check if the file already exists in S3<br>> + ! $aws ls "$bucket_path/$repopath/$file" || \<br>> + $aws rm "$bucket_path/$repopath/$file"<br>> +<br>> + # search the new hash in the old meta file from S3<br>> + grep "pkgid=\"$hash\"" filelists.xml | grep "name=\"$name\"" || continue<br>> + updated_rpms=1<br>> + hashes_old=$(grep -e "<checksum type=" -e "<location href=" primary.xml | \<br>> + grep -B1 "$file" | grep "<checksum type=" | \<br>> + awk -F'>' '{print $2}' | sed 's#<.*##g')<br>> + # NOTE: for the single file name may exists more than one<br>> + # entry in damaged file, to fix it all found entries<br>> + # of this file need to be removed<br>> + for metafile in other filelists primary ; do<br>> + up_lines=''<br>> + if [ "$metafile" == "primary" ]; then<br>> + up_full_lines='(\N+\n)*'<br>> + fi<br>> + packs_rm=0<br>> + # find and remove all <package> tags for the bad hashes<br>> + for hash_rm in $hashes_old ; do<br>> + echo "Removing from ${metafile}.xml file old hash: $hash_rm"<br>> + sed -i '1s/^/\n/' ${metafile}.xml<br>> + pcregrep -Mi -v "(?s)<package ${up_full_lines}\N+(?=${hash_rm}).*?package>" \<br>> + ${metafile}.xml >${metafile}_new.xml<br>> + mv ${metafile}_new.xml ${metafile}.xml<br>> + packs_rm=$(($packs_rm+1))<br>> + done<br>> + # reduce number of packages in metafile counter<br>> + packs=$(($(grep " packages=" ${metafile}.xml | \<br>> + sed 's#.* packages="\([0-9]*\)".*#\1#g')-${packs_rm}))<br>> + sed "s# packages=\"[0-9]*\"# packages=\"${packs}\"#g" \<br>> + -i ${metafile}.xml<br>> + done<br>> + done<br>> + done<br>> +<br>> + # check if any RPM files were newly registered<br>> + [ "$updated_rpms" == "0" ] && \<br>> + return || echo "Updating dists"<br>> +<br>> + # merge metadata files<br>> + mv repomd.xml repomd_saved.xml<br>> + head -n 2 repomd_saved.xml >repomd.xml<br>> + for file in filelists.xml other.xml primary.xml ; do<br>> + # get the new data<br>> + chsnew=$(sha256sum $file | awk '{print $1}')<br>> + sz=$(stat --printf="%s" $file)<br>> + gzip $file<br>> + chsgznew=$(sha256sum $file.gz | awk '{print $1}')<br>> + szgz=$(stat --printf="%s" $file.gz)<br>> + timestamp=$(date +%s -r $file.gz)<br>> +<br>> + # add info to repomd.xml file<br>> + name=$(echo $file | sed 's#\.xml$##g')<br>> + cat <<EOF >>repomd.xml<br>> +<data type="$name"><br>> + <checksum type="sha256">$chsgznew</checksum><br>> + <open-checksum type="sha256">$chsnew</open-checksum><br>> + <location href="repodata/$file.gz"/><br>> + <timestamp>$timestamp</timestamp><br>> + <size>$szgz</size><br>> + <open-size>$sz</open-size><br>> +</data>"<br>> +EOF<br>> + done<br>> + tail -n 1 repomd_saved.xml >>repomd.xml<br>> + rm -f repomd_saved.xml repomd.xml.asc<br>> + popd<br>> + gpg --detach-sign --armor repodata/repomd.xml<br>> +<br>> + # update the metadata at the S3<br>> + $aws_sync_public repodata "$bucket_path/$repopath/repodata"<br>> +}<br>> +<br>> if [ "$os" == "ubuntu" -o "$os" == "debian" ]; then<br>> # prepare the workspace<br>> prepare_ws ${os}<br>> - pack_deb<br>> +<br>> + # we need to push packages into 'main' repository only<br>> + component=main<br>> +<br>> + # debian has special directory 'pool' for packages<br>> + debdir=pool<br>> +<br>> + # set the subpath with binaries based on literal character of the product name<br>> + proddir=$(echo $product | head -c 1)<br>> +<br>> + # copy single distribution with binaries packages<br>> + poolpath=pool/${option_dist}/$component/$proddir/$product<br>> + repopath=$ws/$poolpath<br>> + $mk_dir ${repopath}<br>> +<br>> + if [ "$remove" != "" ]; then<br>> + remove_deb<br>> + else<br>> + pack_deb<br>> + fi<br>> +<br>> # unlock the publishing<br>> $rm_file $ws_lockfile<br>> popd<br>> @@ -726,14 +947,22 @@ elif [ "$os" == "el" -o "$os" == "fedora" ]; then<br>><br>> # prepare the workspace<br>> prepare_ws ${os}_${option_dist}<br>> - pack_rpm x86_64 "*.x86_64.rpm *.noarch.rpm"<br>> + if [ "$remove" != "" ]; then<br>> + remove_rpm x86_64 "-1.*.x86_64.rpm -1.*.noarch.rpm"<br>> + else<br>> + pack_rpm x86_64 "*.x86_64.rpm *.noarch.rpm"<br>> + fi<br>> # unlock the publishing<br>> $rm_file $ws_lockfile<br>> popd<br>><br>> # prepare the workspace<br>> prepare_ws ${os}_${option_dist}<br>> - pack_rpm SRPMS "*.src.rpm"<br>> + if [ "$remove" != "" ]; then<br>> + remove_rpm SRPMS "-1.*.src.rpm"<br>> + else<br>> + pack_rpm SRPMS "*.src.rpm"<br>> + fi<br>> # unlock the publishing<br>> $rm_file $ws_lockfile<br>> popd<br>> --<br>> 2.17.1<br>></div><br>--<br>sergeyb@</div></div></div></div></blockquote> <div> </div><div data-signature-widget="container"><div data-signature-widget="content"><div>--<br>Alexander Tikhonov</div></div></div><div> </div></div></BODY></HTML>