From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0 ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms0.migadu.com with LMTPS id WKzGFqk9Q2FZEQAAgWs5BA (envelope-from ) for ; Thu, 16 Sep 2021 14:50:49 +0200 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0 with LMTPS id MF59Eqk9Q2E2dAAA1q6Kng (envelope-from ) for ; Thu, 16 Sep 2021 12:50:49 +0000 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 090982C599 for ; Thu, 16 Sep 2021 14:50:49 +0200 (CEST) Received: from localhost ([::1]:56238 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mQqql-0005tx-MT for larch@yhetil.org; Thu, 16 Sep 2021 08:50:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51598) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mQqp4-0003sA-PS for guix-patches@gnu.org; Thu, 16 Sep 2021 08:49:02 -0400 Received: from debbugs.gnu.org ([209.51.188.43]:42544) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1mQqp4-0004dZ-I3 for guix-patches@gnu.org; Thu, 16 Sep 2021 08:49:02 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1mQqp4-0007ET-9H for guix-patches@gnu.org; Thu, 16 Sep 2021 08:49:02 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#50359] [PATCH 3/3] import: Add 'generic-git' updater. Resent-From: Xinglu Chen Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Thu, 16 Sep 2021 12:49:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 50359 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Sarah Morgensen Cc: Ludovic =?UTF-8?Q?Court=C3=A8s?= , 50359@debbugs.gnu.org Received: via spool by 50359-submit@debbugs.gnu.org id=B50359.163179652127774 (code B ref 50359); Thu, 16 Sep 2021 12:49:02 +0000 Received: (at 50359) by debbugs.gnu.org; 16 Sep 2021 12:48:41 +0000 Received: from localhost ([127.0.0.1]:54090 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mQqoi-0007Dt-Dp for submit@debbugs.gnu.org; Thu, 16 Sep 2021 08:48:41 -0400 Received: from h87-96-130-155.cust.a3fiber.se ([87.96.130.155]:34060 helo=mail.yoctocell.xyz) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mQqoc-0007Db-JV for 50359@debbugs.gnu.org; Thu, 16 Sep 2021 08:48:38 -0400 From: Xinglu Chen DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=yoctocell.xyz; s=mail; t=1631796506; bh=sqik6FOfVFPmKqsgSwYkJN3vEqN6ixjpqVUDzhm8ND0=; h=From:To:Cc:Subject:In-Reply-To:References:Date; b=tQv9FBimJ1wLBh9WLfDFmP/YmwXiM+Mvd8+7wC8vL1VM7N3AmAGC0eV0jktt/0t69 3WlotXBBhG7SVjw1VtHSZpBtFBTTwWucq2mXwa47bqMJIcj7Gs9tsuUCuDxs7pZTYo pIZyG9E5iTLEpBA1l5BWyl+Qj8G/0QtQLyYEGKXQ= In-Reply-To: <86czp8j38z.fsf@mgsn.dev> References: <5d10dd1e65b0a65ada4a8102310c10de42f53e8d.1631290349.git.public@yoctocell.xyz> <86czp8j38z.fsf@mgsn.dev> Date: Thu, 16 Sep 2021 14:48:23 +0200 Message-ID: <87h7ekr8iw.fsf@yoctocell.xyz> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: "Guix-patches" X-Migadu-Flow: FLOW_IN X-Migadu-Spam-Score: -4.00 Authentication-Results: aspmx1.migadu.com; none X-Migadu-Queue-Id: 090982C599 X-Spam-Score: -4.00 X-Migadu-Scanner: scn0.migadu.com X-TUID: 3sTjcLgpqO0L --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Thu, Sep 16 2021, Sarah Morgensen wrote: > Hi, > > Xinglu Chen writes: > >> On Wed, Sep 15 2021, iskarian@mgsn.dev wrote: >> >>> Hi, >>> >>> September 10, 2021 9:21 AM, "Xinglu Chen" wrote: >>> >>>> * guix/git.scm (ls-remote-refs): New procedure. >>>> * tests/git.scm ("remote-refs" "remote-refs: only tags"): New tests. >>>> * guix/import/git.scm: New file. >>>> * doc/guix.texi (Invoking guix refresh): Document it. >>>> * tests/import-git.scm: New test file. >>>> * Makefile.am (MODULES, SCM_TESTS): Register the new files. >>>>=20 >>>> Co-authored-by: Sarah Morgensen >>> >>> Overall this is looking good. Thank you for adding tests (for >>> remote-refs as well!), much appreciated. It looks like you've done >>> some good polishing. I see a few nits, which I'll point out in a >>> separate email when I'm not on mobile. I'll also give it a good test. >>> >>> But... I've been thinking about the overall approach for a couple >>> days, because I'm not very happy with the complexity of my heuristic. >>> >>> There can be a lot of weird tags in a repository--look at the one for >>> xf86-video-intel for example. My heuristic attempts to capture the >>> assumption that repostories tend to move from using "_" or "-" to "." >>> but it does fail to account for moving to or from dates (because dates >>> don't compare with normal versions). >> >> But if a repo moved from using versions to tags, or vice-versa, we still >> wouldn=E2=80=99t know if say =E2=80=9C3.0.1=E2=80=9D is newer than =E2= =80=9C2021.03.02=E2=80=9D. We would have >> to know when the =E2=80=9C3.0.1=E2=80=9D tag was created. > > You're right; I thought of that afterwards. > >> Maybe we could have a =E2=80=98release-tag-date-scheme?=E2=80=99 propert= y, that way we >> could just try to match dates? > > That seems like it might be the only way to handle it in some cases (if > they have both versions and dates with a "." delimiter). It doesn=E2=80=99t have to be =E2=80=9C.=E2=80=9D delimiter though; if they= both have the same delimiter it would be difficult to distinguish a version from a date, e.g., =E2=80=9C1-2-3=E2=80=9D vs =E2=80=9C2021-03-23=E2=80=9D. > (Though, we are actually interested in the *lack* of a date scheme. > If they use a date scheme now, other versions will be disregarded, so > we're fine; but if they use versions now and used a date scheme > before, the versions will be discarded.) I am not sure what you are trying to say, could you elaborate? >>> I also realized that we are not using a very useful piece of >>> information--the previous version/tag combo. I expect that in the >>> vast majority of cases, the version delimiter for the newest version >>> will be the same as the version delimiter for the last known version. >>> (Perhaps the prefix as well?) Can we use this information to make our >>> guesses better? What do you think? >> >> That sounds like a good idea. What should happen if the delimiter from >> the previous version/tag combo is different from the one that the >> =E2=80=98guess-delimiter=E2=80=99 procedure returns? Should the one fro= m the previous >> version/tag combo take precedence. > > Consider: > > prefix :=3D 'tag-prefix or guess-prefix-from-current-version+tag or def= ault > delim :=3D 'tag-delim or guess-delim-from-current-version+tag or guess-= delimiter > suffix :=3D 'tag-suffix or default > > This should cover: > > 1. Format stayed the same (including date formats) > 2. Format changed from (git-version ...) to proper version > > This does not otherwise cover a complete change in format, such as "_" > -> ".", date(-) -> version, or version -> date(.), for which I could > argue requiring a manual update is reasonable. Yeah, it=E2=80=99s not really possible to automatically detect those kind of changes. > It also does not cover when the tags have both versions and dates with > the same delimiter. > > Though it would be nice to see when such updates are available, is it > worth some bogus results? Are false positives better or false negatives > better? Hmm, good question! If in the future we have some kind of bot that automatically runs =E2=80=98guix refresh -u=E2=80=99, builds the updated pa= ckage, and send a patch to the mailing list, not having false positives might be more important. We could also have a =E2=80=98disable-tag-updater?=E2=80= =99 property to disable the updater for packages which gives false positive, or maybe that will result in to many properties. > Unless you/we want to pursue one or both of the above changes now, the > latest patch LGTM (modulo my nits). I would prefer to wait a bit with the improvements mentioned above. The current patch has been in the works a week or two already, so it=E2=80=99s probably a good idea to get it merged, and try to solve the less important issues later. :-) > Thanks for your work, You are welcome! And thanks for taking the time to test and review the work. On Thu, Sep 16 2021, Sarah Morgensen wrote (again): > Hello, > > Here are my promised nits. > > Xinglu Chen writes: > >> * guix/git.scm (ls-remote-refs): New procedure. >> * tests/git.scm ("remote-refs" "remote-refs: only tags"): New tests. >> * guix/import/git.scm: New file. >> * doc/guix.texi (Invoking guix refresh): Document it. >> * tests/import-git.scm: New test file. >> * Makefile.am (MODULES, SCM_TESTS): Register the new files. >> >> Co-authored-by: Sarah Morgensen > > Again, much thanks for writing tests. > >> +@item generic-git >> +a generic updater for packages hosted on Git repositories. It tries to >> +be smart about parsing Git tag names, but if it is not able to parse the >> +tag name and compare tags correctly, users can define the following >> +properties for a package. >> + >> +@itemize >> +@item @code{release-tag-prefix}: a regular expression for matching a pr= efix of >> +the tag name. >> + >> +@item @code{release-tag-suffix}: a regular expression for matching a su= ffix of >> +the tag name. >> + >> +@item @code{release-tag-version-delimiter}: a string used as the delimi= ter in >> +the tag name for separating the numbers of the version. >> +@end itemize >> + >> +@lisp >> +(package >> + (name "foo") >> + ;; ... >> + (properties >> + '((release-tag-prefix . "^release0-") >> + (release-tag-suffix . "[a-z]?$") >> + (release-tag-version-delimiter . ":")))) >> +@end lisp >> + >> +By default, the updater will ignore pre-releases; to make it also look >> +for pre-releases, set the @code{accept-pre-releases?} property to >> +@code{#t}. > > Should this be itemized above? That=E2=80=99s probably a good idea, since it is related to how the tag wil= l be parsed. >> + >> +;; >> +;;; Remote operations. >> +;;; >> + >> +(define* (remote-refs url #:key tags?) >> + "Return the list of references advertised at Git repository URL. If = TAGS? >> +is true, limit to only refs/tags." >> + (define (ref? ref) >> + ;; Like `git ls-remote --refs', only show actual references. >> + (and (string-prefix? "refs/" ref) >> + (not (string-suffix? "^{}" ref)))) >> + >> + (define (tag? ref) >> + (string-prefix? "refs/tags/" ref)) >> + >> + (define (include? ref) >> + (and (ref? ref) >> + (or (not tags?) (tag? ref)))) >> + >> + (with-libgit2 >> + (call-with-temporary-directory >> + (lambda (cache-directory) >> + (let* ((repository (repository-init cache-directory)) >> + ;; Create an in-memory remote so we don't touch disk. >> + (remote (remote-create-anonymous repository url))) >> + (remote-connect remote) >> + (remote-disconnect remote) >> + (repository-close! repository) >> + >> + (filter-map (lambda (remote) >> + (let ((name (remote-head-name remote))) >> + (and (include? name) >> + name))) >> + (remote-ls remote))))))) > > I discovered that this can segfault unless 'remote-disconnect' and > possibly 'repository-close!' are called *after* copying the data out. > I've attached a diff for this. I don=E2=80=99t see a diff attached; maybe you forgot? :-) >> + >> +;;; Updater >> + >> +(define %pre-release-words >> + '("alpha" "beta" "rc" "dev" "test")) > > I found a few packages that use "pre" as well. Good catch, I noticed that as well when doing some more testing. >> + >> +(define %pre-release-rx >> + (map (cut make-regexp <> regexp/icase) %pre-release-words)) >> + >> +(define* (version-mapping tags #:key prefix suffix delim pre-releases?) >> + "Given a list of Git TAGS, return a association list where the car is= the > ^ an > >> +version corresponding to the tag, and the cdr is the name of the tag." >> + (define (guess-delimiter) >> + (let ((total (length tags)) >> + (dots (reduce + 0 (map (cut string-count <> #\.) tags))) >> + (dashes (reduce + 0 (map (cut string-count <> #\-) tags))) >> + (underscores (reduce + 0 (map (cut string-count <> #\_) tags)= ))) >> + (cond >> + ((>=3D dots (* total 0.35)) ".") >> + ((>=3D dashes (* total 0.8)) "-") >> + ((>=3D underscores (* total 0.8)) "_") >> + (else "")))) >> + >> + (define delim-rx (regexp-quote (or delim (guess-delimiter)))) >> + (define suffix-rx (string-append (or suffix "") "$")) >> + >> +=20=20 >> + (define prefix-rx (string-append "^" (or prefix "[^[:digit:]]*"))) >> + (define pre-release-rx >> + (if pre-releases? >> + (string-append ".*(" (string-join %pre-release-words "|") ").*") >> + "")) >> + >> + (define tag-rx >> + (string-append prefix-rx "([[:digit:]][^" delim-rx "[:punct:]]*" >> + "(" delim-rx "[^[:punct:]" delim-rx "]+)" >> + ;; If there is are no delimiters, it could mean that= the > ^ no "is" > >> + ;; version just contains one number (e.g., "2"), thu= s, use >> + ;; "*" instead of "+" to match zero or more numbers. >> + (if (string=3D? delim-rx "") "*" "+") > > Good catch. > >> + pre-release-rx ")" suffix-rx)) >> + >> + (define (get-version tag) >> + (let ((tag-match (regexp-exec (make-regexp tag-rx) tag))) >> + (and tag-match >> + (regexp-substitute/global >> + #f delim-rx (match:substring tag-match 1) >> + ;; Don't insert "." if there aren't any delimiters in the f= irst > > Nit: "if there were no delimiters", to be consistent with above comment. Noted. >> + ;; place. >> + 'pre (if (string=3D? delim-rx "") "" ".") 'post)))) > > One issue with returning a different delimiter than the package > currently uses is that the automatic updater won't really work as-is. Good point;, the tag name would be incorrect in those cases. > Hmmm. When things are modified so the updater gets both the version and > the git-reference, it should be able to reverse-engineer things well > enough there. Ah, looks like (guix upstream) needs some work. :-) > I imagine this is really only going to be an issue with dates currently > written as "2017-01-01", anyway. I'll put my comments on that in reply > to the other email. > >> + >> + (define (entry> + (eq? (version-compare (car a) (car b)) '<)) >> + >> + (stable-sort (filter-map (lambda (tag) >> + (let ((version (get-version tag))) >> + (and version (cons version tag)))) >> + tags) >> + entry> + >> +(define* (latest-tag url #:key prefix suffix delim pre-releases?) >> + "Return the latest tag available from the Git repository at URL." > > This returns two values (in preparation for the above-mentioned switch), > so maybe something like "Return the latest version and corresponding tag > available from..." Good catch. >> + (define (pre-release? tag) >> + (any (cut regexp-exec <> tag) >> + %pre-release-rx)) >> + >> + (let* ((tags (map (cut string-drop <> (string-length "refs/tags/")) > > Should be "cute" so string-length is only evaluated once -- though it's > probably optimized like that anyway. Good catch, I keep forgetting that =E2=80=98cute=E2=80=99 exists. :-) >> + (remote-refs url #:tags? #t))) >> + (versions->tags >> + (version-mapping (if pre-releases? >> + tags >> + (filter (negate pre-release?) tags)) >> + #:prefix prefix >> + #:suffix suffix >> + #:delim delim >> + #:pre-releases? pre-releases?))) >> + (cond >> + ((null? tags) >> + (git-no-tags-error)) >> + ((null? versions->tags) >> + (git-no-valid-tags-error)) >> + (else >> + (match (last versions->tags) >> + ((version . tag) >> + (values version tag))))))) >> + >> +(define (latest-git-tag-version package) >> + "Given a PACKAGE, return the latest version of it, or #f if the lates= t version >> +could not be determined." >> + (guard (c ((or (git-no-tags-error? c) (git-no-valid-tags-error? c)) >> + (warning (or (package-field-location package 'source) >> + (package-location package)) >> + (G_ "~a for ~a~%") >> + (condition-message c) >> + (package-name package)) >> + #f) >> + ((eq? (exception-kind c) 'git-error) >> + (warning (or (package-field-location package 'source) >> + (package-location package)) >> + (G_ "failed to fetch Git repository for ~a~%") >> + (package-name package)) >> + #f)) >> + (let* ((source (package-source package)) >> + (url (git-reference-url (origin-uri source))) >> + (properties (package-properties package)) >> + (tag-prefix (assq-ref properties 'release-tag-prefix)) >> + (tag-suffix (assq-ref properties 'release-tag-suffix)) >> + (tag-version-delimiter (assq-ref properties 'release-tag-ver= sion-delimiter)) >> + (refresh-pre-releases? (assq-ref properties 'accept-pre-rele= ases?))) >> + (latest-tag url >> + #:prefix tag-prefix >> + #:suffix tag-suffix >> + #:delim tag-version-delimiter >> + #:pre-releases? refresh-pre-releases?)))) > > This is entirely a style preference, so only take this suggestion if you > like it :) > > (let* ((source (package-source package)) > (url (git-reference-url (origin-uri source))) > (property (cute assq-ref (package-properties package) <>))) > (latest-tag url > #:prefix (property 'release-tag-prefix) > #:suffix (property 'release-tag-suffix) > #:delim (property 'release-tag-version-delimiter) > #:pre-releases? (property 'accept-pre-releases?))))) That does look cleaner, thanks for the suggestion! >> + >> +(define (git-package? package) >> + "Whether the origin of PACKAGE is a Git repostiory." > > "Return true if PACKAGE is..." =E2=80=9CPACKAGE is a Git repository.=E2=80=9D doesn=E2=80=99t really sound= right, maybe =E2=80=9Cif PACKAGE is hosted on a Git repository=E2=80=9D? >> + (match (package-source package) >> + ((? origin? origin) >> + (and (eq? (origin-method origin) git-fetch) >> + (git-reference? (origin-uri origin)))) >> + (_ #f))) >> + >> +(define (latest-git-release package) >> + "Return the latest release of PACKAGE." > > "Return an for the latest...", to match the other > updaters. > >> + (let* ((name (package-name package)) >> + (old-version (package-version package)) >> + (url (git-reference-url (origin-uri (package-source package)))) >> + (new-version (latest-git-tag-version package))) >> + >> + (and new-version >> + (upstream-source >> + (package name) >> + (version new-version) >> + (urls (list url)))))) >> + >> +(define %generic-git-updater >> + (upstream-updater >> + (name 'generic-git) >> + (description "Updater for packages hosted on Git repositories") >> + (pred git-package?) >> + (latest latest-git-release))) > > I tested this updater on all packages in .scm files starting with f > through z, and I found the following packages with possibly bogus > updates: > > --8<---------------cut here---------------start------------->8--- > javaxom I assume you meant =E2=80=98java-xom=E2=80=99 :-) That=E2=80=99s a weird scheme; setting the delimiter to =E2=80=9C.=E2=80=9D= doesn=E2=80=99t help since it thinks that =E2=80=9C127=E2=80=9D is greater than =E2=80=9C1.3.7=E2=80= =9D. > luakit > ocproxy > pitivi =E2=80=98pitivi=E2=80=99 has a pretty weird version string to begin with; i= t may be better to change it to the date: =E2=80=9C0.999.0-2021-05.0=E2=80=9D -> =E2= =80=9C2021-05.0=E2=80=9D. > eid-mw > libhomfly > gnuradio > welle-io Setting the delimiter to "." fixes the issue. > racket-minimal Setting the prefix to "v" fixes this. > milkytracker > cl-portal > kodi-cli > openjdk > java-bouncycastle > hurd > opencsg Setting the suffix to "-release" fixes this. > povray > gpsbabel Setting the prefix to "gpsbabel_" fixes this. > go > stepmania > ocaml-mcl > > many minetest packages (minetest will have its own updater, though) > > ocaml4.07-core-kernel, ocamlbuild and many other ocaml packages > (they seem to be covered by the github updater) > --8<---------------cut here---------------end--------------->8--- Hmm, =E2=80=98guix refresh=E2=80=99 says that =E2=80=98ocamlbuild=E2=80=99 = is already the latest version. But you are right, many of the packages are already taken care of by the =E2=80=98github=E2=80=99 updater. > The following packages suggest a version -> date update, which may or > may not be bogus: > > --8<---------------cut here---------------start------------->8--- > cataclysm-dda > autotrace > lbalgtk > nheko > libqalculate > cl-antik > cl-antik-base > cl-hu.dwim.stefil > cl-stefil > cl-gsll > sbcl-cl-gserver > --8<---------------cut here---------------end--------------->8--- Thanks for taking the time to find these false positive! --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQJJBAEBCAAzFiEEAVhh4yyK5+SEykIzrPUJmaL7XHkFAmFDPRcVHHB1YmxpY0B5 b2N0b2NlbGwueHl6AAoJEKz1CZmi+1x5+L0P/jci8tK0hLt7DucS+KeZSQHncSzx fumt9Ln41wxv2WmnnLMb0id8slP+7dSsolk4TXzx+Udly500HLVTNuioLJWV1S86 nvl4bO01DtDz5u48oht6YpRTVjshepAS7mpY39UubGP0aF137ljICsL03uQltuoU 7S5pZggZSlwAfFZtIwpmkrzi+xLMcIMLto2Q+fefe7f2+oKz3XkvZqHhs9hNuCLt TAglODmOgs2fo2A6QBp4K/3CfcMiZphGvPpWUOsTKQ+bFMFnhRD44qBl6q9cyY1J JauSz9nC24nWgOqDhkx3SFxcsDKpc5Oep27aOGSnNS+qrDI1qDsXtBwsfDPbeM28 jH44J9qnzxu69r0trAx5xpLp5sF6YV5GQk49MXandRtsMUChcy4P+w+kg83oR+y/ dYPgFjvG2pDh46EorgO+Yu7T7ND1XcMlrQ4HZfWBwB+nzkhhocMxsPGnOuJHVxhO vmZ42EtrC1XyE2zgtnk7nCZlcrgVyPqpnBpJzeyPd1iLSYVX+fYDP2W1X0YkoZLg YoAiy9Vf3XoU69iiEZmP26nVJUFoTCiK5vUmla6u8mQuGZgZf4ozMF5dRR5xErCl 2WMqgguZGq5DtOIvhH8hvwvvB5LfMNyL8Bu2LyP7mBBR3wTf08iQAT+inBuQSg/b kBypjToJW+j6qFU/ =dF62 -----END PGP SIGNATURE----- --=-=-=--