From 19095ff14b5a1be9240376e527c906a55f7e98f6 Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Mon, 14 Jul 2008 07:56:18 +0000 Subject: [PATCH] * Added `version->integer' * Added tests (mostly just that for now) * Documented `version/utils' svn: r10756 --- collects/tests/mzscheme/all.ss | 1 + collects/tests/mzscheme/version.ss | 64 ++++++++++++++++++++++++ collects/version/utils.ss | 39 +++++++++++++-- collects/version/version.scrbl | 78 +++++++++++++++++++++++++----- 4 files changed, 166 insertions(+), 16 deletions(-) create mode 100644 collects/tests/mzscheme/version.ss diff --git a/collects/tests/mzscheme/all.ss b/collects/tests/mzscheme/all.ss index 12dac8bc3d..2f9387c6e2 100644 --- a/collects/tests/mzscheme/all.ss +++ b/collects/tests/mzscheme/all.ss @@ -3,6 +3,7 @@ (load-relative "mz.ss") (load-relative "scheme.ss") (load-relative "mzlib.ss") +(load-in-sandbox "version.ss") (load-in-sandbox "moddep.ss") (load-in-sandbox "boundmap-test.ss") (load-in-sandbox "net.ss") diff --git a/collects/tests/mzscheme/version.ss b/collects/tests/mzscheme/version.ss new file mode 100644 index 0000000000..c95c32ef72 --- /dev/null +++ b/collects/tests/mzscheme/version.ss @@ -0,0 +1,64 @@ + +(load-relative "loadtest.ss") + +(Section 'version) + +(require version/utils) + +(test #t valid-version? (version)) +(for-each (lambda (v+i) (test (cadr v+i) version->integer (car v+i))) + '(;; legacy version scheme + ["372" 372000000] + ["372.0" #f] ; should be just "372" + ["372.1" 372001000] + ["372.12" 372012000] + ["123.4" 123004000] + ["49" 49000000] ; oldest legacy-version supported + ["103" 103000000] + ;; new version scheme + ["4.0" 400000000] + ["4" #f] ; must have one decimal digit + ["4.1" 401000000] + ["4.0.1" 400001000] + ["4.0.2" 400002000] + ["4.1.2.3" 401002003] + ["4.0.0.99" 400000099] + ["4.12.123.999" 412123999] + ["4.99.99.99" 499099099] + ["4.99.99.099" #f] ; leading zeroes forbidden + ["4.99.099.99" #f] + ["4.09.99.99" #f] + ["04.9.99.0" #f] + ["4.9.99.00" #f] + ["00.0" #f] + ["4.99.099.099" #f] + ["4.99.0" #f] ; single zero forbidden at end + ["4.99.99.0" #f] + ["0.0" 0] ; smallest new-scheme version + ["10.0" 1000000000] + ["10.0.1" 1000001000] + ["48.99.999.999" 4899999999] ; largest new-scheme version allowed + ["4.100" #f] ; second component should be < 100 + ["4.999" #f] + ["1.2.3.4.5" #f] ; only four parts + ["1..2" #f] ; other random junk + [".1" #f] + ["1." #f] + ["foo" #f] + ["0" #f] + )) + +;"planet-shared.ss"> (string->mz-version "1.2.3.4.5") +;#(struct:mz-version 102 3004) SHOULD BE #f +;"planet-shared.ss"> (string->mz-version "1...2") +;#f +;"planet-shared.ss"> (string->mz-version ".2") +;#f +;"planet-shared.ss"> (string->mz-version "2.") +;#f +;"planet-shared.ss"> (string->mz-version "foo") +;#f +;"planet-shared.ss"> (string->mz-version "x.y") +;#f + +(report-errs) diff --git a/collects/version/utils.ss b/collects/version/utils.ss index ec70db66fb..909e67ef4f 100644 --- a/collects/version/utils.ss +++ b/collects/version/utils.ss @@ -1,6 +1,7 @@ #lang scheme/base -(provide valid-version? version->list versionlist versioninteger) (define rx:version ;; (this restricts the last component to be below 999 too, which is @@ -12,6 +13,8 @@ (define (valid-version? s) (and (string? s) (regexp-match? rx:version s))) +;; the following functions assume valid version string inputs + ;; returns a list of 4 integers (see src/mzscheme/src/schvers.h) (define (version->list str) (let ([ver (map string->number (regexp-split #rx"[.]" str))]) @@ -21,8 +24,6 @@ [(4) ver] [else (error 'version->list "bad version: ~e" str)]))) -;; the following functions assume valid version string inputs - (define (versionlist a)] [b (version->list b)]) @@ -37,3 +38,35 @@ (define (alpha-version? v) (let ([l (version->list v)]) (or ((list-ref l 1) . >= . 90) ((list-ref l 2) . >= . 900)))) + +;; returns an integer representing the version (XXYYZZZWWW) or #f if invalid +;; works for pre v4 versions too +(define (version->integer v) + (cond + [(regexp-match-positions #rx"^(?:0|[1-9][0-9]*)" v) ; takes all digits + => (lambda (m) + (let* (;; translate to a new-style version + [n (string->number (substring v 0 (cdar m)))] + [v (if (< n 49) + v + (let-values ([(q r) (quotient/remainder n 100)]) + ;; put numbers and possible .N leftover + (format "~a.~a~a" q r (substring v (cdar m)))))]) + (and (valid-version? v) + (let ([l (version->list v)]) + (let loop ([v (car l)] + [l (cdr l)] + [f '(100 1000 1000)]) + (if (null? l) + v + (loop (+ (* v (car f)) (car l)) (cdr l) (cdr f))))))))] + [else #f])) + +;; general sanity check, performed once when loaded +(when (>= (string->number (car (regexp-match #rx"^[0-9]+" (version)))) 49) + ;; When this happens, we got to numbers that can be confused with old version + ;; numbers, and the above code should be modified. With the current rate of + ;; changes, this should happen in more 150 years. Either programming is + ;; probably done with a direct brain link, or this software has nobody to fix + ;; it because everybody went back to the trees. + (error 'version/utils.ss "this file should be updated")) diff --git a/collects/version/version.scrbl b/collects/version/version.scrbl index f115d4b919..50107263a5 100644 --- a/collects/version/version.scrbl +++ b/collects/version/version.scrbl @@ -1,9 +1,10 @@ #lang scribble/doc @(require scribble/manual - scribble/bnf + scribble/bnf (for-label version/patchlevel version/check version/tool + version/utils scheme/base scheme/contract)) @@ -40,27 +41,27 @@ indicates the current state of the curent installation: @itemize{ - @item{@scheme[`ok] You're fine.} + @item{@scheme[`ok] --- You're fine.} - @item{@scheme[`(ok-but ,_version)] You have a fine stable version, - but note that there is a newer alpha version available numbered - @scheme[_version].} + @item{@scheme[`(ok-but ,_version)] --- You have a fine stable + version, but note that there is a newer alpha version available + numbered @scheme[_version].} - @item{@scheme[`(newer ,_version)] You have an old version. Please - upgrade to @scheme[_version].} + @item{@scheme[`(newer ,_version)] --- You have an old + version. Please upgrade to @scheme[_version].} - @item{@scheme[`(newer ,_version ,_alpha)] You have an + @item{@scheme[`(newer ,_version ,_alpha)] --- You have an old-but-stable version, please upgrade to @scheme[_version]; you may consider also the newer alpha version numbered @scheme[_alpha].} - @item{@scheme[`(error ,_message)] An error occurred, and + @item{@scheme[`(error ,_message)] --- An error occurred, and @scheme[_message] is a string that indicates the error.} - @item{@scheme[`(error ,_message ,_additional-info)] An error + @item{@scheme[`(error ,_message ,_additional-info)] --- An error occurred; @scheme[_message] is a string that indicates the error, and @scheme[_additional-info] is a string containing a - system error. The @scheme[_additional-info] content is always + system error. The @scheme[_additional-info] content is always parenthesizes, so @scheme[message] is a short error and @scheme[(string-append message " " additional-info)] is a verbose one.} @@ -79,11 +80,62 @@ The @scheme[version/tool] library implements a DrScheme tool that @itemize{ - @item{makes the patchlevel appears as a version @tt{p}@nonterm{N} - suffix in DrScheme, though the base verion reported by + @item{makes the patchlevel display as a version @tt{p}@nonterm{N} + suffix in DrScheme (though the base verion reported by @scheme[(version)] is not changed);} @item{if enabled by the user, periodically checks whether a new PLT Scheme distribution is available for download.} } + +@; ---------------------------------------------------------------------- + +@section{Version Utilities} + +@defmodule[version/utils]{ + +The @schememodname[version/utils] library provides a few of convenient +utilities for dealing with version strings. Unless explicitly noted, +these functions do not handle legacy versions of PLT Scheme.} + +@defproc[(valid-version? [str string?]) boolean?]{ + +Returns @scheme[#t] if @scheme[str] is a valid PLT Scheme version +string, @scheme[#f] otherwise.} + +@defproc[(version->list [str valid-version?]) + (list integer? integer? integer? integer?)]{ + +Returns a list of four numbers that the given version string +represent. @scheme[str] is assumed to be a valid version.} + +@defproc[(versioninteger [str string?]) (or/c integer? false/c)]{ + +Converts the version string into an integer. For version +@scheme["X.YY.ZZZ.WWW"], the result will be @schemevalfont{XYYZZZWWW}. +This function works also for legacy PLT Scheme versions, by +translating @scheme["XYY.ZZZ"] to @schemevalfont{XYYZZZ000}. The +resulting integer can thefore be used to conveniently compare any two +(valid) version strings. If the version string is invalid the +resulting value is @scheme[#f]. + +Note that this is the only function that deals with legacy version +strings.}