gnu-arch-users
[Top][All Lists]
Advanced

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

Re: [Gnu-arch-users] Getting script to compare arch versions


From: ams
Subject: Re: [Gnu-arch-users] Getting script to compare arch versions
Date: Thu, 01 Dec 2005 01:26:39 +0100

   I'd like a perl script to be able to compare version numbers, to
   see which is later. Obviously in simple cases like

     cat--branch--1
     cat--branch--2

   it is easy, but how to handle all in the general case?

This isn't a perl script, but a elisp function which does the same
thing, you could modify it to use perl, or port it to some other lisp
implementation that is nicer when run as a batch job.  It handles the
most common cases.


===File ~/slask/version-compare.el========================
;;; subr.el --- basic lisp subroutines for Emacs

;; Copyright (C) 1985, 1986, 1992, 1994, 1995, 1999, 2000, 2001, 2002, 2003,
;;   2004, 2005 Free Software Foundation, Inc.

;; Maintainer: FSF
;; Keywords: internal

;; This file is part of GNU Emacs.

;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.

;;; Commentary:

;;; Code:

;; Removed lots of code that isn't related to the version comparison
;; code.


;;;; Comparing version strings.

(defvar version-separator "."
  "*Specify the string used to separate the version elements.

Usually the separator is \".\", but it can be any other string.")


(defvar version-regexp-alist
  '(("^[-_+]?a\\(lpha\\)?$"   . -3)
    ("^[-_+]$" . -3)    ; treat "1.2.3-20050920" and "1.2-3" as alpha releases
    ("^[-_+]cvs$" . -3) ; treat "1.2.3-CVS" as alpha release
    ("^[-_+]?b\\(eta\\)?$"    . -2)
    ("^[-_+]?\\(pre\\|rc\\)$" . -1))
  "*Specify association between non-numeric version part and a priority.

This association is used to handle version string like \"1.0pre2\",
\"0.9alpha1\", etc.  It's used by `version-to-list' (which see) to convert the
non-numeric part to an integer.  For example:

   String Version    Integer List Version
   \"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)
   \"0.9AlphA1\"       (0  9 -3 1)
   \"0.9alpha\"        (0  9 -3)

Each element has the following form:

   (REGEXP . PRIORITY)

Where:

REGEXP          regexp used to match non-numeric part of a version string.
                It should begin with a `^' anchor and end with a `$' to
                prevent false hits.  Letter-case is ignored while matching
                REGEXP.

PRIORITY        negative integer which indicate the non-numeric priority.")


(defun version-to-list (ver)
  "Convert version string VER into an integer list.

The version syntax is given by the following EBNF:

   VERSION ::= NUMBER ( SEPARATOR NUMBER )*.

   NUMBER ::= (0|1|2|3|4|5|6|7|8|9)+.

   SEPARATOR ::= `version-separator' (which see)
               | `version-regexp-alist' (which see).

The NUMBER part is optional if SEPARATOR is a match for an element
in `version-regexp-alist'.

As an example of valid version syntax:

   1.0pre2   1.0.7.5   22.8beta3   0.9alpha1   6.9.30Beta

As an example of invalid version syntax:

   1.0prepre2   1.0..7.5   22.8X3   alpha3.2   .5

As an example of version convertion:

   String Version    Integer List Version
   \"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)
   \"0.9AlphA1\"       (0  9 -3 1)
   \"0.9alpha\"        (0  9 -3)

See documentation for `version-separator' and `version-regexp-alist'."
  (or (and (stringp ver) (not (string= ver "")))
      (error "Invalid version string: '%s'" ver))
  (save-match-data
    (let ((i 0)
          (case-fold-search t)          ; ignore case in matching
          lst s al)
      (while (and (setq s (string-match "[0-9]+" ver i))
                  (= s i))
        ;; handle numeric part
        (setq lst (cons (string-to-number (substring ver i (match-end 0)))
                        lst)
              i   (match-end 0))
        ;; handle non-numeric part
        (when (and (setq s (string-match "[^0-9]+" ver i))
                   (= s i))
          (setq s (substring ver i (match-end 0))
                i (match-end 0))
          ;; handle alpha, beta, pre, etc. separator
          (unless (string= s version-separator)
            (setq al version-regexp-alist)
            (while (and al (not (string-match (caar al) s)))
              (setq al (cdr al)))
            (or al (error "Invalid version syntax: '%s'" ver))
            (setq lst (cons (cdar al) lst)))))
      (if (null lst)
          (error "Invalid version syntax: '%s'" ver)
        (nreverse lst)))))


