emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] emacs-25 d676e49: Improve parsing of version strings


From: Eli Zaretskii
Subject: [Emacs-diffs] emacs-25 d676e49: Improve parsing of version strings
Date: Sat, 05 Dec 2015 09:33:44 +0000

branch: emacs-25
commit d676e498255541a486c1d8a4cb30439bfb2ca385
Author: Alex Dunn <address@hidden>
Commit: Eli Zaretskii <address@hidden>

    Improve parsing of version strings
    
    * lisp/subr.el (version-regexp-alist): Allow "." as priority separator
    (version-to-list): More helpful error messages.
    (version-to-list): ".5" is valid (update docstring).  Make
    "22.8X3" invalid, as the doc string says.
    
    * test/automated/subr-tests.el (ert-test-version-parsing): New
    tests for version string processing.
    
    Copyright-paperwork-exempt: yes
---
 lisp/subr.el                 |   55 ++++++++++++---------
 test/automated/subr-tests.el |  112 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 143 insertions(+), 24 deletions(-)

diff --git a/lisp/subr.el b/lisp/subr.el
index 420b212..860c14c 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -4686,14 +4686,14 @@ Usually the separator is \".\", but it can be any other 
string.")
 
 
 (defconst version-regexp-alist
-  '(("^[-_+ ]?snapshot$"                                 . -4)
+  '(("^[-._+ ]?snapshot$"                                 . -4)
     ;; treat "1.2.3-20050920" and "1.2-3" as snapshot releases
-    ("^[-_+]$"                                           . -4)
+    ("^[-._+]$"                                           . -4)
     ;; treat "1.2.3-CVS" as snapshot release
-    ("^[-_+ ]?\\(cvs\\|git\\|bzr\\|svn\\|hg\\|darcs\\)$" . -4)
-    ("^[-_+ ]?alpha$"                                    . -3)
-    ("^[-_+ ]?beta$"                                     . -2)
-    ("^[-_+ ]?\\(pre\\|rc\\)$"                           . -1))
+    ("^[-._+ ]?\\(cvs\\|git\\|bzr\\|svn\\|hg\\|darcs\\)$" . -4)
+    ("^[-._+ ]?alpha$"                                    . -3)
+    ("^[-._+ ]?beta$"                                     . -2)
+    ("^[-._+ ]?\\(pre\\|rc\\)$"                           . -1))
   "Specify association between non-numeric version and its priority.
 
 This association is used to handle version string like \"1.0pre2\",
@@ -4703,6 +4703,7 @@ non-numeric part of a version string to an integer.  For 
example:
    String Version    Integer List Version
    \"0.9snapshot\"     (0  9 -4)
    \"1.0-git\"         (1  0 -4)
+   \"1.0.cvs\"         (1  0 -4)
    \"1.0pre2\"         (1  0 -1 2)
    \"1.0PRE2\"         (1  0 -1 2)
    \"22.8beta3\"       (22 8 -2 3)
@@ -4742,41 +4743,47 @@ in `version-regexp-alist'.
 
 Examples of valid version syntax:
 
-   1.0pre2   1.0.7.5   22.8beta3   0.9alpha1   6.9.30Beta
+   1.0pre2   1.0.7.5   22.8beta3   0.9alpha1   6.9.30Beta   2.4.snapshot   .5
 
 Examples of invalid version syntax:
 
-   1.0prepre2   1.0..7.5   22.8X3   alpha3.2   .5
+   1.0prepre2   1.0..7.5   22.8X3   alpha3.2
 
 Examples of version conversion:
 
    Version String    Version as a List of Integers
-   \"1.0.7.5\"         (1  0  7 5)
-   \"1.0pre2\"         (1  0 -1 2)
-   \"1.0PRE2\"         (1  0 -1 2)
-   \"22.8beta3\"       (22 8 -2 3)
-   \"22.8Beta3\"       (22 8 -2 3)
-   \"0.9alpha1\"       (0  9 -3 1)
+   \".5\"              (0 5)
+   \"0.9 alpha\"       (0  9 -3)
    \"0.9AlphA1\"       (0  9 -3 1)
-   \"0.9alpha\"        (0  9 -3)
    \"0.9snapshot\"     (0  9 -4)
    \"1.0-git\"         (1  0 -4)
+   \"1.0.7.5\"         (1  0  7 5)
+   \"1.0.cvs\"         (1  0 -4)
+   \"1.0PRE2\"         (1  0 -1 2)
+   \"1.0pre2\"         (1  0 -1 2)
+   \"22.8 Beta3\"      (22 8 -2 3)
+   \"22.8beta3\"       (22 8 -2 3)
 
 See documentation for `version-separator' and `version-regexp-alist'."
-  (or (and (stringp ver) (> (length ver) 0))
-      (error "Invalid version string: `%s'" ver))
+  (unless (stringp ver)
+    (error "Version must be a string"))
   ;; Change .x.y to 0.x.y
   (if (and (>= (length ver) (length version-separator))
           (string-equal (substring ver 0 (length version-separator))
                         version-separator))
       (setq ver (concat "0" ver)))