(defun version-list-< (l1 l2)
  "Return t if integer list L1 is lesser than L2.

Note that integer list (1) is equal to (1 0), (1 0 0), (1 0 0 0),
etc.  That is, the trailing zeroes are irrelevant.  Also, integer
list (1) is greater than (1 -1) which is greater than (1 -2)
which is greater than (1 -3)."
  (while (and l1 l2 (= (car l1) (car l2)))
    (setq l1 (cdr l1)
          l2 (cdr l2)))
  (cond
   ;; l1 not null and l2 not null
   ((and l1 l2) (< (car l1) (car l2)))
   ;; l1 null and l2 null         ==> l1 length = l2 length
   ((and (null l1) (null l2)) nil)
   ;; l1 not null and l2 null     ==> l1 length > l2 length
   (l1 (< (version-list-not-zero l1) 0))
   ;; l1 null and l2 not null     ==> l2 length > l1 length
   (t  (< 0 (version-list-not-zero l2)))))


(defun version-list-= (l1 l2)
  "Return t if integer list L1 is equal to L2.

Note that integer list (1) is equal to (1 0), (1 0 0), (1 0 0 0),
etc.  That is, the trailing zeroes are irrelevant.  Also, integer
list (1) is greater than (1 -1) which is greater than (1 -2)
which is greater than (1 -3)."
  (while (and l1 l2 (= (car l1) (car l2)))
    (setq l1 (cdr l1)
          l2 (cdr l2)))
  (cond
   ;; l1 not null and l2 not null
   ((and l1 l2) nil)
   ;; l1 null and l2 null     ==> l1 length = l2 length
   ((and (null l1) (null l2)))
   ;; l1 not null and l2 null ==> l1 length > l2 length
   (l1 (zerop (version-list-not-zero l1)))
   ;; l1 null and l2 not null ==> l2 length > l1 length
   (t  (zerop (version-list-not-zero l2)))))


(defun version-list-<= (l1 l2)
  "Return t if integer list L1 is lesser than or equal to L2.

Note that integer list (1) is equal to (1 0), (1 0 0), (1 0 0 0),
etc.  That is, the trailing zeroes are irrelevant.  Also, integer
list (1) is greater than (1 -1) which is greater than (1 -2)
which is greater than (1 -3)."
  (while (and l1 l2 (= (car l1) (car l2)))
    (setq l1 (cdr l1)
          l2 (cdr l2)))
  (cond
   ;; l1 not null and l2 not null
   ((and l1 l2) (< (car l1) (car l2)))
   ;; l1 null and l2 null     ==> l1 length = l2 length
   ((and (null l1) (null l2)))
   ;; l1 not null and l2 null ==> l1 length > l2 length
   (l1 (<= (version-list-not-zero l1) 0))
   ;; l1 null and l2 not null ==> l2 length > l1 length
   (t  (<= 0 (version-list-not-zero l2)))))

(defun version-list-not-zero (lst)
  "Return the first non-zero element of integer list LST.

If all LST elements are zeroes or LST is nil, return zero."
  (while (and lst (zerop (car lst)))
    (setq lst (cdr lst)))
  (if lst
      (car lst)
    ;; there is no element different of zero
    0))


(defun version< (v1 v2)
  "Return t if version V1 is lesser than V2.

Note that version string \"1\" is equal to \"1.0\", \"1.0.0\", \"1.0.0.0\",
etc.  That is, the trailing \".0\"s are irrelevant.  Also, version string \"1\"
is greater than \"1pre\" which is greater than \"1beta\" which is greater than
\"1alpha\"."
  (version-list-< (version-to-list v1) (version-to-list v2)))


(defun version<= (v1 v2)
  "Return t if version V1 is lesser than or equal to V2.

Note that version string \"1\" is equal to \"1.0\", \"1.0.0\", \"1.0.0.0\",
etc.  That is, the trailing \".0\"s are irrelevant.  Also, version string \"1\"
is greater than \"1pre\" which is greater than \"1beta\" which is greater than
\"1alpha\"."
  (version-list-<= (version-to-list v1) (version-to-list v2)))

(defun version= (v1 v2)
  "Return t if version V1 is equal to V2.

Note that version string \"1\" is equal to \"1.0\", \"1.0.0\", \"1.0.0.0\",
etc.  That is, the trailing \".0\"s are irrelevant.  Also, version string \"1\"
is greater than \"1pre\" which is greater than \"1beta\" which is greater than
\"1alpha\"."
  (version-list-= (version-to-list v1) (version-to-list v2)))



;; arch-tag: f7e0e6e5-70aa-4897-ae72-7a3511ec40bc
;;; subr.el ends here
============================================================




reply via email to

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