+  (unless (string-match-p "^[0-9]" ver)
+    (error "Invalid version syntax: `%s' (must start with a number)" ver))
+
   (save-match-data
     (let ((i 0)
          (case-fold-search t)          ; ignore case in matching
          lst s al)
+      ;; Parse the version-string up to a separator until there are none left
       (while (and (setq s (string-match "[0-9]+" ver i))
                  (= s i))
-       ;; handle numeric part
+        ;; Add the numeric part to the beginning of the version list;
+        ;; lst gets reversed at the end
        (setq lst (cons (string-to-number (substring ver i (match-end 0)))
                        lst)
              i   (match-end 0))
@@ -4792,15 +4799,15 @@ See documentation for `version-separator' and 
`version-regexp-alist'."
              (setq al (cdr al)))
            (cond (al
                   (push (cdar al) lst))
-                 ;; Convert 22.3a to 22.3.1, 22.3b to 22.3.2, etc.
-                 ((string-match "^[-_+ ]?\\([a-zA-Z]\\)$" s)
+        ;; Convert 22.3a to 22.3.1, 22.3b to 22.3.2, etc., but only if
+        ;; the letter is the end of the version-string, to avoid
+        ;; 22.8X3 being valid
+        ((and (string-match "^[-._+ ]?\\([a-zA-Z]\\)$" s)
+           (= i (length ver)))
                   (push (- (aref (downcase (match-string 1 s)) 0) ?a -1)
                         lst))
                  (t (error "Invalid version syntax: `%s'" ver))))))
-      (if (null lst)
-         (error "Invalid version syntax: `%s'" ver)
-       (nreverse lst)))))
-
+    (nreverse lst))))
 
 (defun version-list-< (l1 l2)
   "Return t if L1, a list specification of a version, is lower than L2.
diff --git a/test/automated/subr-tests.el b/test/automated/subr-tests.el
index ee8db59..3fcb7d3 100644
--- a/test/automated/subr-tests.el
+++ b/test/automated/subr-tests.el
@@ -103,5 +103,117 @@
   (should (equal (macroexpand-all '(when a b c d))
                  '(if a (progn b c d)))))
 
+(ert-deftest subr-test-version-parsing ()
+  (should (equal (version-to-list ".5") '(0 5)))
+  (should (equal (version-to-list "0.9 alpha1") '(0 9 -3 1)))
+  (should (equal (version-to-list "0.9 snapshot") '(0  9 -4)))
+  (should (equal (version-to-list "0.9-alpha1") '(0 9 -3 1)))
+  (should (equal (version-to-list "0.9-snapshot") '(0  9 -4)))
+  (should (equal (version-to-list "0.9.snapshot") '(0  9 -4)))
+  (should (equal (version-to-list "0.9_snapshot") '(0  9 -4)))
+  (should (equal (version-to-list "0.9alpha1") '(0 9 -3 1)))
+  (should (equal (version-to-list "0.9snapshot") '(0  9 -4)))
+  (should (equal (version-to-list "1.0 git") '(1  0 -4)))
+  (should (equal (version-to-list "1.0 pre2") '(1 0 -1 2)))
+  (should (equal (version-to-list "1.0-git") '(1  0 -4)))
+  (should (equal (version-to-list "1.0-pre2") '(1 0 -1 2)))
+  (should (equal (version-to-list "1.0.1-a") '(1 0 1 1)))
+  (should (equal (version-to-list "1.0.1-f") '(1 0 1 6)))
+  (should (equal (version-to-list "1.0.1.a") '(1 0 1 1)))
+  (should (equal (version-to-list "1.0.1.f") '(1 0 1 6)))
+  (should (equal (version-to-list "1.0.1_a") '(1 0 1 1)))
+  (should (equal (version-to-list "1.0.1_f") '(1 0 1 6)))
+  (should (equal (version-to-list "1.0.1a") '(1 0 1 1)))
+  (should (equal (version-to-list "1.0.1f") '(1 0 1 6)))
+  (should (equal (version-to-list "1.0.7.5") '(1 0 7 5)))
+  (should (equal (version-to-list "1.0.git") '(1  0 -4)))
+  (should (equal (version-to-list "1.0.pre2") '(1 0 -1 2)))
+  (should (equal (version-to-list "1.0_git") '(1  0 -4)))
+  (should (equal (version-to-list "1.0_pre2") '(1 0 -1 2)))
+  (should (equal (version-to-list "1.0git") '(1  0 -4)))
+  (should (equal (version-to-list "1.0pre2") '(1 0 -1 2)))
+  (should (equal (version-to-list "22.8 beta3") '(22 8 -2 3)))
+  (should (equal (version-to-list "22.8-beta3") '(22 8 -2 3)))
+  (should (equal (version-to-list "22.8.beta3") '(22 8 -2 3)))
+  (should (equal (version-to-list "22.8_beta3") '(22 8 -2 3)))
+  (should (equal (version-to-list "22.8beta3") '(22 8 -2 3)))
+  (should (equal (version-to-list "6.9.30 Beta") '(6 9 30 -2)))
+  (should (equal (version-to-list "6.9.30-Beta") '(6 9 30 -2)))
+  (should (equal (version-to-list "6.9.30.Beta") '(6 9 30 -2)))
+  (should (equal (version-to-list "6.9.30Beta") '(6 9 30 -2)))
+  (should (equal (version-to-list "6.9.30_Beta") '(6 9 30 -2)))
+
+  (should (equal
+            (error-message-string (should-error (version-to-list 
"OTP-18.1.5")))
+            "Invalid version syntax: `OTP-18.1.5' (must start with a number)"))
+  (should (equal
+            (error-message-string (should-error (version-to-list "")))
+            "Invalid version syntax: `' (must start with a number)"))
+  (should (equal
+            (error-message-string (should-error (version-to-list "1.0..7.5")))
+            "Invalid version syntax: `1.0..7.5'"))
+  (should (equal
+            (error-message-string (should-error (version-to-list 
"1.0prepre2")))
+            "Invalid version syntax: `1.0prepre2'"))
+  (should (equal
+            (error-message-string (should-error (version-to-list "22.8X3")))
+            "Invalid version syntax: `22.8X3'"))
+  (should (equal
+            (error-message-string (should-error (version-to-list 
"beta22.8alpha3")))
+            "Invalid version syntax: `beta22.8alpha3' (must start with a 
number)"))
+  (should (equal
+            (error-message-string (should-error (version-to-list "honk")))
+            "Invalid version syntax: `honk' (must start with a number)"))
+  (should (equal
+            (error-message-string (should-error (version-to-list 9)))
+            "Version must be a string"))
+
+  (let ((version-separator "_"))
+    (should (equal (version-to-list "_5") '(0 5)))
+    (should (equal (version-to-list "0_9 alpha1") '(0 9 -3 1)))
+    (should (equal (version-to-list "0_9 snapshot") '(0  9 -4)))
+    (should (equal (version-to-list "0_9-alpha1") '(0 9 -3 1)))
+    (should (equal (version-to-list "0_9-snapshot") '(0  9 -4)))
+    (should (equal (version-to-list "0_9.alpha1") '(0 9 -3 1)))
+    (should (equal (version-to-list "0_9.snapshot") '(0  9 -4)))
+    (should (equal (version-to-list "0_9alpha1") '(0 9 -3 1)))
+    (should (equal (version-to-list "0_9snapshot") '(0  9 -4)))
+    (should (equal (version-to-list "1_0 git") '(1  0 -4)))
+    (should (equal (version-to-list "1_0 pre2") '(1 0 -1 2)))
+    (should (equal (version-to-list "1_0-git") '(1  0 -4)))
+    (should (equal (version-to-list "1_0.pre2") '(1 0 -1 2)))
+    (should (equal (version-to-list "1_0_1-a") '(1 0 1 1)))
+    (should (equal (version-to-list "1_0_1-f") '(1 0 1 6)))
+    (should (equal (version-to-list "1_0_1.a") '(1 0 1 1)))
+    (should (equal (version-to-list "1_0_1.f") '(1 0 1 6)))
+    (should (equal (version-to-list "1_0_1_a") '(1 0 1 1)))
+    (should (equal (version-to-list "1_0_1_f") '(1 0 1 6)))
+    (should (equal (version-to-list "1_0_1a") '(1 0 1 1)))
+    (should (equal (version-to-list "1_0_1f") '(1 0 1 6)))
+    (should (equal (version-to-list "1_0_7_5") '(1 0 7 5)))
+    (should (equal (version-to-list "1_0_git") '(1  0 -4)))
+    (should (equal (version-to-list "1_0pre2") '(1 0 -1 2)))
+    (should (equal (version-to-list "22_8 beta3") '(22 8 -2 3)))
+    (should (equal (version-to-list "22_8-beta3") '(22 8 -2 3)))
+    (should (equal (version-to-list "22_8.beta3") '(22 8 -2 3)))
+    (should (equal (version-to-list "22_8beta3") '(22 8 -2 3)))
+    (should (equal (version-to-list "6_9_30 Beta") '(6 9 30 -2)))
+    (should (equal (version-to-list "6_9_30-Beta") '(6 9 30 -2)))
+    (should (equal (version-to-list "6_9_30.Beta") '(6 9 30 -2)))
+    (should (equal (version-to-list "6_9_30Beta") '(6 9 30 -2)))
+
+    (should (equal
+              (error-message-string (should-error (version-to-list 
"1_0__7_5")))
+              "Invalid version syntax: `1_0__7_5'"))
+    (should (equal
+              (error-message-string (should-error (version-to-list 
"1_0prepre2")))
+              "Invalid version syntax: `1_0prepre2'"))
+    (should (equal
+              (error-message-string (should-error (version-to-list "22.8X3")))
+              "Invalid version syntax: `22.8X3'"))
+    (should (equal
+              (error-message-string (should-error (version-to-list 
"beta22_8alpha3")))
+              "Invalid version syntax: `beta22_8alpha3' (must start with a 
number)"))))
+
 (provide 'subr-tests)
 ;;; subr-tests.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]